refactor(FE): Refactor chickin approval modal logic into Zustand store

This commit is contained in:
rstubryan
2026-02-19 15:22:28 +07:00
parent a4ff92520a
commit 6ac903313c
4 changed files with 147 additions and 43 deletions
@@ -2,8 +2,6 @@ import Alert from '@/components/Alert';
import Button from '@/components/Button';
import Card from '@/components/Card';
import RequirePermission from '@/components/helper/RequirePermission';
import { useModal } from '@/components/Modal';
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
import PillBadge from '@/components/PillBadge';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { formatDate, formatNumber } from '@/lib/helper';
@@ -13,6 +11,7 @@ import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandan
import { Icon } from '@iconify/react';
import { useState } from 'react';
import toast from 'react-hot-toast';
import { useChickinStore } from '@/stores/production/chickin/chickin.store';
const ChickinLogsView = ({
initialValues,
@@ -23,32 +22,26 @@ const ChickinLogsView = ({
afterSubmit?: () => void;
rawDataApprovals: BaseApproval[];
}) => {
const confirmModal = useModal();
const [isApproveLoading, setIsApproveLoading] = useState(false);
const [chickinErrorMessage, setChickinErrorMessage] = useState('');
const { openChickinApproveModal } = useChickinStore();
const handleClickApprove = () => {
confirmModal.openModal();
};
const confirmationModalApproveClickHandler = async (notes?: string) => {
setChickinErrorMessage('');
setIsApproveLoading(true);
const approveChickinRes = await ChickinApi.singleApproval(
initialValues?.id as number,
'APPROVED',
notes
);
if (isResponseSuccess(approveChickinRes)) {
toast.success(approveChickinRes?.message as string);
}
if (isResponseError(approveChickinRes)) {
toast.error(approveChickinRes?.message as string);
setChickinErrorMessage(approveChickinRes?.message as string);
}
confirmModal.closeModal();
setIsApproveLoading(false);
afterSubmit && afterSubmit();
openChickinApproveModal(initialValues, async (notes?: string) => {
setChickinErrorMessage('');
const approveChickinRes = await ChickinApi.singleApproval(
initialValues?.id as number,
'APPROVED',
notes
);
if (isResponseSuccess(approveChickinRes)) {
toast.success(approveChickinRes?.message as string);
}
if (isResponseError(approveChickinRes)) {
toast.error(approveChickinRes?.message as string);
setChickinErrorMessage(approveChickinRes?.message as string);
}
afterSubmit && afterSubmit();
});
};
return (
@@ -83,7 +76,7 @@ const ChickinLogsView = ({
key={chickin.id || index}
variant='bordered'
className={{
wrapper: 'w-full',
wrapper: 'w-full mt-3',
body: 'p-3',
}}
>
@@ -176,23 +169,6 @@ const ChickinLogsView = ({
</div>
)}
</div>
<ConfirmationModalWithNotes
ref={confirmModal.ref}
type='success'
text={`Apakah anda yakin ingin approve data Chickin yang Pending?`}
secondaryButton={{
text: 'Tidak',
}}
primaryButton={{
text: 'Ya',
color: 'success',
onClick: (notes) => {
confirmationModalApproveClickHandler(notes);
},
isLoading: isApproveLoading,
}}
/>
</>
);
};
@@ -36,6 +36,7 @@ import PopoverContent from '@/components/popover/PopoverContent';
import ProjectFlockConfirmationModal from './ProjectFlockConfirmationModal';
import { useProjectFlockStore } from '@/stores/production/project-flock/project-flock.store';
import { ProjectFlockFormValues } from './form/ProjectFlockForm.schema';
import { useChickinStore } from '@/stores/production/chickin/chickin.store';
const RowOptionsMenu = ({
props,
@@ -193,6 +194,7 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
const deleteModal = useModal();
const confirmModal = useModal();
const successModal = useModal();
const chickinApproveModal = useModal();
const [approvalAction, setApprovalAction] = useState<'APPROVED' | 'REJECTED'>(
'APPROVED'
);
@@ -200,6 +202,13 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
const [isApproveLoading, setIsApproveLoading] = useState(false);
const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] =
useState(false);
const {
isChickinApproveModalOpen,
isChickinApproveLoading,
chickinApproveCallback,
closeChickinApproveModal,
setChickinApproveLoading,
} = useChickinStore();
// ===== Fetch Data =====
const {
@@ -292,6 +301,14 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
refreshProjectFlocks();
}, [refresh]);
useEffect(() => {
if (isChickinApproveModalOpen) {
chickinApproveModal.openModal();
} else {
chickinApproveModal.closeModal();
}
}, [isChickinApproveModalOpen, chickinApproveModal]);
useEffect(() => {
if (isSuccess) {
successModal.openModal();
@@ -974,6 +991,40 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
onClose={handleSuccessModalClose}
secondaryButton={undefined}
/>
{/* Chickin Approval Modal */}
<ConfirmationModalWithNotes
ref={chickinApproveModal.ref}
type='success'
text={`Apakah anda yakin ingin approve data Chickin yang Pending?`}
className={{
modal: 'z-9999',
}}
secondaryButton={{
text: 'Tidak',
onClick: () => {
closeChickinApproveModal();
chickinApproveModal.closeModal();
},
}}
primaryButton={{
text: 'Ya',
color: 'success',
onClick: async (notes) => {
if (chickinApproveCallback) {
setChickinApproveLoading(true);
try {
await chickinApproveCallback(notes);
} finally {
setChickinApproveLoading(false);
closeChickinApproveModal();
chickinApproveModal.closeModal();
}
}
},
isLoading: isChickinApproveLoading,
}}
/>
</>
);
};
@@ -0,0 +1,19 @@
'use client';
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { createChickinApprovalSlice } from '@/stores/production/chickin/slices/chickin-approval.slice';
import { ChickinApprovalSlice } from '@/stores/production/chickin/slices/chickin-approval.slice';
export type ChickinStore = ChickinApprovalSlice;
export const useChickinStore = create<ChickinStore>()(
devtools(
(...args) => ({
...createChickinApprovalSlice(...args),
}),
{
name: 'ChickinStore',
}
)
);
@@ -0,0 +1,58 @@
import { StateCreator } from 'zustand';
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
export type ChickinApprovalSlice = {
// State
isChickinApproveModalOpen: boolean;
selectedChickinForApproval: ProjectFlockKandang | null;
isChickinApproveLoading: boolean;
chickinApproveCallback: ((notes?: string) => Promise<void>) | null;
// Actions
openChickinApproveModal: (
data: ProjectFlockKandang,
callback: (notes?: string) => Promise<void>
) => void;
closeChickinApproveModal: () => void;
setChickinApproveLoading: (loading: boolean) => void;
resetChickinApproval: () => void;
};
export const createChickinApprovalSlice: StateCreator<
ChickinApprovalSlice,
[],
[],
ChickinApprovalSlice
> = (set) => ({
// Initial state
isChickinApproveModalOpen: false,
selectedChickinForApproval: null,
isChickinApproveLoading: false,
chickinApproveCallback: null,
// Actions
openChickinApproveModal: (data, callback) =>
set({
isChickinApproveModalOpen: true,
selectedChickinForApproval: data,
chickinApproveCallback: callback,
}),
closeChickinApproveModal: () =>
set({
isChickinApproveModalOpen: false,
selectedChickinForApproval: null,
chickinApproveCallback: null,
}),
setChickinApproveLoading: (loading) =>
set({ isChickinApproveLoading: loading }),
resetChickinApproval: () =>
set({
isChickinApproveModalOpen: false,
selectedChickinForApproval: null,
isChickinApproveLoading: false,
chickinApproveCallback: null,
}),
});