From 2216e37c59f874faa45b6b6df4e2a950f9559c4d Mon Sep 17 00:00:00 2001 From: JoaoGabrielGarcia Date: Wed, 27 Nov 2024 11:49:22 -0300 Subject: [PATCH] =?UTF-8?q?[Front]:=20=E2=9C=A8=20Feat:=20Supplier=20selec?= =?UTF-8?q?t=20component=20in=20product=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/constants/cache.ts | 6 ++ .../commons/supplier-select/index.tsx | 81 ++++++++++++++++++ .../supplier-select/use-supplier-select.ts | 85 +++++++++++++++++++ .../products/register-product-form/index.tsx | 15 +++- .../use-register-product-form.ts | 1 + .../products/update-product-form/index.tsx | 14 ++- .../use-update-product-form.ts | 1 + 7 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/ui/components/commons/supplier-select/index.tsx create mode 100644 apps/web/src/ui/components/commons/supplier-select/use-supplier-select.ts diff --git a/apps/web/src/constants/cache.ts b/apps/web/src/constants/cache.ts index 5a3433f2..b5310b1b 100644 --- a/apps/web/src/constants/cache.ts +++ b/apps/web/src/constants/cache.ts @@ -44,4 +44,10 @@ export const CACHE = { company: { key: '/company', }, + supplier: { + key: '/supplier', + }, + suppliers: { + key: '/suppliers', + }, } diff --git a/apps/web/src/ui/components/commons/supplier-select/index.tsx b/apps/web/src/ui/components/commons/supplier-select/index.tsx new file mode 100644 index 00000000..565f0bde --- /dev/null +++ b/apps/web/src/ui/components/commons/supplier-select/index.tsx @@ -0,0 +1,81 @@ +import { Button, Pagination, Spinner } from '@nextui-org/react' +import { Icon } from '@/ui/components/commons/icon' +import { Select } from '@/ui/components/commons/select' +import { Dialog } from '../dialog' +import { useSupplierSelect } from './use-supplier-select' + +type SupplierSelectProps = { + defeaultSupplierId?: string + className?: string + onSelectChange: (supplierId: string) => void +} + +export const SupplierSelect = ({ + className, + defeaultSupplierId, + onSelectChange, +}: SupplierSelectProps) => { + const { + suppliers, + isFetching, + page, + totalPages, + selectedSupplierName, + handleSupplierIdChange, + handleSupplierPageChange, + } = useSupplierSelect(onSelectChange, defeaultSupplierId) + + return isFetching ? ( + + ) : ( +
+ + {selectedSupplierName ? selectedSupplierName : 'Selecione fornecedor'} + + } + > + {(closeDrawer) => + suppliers.length === 0 ? ( +

+ Nenhum fornecedor registrado. +

+ ) : ( + <> +
+ {suppliers.map((supplier) => ( +
+ {supplier.name} + +
+ ))} +
+ {totalPages !== 1 && ( + + )} + + ) + } +
+
+ ) +} diff --git a/apps/web/src/ui/components/commons/supplier-select/use-supplier-select.ts b/apps/web/src/ui/components/commons/supplier-select/use-supplier-select.ts new file mode 100644 index 00000000..2304786f --- /dev/null +++ b/apps/web/src/ui/components/commons/supplier-select/use-supplier-select.ts @@ -0,0 +1,85 @@ +import { CACHE } from '@/constants' +import { useApi, useCache, useToast, useUrlParamNumber } from '@/ui/hooks' +import { Supplier } from '@stocker/core/entities' +import { useEffect, useState } from 'react' +import { useAuthContext } from '../../contexts/auth-context' + +export function useSupplierSelect( + onSelectChange: (supplierId: string) => void, + defeaultSelectedSupplierId?: string, +) { + const [supplierId, setSupplierId] = useState(defeaultSelectedSupplierId) + const { suppliersService } = useApi() + const { company } = useAuthContext() + const { showError } = useToast() + const [page, setPage] = useUrlParamNumber('supplierPage', 1) + const [expandedItems, setExpandedItems] = useState<{ [key: string]: boolean }>({}) + + function handleSupplierIdChange(supplierId: string) { + setSupplierId(supplierId) + onSelectChange(supplierId) + } + + async function fetchSupplier() { + if (!supplierId) return + + const response = await suppliersService.getSupplier(supplierId) + if (response.isFailure) { + showError(response.errorMessage) + return + } + return response.body + } + + async function fetchSuppliers() { + if (!company) return + + const response = await suppliersService.listSuppliers({ + page, + companyId: company.id, + }) + if (response.isFailure) { + showError(response.errorMessage) + return + } + return response.body + } + + const { data: supplierData } = useCache({ + fetcher: fetchSupplier, + key: CACHE.supplier.key, + dependencies: [supplierId], + }) + + const { data: suppliersData, isFetching } = useCache({ + fetcher: fetchSuppliers, + key: CACHE.suppliers.key, + dependencies: [page], + }) + + function handlePageChange(page: number) { + setPage(page) + } + + function handleAccordionClick(id: string) { + setExpandedItems((prev) => ({ + ...prev, + [id]: !prev[id], + })) + } + + const suppliers = suppliersData ? suppliersData.items.map(Supplier.create) : [] + const itemsCount = suppliersData ? suppliersData.itemsCount : 0 + + return { + isFetching, + totalPages: Math.ceil(itemsCount / 10), + page, + suppliers, + selectedSupplierName: supplierData?.name, + expandedItems, + handleSupplierIdChange, + handleAccordionClick, + handleSupplierPageChange: handlePageChange, + } +} diff --git a/apps/web/src/ui/components/pages/products/register-product-form/index.tsx b/apps/web/src/ui/components/pages/products/register-product-form/index.tsx index 0c96b682..0e5425a4 100644 --- a/apps/web/src/ui/components/pages/products/register-product-form/index.tsx +++ b/apps/web/src/ui/components/pages/products/register-product-form/index.tsx @@ -8,6 +8,8 @@ import { useRegisterProductForm } from './use-register-product-form' import { ImageInput } from '@/ui/components/commons/image-input' import type { ImageInputRef } from '@/ui/components/commons/image-input/types' import { CategorySelect } from '@/ui/components/commons/category-select' +import { SupplierSelect } from '@/ui/components/commons/supplier-select' + type RegisterProductFormProps = { onCancel: VoidFunction @@ -66,7 +68,18 @@ export const RegisterProductForm = ({ onSubmit, onCancel }: RegisterProductFormP />
- + ( +
+ + {errors.supplierId && ( +

{errors.supplierId?.message}

+ )} +
+ )} + /> (value === '' ? undefined : value)) diff --git a/apps/web/src/ui/components/pages/products/update-product-form/index.tsx b/apps/web/src/ui/components/pages/products/update-product-form/index.tsx index 4ab9e466..07979c58 100644 --- a/apps/web/src/ui/components/pages/products/update-product-form/index.tsx +++ b/apps/web/src/ui/components/pages/products/update-product-form/index.tsx @@ -10,6 +10,7 @@ import { ImageInput } from '@/ui/components/commons/image-input' import type { ImageInputRef } from '@/ui/components/commons/image-input/types' import { useUpdateProductForm } from './use-update-product-form' import { CategorySelect } from '@/ui/components/commons/category-select' +import { SupplierSelect } from '@/ui/components/commons/supplier-select' type RegisterProductFormProps = { product: Product @@ -87,7 +88,18 @@ export const UpdateProductForm = ({ />
- + ( +
+ + {errors.supplierId && ( +

{errors.supplierId?.message}

+ )} +
+ )} + />