"use client"; import { Location, Product } from "@prisma/client"; import AsyncSelect from "react-select/async" import styles from "./stock-opname.module.css" import { Button, Card, CardBody, Input, Modal, ModalBody, ModalContent, ModalHeader, Spacer, Spinner } from "@nextui-org/react"; import { SelectOption } from "@/common/types/select"; import { useStockOpnameStore } from "@/common/stores/useStockOpnameStore"; import { ActionMeta, SingleValue } from "react-select"; import { useMutation } from "@tanstack/react-query"; import { useEffect, useState } from "react"; import toast from "@/common/libs/toast"; import Scanner from "@/common/components/Scanner"; import { AlertCircleIcon, ScanLineIcon } from "lucide-react"; import Link from "next/link"; type ActiveScanner = "product" | "location" | null type ScannerOption = { value: number, label: string } const StockOpname = () => { const { form, updateForm, oldOpname, setOldOpname, resetForm } = useStockOpnameStore() useEffect(() => { const productId = form.product?.value const locationId = form.location?.value if ( typeof productId === 'number' && typeof locationId === 'number' ) { loadOldQuantity(productId, locationId) .then((data) => setOldOpname(data)) } }, [form.product, form.location, setOldOpname]) const handleSelectChange = (val: SingleValue, action: ActionMeta) => { updateForm(action.name as keyof typeof form, val) } const handleInputChange = (e: React.ChangeEvent) => { updateForm(e.target.name as keyof typeof form, e.target.value) } const saveMutation = useMutation({ mutationKey: ['stock-opname'], mutationFn: async (data: typeof form) => await fetch("/api/stock-opname", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ location: data.location?.value, product: data.product?.value, quantity: parseInt(data.quantity), }), }), onSuccess(data) { if (data.status === 200) { toast('Data berhasil disimpan') resetForm() } }, }) const handleSubmit = (e: React.FormEvent) => { e.preventDefault() saveMutation.mutate(form) } const [activeScanner, setActiveScanner] = useState(null) const [scannerOptions, setScannerOptions] = useState() const [scannerOptionLoading, setScannerOptionLoading] = useState(false) const handleOnScan = async (data: string) => { if (!activeScanner) return const loadFunc = activeScanner === 'product' ? loadProduct : loadLocation setScannerOptionLoading(true) const response = await loadFunc(data) setScannerOptionLoading(false) setScannerOptions(response) } const handleScannerOptionPress = (option: ScannerOption) => { toast(`${activeScanner} berhasil diubah`) updateForm(activeScanner as keyof typeof form, option) closeModal() } const closeModal = () => { setActiveScanner(null) setScannerOptions(undefined) } return ( <>
Stock Opname
{oldOpname && (
Jumlah terakhir adalah {' '} {oldOpname.quantity} {' '} diisi oleh {' '} {oldOpname.user.name}. {' '}
)}
Scan {activeScanner} {!scannerOptions && !scannerOptionLoading && ( )} {!scannerOptions && scannerOptionLoading && } {!!scannerOptions && ( <>
{scannerOptions.map((option) => ( handleScannerOptionPress(option)}> {option.label} ))}
{scannerOptions.length === 0 && (
Tidak ada opsi untuk ditampilkan
)} )}
) } const loadOldQuantity = async (productId: number, locationId: number) => { const queryParams = new URLSearchParams({ productId: productId.toString(), locationId: locationId.toString() }) const response = await fetch(`/api/stock-opname/quantity?${queryParams}`) const data = await response.json() return data } const loadLocation = async (inputValue: string) => { const response = await fetch(`/api/location?search=${inputValue}`) const data: Location[] = await response.json() || [] return data.map((location) => ({ value: location.id, label: location.name })) } const loadProduct = async (inputValue: string) => { const response = await fetch(`/api/product?search=${inputValue}`) const data: { products: Product[] } = await response.json() || [] return data?.products.map((product) => ({ value: product.id, label: `${product.itemCode ? `[${product.itemCode}]` : ''} ${product.name} ${product.barcode ? ` [${product.barcode}]` : ''}` } )) } export default StockOpname