From 36a0111fe8e1c8f6d98b927c348005ef83662f04 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Sat, 2 Dec 2023 23:53:26 +0800 Subject: [PATCH] Added edit and delete SKU functionality --- src/Components/API/API.tsx | 46 ++- src/Components/EditSKUModal/EditSKUModal.tsx | 299 ++++++++++++++++++ src/Components/Types/Types.tsx | 7 + .../EquipmentListPage/EquipmentListPage.tsx | 33 +- 4 files changed, 382 insertions(+), 3 deletions(-) create mode 100644 src/Components/EditSKUModal/EditSKUModal.tsx diff --git a/src/Components/API/API.tsx b/src/Components/API/API.tsx index 322f794..e9ff3b1 100644 --- a/src/Components/API/API.tsx +++ b/src/Components/API/API.tsx @@ -12,6 +12,7 @@ import { AddEquipmentInstanceType, EquipmentInstanceType, PatchEquipmentInstanceType, + PatchEquipmentType, } from "../Types/Types"; const instance = axios.create({ @@ -164,6 +165,47 @@ export function ResetPasswordConfirmAPI(info: ResetPasswordConfirmType) { // Equipment APIs +export async function EquipmentAPI(id: number) { + const config = await GetConfig(); + return instance + .get(`api/v1/equipments/equipments/${id}/`, config) + .then((response) => { + return response.data as EquipmentType; + }) + .catch(() => { + console.log("Error retrieving equipment"); + }); +} + +export async function EquipmentUpdateAPI( + equipment: PatchEquipmentType, + id: number +) { + const config = await GetConfig(); + return instance + .patch(`api/v1/equipments/equipments/${id}/`, equipment, config) + .then((response) => { + return [true, response.data as EquipmentType]; + }) + .catch((error) => { + console.log("Error updating equipment instance"); + return [false, ParseError(error)]; + }); +} + +export async function EquipmentRemoveAPI(id: number) { + const config = await GetConfig(); + return instance + .delete(`api/v1/equipments/equipments/${id}/`, config) + .then((response) => { + return [true, response.data as EquipmentType]; + }) + .catch((error) => { + console.log("Error deleting equipment instance"); + return [false, ParseError(error)]; + }); +} + export async function EquipmentsAPI() { const config = await GetConfig(); return instance @@ -194,7 +236,7 @@ export async function EquipmentCreateAPI(equipment: AddEquipmentType) { export async function EquipmentInstanceAPI(id: number) { const config = await GetConfig(); return instance - .get(`api/v1/equipments/equipment_instances/${id}`, config) + .get(`api/v1/equipments/equipment_instances/${id}/`, config) .then((response) => { return response.data as EquipmentInstanceType; }) @@ -227,7 +269,7 @@ export async function EquipmentInstanceRemoveAPI(id: number) { return [true, response.data]; }) .catch((error) => { - console.log("Error updating equipment instance"); + console.log("Error deleting equipment instance"); return [false, ParseError(error)]; }); } diff --git a/src/Components/EditSKUModal/EditSKUModal.tsx b/src/Components/EditSKUModal/EditSKUModal.tsx new file mode 100644 index 0000000..713421e --- /dev/null +++ b/src/Components/EditSKUModal/EditSKUModal.tsx @@ -0,0 +1,299 @@ +import { useEffect, useState } from "react"; +import styles from "../../styles"; +import { colors } from "../../styles"; +import TextField from "@mui/material/TextField"; +import EditIcon from "@mui/icons-material/Edit"; +import Button from "../Button/Button"; +import { toast } from "react-toastify"; +import { + EquipmentAPI, + EquipmentRemoveAPI, + EquipmentUpdateAPI, +} from "../API/API"; +import RadioGroup from "@mui/material/RadioGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import FormControl from "@mui/material/FormControl"; +import FormLabel from "@mui/material/FormLabel"; +import Radio from "@mui/material/Radio"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { useQuery } from "@tanstack/react-query"; +import { CircularProgress } from "@mui/material"; +import React from "react"; + +export default function EditSKUModal(props: { + id: number; + setOpen: React.Dispatch>; +}) { + const queryClient = useQueryClient(); + const [item, setItem] = useState({ + name: "", + description: "", + category: "", + }); + const [error, setError] = useState(""); + + const equipment = useQuery({ + queryKey: ["equipment", props.id], + queryFn: () => EquipmentAPI(Number(props.id)), + }); + + useEffect(() => { + if (equipment.data) { + setItem({ + ...item, + name: equipment.data.name, + description: equipment.data.description, + category: equipment.data.category, + }); + } + }, [equipment.data]); + + const update_mutation = useMutation({ + mutationFn: async () => { + const data = await EquipmentUpdateAPI(item, props.id); + if (data[0] != true) { + return Promise.reject(new Error(JSON.stringify(data[1]))); + } + return data; + }, + onSuccess: (data) => { + queryClient.invalidateQueries({ queryKey: ["equipments"] }); + queryClient.invalidateQueries({ + queryKey: ["equipment", props.id], + }); + setError("Updated successfully"); + toast( + `Item updated successfuly, ${ + typeof data[1] == "object" ? "ID:" + data[1].id : "" + }`, + { + position: "top-right", + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "light", + } + ); + if (typeof data[1] == "object") { + setItem({ + ...item, + name: data[1].name, + description: data[1].description, + category: data[1].category, + }); + } + }, + onError: (error) => { + setError(JSON.stringify(error)); + }, + }); + + const delete_mutation = useMutation({ + mutationFn: async () => { + const data = await EquipmentRemoveAPI(props.id); + if (data[0] != true) { + return Promise.reject(new Error(JSON.stringify(data[1]))); + } + return data; + }, + onSuccess: (data) => { + queryClient.invalidateQueries({ queryKey: ["equipments"] }); + queryClient.invalidateQueries({ + queryKey: ["equipment", props.id], + }); + setError("Deleted successfully"); + toast("SKU deleted successfuly", { + position: "top-right", + autoClose: 2000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "light", + }); + props.setOpen(false); + if (typeof data[1] == "object") { + setItem({ + ...item, + name: data[1].name, + description: data[1].description, + category: data[1].category, + }); + } + }, + onError: (error) => { + setError(JSON.stringify(error)); + }, + }); + + if (equipment.isLoading) { + return ( +
+ +

+ Loading +

+
+ ); + } + return ( + <> +
+ +

Edit SKU

+
+ +
+ + ) => { + setItem({ ...item, name: e.target.value }); + setError(""); + }} + value={item.name} + placeholder={"Enter SKU name"} + /> + ) => + setItem({ ...item, description: e.target.value }) + } + value={item.description} + placeholder={"Give a brief description of the SKU"} + /> + + Category + + ) => { + setItem({ ...item, category: e.target.value }); + setError(""); + }} + value={item.category} + > +
+
+ } + label="Workstation" + style={styles.text_dark} + /> + } + label="Networking" + style={styles.text_dark} + /> + } + label="CCTV" + style={styles.text_dark} + /> +
+
+ } + label="Furniture" + style={styles.text_dark} + /> + } + label="Peripherals" + style={styles.text_dark} + /> + } + label="Miscellaneous" + style={styles.text_dark} + /> +
+
+
+
+
+

