diff --git a/src/components/input/SelectInput.tsx b/src/components/input/SelectInput.tsx index a79054dd..38be09e4 100644 --- a/src/components/input/SelectInput.tsx +++ b/src/components/input/SelectInput.tsx @@ -246,8 +246,8 @@ const SelectInput = (props: SelectInputProps) => { className={cn( 'inline-flex items-center px-3 border border-r-0 border-base-content/10 rounded-l-lg transition-all duration-200', { - 'bg-gray-100 border-base-content/10': !isDisabled, - 'bg-gray-50 border-base-content/10': isDisabled, + 'bg-base-100 border-base-content/10': !isDisabled, + 'bg-base-200 border-base-content/10': isDisabled, 'border-error': isError, }, className?.inputPrefix @@ -278,15 +278,16 @@ const SelectInput = (props: SelectInputProps) => { className={cn('w-full flex-1', className?.select)} classNames={{ control: ({ isFocused, isDisabled }) => - cn('w-full border bg-white transition-shadow', 'rounded-lg!', { + cn('w-full border transition-shadow', 'rounded-lg!', { + 'bg-base-100!': !isDisabled && !readOnly, + 'bg-base-200! text-gray-400 cursor-not-allowed': + isDisabled && !readOnly, + 'bg-transparent! cursor-not-allowed!': readOnly, 'cursor-pointer!': !readOnly && !isDisabled, 'border-red-500! ring-2 ring-red-200': isError, 'border-indigo-500 ring-2 ring-indigo-200': isFocused && !startAdornment, 'border-base-content/10!': !isError && !isFocused, - 'bg-gray-100 text-gray-400 cursor-not-allowed': - isDisabled && !readOnly, - 'bg-transparent! cursor-not-allowed!': readOnly, 'rounded-l-none!': inputPrefix && !startAdornment, 'rounded-r-none!': inputSuffix && !startAdornment, }), @@ -370,8 +371,8 @@ const SelectInput = (props: SelectInputProps) => { className={cn( 'inline-flex items-center px-3 border border-l-0 border-base-content/10 rounded-r-lg transition-all duration-200', { - 'bg-gray-100 border-base-content/10': !isDisabled, - 'bg-gray-50 border-base-content/10': isDisabled, + 'bg-base-100 border-base-content/10': !isDisabled, + 'bg-base-200 border-base-content/10': isDisabled, 'border-error': isError, }, className?.inputSuffix @@ -404,18 +405,19 @@ const SelectInput = (props: SelectInputProps) => { classNames={{ control: ({ isFocused, isDisabled }) => cn( - 'w-full border bg-white transition-shadow', + 'w-full border transition-shadow', // Gunakan rounded-lg untuk semua kasus 'rounded-lg!', { + 'bg-base-100!': !isDisabled && !readOnly, + 'bg-base-200! text-gray-400 cursor-not-allowed': + isDisabled && !readOnly, + 'bg-transparent! cursor-not-allowed!': readOnly, 'cursor-pointer!': !readOnly && !isDisabled, 'border-red-500! ring-2 ring-red-200': isError, 'border-indigo-500 ring-2 ring-indigo-200': isFocused && !startAdornment, 'border-base-content/10!': !isError && !isFocused, - 'bg-gray-100 text-gray-400 cursor-not-allowed': - isDisabled && !readOnly, - 'bg-transparent! cursor-not-allowed!': readOnly, } ), valueContainer: () => cn('flex-1 px-3! pr-2! py-2.5! gap-1'), diff --git a/src/components/input/TextInput.tsx b/src/components/input/TextInput.tsx index 89d4f059..b7d0984f 100644 --- a/src/components/input/TextInput.tsx +++ b/src/components/input/TextInput.tsx @@ -104,8 +104,8 @@ const TextInput = ({ className={cn( 'inline-flex items-center px-3 border border-r-0 border-base-content/10 rounded-l-lg transition-all duration-200', { - 'bg-gray-100 border-base-content/10': !disabled, - 'bg-gray-50 border-base-content/10': disabled, + 'bg-base-100 border-base-content/10': !disabled, + 'bg-base-200 border-base-content/10': disabled, 'border-error': isError, 'border-success!': isValid, }, @@ -118,7 +118,7 @@ const TextInput = ({
diff --git a/src/components/pages/production/project-flock/ProjectFlockTable.tsx b/src/components/pages/production/project-flock/ProjectFlockTable.tsx index 7c4973eb..4085bc56 100644 --- a/src/components/pages/production/project-flock/ProjectFlockTable.tsx +++ b/src/components/pages/production/project-flock/ProjectFlockTable.tsx @@ -33,6 +33,9 @@ import RequirePermission from '@/components/helper/RequirePermission'; import StatusBadge from '@/components/helper/StatusBadge'; import PopoverButton from '@/components/popover/PopoverButton'; import PopoverContent from '@/components/popover/PopoverContent'; +import ProjectFlockConfirmationModal from './ProjectFlockConfirmationModal'; +import { useProjectFlockStore } from '@/stores/project-flock/project-flock.store'; +import { ProjectFlockFormValues } from './form/ProjectFlockForm.schema'; const RowOptionsMenu = ({ props, @@ -137,6 +140,15 @@ const RowOptionsMenu = ({ }; const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { + const isSuccess = useProjectFlockStore((s) => s.isSuccess); + const setIsSuccess = useProjectFlockStore((s) => s.setIsSuccess); + const createdProjectFlock = useProjectFlockStore( + (s) => s.createdProjectFlock + ); + const setCreatedProjectFlock = useProjectFlockStore( + (s) => s.setCreatedProjectFlock + ); + const { state: tableFilterState, updateFilter, @@ -180,6 +192,7 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { const [sorting, setSorting] = useState([]); const deleteModal = useModal(); const confirmModal = useModal(); + const successModal = useModal(); const [approvalAction, setApprovalAction] = useState<'APPROVED' | 'REJECTED'>( 'APPROVED' ); @@ -275,6 +288,64 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { refreshProjectFlocks(); }, [refresh]); + useEffect(() => { + if (isSuccess) { + successModal.openModal(); + } + }, [isSuccess, successModal]); + + const handleSuccessModalClose = () => { + successModal.closeModal(); + setIsSuccess(false); + setCreatedProjectFlock(null); + }; + + const projectFlockFormValues = useMemo(() => { + if (!createdProjectFlock) return undefined; + + return { + flock: { + value: 0, + label: createdProjectFlock.flock_name || '', + }, + flock_name: createdProjectFlock.flock_name || '', + area: { + value: createdProjectFlock.area_id, + label: createdProjectFlock.area?.name || '', + }, + area_id: createdProjectFlock.area_id, + category_option: { + value: createdProjectFlock.category, + label: createdProjectFlock.category, + }, + category: createdProjectFlock.category, + production_standard: { + value: createdProjectFlock.production_standard_id, + label: createdProjectFlock.production_standard?.name || '', + }, + production_standard_id: createdProjectFlock.production_standard_id, + location: { + value: createdProjectFlock.location_id, + label: createdProjectFlock.location?.name || '', + }, + location_id: createdProjectFlock.location_id, + kandang_ids: createdProjectFlock.kandangs?.map((k) => k.id) || [], + project_budgets: + createdProjectFlock.project_budgets?.map((budget) => ({ + nonstock: budget.nonstock + ? { + value: budget.nonstock_id, + label: budget.nonstock.name || '', + } + : null, + nonstock_id: budget.nonstock_id, + qty: budget.qty, + price: budget.price, + total_price: budget.qty * budget.price, + })) || [], + } as ProjectFlockFormValues; + }, [createdProjectFlock]); + // ====== MEMO ====== const selectedSingleRow: ProjectFlock | null | undefined = useMemo(() => { return selectedRowIds.length === 1 @@ -873,6 +944,16 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { isLoading: isApproveLoading, }} /> + + ); }; diff --git a/src/components/pages/production/project-flock/form/ProjectFlockForm.tsx b/src/components/pages/production/project-flock/form/ProjectFlockForm.tsx index 82c9e595..d56550a6 100644 --- a/src/components/pages/production/project-flock/form/ProjectFlockForm.tsx +++ b/src/components/pages/production/project-flock/form/ProjectFlockForm.tsx @@ -52,7 +52,7 @@ import Table from '@/components/Table'; import { ColumnDef } from '@tanstack/react-table'; import StatusBadge from '@/components/helper/StatusBadge'; import { getUniqueFormikErrors } from '@/lib/formik-helper'; -import ProjectFlockConfirmationModal from '../ProjectFlockConfirmationModal'; +import { useProjectFlockStore } from '@/stores/project-flock/project-flock.store'; interface ProjectFlockFormProps { formType?: 'add' | 'edit' | 'detail'; @@ -213,6 +213,10 @@ const ProjectFlockForm = ({ }: ProjectFlockFormProps) => { // State const router = useRouter(); + const setIsSuccess = useProjectFlockStore((s) => s.setIsSuccess); + const setCreatedProjectFlock = useProjectFlockStore( + (s) => s.setCreatedProjectFlock + ); const [formStep, setFormStep] = useState<'form' | 'confirmation'>('form'); @@ -239,7 +243,6 @@ const ProjectFlockForm = ({ const subscribeValidate = useUiStore((s) => s.subscribeValidate); const setIsValid = useUiStore((s) => s.setIsValid); - const successModal = useModal(); const deleteModal = useModal(); const [isDeleteLoading, setIsDeleteLoading] = useState(false); @@ -262,6 +265,8 @@ const ProjectFlockForm = ({ loadMore: loadMoreFlock, } = useSelect(FlockApi.basePath, 'id', 'name', '', { project_category: selectedCategory, + location_id: selectedLocation, + area_id: selectedArea, }); const { @@ -431,7 +436,9 @@ const ProjectFlockForm = ({ if (isResponseSuccess(createProjectFlockRes)) { toast.success(createProjectFlockRes?.message as string); handleReset(); - successModal.openModal(); + setCreatedProjectFlock(createProjectFlockRes?.data ?? null); + setIsSuccess(true); + router.push('/production/project-flock'); } if (isResponseError(createProjectFlockRes)) { setProjectFlockFormErrorMessage(createProjectFlockRes?.message as string); @@ -449,7 +456,9 @@ const ProjectFlockForm = ({ if (isResponseSuccess(updateProjectFlockRes)) { toast.success(updateProjectFlockRes?.message as string); handleReset(); - successModal.openModal(); + setCreatedProjectFlock(updateProjectFlockRes?.data ?? null); + setIsSuccess(true); + router.push('/production/project-flock'); } if (isResponseError(updateProjectFlockRes)) { setProjectFlockFormErrorMessage(updateProjectFlockRes?.message as string); @@ -1388,19 +1397,6 @@ const ProjectFlockForm = ({
- { - router.push('/production/project-flock'); - setFormikLastValues(undefined); - }} - secondaryButton={undefined} - /> - { ) : null } + disabled={type === 'detail'} /> {getStockUsageAdornment(idx)} @@ -2675,6 +2676,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ) : null } + disabled={type === 'detail'} /> {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( @@ -2891,6 +2893,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { }} placeholder='Masukkan jumlah telur' inputSuffix={'Butir'} + disabled={type === 'detail'} /> @@ -2917,6 +2920,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { }} placeholder='Masukkan total berat telur (Kilogram)...' inputSuffix='Kilogram' + disabled={type === 'detail'} /> {(type as 'add' | 'edit' | 'detail') !== diff --git a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx index c7b196a2..f872e7e0 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm.tsx @@ -402,6 +402,13 @@ const PurchaseOrderAcceptApprovalForm = ({ {purchaseItems?.map((purchaseItem, idx) => { const formItem = formik.values.items?.[idx]; + + const originalPurchaseItem = initialValues?.items?.find( + (item) => item.id === purchaseItem.id + ); + const isReceivedQtyDisabled = + originalPurchaseItem?.has_chickin === true; + return ( @@ -580,7 +587,12 @@ const PurchaseOrderAcceptApprovalForm = ({ decimalScale={0} thousandSeparator=',' decimalSeparator='.' - bottomLabel={`Total: ${purchaseItems[idx]?.quantity ? formatNumber(purchaseItems[idx].quantity) : 0}`} + disabled={isReceivedQtyDisabled} + bottomLabel={ + isReceivedQtyDisabled + ? 'Sudah chickin, tidak bisa diubah' + : `Total: ${purchaseItems[idx]?.quantity ? formatNumber(purchaseItems[idx].quantity) : 0}` + } isError={ isRepeaterInputError(idx, 'received_qty').isError || (formItem?.received_qty diff --git a/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx b/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx index 000c212b..1e674f4f 100644 --- a/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx +++ b/src/components/pages/purchase/form/order/PurchaseOrderStaffApprovalForm.tsx @@ -740,6 +740,13 @@ const PurchaseOrderStaffApprovalForm = ({ ) return null; + const originalPurchaseItem = + initialValues?.items?.find( + (item) => item.id === purchaseItem.id + ); + const isQtyDisabled = + originalPurchaseItem?.has_chickin === true; + return ( @@ -807,7 +814,12 @@ const PurchaseOrderStaffApprovalForm = ({ placeholder='Masukkan jumlah' allowNegative={false} decimalScale={0} - bottomLabel={`Previous: ${formatNumber(purchaseItem.quantity)}`} + disabled={isQtyDisabled} + bottomLabel={ + isQtyDisabled + ? 'Sudah chickin, tidak bisa diubah' + : `Previous: ${formatNumber(purchaseItem.quantity)}` + } className={{ wrapper: 'min-w-32', }} diff --git a/src/stores/project-flock/project-flock.store.ts b/src/stores/project-flock/project-flock.store.ts new file mode 100644 index 00000000..61efcb97 --- /dev/null +++ b/src/stores/project-flock/project-flock.store.ts @@ -0,0 +1,19 @@ +'use client'; + +import { create } from 'zustand'; +import { devtools } from 'zustand/middleware'; +import { createProjectFlockSlice } from '@/stores/project-flock/slices/project-flock.slice'; +import { ProjectFlockSlice } from '@/types/stores'; + +export type ProjectFlockStore = ProjectFlockSlice; + +export const useProjectFlockStore = create()( + devtools( + (...args) => ({ + ...createProjectFlockSlice(...args), + }), + { + name: 'ProjectFlockStore', + } + ) +); diff --git a/src/stores/project-flock/slices/project-flock.slice.ts b/src/stores/project-flock/slices/project-flock.slice.ts new file mode 100644 index 00000000..03f3205d --- /dev/null +++ b/src/stores/project-flock/slices/project-flock.slice.ts @@ -0,0 +1,24 @@ +import { ProjectFlockSlice } from '@/types/stores'; +import { StateCreator } from 'zustand'; + +export const createProjectFlockSlice: StateCreator< + ProjectFlockSlice, + [], + [], + ProjectFlockSlice +> = (set) => ({ + // Initial state + isSuccess: false, + createdProjectFlock: null, + + // Actions + setIsSuccess: (success) => set({ isSuccess: success }), + + setCreatedProjectFlock: (data) => set({ createdProjectFlock: data }), + + resetProjectFlock: () => + set({ + isSuccess: false, + createdProjectFlock: null, + }), +}); diff --git a/src/types/api/purchase/purchase.d.ts b/src/types/api/purchase/purchase.d.ts index f64d4275..d39719a3 100644 --- a/src/types/api/purchase/purchase.d.ts +++ b/src/types/api/purchase/purchase.d.ts @@ -50,6 +50,7 @@ export type PurchaseItem = { expedition_vendor_name?: string | null; received_qty?: number | null; transport_per_item?: number | null; + has_chickin?: boolean; expedition_vendor?: { id?: number; name?: string; diff --git a/src/types/stores.d.ts b/src/types/stores.d.ts index 47d2c1fd..c358e2a1 100644 --- a/src/types/stores.d.ts +++ b/src/types/stores.d.ts @@ -5,6 +5,7 @@ import type { UniformityDetail, VerifyUniformityResponse, } from '@/types/api/production/uniformity'; +import type { ProjectFlock } from '@/types/api/production/project-flock'; type MainUiSlice = { mainDrawerOpen: boolean; @@ -97,3 +98,14 @@ export type DashboardFilterSlice = { setFilterValues: (values: DashboardFilterType) => void; resetFilterValues: () => void; }; + +export type ProjectFlockSlice = { + // State + isSuccess: boolean; + createdProjectFlock: ProjectFlock | null; + + // Actions + setIsSuccess: (success: boolean) => void; + setCreatedProjectFlock: (data: ProjectFlock | null) => void; + resetProjectFlock: () => void; +};