-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
370 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<Flex | ||
justifyContent="space-between" | ||
alignItems="bottom" | ||
marginTop="10px" | ||
width="15%" | ||
> | ||
<CreateItem postItem={createItem} /> | ||
</Flex> | ||
); | ||
}; | ||
|
||
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<HTMLInputElement>) => { | ||
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 ( | ||
<> | ||
<Popover | ||
isOpen={isOpen} | ||
onOpen={onOpen} | ||
onClose={() => { | ||
setError({ state: false, msg: "" }); | ||
onClose(); | ||
}} | ||
placement="bottom-end" | ||
autoFocus | ||
closeOnBlur | ||
> | ||
<PopoverTrigger> | ||
<Button | ||
color="var(--col-dark)" | ||
borderRadius="30px" | ||
borderColor="var(--col-secondary)" | ||
borderWidth="3px" | ||
width="100px" | ||
height="30px" | ||
marginRight="2px" | ||
fontWeight="300" | ||
fontSize="14px" | ||
letterSpacing="1px" | ||
> | ||
ADD ITEM | ||
</Button> | ||
</PopoverTrigger> | ||
<PopoverContent | ||
bgColor="var(--col-bright)" | ||
borderWidth="5px" | ||
borderColor="var(--col-secondary)" | ||
p="20px" | ||
borderRadius="10px" | ||
> | ||
<PopoverHeader | ||
display="flex" | ||
justifyContent="center" | ||
fontSize="1.4rem" | ||
color="var(--col-secondary)" | ||
borderBottomColor="var(--col-dark)" | ||
padding="0px" | ||
paddingBottom="5px" | ||
marginBottom="10px" | ||
> | ||
Create new Item | ||
</PopoverHeader> | ||
<form> | ||
<label htmlFor="name" className="i-b"> | ||
Name | ||
</label> | ||
<input | ||
type="text" | ||
name="name" | ||
id="name" | ||
value={item.name} | ||
className="i-b text-container" | ||
onChange={handleChange} | ||
/> | ||
<label htmlFor="desc" className="i-b"> | ||
Description | ||
</label> | ||
<input | ||
type="text" | ||
name="notes" | ||
id="notes" | ||
value={item.notes} | ||
onChange={handleChange} | ||
className="i-b text-container multiline" | ||
/> | ||
<label htmlFor="desc" className="i-b"> | ||
Type | ||
</label> | ||
<input | ||
type="text" | ||
name="type" | ||
id="type" | ||
value={item.type} | ||
onChange={handleChange} | ||
className="i-b text-container multiline" | ||
/> | ||
<PopoverFooter | ||
display="flex" | ||
flexDirection="column" | ||
justifyContent="space-between" | ||
alignItems="center" | ||
> | ||
<Flex width="100%" justifyContent="space-between" mb="10px"> | ||
<FormControl width="45%"> | ||
<label htmlFor="desc" className="i-b"> | ||
Price | ||
</label> | ||
<NumberInput | ||
onChange={(valueAsString) => | ||
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 | ||
> | ||
<NumberInputField | ||
id="price" | ||
borderColor="var(--col-dark)" | ||
_hover={{ bg: "var(--col-tertiary)" }} | ||
/> | ||
<NumberInputStepper> | ||
<NumberIncrementStepper /> | ||
<NumberDecrementStepper /> | ||
</NumberInputStepper> | ||
</NumberInput> | ||
</FormControl> | ||
<FormControl width="45%"> | ||
<label htmlFor="desc" className="i-b"> | ||
Quantity | ||
</label> | ||
<NumberInput | ||
onChange={handleNumberInputChangeQuantity} | ||
value={item.quantity || ""} | ||
max={100000} | ||
min={0} | ||
> | ||
<NumberInputField | ||
borderColor="var(--col-dark)" | ||
_hover={{ bg: "var(--col-tertiary)" }} | ||
/> | ||
<NumberInputStepper> | ||
<NumberIncrementStepper /> | ||
<NumberDecrementStepper /> | ||
</NumberInputStepper> | ||
</NumberInput> | ||
</FormControl> | ||
</Flex> | ||
<Box | ||
display="flex" | ||
width="100%" | ||
justifyContent="space-between" | ||
mb="10px" | ||
> | ||
<Box> | ||
<input | ||
type="checkbox" | ||
name="toShare" | ||
id="toShare" | ||
checked={item.toShare === true} | ||
onChange={handleChange} | ||
className="checkbox" | ||
/> | ||
<label htmlFor="toShare" className="sidenote"> | ||
Sharable | ||
</label> | ||
</Box> | ||
<Box> | ||
<input | ||
type="checkbox" | ||
name="isPrivate" | ||
id="isPrivate" | ||
checked={item.isPrivate === true} | ||
onChange={handleChange} | ||
className="checkbox" | ||
/> | ||
<label htmlFor="isPrivate" className="sidenote"> | ||
Private | ||
</label> | ||
</Box> | ||
</Box> | ||
<Box | ||
display={`${errored.state ? "inherit" : "none"}`} | ||
color="red" | ||
fontSize="0.6rem" | ||
wordBreak="break-word" | ||
width="100%" | ||
mb="10px" | ||
> | ||
Error: {errored.msg} | ||
</Box> | ||
<input | ||
type="button" | ||
value="Add Item" | ||
onClick={handleSubmit} | ||
className="submit-button" | ||
/> | ||
</PopoverFooter> | ||
</form> | ||
<PopoverCloseButton color="var(--col-dark)" /> | ||
</PopoverContent> | ||
</Popover> | ||
</> | ||
); | ||
}; | ||
export default NewItemOptions; |