{error}

+
+
+
+ + ); +} diff --git a/src/Components/Types/Types.tsx b/src/Components/Types/Types.tsx index bab625f..c7b6040 100644 --- a/src/Components/Types/Types.tsx +++ b/src/Components/Types/Types.tsx @@ -28,6 +28,12 @@ export type AddEquipmentType = { category?: string; }; +export type PatchEquipmentType = { + name: string; + description: string; + category?: string; +}; + export type EquipmentType = { id: number; name: string; @@ -35,6 +41,7 @@ export type EquipmentType = { last_updated: string; last_updated_by: string; date_added: string; + category: string; }; export type EquipmentListType = Array; diff --git a/src/Pages/EquipmentListPage/EquipmentListPage.tsx b/src/Pages/EquipmentListPage/EquipmentListPage.tsx index 83baf0b..c7576a2 100644 --- a/src/Pages/EquipmentListPage/EquipmentListPage.tsx +++ b/src/Pages/EquipmentListPage/EquipmentListPage.tsx @@ -11,8 +11,13 @@ import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; import Paper from "@mui/material/Paper"; import { colors } from "../../styles"; +import EditSKUModal from "../../Components/EditSKUModal/EditSKUModal"; +import Popup from "reactjs-popup"; +import { useState } from "react"; export default function EquipmentListPage() { + const [editmodalOpen, SetEditModalOpen] = useState(false); + const [selectedItem, SetSelectedItem] = useState(0); const equipments = useQuery({ queryKey: ["equipments"], queryFn: EquipmentsAPI, @@ -73,6 +78,9 @@ export default function EquipmentListPage() { Description + + Category + Last Modified @@ -85,7 +93,8 @@ export default function EquipmentListPage() { key={equipment.id} sx={{ "&:last-child td, &:last-child th": { border: 0 } }} onClick={() => { - console.log("HEH"); + SetSelectedItem(equipment.id); + SetEditModalOpen(true); }} > @@ -98,6 +107,9 @@ export default function EquipmentListPage() { {equipment.description} + + {equipment.category} +
+ SetEditModalOpen(false)} + modal + position={"top center"} + contentStyle={{ + width: "512px", + borderRadius: 16, + borderColor: "grey", + borderStyle: "solid", + borderWidth: 1, + padding: 16, + alignContent: "center", + justifyContent: "center", + textAlign: "center", + }} + > + + ); }