import React, { useState } from "react"; import { makeStyles } from "@material-ui/core/styles"; import { Typography, Button, Grid, TextField, ButtonGroup, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Paper, Divider, Card, CardContent, CardMedia, } from "@material-ui/core"; import CloseIcon from "@material-ui/icons/Close"; import AddIcon from "@material-ui/icons/Add"; import RemoveIcon from "@material-ui/icons/Remove"; import Autocomplete from "@material-ui/lab/Autocomplete"; import useAutocomplete from "@material-ui/lab/useAutocomplete"; import { writeConfigRequest, useConfigInMainRequest, } from "secure-electron-store"; import { connect } from "react-redux"; import { v4 as uuidv4 } from "uuid"; import algoliasearch from "algoliasearch"; import { closeModal } from "../../redux/modals/addItemModalSlice"; import { addItem } from "../../redux/data/inventorySlice"; import { Children } from "react"; const useStyles = makeStyles((theme) => ({ paper: { paddingRight: theme.spacing(0.5), paddingLeft: theme.spacing(0.5), color: theme.palette.text.secondary, display: "flex", alignItems: "center", marginBottom: theme.spacing(1), }, paperTitle: { paddingRight: theme.spacing(2.5), paddingLeft: theme.spacing(2.5), marginBottom: theme.spacing(0.5), }, verticalSpacing: { marginBottom: theme.spacing(0.5), }, verticalSpacing2: { marginBottom: theme.spacing(2), }, root: { display: "flex", }, details: { display: "flex", flexDirection: "column", }, content: { flex: "1 0 auto", }, cover: { width: 75, minWidth: 75, display: "flex", alignItems: "center", marginLeft: theme.spacing(1.5), }, })); const AddItemModal = (props) => { const styles = useStyles(); // Request so that the main process can use the store React.useEffect(() => { window.api.store.send(useConfigInMainRequest); window.api.stockxData("receiveProductData", (data) => { setFetchedProduct(data); }); }, []); const [fetchedProduct, setFetchedProduct] = useState({}); React.useEffect(() => { console.log(fetchedProduct); }, [fetchedProduct]); const stockxClient = algoliasearch( "XW7SBCT9V6", "6b5e76b49705eb9f51a06d3c82f7acee" ); const stockxIndex = stockxClient.initIndex("products"); const requestOptions = { headers: { "X-Algolia-UserToken": "xw7sbct9v6" }, }; const SaveItem = async (e) => { e.preventDefault(); var prevItems = props.inventory.items; console.log("PREV ITEMS", prevItems); prodSizes.map((size) => { for (let i = 0; i < size.qty; i++) { Object.keys(fetchedProduct.Product.children).map((child) => { let prodSize = 0; if ( !isNaN(fetchedProduct.Product.children[child].shoeSize.slice(-1)) ) { if (fetchedProduct.Product.children[child].shoeSize == size.size) prodSize = size.size; } else { prodSize = fetchedProduct.Product.children[child].shoeSize.replace( /[^\d.-]/g, "" ); } if (prodSize == size.size) { const newItem = { id: uuidv4(), name: prodName, sku: prodId, size: fetchedProduct.Product.children[child].shoeSize, status: "Sitting", brand: prodBrand, colorway: prodColor, condition: prodCondition, cost: prodCost, costShipping: prodCostShip, costTax: prodCostTax, store: prodStore, dateObtained: new Date(prodDate).toLocaleDateString("en-US"), dateAdded: new Date().toLocaleDateString("en-US"), description: prodDesc, image: prodImage, siteLinks: { stockX: { parentId: stockxParentId, urlKey: stockxUrl, id: child, }, goat: {}, flightClub: {}, }, marketPrices: { stockX: { lowestAsk: fetchedProduct.Product.children[child].market .lowestAskFloat, highestBid: fetchedProduct.Product.children[child].market .highestBidFloat, }, goat: {}, flightClub: {}, }, }; prevItems = [...prevItems, newItem]; props.addItem(newItem); return; } }); } }); window.api.store.send(writeConfigRequest, "inventoryItems", prevItems); props.closeModal(); }; const [prodName, setProdName] = useState(""); const [prodId, setProdId] = useState(""); const [prodCost, setProdCost] = useState(0); const [prodCostTax, setProdCostTax] = useState(0); const [prodCostShip, setProdCostShip] = useState(0); const [prodStore, setProdStore] = useState(""); const [prodDate, setProdDate] = useState(new Date()); const [prodDesc, setProdDesc] = useState(""); const [prodBrand, setProdBrand] = useState(""); const [prodColor, setProdColor] = useState(""); const [prodCondition, setProdCondition] = useState("Deadstock"); const [prodImage, setProdImage] = useState(""); const [stockxParentId, setStockxParentId] = useState(""); const [stockxUrl, setStockxUrl] = useState(""); const [queryResults, setQueryResults] = useState([]); React.useEffect(() => { if (prodName.length > 2) { stockxIndex.search(prodName, requestOptions).then(({ hits }) => { setQueryResults(hits); }); } }, [prodName]); React.useEffect(() => { console.log(queryResults, "query results:" + prodName); }, [queryResults]); const [sizeType, setSizeType] = useState("sneakers"); const shoeSizes = [ 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 15, ]; const apparelSizes = ["XS", "S", "M", "L", "XL", "2XL", "3XL", "4XL"]; const otherSizes = ["N/A", "OS", "Custom"]; const [prodSizes, setProdSizes] = useState([]); const AddSize = (size) => { if (CheckSizeAdded(size)) { const objIndex = prodSizes.findIndex((sizeItem) => sizeItem.size == size); const newSize = { ...prodSizes[objIndex], qty: prodSizes[objIndex].qty + 1, }; setProdSizes([ ...prodSizes.slice(0, objIndex), newSize, ...prodSizes.slice(objIndex + 1), ]); } else { setProdSizes((sizes) => [...sizes, { size: size, qty: 1 }]); setAddedSizes((sizes) => [...sizes, size]); } }; const MinusSize = (size) => { if (CheckSizeAdded(size)) { var result = prodSizes.filter((sizeItem) => { return sizeItem.size === size; }); if (result[0].qty == 1) { RemoveSize(size); } else { const objIndex = prodSizes.findIndex( (sizeItem) => sizeItem.size == size ); const newSize = { ...prodSizes[objIndex], qty: prodSizes[objIndex].qty - 1, }; setProdSizes([ ...prodSizes.slice(0, objIndex), newSize, ...prodSizes.slice(objIndex + 1), ]); } } }; const RemoveSize = (size) => { setProdSizes( prodSizes.filter((sizeItem) => { return sizeItem.size !== size; }) ); setAddedSizes( addedSizes.filter((sizes) => { return sizes !== size; }) ); }; const [addedSizes, setAddedSizes] = useState([]); const CheckSizeAdded = (size) => { if (addedSizes.includes(size)) { return true; } return false; }; const resetModalState = () => { setProdName(""); setProdId(""); setProdCost(0); setProdCostTax(0); setProdCostShip(0); setProdStore(""); setProdDate(new Date()); setProdDesc(""); setProdBrand(""); setProdColor(""); setProdCondition("Deadstock"); setStockxParentId(""); setStockxUrl(""); setProdImage(""); setProdSizes([]); setAddedSizes([]); }; React.useEffect(() => { resetModalState(); }, [props.addItemModal.visibility]); const { getRootProps, getInputLabelProps, getInputProps, getListboxProps, getOptionProps, groupedOptions, } = useAutocomplete({ id: "use-autocomplete-demo", options: queryResults, getOptionLabel: (res) => res.title, }); return ( <> <Dialog open={props.addItemModal.visibility} aria-labelledby="form-dialog-title" > <DialogTitle id="form-dialog-title">Add New Item</DialogTitle> <DialogContent> <Grid container spacing={1}> <Grid container item xs={12} spacing={1} className={styles.verticalSpacing} > <Grid item xs={8}> <Autocomplete id="stockxQueryResults" freeSolo options={queryResults} getOptionLabel={(option) => option.name} renderOption={(option) => ( <Card className={styles.root} onClick={() => { setProdName(option.name); setProdId(option.style_id); setProdDate(option.release_date); setProdCost(option.price); setProdBrand(option.brand); setProdColor(option.colorway); setStockxParentId(option.id); setStockxUrl(option.url); setProdImage(option.thumbnail_url); window.api.stockxData("getProductData", option.url); }} > <CardMedia className={styles.cover} title={option.name}> <img src={option.media.thumbUrl} /> </CardMedia> <div className={styles.details}> <CardContent className={styles.content}> <Typography variant="subtitle1"> {option.name} </Typography> <Typography variant="subtitle2" color="textSecondary"> {option.style_id} </Typography> <Typography variant="overline" color="textSecondary"> Released {option.release_date} </Typography> </CardContent> </div> </Card> )} renderInput={(params) => ( <TextField {...params} id="prodName" label="Product Name" variant="filled" size="small" fullWidth onChange={(e) => { setProdName(e.target.value); }} /> )} /> </Grid> <Grid item xs={4}> <TextField id="prodId" label="Product ID" variant="filled" size="small" fullWidth value={prodId} onChange={(e) => { setProdId(e.target.value); }} /> </Grid> </Grid> <Grid container item xs={12} spacing={1} className={styles.verticalSpacing} > <Grid item xs={4}> <TextField id="prodBrand" label="Brand" variant="filled" size="small" placeholder="Nike" fullWidth value={prodBrand} onChange={(e) => { setProdBrand(e.target.value); }} /> </Grid> <Grid item xs={4}> <TextField id="prodColor" label="Colorway" variant="filled" size="small" fullWidth placeholder="Black" value={prodColor} onChange={(e) => { setProdColor(e.target.value); }} /> </Grid> <Grid item xs={4}> <TextField id="prodCondition" label="Condition" variant="filled" size="small" fullWidth value={prodCondition} onChange={(e) => { setProdCondition(e.target.value); }} /> </Grid> </Grid> <Grid container item xs={12} spacing={1} className={styles.verticalSpacing} > <Grid item xs={4}> <TextField id="prodCost" label="Cost" variant="filled" size="small" fullWidth value={prodCost} onChange={(e) => { setProdCost(e.target.value); }} /> </Grid> <Grid item xs={4}> <TextField id="prodCostTax" label="Tax" variant="filled" size="small" fullWidth value={prodCostTax} onChange={(e) => { setProdCostTax(e.target.value); }} /> </Grid> <Grid item xs={4}> <TextField id="prodCostShip" label="Shipping" variant="filled" size="small" fullWidth value={prodCostShip} onChange={(e) => { setProdCostShip(e.target.value); }} /> </Grid> </Grid> <Grid container item xs={12} spacing={1} className={styles.verticalSpacing2} > <Grid item xs={6}> <TextField id="prodStore" label="Store Purchased" variant="filled" size="small" fullWidth value={prodStore} onChange={(e) => { setProdStore(e.target.value); }} /> </Grid> <Grid item xs={6}> <TextField id="prodDate" label="Purchase Date" variant="filled" size="small" type="date" value={prodDate} onChange={(e) => { setProdDate(e.target.value); }} InputLabelProps={{ shrink: true, }} fullWidth /> </Grid> </Grid> <Grid container item xs={12} spacing={1} justify="center" className={styles.verticalSpacing} > <ButtonGroup color="primary"> <Button variant={sizeType == "sneakers" ? "contained" : ""} onClick={() => { setSizeType("sneakers"); }} > Sneakers </Button> <Button variant={sizeType == "apparel" ? "contained" : ""} onClick={() => { setSizeType("apparel"); }} > Apparel </Button> <Button variant={sizeType == "other" ? "contained" : ""} onClick={() => { setSizeType("other"); }} > Other </Button> </ButtonGroup> </Grid> <Grid container item xs={12} spacing={1} justify="center" className={styles.verticalSpacing2} > {sizeType == "sneakers" ? shoeSizes.map((size) => ( <Grid item key={size}> <Button variant="contained" color="primary" size="small" onClick={() => { AddSize(size); }} disabled={CheckSizeAdded(size)} > {size} </Button> </Grid> )) : sizeType == "apparel" ? apparelSizes.map((size) => ( <Grid item key={size}> <Button variant="contained" color="primary" size="small" onClick={() => { AddSize(size); }} disabled={CheckSizeAdded(size)} > {size} </Button> </Grid> )) : otherSizes.map((size) => ( <Grid item key={size}> {size.toLowerCase() == "custom" ? ( <Button variant="outlined" color="primary" size="small" onClick={() => { AddSize(size); }} > {size} </Button> ) : ( <Button variant="contained" color="primary" size="small" onClick={() => { AddSize(size); }} disabled={CheckSizeAdded(size)} > {size} </Button> )} </Grid> ))} </Grid> {prodSizes.length > 0 && ( <Grid container xs={12} spacing={1} direction="column" justify="center" className={styles.verticalSpacing} > <Grid container xs={12} direction="row" className={styles.paperTitle} > <Grid container xs={6} direction="row" justify="flex-start" alignItems="flex-start" > <Typography variant="h6">Size</Typography> </Grid> <Grid container xs={6} direction="row" justify="flex-end" alignItems="flex-start" > <Typography variant="h6">Quantity</Typography> </Grid> </Grid> {prodSizes.map((sizeItem) => ( <Paper className={styles.paper} elevation={1}> <Grid container xs={6} alignItems="center"> <IconButton color="primary" aria-label="remove-size" onClick={() => { RemoveSize(sizeItem.size); }} > <CloseIcon /> </IconButton> <Typography variant="h6">{sizeItem.size}</Typography> </Grid> <Grid container xs={6} alignItems="center" justify="flex-end" > <IconButton color="primary" aria-label="minus-size" component="span" onClick={() => { MinusSize(sizeItem.size); }} > <RemoveIcon /> </IconButton> <Typography variant="h6">{sizeItem.qty}</Typography> <IconButton color="primary" aria-label="add-size" onClick={() => { AddSize(sizeItem.size); }} > <AddIcon /> </IconButton> </Grid> </Paper> ))} </Grid> )} <Grid container xs={12}> <TextField id="prodDesc" label="Description" multiline rows={3} variant="filled" size="small" type="date" onChange={(e) => { setProdDesc(e.target.value); }} fullWidth /> </Grid> </Grid> </DialogContent> <DialogActions> <Button color="primary" onClick={() => { props.closeModal(); }} > Cancel </Button> <Button color="primary" onClick={(e) => { SaveItem(e); }} > Add Item </Button> </DialogActions> </Dialog> </> ); }; const mapStateToProps = (state, props) => ({ addItemModal: state.addItemModal, inventory: state.inventory, }); const mapDispatch = { closeModal, addItem }; export default connect(mapStateToProps, mapDispatch)(AddItemModal);