From c24150b741f27c0b5861904d433ca311bb908cfc Mon Sep 17 00:00:00 2001 From: Zach Mattes Date: Sun, 26 May 2024 12:06:47 -0700 Subject: [PATCH] finished add item --- frontend/src/components/Basket.tsx | 4 +- frontend/src/components/NewItemOptions.tsx | 367 +++++++++++++++++++++ 2 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/NewItemOptions.tsx diff --git a/frontend/src/components/Basket.tsx b/frontend/src/components/Basket.tsx index f4edcbf..b59cee5 100644 --- a/frontend/src/components/Basket.tsx +++ b/frontend/src/components/Basket.tsx @@ -11,6 +11,7 @@ import { import { useEffect, useState } from "react"; import BasketItem from "./BasketItem"; import "../styles/Basket.css"; +import NewItemOptions from "./NewItemOptions"; export interface Basket { basketName: string; @@ -166,7 +167,8 @@ const BasketComp = ({ basketId, stateObj, isOwnerView }: Props) => { > Basket Items - + + diff --git a/frontend/src/components/NewItemOptions.tsx b/frontend/src/components/NewItemOptions.tsx new file mode 100644 index 0000000..0ac14fc --- /dev/null +++ b/frontend/src/components/NewItemOptions.tsx @@ -0,0 +1,367 @@ +import { + Button, + Flex, + Box, + Popover, + PopoverCloseButton, + PopoverContent, + PopoverFooter, + PopoverHeader, + PopoverTrigger, + useDisclosure, + FormControl, + NumberInput, + NumberInputField, + NumberInputStepper, + NumberIncrementStepper, + NumberDecrementStepper, +} from "@chakra-ui/react"; +import { FormEvent, useState } from "react"; +import "../styles/JoinGroup.css"; + +const NewItemOptions = ({ + basket, + updateBasket, +}: { + basket: any; + updateBasket: any; +}) => { + const createItem = async ( + name: string, + toShare: boolean, + isPrivate: boolean, + type: string, + notes: string, + price: number, + quantity: number, + ) => { + const res = await fetch(`http://localhost:3001/baskets/${basket}`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + }); + + if (res.ok) { + const currentBasket = await res.json(); + const payload = { + name, + toShare, + isPrivate, + type, + notes, + price, + quantity, + basket: [currentBasket._id], + }; + + const promise = await fetch("http://localhost:3001/items/", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify(payload), + }); + + if (promise.status === 201) { + const data = await promise.json(); + const newData = [...currentBasket.items, data._id]; + const basketPromise = await fetch( + `http://localhost:3001/baskets/${currentBasket._id}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + body: JSON.stringify({ items: newData }), + }, + ); + + if (basketPromise.status === 200) { + const basketData = await basketPromise.json(); + updateBasket(basketData); + } + } + } + }; + + return ( + + + + ); +}; + +interface CreateProps { + postItem: ( + name: string, + toShare: boolean, + isPrivate: boolean, + type: string, + notes: string, + price: number, + quantity: number, + ) => void; +} + +const CreateItem = ({ postItem }: CreateProps) => { + const [item, setItem] = useState({ + name: "", + toShare: false, + isPrivate: false, + type: "", + notes: "", + price: 0, + quantity: 0, + }); + const [errored, setError] = useState({ state: false, msg: "" }); + const { onOpen, onClose, isOpen } = useDisclosure(); + + const handleChange = (event: FormEvent) => { + const { name, value, type, checked } = event.currentTarget; + + setItem((prevItem) => ({ + ...prevItem, + [name]: type === "checkbox" ? checked : value, + })); + }; + + const handleSubmit = () => { + console.log(item); + postItem( + item.name, + item.toShare, + item.isPrivate, + item.type, + item.notes === "" ? "No description given" : item.notes, + item.price, + item.quantity, + ); + setItem({ + name: "", + toShare: false, + isPrivate: false, + type: "", + notes: "", + price: 0, + quantity: 0, + }); + }; + + const handleNumberInputChangePrice = (valueAsString: string) => { + // Convert string to float because the input will provide a formatted string with a dollar sign + const valueAsNumber = parseFloat(valueAsString.replace(/^\$/, "")); + setItem((prevItem) => ({ ...prevItem, price: valueAsNumber })); + }; + + const handleNumberInputChangeQuantity = ( + valueAsString: string, + valueAsNumber: number, + ) => { + console.log(valueAsString); + setItem((prevItem) => ({ ...prevItem, quantity: valueAsNumber })); + }; + + return ( + <> + { + setError({ state: false, msg: "" }); + onClose(); + }} + placement="bottom-end" + autoFocus + closeOnBlur + > + + + + + + Create new Item + +
+ + + + + + + + + + + + handleNumberInputChangePrice(valueAsString) + } + value={item.price || ""} + precision={2} // Allows two decimal places + step={1.0} // Step size for increment and decrement steppers + max={100000} + min={0} + clampValueOnBlur={false} // Prevents automatic rounding on blur + format={(val) => `$${val}`} // Prefixing the dollar sign + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Error: {errored.msg} + + + +
+ +
+
+ + ); +}; +export default NewItemOptions;