Untitled
unknown
javascript
2 years ago
8.7 kB
9
Indexable
import React, { useState } from "react";
import {
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
Flex,
Heading,
Button,
Editable,
EditableInput,
EditablePreview,
Image,
useColorModeValue,
IconButton,
useToast,
} from "@chakra-ui/react";
import { AiOutlineDelete, AiOutlineSave } from "react-icons/ai";
const InventoryCard = ({
itemToDisplay,
updateCatalogueAfterDelete,
updateCatalogueAfterPatch,
}) => {
const [currentItem, setCurrentItem] = useState(itemToDisplay);
const toast = useToast();
const toggleAvailability = () => {
setCurrentItem({
...currentItem,
availability: !currentItem.availability,
});
};
const setPrice = (event) => {
const numericValue = event.target.value.replace(/[^0-9]/g, ""); // only numbers.
const price = parseInt(numericValue) || 0;
setCurrentItem({ ...currentItem, price });
};
//item listing deleted from db, grandparent state update and according toast
const listenForItemDeletion = () => {
const successToastMessageDelete = () => {
toast({
title: "Item Deleted.",
description: "We've deleted your listing for you.",
status: "success",
duration: 3000,
isClosable: true,
});
};
const errorToastMessageDelete = () => {
toast({
title: "Error encountered.",
description: "We were unable to delete your item, please try again.",
status: "error",
duration: 3000,
isClosable: true,
});
};
const itemDeletion = async () => {
try {
const resp = await fetch(
`${process.env.REACT_APP_API_CATALOGUE}/${currentItem.id}`,
{
method: "DELETE",
}
);
const data = await resp.json();
updateCatalogueAfterDelete(currentItem.id);
successToastMessageDelete();
} catch (error) {
console.error(`Error: ${error}`);
errorToastMessageDelete();
}
};
itemDeletion();
};
//item listing patched in db, grandparent state update and according toast
const listenForItemPatch = () => {
const successToastMessagePatch = () => {
toast({
title: "Item Saved.",
description: "We've updated your listing for you.",
status: "success",
duration: 3000,
isClosable: true,
});
};
const errorToastMessagePatch = () => {
toast({
title: "Error encountered.",
description: "We were unable to save your item, please try again.",
status: "error",
duration: 3000,
isClosable: true,
});
};
const itemPatch = async () => {
try {
const resp = await fetch(
`${process.env.REACT_APP_API_CATALOGUE}/${currentItem.id}`,
{
method: "PATCH",
header: {
"Content-Type": "application/json",
},
body: JSON.stringify({
id: currentItem.id,
item: currentItem.item,
category: currentItem.category,
type: currentItem.type,
image: currentItem.image,
description: currentItem.description,
size: currentItem.sizes,
colors: currentItem.colors,
price: currentItem.price + 0.99,
availability: currentItem.availability,
}),
}
);
const data = await resp.json();
console.log(`currentItem state: `);
console.log(currentItem);
console.log(`data sent back: `);
console.log(data);
successToastMessagePatch();
} catch (error) {
console.log(`Error: ${error}`);
errorToastMessagePatch();
}
};
itemPatch();
};
const toggleSizeAvailability = (sizeToToggle) => {
setCurrentItem((prevItem) => {
const updatedSizes = prevItem.sizes.map((size) => {
const { size: currentSize, isAvailable } = size;
return currentSize === sizeToToggle
? { size: currentSize, isAvailable: !isAvailable }
: size;
});
return { ...prevItem, sizes: updatedSizes };
});
};
const toggleColorAvailability = (colorName) => {
setCurrentItem((prevItem) => ({
...prevItem,
colors: prevItem.colors.map((color) =>
color.colorName === colorName
? { ...color, isAvailable: !color.isAvailable }
: color
),
}));
};
return (
<AccordionItem mt={4} mb={4} display="flex" flexDir={"column"}>
<Flex>
<AccordionButton>
{/* Item Name */}
<Heading size="sm" color="accent.500">
Item Name:
</Heading>
<Editable
value={currentItem.item}
w="300px"
color={useColorModeValue("black", "white")}
>
<EditablePreview />
<EditableInput
name="item"
onChange={(event) => {
setCurrentItem({ ...currentItem, item: event.target.value });
}}
/>
</Editable>
{/* Item Icon */}
<Box as="span" flex="1" textAlign="right">
<AccordionIcon />
</Box>
</AccordionButton>
<Flex>
<AccordionPanel>
{/* Item Image */}
<Image
marginTop={"2"}
src={currentItem.image || "https://placehold.co/400"}
alt="Item's displayed image"
rounded="full"
width={["100px", "100px", "100px", "100px", "100px"]}
objectFit={"cover"}
/>
</AccordionPanel>
</Flex>
</Flex>
{/* Item Price */}
<AccordionPanel>
<Box as="span" flex="1" textAlign="left">
<Heading size="sm" color="accent.500">
Item Price:
</Heading>
<Editable value={currentItem.price} w="300px">
<EditablePreview />
<EditableInput name="price" onChange={setPrice} />
</Editable>
</Box>
{/* Item Description */}
<Box as="span" display={"flex"} flexDirection="column" textAlign="left">
<Heading size="sm" color="accent.500">
Item Description:
</Heading>
<Editable
value={currentItem.description}
isTruncated
whiteSpace={"wrap"}
maxWidth={"500px"}
>
<EditablePreview isTruncated whiteSpace={"wrap"} />
<EditableInput
name="description"
fontFamily={"body"}
onChange={(e) =>
setCurrentItem({ ...currentItem, description: e.target.value })
}
isTruncated
whiteSpace={"wrap"}
/>
</Editable>
</Box>
{/* Sizes */}
<Flex mb={2}>
{currentItem.sizes &&
currentItem.sizes.map((size) => (
<Button
key={size.size}
variant={size.isAvailable ? "secondary" : "accent"}
onClick={() => toggleSizeAvailability(size.size)}
border={"1px solid"}
maxWidth={"20px"}
marginRight={"2"}
>
{size.size}
</Button>
))}
</Flex>
{/* Colors */}
<Flex mb={2}>
{currentItem.colors.map((color) => (
<Button
key={color.colorName}
variantColor={color.colorName}
variant={color.isAvailable ? "dynamic" : "dynamicSelected"}
onClick={() => toggleColorAvailability(color.colorName)}
maxWidth={"20px"}
marginRight={"2"}
/>
))}
</Flex>
{/* Availability */}
<Flex marginTop={4}>
<div className="flex-1">
<IconButton
colorScheme="red"
icon={<AiOutlineDelete />}
marginRight={2}
onClick={listenForItemDeletion}
/>
</div>
<div>
<Button
colorScheme={currentItem.availability ? "green" : "red"}
onClick={toggleAvailability}
marginRight={"2"}
>
{currentItem.availability ? "Available" : "Unavailable"}
</Button>
<IconButton
colorScheme="green"
icon={<AiOutlineSave />}
marginRight={2}
onClick={listenForItemPatch}
/>
</div>
</Flex>
</AccordionPanel>
</AccordionItem>
);
};
export default InventoryCard;
Editor is loading...