From ae3207e9778c3f2fb01d64714ff15fc073ec093d Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 1 Dec 2023 10:16:12 +0700 Subject: Update compute different, result, and product list feature --- src/modules/result/components/DetailRow.tsx | 32 ++++++++++++---- src/modules/result/components/ProductModal.tsx | 34 ++++++++++++++--- src/modules/result/components/Table.tsx | 52 +++++++++++++++++--------- 3 files changed, 88 insertions(+), 30 deletions(-) (limited to 'src/modules/result/components') diff --git a/src/modules/result/components/DetailRow.tsx b/src/modules/result/components/DetailRow.tsx index 18dcb8f..bb5b1ef 100644 --- a/src/modules/result/components/DetailRow.tsx +++ b/src/modules/result/components/DetailRow.tsx @@ -4,10 +4,11 @@ import { StockOpnameLocationRes } from '@/common/types/stockOpname'; import { Skeleton } from '@nextui-org/react'; import { useQuery } from '@tanstack/react-query' import styles from './table.module.css' -import { CornerDownRightIcon } from 'lucide-react'; -import { User } from 'prisma/generated/client'; +import { CheckIcon, CornerDownRightIcon, XIcon } from 'lucide-react'; +import { Team, User } from 'prisma/generated/client'; import clsxm from '@/common/libs/clsxm'; import getClientCredential from '@/common/libs/getClientCredential'; +import _ from 'lodash'; const DetailRow = ({ productId }: { productId: number }) => { const { filter } = useResultStore() @@ -48,16 +49,16 @@ const DetailRow = ({ productId }: { productId: number }) => { - + - + - + - + @@ -67,14 +68,29 @@ const DetailRow = ({ productId }: { productId: number }) => { ) } -const QuantityColumn = ({ data }: { data: { quantity?: number | undefined, user?: User } }) => { +type Data = { quantity?: number | undefined, user?: User } + +const Column = ({ team, data }: { team: Team, data: Data }) => { + const credential = getClientCredential() + + return credential?.team === team && credential.team !== 'VERIFICATION' ? ( +
+ {_.isNumber(data.quantity) && } + {_.isUndefined(data.quantity) && } +
+ ) : ( + + ) +} + +const QuantityColumn = ({ data }: { data: Data }) => { const credential = getClientCredential() if (!(credential?.team == "VERIFICATION")) return '-' return (
- {typeof data?.quantity !== 'number' && '-'} + {_.isUndefined(data.quantity) && '-'} {data.quantity !== null && ( <> {data.quantity} diff --git a/src/modules/result/components/ProductModal.tsx b/src/modules/result/components/ProductModal.tsx index 1fe4130..0d7a7fc 100644 --- a/src/modules/result/components/ProductModal.tsx +++ b/src/modules/result/components/ProductModal.tsx @@ -1,9 +1,10 @@ import { useResultStore } from '@/common/stores/useResultStore' -import { Input, Modal, ModalBody, ModalContent, ModalHeader, Pagination, Skeleton, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react' +import { Input, Modal, ModalBody, ModalContent, ModalHeader, Pagination, Select, SelectItem, Skeleton, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react' import { Product } from 'prisma/generated/client' import { useQuery } from '@tanstack/react-query' import React, { useEffect, useMemo, useState } from 'react' import { useDebounce } from 'usehooks-ts' +import { SHOWING_SELECTIONS } from '@/common/constants/product' type Props = { modal: { @@ -15,20 +16,23 @@ type Props = { const ProductModal = ({ modal }: Props) => { const [page, setPage] = useState(1) const [search, setSearch] = useState("") + const [show, setShow] = useState("1") const debouncedSearch = useDebounce(search, 500) const { filter } = useResultStore() useEffect(() => { setPage(1) - }, [debouncedSearch]) + }, [debouncedSearch, show, filter.company]) const { data } = useQuery({ - queryKey: ['product', page, debouncedSearch, filter.company], + queryKey: ['product', page, debouncedSearch, filter.company, show], queryFn: async () => { + const showValue = SHOWING_SELECTIONS.find((item) => item.key === show)?.value || '' const searchParams = new URLSearchParams({ page: page.toString(), search: debouncedSearch, - companyId: filter.company + companyId: filter.company, + show: showValue }) const response = await fetch(`/api/product?${searchParams}`) const data: { @@ -47,12 +51,32 @@ const ProductModal = ({ modal }: Props) => { if (data?.totalPage) setTotalPage(data?.totalPage) }, [data?.totalPage]) + const handleSelectChange = (e: React.ChangeEvent) => { + setShow(e.target.value) + } + return ( Product List - setSearch(e.target.value)} /> +
+
+ setSearch(e.target.value)} /> +
+
+ +
+
{!data && ( )} diff --git a/src/modules/result/components/Table.tsx b/src/modules/result/components/Table.tsx index a6a9f30..7478e1b 100644 --- a/src/modules/result/components/Table.tsx +++ b/src/modules/result/components/Table.tsx @@ -1,7 +1,7 @@ "use client"; import { useResultStore } from "@/common/stores/useResultStore"; import { StockOpnameRes } from "@/common/types/stockOpname"; -import { Button, 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 clsxm from "@/common/libs/clsxm"; @@ -11,6 +11,9 @@ import getClientCredential from "@/common/libs/getClientCredential"; import { SHOWING_SELECTIONS } from "@/common/constants/result"; import { useEffect, useState } from "react"; import moment from "moment"; +import { MoreVerticalIcon } from "lucide-react"; +import toast from "@/common/libs/toast"; +import { Product } from "prisma/generated/client"; const Table = () => { const credential = getClientCredential() @@ -37,7 +40,10 @@ const Table = () => { searchParams.set('page', page.toString()); return await fetch(`/api/stock-opname?${searchParams}`) - .then(res => res.json()) + .then(res => { + window.scrollTo({ top: 0, 'behavior': 'smooth' }) + return res.json() + }) }, placeholderData: keepPreviousData }) @@ -63,21 +69,17 @@ const Table = () => { setExportLoad(false) } - let debounceTimeout: NodeJS.Timeout | null = null; - - const paginationOnChange = (page: number) => { - updateFilter('page', page) - - if (debounceTimeout) clearTimeout(debounceTimeout) - - debounceTimeout = setTimeout(() => { - window.scrollTo({ top: 0, 'behavior': 'smooth' }); - debounceTimeout = null - }, 1000); + 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 isLoading = stockOpnames.isLoading || stockOpnames.isRefetching + const COL_LENGTH = 9 + return ( <>
@@ -97,6 +99,7 @@ const Table = () => { TIM VERIFIKASI ON-HAND QTY GUDANG SELISIH + {!isLoading && stockOpnames.data?.result.map((stockOpname: StockOpnameRes['result']) => ( @@ -137,6 +140,22 @@ const Table = () => { {credential?.team == 'VERIFICATION' ? stockOpname.differenceQty : '-'} + + {credential?.team == 'VERIFICATION' && ( + + + + + + toggleDifferent(stockOpname.id)}> + Tandai {stockOpname.isDifferent ? 'aman' : 'selisih'} + + + + )} + @@ -145,13 +164,13 @@ const Table = () => { {!isLoading && stockOpnames.data?.result.length === 0 && ( - Belum ada data untuk ditampilkan + Belum ada data untuk ditampilkan )} {isLoading && ( - +
{Array.from({ length: 10 }, (_, i) => ( @@ -165,10 +184,9 @@ const Table = () => { updateFilter('page', page)} />
-- cgit v1.2.3