mirror of
https://github.com/Qortal/q-shop.git
synced 2025-02-01 07:42:21 +00:00
Added advanced setting to reset data container
This commit is contained in:
parent
d366c60050
commit
9348a52e97
@ -195,3 +195,52 @@ export const DownloadArrrWalletIcon = styled(DownloadSVG)(({ theme }) => ({
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export const AdvancedSettingsBox = styled(Box)(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
padding: "5px 10px",
|
||||||
|
borderRadius: "5px",
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
"& .MuiTypography-root": {
|
||||||
|
fontFamily: "Karla",
|
||||||
|
fontSize: "20px",
|
||||||
|
fontWeight: 300,
|
||||||
|
letterSpacing: "0.2px",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const EditStoreButtonsRow = styled(Box)({
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "10px",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const CreateNewDataContainerRow = styled(Box)({
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const CreateNewDataContainerButton = styled(Button)(({ theme }) => ({
|
||||||
|
backgroundColor: "#d43232",
|
||||||
|
textTransform: "none",
|
||||||
|
fontFamily: "Raleway",
|
||||||
|
fontWeight: 300,
|
||||||
|
gap: "5px",
|
||||||
|
fontSize: "17px",
|
||||||
|
borderRadius: "5px",
|
||||||
|
border: "none",
|
||||||
|
color: "white",
|
||||||
|
padding: "5px 15px",
|
||||||
|
transition: "all 0.3s ease-in-out",
|
||||||
|
boxShadow:
|
||||||
|
"rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;",
|
||||||
|
"&:hover": {
|
||||||
|
cursor: "pointer",
|
||||||
|
backgroundColor: "#a72727",
|
||||||
|
boxShadow:
|
||||||
|
"rgba(50, 50, 93, 0.35) 0px 3px 5px -1px, rgba(0, 0, 0, 0.4) 0px 2px 3px -1px;"
|
||||||
|
}
|
||||||
|
}));
|
@ -7,9 +7,15 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Zoom,
|
Zoom,
|
||||||
|
Box,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { toggleCreateStoreModal } from "../../state/features/globalSlice";
|
import {
|
||||||
|
toggleCreateStoreModal,
|
||||||
|
setDataContainer,
|
||||||
|
resetListProducts,
|
||||||
|
resetProducts
|
||||||
|
} from "../../state/features/globalSlice";
|
||||||
import { RootState } from "../../state/store";
|
import { RootState } from "../../state/store";
|
||||||
import {
|
import {
|
||||||
AddLogoButton,
|
AddLogoButton,
|
||||||
@ -25,6 +31,10 @@ import {
|
|||||||
ModalTitle,
|
ModalTitle,
|
||||||
StoreLogoPreview,
|
StoreLogoPreview,
|
||||||
TimesIcon,
|
TimesIcon,
|
||||||
|
AdvancedSettingsBox,
|
||||||
|
EditStoreButtonsRow,
|
||||||
|
CreateNewDataContainerRow,
|
||||||
|
CreateNewDataContainerButton,
|
||||||
} from "./CreateStoreModal-styles";
|
} from "./CreateStoreModal-styles";
|
||||||
import ImageUploader from "../common/ImageUploader";
|
import ImageUploader from "../common/ImageUploader";
|
||||||
import {
|
import {
|
||||||
@ -37,6 +47,11 @@ import {
|
|||||||
import { supportedCoinsArray } from "../../constants/supported-coins";
|
import { supportedCoinsArray } from "../../constants/supported-coins";
|
||||||
import { QortalSVG } from "../../assets/svgs/QortalSVG";
|
import { QortalSVG } from "../../assets/svgs/QortalSVG";
|
||||||
import { ARRRSVG } from "../../assets/svgs/ARRRSVG";
|
import { ARRRSVG } from "../../assets/svgs/ARRRSVG";
|
||||||
|
import { ReusableModal } from "./ReusableModal";
|
||||||
|
import { DATA_CONTAINER_BASE, STORE_BASE } from "../../constants/identifiers";
|
||||||
|
import { objectToBase64 } from "../../utils/toBase64";
|
||||||
|
import { ShortDataContainer } from "../../wrappers/GlobalWrapper";
|
||||||
|
import { setNotification } from "../../state/features/notificationsSlice";
|
||||||
|
|
||||||
interface ForeignCoins {
|
interface ForeignCoins {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
@ -62,6 +77,7 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
const currentStore = useSelector(
|
const currentStore = useSelector(
|
||||||
(state: RootState) => state.global.currentStore
|
(state: RootState) => state.global.currentStore
|
||||||
);
|
);
|
||||||
|
const user = useSelector((state: RootState) => state.auth.user);
|
||||||
|
|
||||||
const storeId = useSelector((state: RootState) => state.store.storeId);
|
const storeId = useSelector((state: RootState) => state.store.storeId);
|
||||||
|
|
||||||
@ -76,6 +92,10 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
>(["QORT"]);
|
>(["QORT"]);
|
||||||
const [qortWalletAddress, setQortWalletAddress] = useState<string>("");
|
const [qortWalletAddress, setQortWalletAddress] = useState<string>("");
|
||||||
const [arrrWalletAddress, setArrrWalletAddress] = useState<string>("");
|
const [arrrWalletAddress, setArrrWalletAddress] = useState<string>("");
|
||||||
|
const [showAdvancedSettings, setShowAdvancedSettings] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
const [showCreateNewDataContainerModal, setShowCreateNewDataContainerModal] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@ -88,11 +108,14 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const foreignCoins: ForeignCoins = {
|
const foreignCoins: ForeignCoins = {
|
||||||
ARRR: arrrWalletAddress
|
ARRR: arrrWalletAddress,
|
||||||
}
|
};
|
||||||
supportedCoinsSelected.filter((coin)=> coin !== 'QORT').forEach((item: string)=> {
|
supportedCoinsSelected
|
||||||
if(!foreignCoins[item]) throw new Error(`Please add a ${item} address`)
|
.filter(coin => coin !== "QORT")
|
||||||
})
|
.forEach((item: string) => {
|
||||||
|
if (!foreignCoins[item])
|
||||||
|
throw new Error(`Please add a ${item} address`);
|
||||||
|
});
|
||||||
await onPublish({
|
await onPublish({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
@ -100,9 +123,9 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
location,
|
location,
|
||||||
logo,
|
logo,
|
||||||
foreignCoins: {
|
foreignCoins: {
|
||||||
ARRR: arrrWalletAddress
|
ARRR: arrrWalletAddress,
|
||||||
},
|
},
|
||||||
supportedCoins: supportedCoinsSelected
|
supportedCoins: supportedCoinsSelected,
|
||||||
});
|
});
|
||||||
handleClose();
|
handleClose();
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@ -117,8 +140,8 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
setLogo(currentStore?.logo || null);
|
setLogo(currentStore?.logo || null);
|
||||||
setLocation(currentStore?.location || "");
|
setLocation(currentStore?.location || "");
|
||||||
setShipsTo(currentStore?.shipsTo || "");
|
setShipsTo(currentStore?.shipsTo || "");
|
||||||
setSupportedCoinsSelected(currentStore?.supportedCoins || ['QORT'])
|
setSupportedCoinsSelected(currentStore?.supportedCoins || ["QORT"]);
|
||||||
setArrrWalletAddress(currentStore?.foreignCoins?.ARRR || "")
|
setArrrWalletAddress(currentStore?.foreignCoins?.ARRR || "");
|
||||||
}
|
}
|
||||||
}, [currentStore, storeId, open]);
|
}, [currentStore, storeId, open]);
|
||||||
|
|
||||||
@ -130,8 +153,9 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
setLogo(null);
|
setLogo(null);
|
||||||
setLocation("");
|
setLocation("");
|
||||||
setShipsTo("");
|
setShipsTo("");
|
||||||
setArrrWalletAddress("")
|
setArrrWalletAddress("");
|
||||||
setSupportedCoinsSelected(["QORT"])
|
setSupportedCoinsSelected(["QORT"]);
|
||||||
|
setShowAdvancedSettings(false);
|
||||||
dispatch(toggleCreateStoreModal(false));
|
dispatch(toggleCreateStoreModal(false));
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
@ -145,19 +169,82 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
setSupportedCoinsSelected(prevChips => prevChips.filter(c => c !== chip));
|
setSupportedCoinsSelected(prevChips => prevChips.filter(c => c !== chip));
|
||||||
};
|
};
|
||||||
|
|
||||||
const importAddress = async (coin: string)=> {
|
const importAddress = async (coin: string) => {
|
||||||
try {
|
try {
|
||||||
const res = await qortalRequest({
|
const res = await qortalRequest({
|
||||||
action: 'GET_USER_WALLET',
|
action: "GET_USER_WALLET",
|
||||||
coin
|
coin,
|
||||||
})
|
});
|
||||||
if(res?.address){
|
if (res?.address) {
|
||||||
setArrrWalletAddress(res.address)
|
setArrrWalletAddress(res.address);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Recreate Shop Data
|
||||||
|
|
||||||
|
const handleRecreateShopData = async () => {
|
||||||
|
if (!currentStore || !user?.name) {
|
||||||
|
dispatch(
|
||||||
|
setNotification({
|
||||||
|
msg: "Error! Missing shop data or name",
|
||||||
|
alertType: "error",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const shortStoreId = currentStore?.shortStoreId;
|
||||||
|
const dataContainer: ShortDataContainer = {
|
||||||
|
storeId: currentStore.id,
|
||||||
|
shortStoreId: shortStoreId,
|
||||||
|
owner: user.name,
|
||||||
|
products: {},
|
||||||
|
};
|
||||||
|
const dataContainerToBase64 = await objectToBase64(dataContainer);
|
||||||
|
|
||||||
|
const dataContainerCreated = await qortalRequest({
|
||||||
|
action: "PUBLISH_QDN_RESOURCE",
|
||||||
|
name: user?.name,
|
||||||
|
service: "DOCUMENT",
|
||||||
|
data64: dataContainerToBase64,
|
||||||
|
identifier: `${currentStore.id}-${DATA_CONTAINER_BASE}`,
|
||||||
|
});
|
||||||
|
console.log({ dataContainerCreated });
|
||||||
|
if (dataContainerCreated && !dataContainerCreated.error) {
|
||||||
|
dispatch(
|
||||||
|
setDataContainer({
|
||||||
|
...dataContainer,
|
||||||
|
id: `${currentStore.id}-${DATA_CONTAINER_BASE}`,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
dispatch(resetListProducts());
|
||||||
|
dispatch(resetProducts());
|
||||||
|
dispatch(
|
||||||
|
setNotification({
|
||||||
|
msg: "Data Container Created!",
|
||||||
|
alertType: "success",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
setShowCreateNewDataContainerModal(false);
|
||||||
|
setShowAdvancedSettings(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
navigate("/");
|
||||||
|
dispatch(
|
||||||
|
setNotification({
|
||||||
|
msg: "Error when creating the data container. Please try again!",
|
||||||
|
alertType: "error",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
dispatch(updateRecentlyVisitedStoreId(""));
|
||||||
|
dispatch(clearDataCotainer());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -294,7 +381,11 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
arrow={true}
|
arrow={true}
|
||||||
title="Import your ARRR Wallet Address from your current account"
|
title="Import your ARRR Wallet Address from your current account"
|
||||||
>
|
>
|
||||||
<IconButton disableFocusRipple={true} disableRipple={true} onClick={()=> importAddress('ARRR')}>
|
<IconButton
|
||||||
|
disableFocusRipple={true}
|
||||||
|
disableRipple={true}
|
||||||
|
onClick={() => importAddress("ARRR")}
|
||||||
|
>
|
||||||
<DownloadArrrWalletIcon
|
<DownloadArrrWalletIcon
|
||||||
color={theme.palette.text.primary}
|
color={theme.palette.text.primary}
|
||||||
height="40"
|
height="40"
|
||||||
@ -361,20 +452,81 @@ const MyModal: React.FC<MyModalProps> = ({ open, onClose, onPublish }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{showAdvancedSettings && (
|
||||||
|
<CreateNewDataContainerRow
|
||||||
|
onClick={() => {
|
||||||
|
setShowCreateNewDataContainerModal(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CreateNewDataContainerButton>
|
||||||
|
Recreate Shop Data
|
||||||
|
</CreateNewDataContainerButton>
|
||||||
|
</CreateNewDataContainerRow>
|
||||||
|
)}
|
||||||
<FormControl fullWidth sx={{ marginBottom: 2 }}></FormControl>
|
<FormControl fullWidth sx={{ marginBottom: 2 }}></FormControl>
|
||||||
{errorMessage && (
|
{errorMessage && (
|
||||||
<Typography color="error" variant="body1">
|
<Typography color="error" variant="body1">
|
||||||
{errorMessage}
|
{errorMessage}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<ButtonRow sx={{ display: "flex", justifyContent: "flex-end", gap: 1 }}>
|
<ButtonRow sx={{ display: "flex", justifyContent: "space-between" }}>
|
||||||
<CancelButton variant="outlined" color="error" onClick={handleClose}>
|
<AdvancedSettingsBox>
|
||||||
Cancel
|
<Typography>Advanced Settings</Typography>
|
||||||
</CancelButton>
|
<FiltersCheckbox
|
||||||
<CreateButton variant="contained" onClick={handlePublish}>
|
checked={showAdvancedSettings}
|
||||||
Edit Shop
|
onChange={() => setShowAdvancedSettings(!showAdvancedSettings)}
|
||||||
</CreateButton>
|
/>
|
||||||
|
</AdvancedSettingsBox>
|
||||||
|
<EditStoreButtonsRow>
|
||||||
|
<CancelButton
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</CancelButton>
|
||||||
|
<CreateButton variant="contained" onClick={handlePublish}>
|
||||||
|
Edit Shop
|
||||||
|
</CreateButton>
|
||||||
|
</EditStoreButtonsRow>
|
||||||
</ButtonRow>
|
</ButtonRow>
|
||||||
|
<ReusableModal
|
||||||
|
open={showCreateNewDataContainerModal}
|
||||||
|
customStyles={{
|
||||||
|
width: "50%",
|
||||||
|
maxWidth: 1700,
|
||||||
|
height: "auto",
|
||||||
|
backgroundColor:
|
||||||
|
theme.palette.mode === "light" ? "#e8e8e8" : "#32333c",
|
||||||
|
position: "relative",
|
||||||
|
padding: "25px",
|
||||||
|
borderRadius: "3px",
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "hidden",
|
||||||
|
maxHeight: "90vh",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box>
|
||||||
|
Warning! ⚠️ Are you sure you want to recreate your shop's data? This
|
||||||
|
will clear all your shop's products. This should only be done as a
|
||||||
|
last resort if you cannot access your product manager or if you are
|
||||||
|
experiencing issues products displaying properly.
|
||||||
|
</Box>
|
||||||
|
<ButtonRow>
|
||||||
|
<CancelButton
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
onClick={() => {
|
||||||
|
setShowCreateNewDataContainerModal(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</CancelButton>
|
||||||
|
<CreateButton variant="contained" onClick={handleRecreateShopData}>
|
||||||
|
Recreate Shop Data
|
||||||
|
</CreateButton>
|
||||||
|
</ButtonRow>
|
||||||
|
</ReusableModal>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -217,13 +217,17 @@ export const Store = () => {
|
|||||||
|
|
||||||
const switchCoin = async ()=> {
|
const switchCoin = async ()=> {
|
||||||
dispatch(setIsLoadingGlobal(true));
|
dispatch(setIsLoadingGlobal(true));
|
||||||
|
|
||||||
await calculateARRRExchangeRate()
|
await calculateARRRExchangeRate()
|
||||||
dispatch(setIsLoadingGlobal(false));
|
dispatch(setIsLoadingGlobal(false));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If shop's datacontainer changes, and listProducts becomes empty, clear local products array
|
||||||
|
useEffect(() => {
|
||||||
|
if (username === user?.name && userOwnDataContainer && Object.keys(userOwnDataContainer.products).length === 0) {
|
||||||
|
setProducts([]);
|
||||||
|
}
|
||||||
|
}, [userOwnDataContainer]);
|
||||||
|
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
if(preferredCoin === CoinFilter.arrr && storeToUse?.supportedCoins?.includes(CoinFilter.arrr)){
|
if(preferredCoin === CoinFilter.arrr && storeToUse?.supportedCoins?.includes(CoinFilter.arrr)){
|
||||||
switchCoin()
|
switchCoin()
|
||||||
|
@ -53,7 +53,8 @@ interface Props {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
setTheme: (val: string) => void;
|
setTheme: (val: string) => void;
|
||||||
}
|
}
|
||||||
interface ShortDataContainer {
|
|
||||||
|
export interface ShortDataContainer {
|
||||||
storeId: string;
|
storeId: string;
|
||||||
shortStoreId: string;
|
shortStoreId: string;
|
||||||
owner: string;
|
owner: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user