summaryrefslogtreecommitdiff
path: root/src/modules/result
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/result')
-rw-r--r--src/modules/result/components/Table.tsx278
1 files changed, 138 insertions, 140 deletions
diff --git a/src/modules/result/components/Table.tsx b/src/modules/result/components/Table.tsx
index fc40932..19a1e8b 100644
--- a/src/modules/result/components/Table.tsx
+++ b/src/modules/result/components/Table.tsx
@@ -1,9 +1,9 @@
"use client";
import { useResultStore } from "@/common/stores/useResultStore";
import { StockOpnameRes } from "@/common/types/stockOpname";
-import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Pagination, Skeleton, Spacer, Spinner } from "@nextui-org/react"
+import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Pagination, Skeleton, Spacer, Spinner } from "@nextui-org/react";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
-import styles from "./table.module.css"
+import styles from "./table.module.css";
import clsxm from "@/common/libs/clsxm";
import DetailRow from "./DetailRow";
import { useDebounce } from "usehooks-ts";
@@ -16,169 +16,173 @@ import toast from "@/common/libs/toast";
import { Product } from "prisma/generated/client";
const Table = () => {
- const credential = getClientCredential()
+ const credential = getClientCredential();
- const { filter: { company, search, show, page }, updateFilter } = useResultStore()
- const debouncedSearch = useDebounce(search, 500)
+ const {
+ filter: { company, search, show, page },
+ updateFilter,
+ } = useResultStore();
+ const debouncedSearch = useDebounce(search, 500);
useEffect(() => {
- updateFilter('page', 1)
- }, [company, debouncedSearch, show, updateFilter])
+ updateFilter("page", 1);
+ }, [company, debouncedSearch, show, updateFilter]);
const stockOpnames = useQuery({
- queryKey: ['stockOpnames', company, debouncedSearch, page, show],
+ queryKey: ["stockOpnames", company, debouncedSearch, page, show],
queryFn: async () => {
- const searchParams = new URLSearchParams()
- if (!company) return null
- searchParams.set('companyId', company)
+ const searchParams = new URLSearchParams();
+ if (!company) return null;
+ searchParams.set("companyId", company);
- const showValue = SHOWING_SELECTIONS.find((item) => item.key === show)?.value || ''
- searchParams.set('show', showValue);
+ const showValue = SHOWING_SELECTIONS.find((item) => item.key === show)?.value || "";
+ searchParams.set("show", showValue);
- if (debouncedSearch) searchParams.set('search', debouncedSearch)
+ if (debouncedSearch) searchParams.set("search", debouncedSearch);
- searchParams.set('page', page.toString());
+ searchParams.set("page", page.toString());
- return await fetch(`/api/stock-opname?${searchParams}`)
- .then(res => {
- window.scrollTo({ top: 0, 'behavior': 'smooth' })
- return res.json()
- })
+ return await fetch(`/api/stock-opname?${searchParams}`).then((res) => {
+ window.scrollTo({ top: 0, behavior: "smooth" });
+ return res.json();
+ });
},
- placeholderData: keepPreviousData
- })
+ placeholderData: keepPreviousData,
+ });
- const { filter } = useResultStore()
+ const { filter } = useResultStore();
- const [exportLoad, setExportLoad] = useState<boolean>(false)
+ const [exportLoad, setExportLoad] = useState<boolean>(false);
const exportResult = async () => {
- setExportLoad(true)
- const response = await fetch(`/api/stock-opname/export?companyId=${filter.company}`)
- const buffer = await response.arrayBuffer()
- console.log({ type: response.headers.get('type') });
-
- const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
- const url = window.URL.createObjectURL(blob)
- const a = document.createElement('a')
- a.href = url
- a.download = `export_${moment().format('MM_DD_HH_ss')}.xlsx`
- document.body.appendChild(a)
- a.click()
- document.body.removeChild(a)
- setExportLoad(false)
- }
+ setExportLoad(true);
+ const response = await fetch(`/api/stock-opname/export?companyId=${filter.company}`);
+ const buffer = await response.arrayBuffer();
+ console.log({ type: response.headers.get("type") });
+
+ const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `export_${moment().format("MM_DD_HH_ss")}.xlsx`;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ setExportLoad(false);
+ };
const toggleDifferent = async (id: number) => {
- const response = await fetch(`/api/product/${id}/toggle-different`, { method: 'POST' })
- const product: Product = await response.json()
- toast(`Berhasil mengubah status barang ${product.itemCode} ${product.name} menjadi ${product.isDifferent ? 'selisih' : 'aman'}`, { duration: 10000 })
- stockOpnames.refetch()
- }
+ const response = await fetch(`/api/product/${id}/toggle-different`, { method: "POST" });
+ const product: Product = await response.json();
+ toast(`Berhasil mengubah status barang ${product.itemCode} ${product.name} menjadi ${product.isDifferent ? "selisih" : "aman"}`, { duration: 10000 });
+ stockOpnames.refetch();
+ };
const recompute = async (productId: number, companyId: string) => {
- const response = await fetch(`/api/company/${companyId}/product/${productId}/compute-different`, { method: 'POST' })
- console.log("response",response)
- const stockOpname = await response.json()
- console.log("stockOpname",stockOpname)
- toast(`Berhasil menghitung ulang status barang, hasilnya ${stockOpname.data.isDifferent ? 'selisih' : 'aman'}`)
- stockOpnames.refetch()
- }
+ const response = await fetch(`/api/company/${companyId}/product/${productId}/compute-different`, { method: "POST" });
+ console.log("response", response);
+ const stockOpname = await response.json();
+ console.log("stockOpname", stockOpname);
+ toast(`Berhasil menghitung ulang status barang, hasilnya ${stockOpname.data.isDifferent ? "selisih" : "aman"}`);
+ stockOpnames.refetch();
+ };
- const isLoading = stockOpnames.isLoading || stockOpnames.isRefetching
+ const isLoading = stockOpnames.isLoading || stockOpnames.isRefetching;
- const COL_LENGTH = 9
+ const COL_LENGTH = 9;
return (
<>
<div className="flex">
<Button type="button" onPress={exportResult} disabled={exportLoad} variant="flat" className="ml-auto mb-4">
- {exportLoad ? <><Spinner size="sm" />Exporting...</> : 'Export'}
+ {exportLoad ? (
+ <>
+ <Spinner size="sm" />
+ Exporting...
+ </>
+ ) : (
+ "Export"
+ )}
</Button>
</div>
<div className="w-full flex-1 overflow-auto pb-4">
<table className="w-full">
- <thead className={styles.thead}>
- <tr>
- <th className={styles.th}>STATUS</th>
- <th className={clsxm(styles.th, '!text-left')}>NAMA PRODUK</th>
- <th className={styles.th}>TIM HITUNG 1</th>
- <th className={styles.th}>TIM HITUNG 2</th>
- <th className={styles.th}>TIM HITUNG 3</th>
- <th className={styles.th}>TIM VERIFIKASI</th>
- <th className={styles.th}>ON-HAND QTY</th>
- <th className={styles.th}>GUDANG SELISIH</th>
- <th className={styles.th}></th>
- </tr>
- </thead>
+ <thead className={styles.thead}>
+ <tr>
+ <th className={styles.th}>STATUS</th>
+ <th className={clsxm(styles.th, "!text-left")}>NAMA PRODUK</th>
+ <th className={styles.th}>TIM HITUNG 1</th>
+ <th className={styles.th}>TIM HITUNG 2</th>
+ <th className={styles.th}>TIM HITUNG 3</th>
+ <th className={styles.th}>TIM VERIFIKASI</th>
+ <th className={styles.th}>ON-HAND QTY</th>
+ <th className={styles.th}>GUDANG SELISIH</th>
+ <th className={styles.th}></th>
+ </tr>
+ </thead>
<tbody className={styles.tbody}>
- {!isLoading && stockOpnames.data?.result.map((stockOpname: StockOpnameRes['result']) => (
- <>
- <tr key={stockOpname.id} className={clsxm("border-t border-neutral-200", {
- "text-danger-600": stockOpname.isDifferent,
- "text-success-600": !stockOpname.isDifferent
- })}
- >
- <td className={styles.td}>
- <div className={clsxm("w-full rounded-lg mr-1 p-1 text-xs text-white whitespace-nowrap", {
- "bg-danger-600": stockOpname.isDifferent,
- "bg-success-600": !stockOpname.isDifferent,
- })}>
- {stockOpname.isDifferent ? 'Selisih' : 'Aman'}
- </div>
- </td>
- <td className={clsxm(styles.td, '!text-left flex min-w-[250px]')} aria-label="name">
- {stockOpname.itemCode ? `[${stockOpname.itemCode}] ` : ''}
- {stockOpname.name}
- {stockOpname.barcode ? ` [${stockOpname.barcode}]` : ''}
- </td>
- <td className={styles.td}>
- {credential?.team == 'VERIFICATION' && typeof stockOpname.quantity.COUNT1 === 'number' ? stockOpname.quantity.COUNT1 : '-'}
- </td>
- <td className={styles.td}>
- {credential?.team == 'VERIFICATION' && typeof stockOpname.quantity.COUNT2 === 'number' ? stockOpname.quantity.COUNT2 : '-'}
- </td>
- <td className={styles.td}>
- {credential?.team == 'VERIFICATION' && typeof stockOpname.quantity.COUNT3 === 'number' ? stockOpname.quantity.COUNT3 : '-'}
- </td>
- <td className={styles.td}>
- {credential?.team == 'VERIFICATION' && typeof stockOpname.quantity.VERIFICATION === 'number' ? stockOpname.quantity.VERIFICATION : '-'}
- </td>
- <td className={styles.td}>
- {credential?.team == 'VERIFICATION' ? stockOpname.onhandQty : '-'}
- </td>
- <td className={styles.td}>
- {credential?.team == 'VERIFICATION' ? stockOpname.differenceQty : '-'}
- </td>
- <td>
- {credential?.team == 'VERIFICATION' && (
- <Dropdown>
- <DropdownTrigger>
- <Button variant="light" className="p-1 min-w-fit">
- <MoreVerticalIcon size={16} />
- </Button>
- </DropdownTrigger>
- <DropdownMenu>
- <DropdownItem key="recompute" onPress={() => recompute(stockOpname.id, company)}>
- Re-compute
- </DropdownItem>
- <DropdownItem key="toggleDifferent" onPress={() => toggleDifferent(stockOpname.id)}>
- Tandai {stockOpname.isDifferent ? 'aman' : 'selisih'}
- </DropdownItem>
- </DropdownMenu>
- </Dropdown>
- )}
- </td>
- </tr>
-
- <DetailRow productId={stockOpname.id} />
- </>
- ))}
+ {!isLoading &&
+ stockOpnames.data?.result.map((stockOpname: StockOpnameRes["result"]) => (
+ <>
+ <tr
+ key={stockOpname.id}
+ className={clsxm("border-t border-neutral-200", {
+ "text-danger-600": stockOpname.isDifferent,
+ "text-success-600": !stockOpname.isDifferent,
+ })}
+ >
+ <td className={styles.td}>
+ <div
+ className={clsxm("w-full rounded-lg mr-1 p-1 text-xs text-white whitespace-nowrap", {
+ "bg-danger-600": stockOpname.isDifferent,
+ "bg-success-600": !stockOpname.isDifferent,
+ })}
+ >
+ {stockOpname.isDifferent ? "Selisih" : "Aman"}
+ </div>
+ </td>
+ <td className={clsxm(styles.td, "!text-left flex min-w-[250px]")} aria-label="name">
+ {stockOpname.itemCode ? `[${stockOpname.itemCode}] ` : ""}
+ {stockOpname.name}
+ {stockOpname.barcode ? ` [${stockOpname.barcode}]` : ""}
+ </td>
+ <td className={styles.td}>{credential?.team == "VERIFICATION" && typeof stockOpname.quantity.COUNT1 === "number" ? stockOpname.quantity.COUNT1 : "-"}</td>
+ <td className={styles.td}>{credential?.team == "VERIFICATION" && typeof stockOpname.quantity.COUNT2 === "number" ? stockOpname.quantity.COUNT2 : "-"}</td>
+ <td className={styles.td}>{credential?.team == "VERIFICATION" && typeof stockOpname.quantity.COUNT3 === "number" ? stockOpname.quantity.COUNT3 : "-"}</td>
+ <td className={styles.td}>{credential?.team == "VERIFICATION" && typeof stockOpname.quantity.VERIFICATION === "number" ? stockOpname.quantity.VERIFICATION : "-"}</td>
+ <td className={styles.td}>{credential?.team == "VERIFICATION" ? stockOpname.onhandQty : "-"}</td>
+ <td className={styles.td}>{credential?.team == "VERIFICATION" ? stockOpname.differenceQty : "-"}</td>
+ <td>
+ {credential?.team == "VERIFICATION" && (
+ <Dropdown>
+ <DropdownTrigger>
+ <Button variant="light" className="p-1 min-w-fit">
+ <MoreVerticalIcon size={16} />
+ </Button>
+ </DropdownTrigger>
+ <DropdownMenu>
+ <DropdownItem key="recompute" onPress={() => recompute(stockOpname.id, company)}>
+ Re-compute
+ </DropdownItem>
+ <DropdownItem key="toggleDifferent" onPress={() => toggleDifferent(stockOpname.id)}>
+ Tandai {stockOpname.isDifferent ? "aman" : "selisih"}
+ </DropdownItem>
+ </DropdownMenu>
+ </Dropdown>
+ )}
+ </td>
+ </tr>
+
+ <DetailRow productId={stockOpname.id} />
+ </>
+ ))}
{!isLoading && stockOpnames.data?.result.length === 0 && (
<tr>
- <td colSpan={COL_LENGTH} className="text-center text-neutral-600 py-4">Belum ada data untuk ditampilkan</td>
+ <td colSpan={COL_LENGTH} className="text-center text-neutral-600 py-4">
+ Belum ada data untuk ditampilkan
+ </td>
</tr>
)}
@@ -195,19 +199,13 @@ const Table = () => {
)}
</tbody>
</table>
-
</div>
<Spacer y={4} />
- <Pagination
- page={stockOpnames.data?.page || 1}
- total={stockOpnames.data?.totalPage || 1}
- onChange={(page) => updateFilter('page', page)}
- className="min-h-[36px] m-0 p-0"
- />
+ <Pagination page={stockOpnames.data?.page || 1} total={stockOpnames.data?.totalPage || 1} onChange={(page) => updateFilter("page", page)} className="min-h-[36px] m-0 p-0" />
</>
- )
-}
+ );
+};
-export default Table \ No newline at end of file
+export default Table;