@ -3,23 +3,20 @@ import { useDispatch, useSelector } from "react-redux";
import { addUser } from "../state/features/authSlice" ;
import { addUser } from "../state/features/authSlice" ;
import { RootState } from "../state/store" ;
import { RootState } from "../state/store" ;
import CreateStoreModal , {
import CreateStoreModal , {
onPublishParam
onPublishParam ,
} from "../components/modals/CreateStoreModal" ;
} from "../components/modals/CreateStoreModal" ;
import EditStoreModal , {
import EditStoreModal , {
onPublishParamEdit
onPublishParamEdit ,
} from "../components/modals/EditStoreModal" ;
} from "../components/modals/EditStoreModal" ;
import {
import {
setCurrentStore ,
setCurrentStore ,
setDataContainer ,
setDataContainer ,
toggleEditStoreModal ,
toggleEditStoreModal ,
toggleCreateStoreModal ,
setIsLoadingGlobal ,
setIsLoadingGlobal ,
resetProducts ,
resetListProducts ,
resetListProducts ,
DataContainer ,
ProductDataContainer ,
ProductDataContainer ,
updateRecentlyVisitedStoreId ,
updateRecentlyVisitedStoreId ,
clearDataCotainer
clearDataCotainer ,
} from "../state/features/globalSlice" ;
} from "../state/features/globalSlice" ;
import NavBar from "../components/layout/Navbar/Navbar" ;
import NavBar from "../components/layout/Navbar/Navbar" ;
import PageLoader from "../components/common/PageLoader" ;
import PageLoader from "../components/common/PageLoader" ;
@ -32,14 +29,26 @@ import {
addToAllMyStores ,
addToAllMyStores ,
addToHashMapStores ,
addToHashMapStores ,
addToStores ,
addToStores ,
setAllMyStores
setAllMyStores ,
} from "../state/features/storeSlice" ;
} from "../state/features/storeSlice" ;
import { useFetchStores } from "../hooks/useFetchStores" ;
import { useFetchStores } from "../hooks/useFetchStores" ;
import { DATA_CONTAINER_BASE , STORE_BASE } from "../constants/identifiers" ;
import { DATA_CONTAINER_BASE , STORE_BASE } from "../constants/identifiers" ;
import { ReusableModal } from "../components/modals/ReusableModal" ;
import { ReusableModal } from "../components/modals/ReusableModal" ;
import { Box , Button , Stack , Typography } from "@mui/material" ;
import { Stack , Typography , useTheme } from "@mui/material" ;
import { useNavigate } from "react-router-dom" ;
import { useNavigate } from "react-router-dom" ;
import { CustomModalButton , CustomModalTitle } from "./GlobalWrapper-styles" ;
import {
CustomModalButton ,
CustomModalTitle ,
DownloadNowButton ,
DownloadQortalCol ,
DownloadQortalFont ,
DownloadQortalSubFont ,
QortalIcon ,
} from "./GlobalWrapper-styles" ;
import QortalLogo from "../assets/img/Q-AppsLogo.webp" ;
import { DownloadCircleSVG } from "../assets/svgs/DownloadCircleSVG" ;
import { UAParser } from "ua-parser-js" ;
interface Props {
interface Props {
children : React.ReactNode ;
children : React.ReactNode ;
setTheme : ( val : string ) = > void ;
setTheme : ( val : string ) = > void ;
@ -54,6 +63,10 @@ interface ShortDataContainer {
const GlobalWrapper : React.FC < Props > = ( { children , setTheme } ) = > {
const GlobalWrapper : React.FC < Props > = ( { children , setTheme } ) = > {
const dispatch = useDispatch ( ) ;
const dispatch = useDispatch ( ) ;
const navigate = useNavigate ( ) ;
const navigate = useNavigate ( ) ;
const theme = useTheme ( ) ;
// Determine which OS they're on
const parser = new UAParser ( ) ;
// Get user from auth
// Get user from auth
const user = useSelector ( ( state : RootState ) = > state . auth . user ) ;
const user = useSelector ( ( state : RootState ) = > state . auth . user ) ;
@ -94,6 +107,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const [ openDataContainerModal , setOpenDataContainer ] =
const [ openDataContainerModal , setOpenDataContainer ] =
useState < boolean > ( false ) ;
useState < boolean > ( false ) ;
const [ retryDataContainer , setRetryDataContainer ] = useState < boolean > ( false ) ;
const [ retryDataContainer , setRetryDataContainer ] = useState < boolean > ( false ) ;
const [ showDownloadModal , setShowDownloadModal ] = useState < boolean > ( false ) ;
useEffect ( ( ) = > {
useEffect ( ( ) = > {
if ( ! user ? . name ) return ;
if ( ! user ? . name ) return ;
@ -107,7 +121,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
action : "GET_QDN_RESOURCE_URL" ,
action : "GET_QDN_RESOURCE_URL" ,
name : user?.name ,
name : user?.name ,
service : "THUMBNAIL" ,
service : "THUMBNAIL" ,
identifier : "qortal_avatar"
identifier : "qortal_avatar" ,
} ) ;
} ) ;
if ( url === "Resource does not exist" ) return ;
if ( url === "Resource does not exist" ) return ;
@ -142,8 +156,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const responseBlogs = await fetch ( url2 , {
const responseBlogs = await fetch ( url2 , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const dataMetadata = await responseBlogs . json ( ) ;
const dataMetadata = await responseBlogs . json ( ) ;
if ( dataMetadata . length === 0 ) {
if ( dataMetadata . length === 0 ) {
@ -157,8 +171,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const responseBlogs = await fetch ( url , {
const responseBlogs = await fetch ( url , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const responseDataBlogs = await responseBlogs . json ( ) ;
const responseDataBlogs = await responseBlogs . json ( ) ;
const filterOut = responseDataBlogs . filter ( ( blog : any ) = >
const filterOut = responseDataBlogs . filter ( ( blog : any ) = >
@ -173,8 +187,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const response = await fetch ( urlBlog , {
const response = await fetch ( urlBlog , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const responseData = await response . json ( ) ;
const responseData = await response . json ( ) ;
@ -182,8 +196,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const response2 = await fetch ( urlDataContainer , {
const response2 = await fetch ( urlDataContainer , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const responseData2 = await response2 . json ( ) ;
const responseData2 = await response2 . json ( ) ;
// Set currentStore in the Redux global state
// Set currentStore in the Redux global state
@ -200,7 +214,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
logo : responseData?.logo || "" ,
logo : responseData?.logo || "" ,
shortStoreId : responseData?.shortStoreId ,
shortStoreId : responseData?.shortStoreId ,
supportedCoins : responseData?.supportedCoins || [ ] ,
supportedCoins : responseData?.supportedCoins || [ ] ,
foreignCoins : responseData?.foreignCoins || { }
foreignCoins : responseData?.foreignCoins || { } ,
} )
} )
) ;
) ;
// Set listProducts in the Redux global state
// Set listProducts in the Redux global state
@ -208,7 +222,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setDataContainer ( {
setDataContainer ( {
. . . responseData2 ,
. . . responseData2 ,
id : ` ${ store . identifier } - ${ DATA_CONTAINER_BASE } `
id : ` ${ store . identifier } - ${ DATA_CONTAINER_BASE } ` ,
} )
} )
) ;
) ;
} else {
} else {
@ -218,7 +232,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
storeId : store.identifier ,
storeId : store.identifier ,
shortStoreId : shortStoreId ,
shortStoreId : shortStoreId ,
owner : store.name ,
owner : store.name ,
products : { }
products : { } ,
} ;
} ;
const dataContainerToBase64 = await objectToBase64 ( dataContainer ) ;
const dataContainerToBase64 = await objectToBase64 ( dataContainer ) ;
@ -227,15 +241,21 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
name : store.name ,
name : store.name ,
service : "DOCUMENT" ,
service : "DOCUMENT" ,
data64 : dataContainerToBase64 ,
data64 : dataContainerToBase64 ,
identifier : ` ${ store . identifier } - ${ DATA_CONTAINER_BASE } `
identifier : ` ${ store . identifier } - ${ DATA_CONTAINER_BASE } ` ,
} ) ;
} ) ;
}
}
}
}
// Only called when user clicks authenticate from inside a gateway
const displayDownloadQortalGatewayModalFunc = ( ) = > {
setShowDownloadModal ( true ) ;
} ;
const askForAccountInformation = React . useCallback ( async ( ) = > {
const askForAccountInformation = React . useCallback ( async ( ) = > {
try {
try {
let account = await qortalRequest ( {
let account = await qortalRequest ( {
action : "GET_USER_ACCOUNT"
action : "GET_USER_ACCOUNT" ,
} ) ;
} ) ;
const name = await getNameInfo ( account . address ) ;
const name = await getNameInfo ( account . address ) ;
@ -258,7 +278,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
service : "DOCUMENT" ,
service : "DOCUMENT" ,
data64 : dataContainerToBase64 ,
data64 : dataContainerToBase64 ,
identifier : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } ` ,
identifier : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } ` ,
filename : "datacontainer.json"
filename : "datacontainer.json" ,
} ) ;
} ) ;
if ( isSuccessful ( resourceResponse ) ) {
if ( isSuccessful ( resourceResponse ) ) {
await new Promise < void > ( ( res , rej ) = > {
await new Promise < void > ( ( res , rej ) = > {
@ -269,13 +289,13 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setDataContainer ( {
setDataContainer ( {
. . . storedDataContainer ,
. . . storedDataContainer ,
id : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } `
id : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } ` ,
} )
} )
) ;
) ;
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "Shop successfully created" ,
msg : "Shop successfully created" ,
alertType : "success"
alertType : "success" ,
} )
} )
) ;
) ;
setCloseCreateStoreModal ( true ) ;
setCloseCreateStoreModal ( true ) ;
@ -289,7 +309,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "You must create a data container in order to create a shop!" ,
msg : "You must create a data container in order to create a shop!" ,
alertType : "error"
alertType : "error" ,
} )
} )
) ;
) ;
// Try again after 8 seconds automatically
// Try again after 8 seconds automatically
@ -304,7 +324,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
service : "DOCUMENT" ,
service : "DOCUMENT" ,
data64 : dataContainerToBase64 ,
data64 : dataContainerToBase64 ,
identifier : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } ` ,
identifier : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } ` ,
filename : "datacontainer.json"
filename : "datacontainer.json" ,
} ) ;
} ) ;
if ( isSuccessful ( resourceResponse ) ) {
if ( isSuccessful ( resourceResponse ) ) {
await new Promise < void > ( ( res , rej ) = > {
await new Promise < void > ( ( res , rej ) = > {
@ -315,13 +335,13 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setDataContainer ( {
setDataContainer ( {
. . . storedDataContainer ,
. . . storedDataContainer ,
id : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } `
id : ` ${ storedDataContainer ? . storeId } - ${ DATA_CONTAINER_BASE } ` ,
} )
} )
) ;
) ;
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "Shop successfully created" ,
msg : "Shop successfully created" ,
alertType : "success"
alertType : "success" ,
} )
} )
) ;
) ;
setCloseCreateStoreModal ( true ) ;
setCloseCreateStoreModal ( true ) ;
@ -339,7 +359,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "You must create a data container in order to create a shop!" ,
msg : "You must create a data container in order to create a shop!" ,
alertType : "error"
alertType : "error" ,
} )
} )
) ;
) ;
}
}
@ -359,7 +379,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
storeIdentifier ,
storeIdentifier ,
logo ,
logo ,
foreignCoins ,
foreignCoins ,
supportedCoins
supportedCoins ,
} : onPublishParam ) = > {
} : onPublishParam ) = > {
if ( ! user || ! user . name )
if ( ! user || ! user . name )
throw new Error ( "Cannot publish: You do not have a Qortal name" ) ;
throw new Error ( "Cannot publish: You do not have a Qortal name" ) ;
@ -394,18 +414,19 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
shortStoreId : formatStoreIdentifier ,
shortStoreId : formatStoreIdentifier ,
logo ,
logo ,
foreignCoins ,
foreignCoins ,
supportedCoins
supportedCoins ,
} ;
} ;
if ( ! storeObj . shortStoreId ) {
if ( ! storeObj . shortStoreId ) {
throw new Error ( "Please insert a valid store id" ) ;
throw new Error ( "Please insert a valid store id" ) ;
}
}
// Store Data Container to send to QDN (this will allow easier querying of products afterwards. Think of it as a database in the redux global state for the current store. Max 1 per store). At first there's no products, but they will be added later. We store this in the state so we can reuse it easily if our data container fails to publish.
// Store Data Container to send to QDN (this will allow easier querying of products afterwards. Think of it as a database in the redux global state for the current store. Max 1 per store). At first there's no products, but they will be added later. We store this in the state so we can reuse it easily if our data container fails to publish.
try {
try {
const storeToBase64 = await objectToBase64 ( storeObj ) ;
const storeToBase64 = await objectToBase64 ( storeObj ) ;
// Publish Store to QDN
// Publish Store to QDN
let metadescription = ` **coins:QORTtrue,ARRR ${ supportedCoins . includes ( 'ARRR' ) } ** ` + description . slice ( 0 , 180 )
let metadescription =
` **coins:QORTtrue,ARRR ${ supportedCoins . includes ( "ARRR" ) } ** ` +
description . slice ( 0 , 180 ) ;
const resourceResponse = await qortalRequest ( {
const resourceResponse = await qortalRequest ( {
action : "PUBLISH_QDN_RESOURCE" ,
action : "PUBLISH_QDN_RESOURCE" ,
@ -415,7 +436,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
filename : "store.json" ,
filename : "store.json" ,
title ,
title ,
description : metadescription ,
description : metadescription ,
identifier : identifier
identifier : identifier ,
} ) ;
} ) ;
if ( isSuccessful ( resourceResponse ) ) {
if ( isSuccessful ( resourceResponse ) ) {
await new Promise < void > ( ( res , rej ) = > {
await new Promise < void > ( ( res , rej ) = > {
@ -428,7 +449,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
storeId : identifier ,
storeId : identifier ,
shortStoreId : formatStoreIdentifier ,
shortStoreId : formatStoreIdentifier ,
owner : name ,
owner : name ,
products : { }
products : { } ,
} ;
} ;
// Store data (other than the raw data or metadata) to add to Redux
// Store data (other than the raw data or metadata) to add to Redux
const storeData = {
const storeData = {
@ -438,7 +459,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
owner : name ,
owner : name ,
id : storeIdentifier ,
id : storeIdentifier ,
shortStoreId : formatStoreIdentifier ,
shortStoreId : formatStoreIdentifier ,
logo : logo
logo : logo ,
} ;
} ;
// Store Full Object to send to redux hashMapStores
// Store Full Object to send to redux hashMapStores
const storefullObj = {
const storefullObj = {
@ -447,7 +468,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
isValid : true ,
isValid : true ,
owner : name ,
owner : name ,
created : createdAt ,
created : createdAt ,
updated : createdAt
updated : createdAt ,
} ;
} ;
dispatch ( setCurrentStore ( storefullObj ) ) ;
dispatch ( setCurrentStore ( storefullObj ) ) ;
@ -464,17 +485,17 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
if ( typeof error === "string" ) {
if ( typeof error === "string" ) {
notificationObj = {
notificationObj = {
msg : error || "Failed to create store" ,
msg : error || "Failed to create store" ,
alertType : "error"
alertType : "error" ,
} ;
} ;
} else if ( typeof error ? . error === "string" ) {
} else if ( typeof error ? . error === "string" ) {
notificationObj = {
notificationObj = {
msg : error?.error || "Failed to create store" ,
msg : error?.error || "Failed to create store" ,
alertType : "error"
alertType : "error" ,
} ;
} ;
} else {
} else {
notificationObj = {
notificationObj = {
msg : error?.message || "Failed to create store" ,
msg : error?.message || "Failed to create store" ,
alertType : "error"
alertType : "error" ,
} ;
} ;
}
}
if ( ! notificationObj ) return ;
if ( ! notificationObj ) return ;
@ -498,7 +519,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
shipsTo ,
shipsTo ,
logo ,
logo ,
foreignCoins ,
foreignCoins ,
supportedCoins
supportedCoins ,
} : onPublishParamEdit ) = > {
} : onPublishParamEdit ) = > {
if ( ! user || ! user . name || ! currentStore )
if ( ! user || ! user . name || ! currentStore )
throw new Error ( "Cannot publish: You do not have a Qortal name" ) ;
throw new Error ( "Cannot publish: You do not have a Qortal name" ) ;
@ -522,13 +543,15 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
logo ,
logo ,
shortStoreId : currentStore.shortStoreId ? ? shortStoreId ,
shortStoreId : currentStore.shortStoreId ? ? shortStoreId ,
foreignCoins ,
foreignCoins ,
supportedCoins
supportedCoins ,
} ;
} ;
try {
try {
const storeToBase64 = await objectToBase64 ( storeObj ) ;
const storeToBase64 = await objectToBase64 ( storeObj ) ;
let metadescription = ` **coins:QORTtrue,ARRR ${ supportedCoins . includes ( 'ARRR' ) } ** ` + description . slice ( 0 , 180 )
let metadescription =
` **coins:QORTtrue,ARRR ${ supportedCoins . includes ( "ARRR" ) } ** ` +
description . slice ( 0 , 180 ) ;
const resourceResponse = await qortalRequest ( {
const resourceResponse = await qortalRequest ( {
action : "PUBLISH_QDN_RESOURCE" ,
action : "PUBLISH_QDN_RESOURCE" ,
name : name ,
name : name ,
@ -537,7 +560,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
filename : "store.json" ,
filename : "store.json" ,
title ,
title ,
description : metadescription ,
description : metadescription ,
identifier : currentStore.id
identifier : currentStore.id ,
} ) ;
} ) ;
await new Promise < void > ( ( res , rej ) = > {
await new Promise < void > ( ( res , rej ) = > {
@ -550,7 +573,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "Shop successfully updated" ,
msg : "Shop successfully updated" ,
alertType : "success"
alertType : "success" ,
} )
} )
) ;
) ;
} catch ( error : any ) {
} catch ( error : any ) {
@ -558,17 +581,17 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
if ( typeof error === "string" ) {
if ( typeof error === "string" ) {
notificationObj = {
notificationObj = {
msg : error || "Failed to update blog" ,
msg : error || "Failed to update blog" ,
alertType : "error"
alertType : "error" ,
} ;
} ;
} else if ( typeof error ? . error === "string" ) {
} else if ( typeof error ? . error === "string" ) {
notificationObj = {
notificationObj = {
msg : error?.error || "Failed to update blog" ,
msg : error?.error || "Failed to update blog" ,
alertType : "error"
alertType : "error" ,
} ;
} ;
} else {
} else {
notificationObj = {
notificationObj = {
msg : error?.message || "Failed to update blog" ,
msg : error?.message || "Failed to update blog" ,
alertType : "error"
alertType : "error" ,
} ;
} ;
}
}
if ( ! notificationObj ) return ;
if ( ! notificationObj ) return ;
@ -597,8 +620,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const response = await fetch ( url , {
const response = await fetch ( url , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const responseData = await response . json ( ) ;
const responseData = await response . json ( ) ;
// Data returned from that endpoint of the API
// Data returned from that endpoint of the API
@ -612,7 +635,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
created : storeItem.created ,
created : storeItem.created ,
updated : storeItem.updated ,
updated : storeItem.updated ,
owner : storeItem.name ,
owner : storeItem.name ,
id : storeItem.identifier
id : storeItem.identifier ,
} ;
} ;
} ) ;
} ) ;
@ -624,7 +647,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
if ( content . owner && content . id ) {
if ( content . owner && content . id ) {
const res = checkAndUpdateResource ( {
const res = checkAndUpdateResource ( {
id : content.id ,
id : content.id ,
updated : content.updated
updated : content.updated ,
} ) ;
} ) ;
if ( res ) {
if ( res ) {
getStore ( content . owner , content . id , content ) ;
getStore ( content . owner , content . id , content ) ;
@ -668,8 +691,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const shopData = await fetch ( urlShop , {
const shopData = await fetch ( urlShop , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const shopResource = await shopData . json ( ) ;
const shopResource = await shopData . json ( ) ;
// Clear product list from redux global state
// Clear product list from redux global state
@ -687,7 +710,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
logo : shopResource?.logo ,
logo : shopResource?.logo ,
shortStoreId : shopResource?.shortStoreId ,
shortStoreId : shopResource?.shortStoreId ,
supportedCoins : shopResource?.supportedCoins || [ ] ,
supportedCoins : shopResource?.supportedCoins || [ ] ,
foreignCoins : shopResource?.foreignCoins || { }
foreignCoins : shopResource?.foreignCoins || { } ,
} )
} )
) ;
) ;
// Fetch data container data on QDN (product resources)
// Fetch data container data on QDN (product resources)
@ -695,8 +718,8 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
const response = await fetch ( urlDataContainer , {
const response = await fetch ( urlDataContainer , {
method : "GET" ,
method : "GET" ,
headers : {
headers : {
"Content-Type" : "application/json"
"Content-Type" : "application/json" ,
}
} ,
} ) ;
} ) ;
const responseData2 = await response . json ( ) ;
const responseData2 = await response . json ( ) ;
if (
if (
@ -707,7 +730,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setDataContainer ( {
setDataContainer ( {
. . . responseData2 ,
. . . responseData2 ,
id : ` ${ myStoreFound . id } - ${ DATA_CONTAINER_BASE } `
id : ` ${ myStoreFound . id } - ${ DATA_CONTAINER_BASE } ` ,
} )
} )
) ;
) ;
} else if ( user ? . name && recentlyVisitedStoreId ) {
} else if ( user ? . name && recentlyVisitedStoreId ) {
@ -722,7 +745,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
limit : 0 ,
limit : 0 ,
offset : 0 ,
offset : 0 ,
reverse : true ,
reverse : true ,
mode : "ALL"
mode : "ALL" ,
} ) ;
} ) ;
if ( dataContainerExists ? . length === 0 ) {
if ( dataContainerExists ? . length === 0 ) {
// Publish Data Container to QDN
// Publish Data Container to QDN
@ -737,7 +760,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
storeId : recentlyVisitedStoreId ,
storeId : recentlyVisitedStoreId ,
shortStoreId : formatStoreIdentifier ,
shortStoreId : formatStoreIdentifier ,
owner : user?.name ,
owner : user?.name ,
products : { }
products : { } ,
} ;
} ;
const dataContainerToBase64 = await objectToBase64 (
const dataContainerToBase64 = await objectToBase64 (
dataContainer
dataContainer
@ -749,20 +772,20 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
service : "DOCUMENT" ,
service : "DOCUMENT" ,
data64 : dataContainerToBase64 ,
data64 : dataContainerToBase64 ,
identifier : ` ${ recentlyVisitedStoreId } - ${ DATA_CONTAINER_BASE } ` ,
identifier : ` ${ recentlyVisitedStoreId } - ${ DATA_CONTAINER_BASE } ` ,
filename : "datacontainer.json"
filename : "datacontainer.json" ,
} ) ;
} ) ;
if ( dataContainerCreated && ! dataContainerCreated . error ) {
if ( dataContainerCreated && ! dataContainerCreated . error ) {
dispatch (
dispatch (
setDataContainer ( {
setDataContainer ( {
. . . dataContainer ,
. . . dataContainer ,
id : ` ${ recentlyVisitedStoreId } - ${ DATA_CONTAINER_BASE } `
id : ` ${ recentlyVisitedStoreId } - ${ DATA_CONTAINER_BASE } ` ,
} )
} )
) ;
) ;
}
}
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "Data Container Created!" ,
msg : "Data Container Created!" ,
alertType : "success"
alertType : "success" ,
} )
} )
) ;
) ;
} catch ( error ) {
} catch ( error ) {
@ -770,7 +793,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "Error when creating the data container. Please try again!" ,
msg : "Error when creating the data container. Please try again!" ,
alertType : "error"
alertType : "error" ,
} )
} )
) ;
) ;
dispatch ( updateRecentlyVisitedStoreId ( "" ) ) ;
dispatch ( updateRecentlyVisitedStoreId ( "" ) ) ;
@ -780,7 +803,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch (
dispatch (
setNotification ( {
setNotification ( {
msg : "Error when fetching store data. Please try again!" ,
msg : "Error when fetching store data. Please try again!" ,
alertType : "error"
alertType : "error" ,
} )
} )
) ;
) ;
navigate ( "/" ) ;
navigate ( "/" ) ;
@ -862,11 +885,94 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
userName = { user ? . name || "" }
userName = { user ? . name || "" }
userAvatar = { userAvatar }
userAvatar = { userAvatar }
authenticate = { askForAccountInformation }
authenticate = { askForAccountInformation }
displayDownloadGatewayModalFunc = { displayDownloadQortalGatewayModalFunc }
hasAttemptedToFetchShopInitial = { hasAttemptedToFetchShopInitial }
hasAttemptedToFetchShopInitial = { hasAttemptedToFetchShopInitial }
/ >
/ >
< ConsentModal / >
< ConsentModal / >
{ /* Cart opens when setIsOpen action is dispatched to Redux Global State */ }
{ /* Cart opens when setIsOpen action is dispatched to Redux Global State */ }
< Cart / >
< Cart / >
{ showDownloadModal && (
< ReusableModal
open = { showDownloadModal }
onClose = { ( ) = > {
setShowDownloadModal ( false ) ;
} }
customStyles = { {
width : "370px" ,
height : "80%" ,
backgroundColor :
theme . palette . mode === "light" ? "#e8e8e8" : "#030d1a" ,
position : "relative" ,
padding : "15px 20px" ,
borderRadius : "3px" ,
overflowY : "auto" ,
overflowX : "hidden" ,
maxHeight : "90vh" ,
} }
className = "download-qortal-modal"
>
< DownloadQortalCol >
< QortalIcon src = { QortalLogo } alt = "qortal-icon" / >
< DownloadQortalFont > Download Qortal < / DownloadQortalFont >
< DownloadQortalSubFont >
Experience a new internet paradigm , and start your Qortal
experience today by downloading and installing the Qortal
software .
< / DownloadQortalSubFont >
< DownloadNowButton
onClick = { ( ) = > {
const userOS = parser . getOS ( ) . name ;
if ( userOS ? . includes ( "Android" || "iOS" ) ) {
dispatch (
setNotification ( {
msg : "Qortal is not available on mobile devices yet. Please download on a desktop or laptop." ,
alertType : "error" ,
} )
) ;
return ;
} else if ( userOS ? . includes ( "Mac" ) ) {
window . location . href =
"https://github.com/Qortal/qortal-ui/releases/latest/download/Qortal-Setup-macOS.dmg" ;
dispatch (
setNotification ( {
msg : "Download successful!" ,
alertType : "success" ,
} )
) ;
return ;
} else if ( userOS ? . includes ( "Windows" ) ) {
window . location . href =
"https://github.com/Qortal/qortal-ui/releases/latest/download/Qortal-Setup-win64.exe" ;
dispatch (
setNotification ( {
msg : "Download successful!" ,
alertType : "success" ,
} )
) ;
return ;
} else if ( userOS ? . includes ( "Linux" ) ) {
window . location . href =
"https://github.com/Qortal/qortal-ui/releases/latest/download/Qortal-Setup-amd64.AppImage" ;
dispatch (
setNotification ( {
msg : "Download successful!" ,
alertType : "success" ,
} )
) ;
return ;
}
} }
>
Download Now { " " }
< DownloadCircleSVG
color = { theme . palette . text . primary }
height = "30"
width = "30"
/ >
< / DownloadNowButton >
< / DownloadQortalCol >
< / ReusableModal >
) }
{ children }
{ children }
< / >
< / >
) ;
) ;