mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 07:15:44 +00:00
refactor(FE-238-239-240): implement approval workflow chickin & project flock, membuat custom hook useApprovals, dan handling error format approvals
This commit is contained in:
@@ -10,6 +10,9 @@ import Tabs from '@/components/Tabs';
|
||||
import ChickinFormView from './tabs/ChickinFormView';
|
||||
import ChickinLogsView from './tabs/ChickLogsView';
|
||||
import { useState } from 'react';
|
||||
import ApprovalSteps, {
|
||||
useApprovalSteps,
|
||||
} from '@/components/pages/ApprovalSteps';
|
||||
const ChickinFormKandang = ({
|
||||
formType = 'add',
|
||||
initialValues,
|
||||
@@ -21,9 +24,20 @@ const ChickinFormKandang = ({
|
||||
}) => {
|
||||
const [activeTabId, setActiveTabId] = useState<string>('formChickIn');
|
||||
|
||||
const {
|
||||
approvals,
|
||||
isLoading: approvalsLoading,
|
||||
refresh: refreshApprovals,
|
||||
} = useApprovalSteps({
|
||||
moduleUrl: `/production/project-flock-kandangs/${initialValues?.id}`,
|
||||
moduleName: 'PROJECT_FLOCK_KANDANGS',
|
||||
moduleId: initialValues?.id.toString() ?? '',
|
||||
});
|
||||
|
||||
const afterSubmitFormChickin = () => {
|
||||
setActiveTabId('logsChickIn');
|
||||
afterSubmit && afterSubmit();
|
||||
refreshApprovals();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -32,6 +46,11 @@ const ChickinFormKandang = ({
|
||||
title='Chick In DOC'
|
||||
backUrl={`/production/project-flock/chickin/add?projectFlockId=${initialValues?.project_flock?.id}`}
|
||||
/>
|
||||
|
||||
{approvals && !approvalsLoading && (
|
||||
<ApprovalSteps approvals={approvals} />
|
||||
)}
|
||||
|
||||
<Card
|
||||
title='Informasi Kandang'
|
||||
className={{
|
||||
@@ -108,7 +127,7 @@ const ChickinFormKandang = ({
|
||||
content: (
|
||||
<ChickinLogsView
|
||||
initialValues={initialValues}
|
||||
afterSubmit={afterSubmit}
|
||||
afterSubmit={afterSubmitFormChickin}
|
||||
/>
|
||||
),
|
||||
id: 'logsChickIn',
|
||||
|
||||
@@ -47,9 +47,7 @@ const ChickinLogsView = ({
|
||||
}
|
||||
confirmModal.closeModal();
|
||||
setIsApproveLoading(false);
|
||||
if (afterSubmit) {
|
||||
afterSubmit();
|
||||
}
|
||||
afterSubmit && afterSubmit();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+13
-2
@@ -58,7 +58,15 @@ const ProjectFlockChickinDetail = ({
|
||||
options: options,
|
||||
isLoadingOptions: isLoadingListProjectFlock,
|
||||
rawData: listProjectFlock,
|
||||
} = useSelect<ProjectFlock>(ProjectFlockApi.basePath, 'id', 'flock_name');
|
||||
} = useSelect<ProjectFlock>(
|
||||
ProjectFlockApi.basePath,
|
||||
'id',
|
||||
'flock_name',
|
||||
'',
|
||||
{
|
||||
search: searchProjectFlock,
|
||||
}
|
||||
);
|
||||
|
||||
// Handle Function
|
||||
const handleChickinClick = async (
|
||||
@@ -242,7 +250,7 @@ const ProjectFlockChickinDetail = ({
|
||||
</div>
|
||||
}
|
||||
data={
|
||||
isResponseSuccess(listProjectFlockKandang)
|
||||
projectFlock && isResponseSuccess(listProjectFlockKandang)
|
||||
? listProjectFlockKandang.data
|
||||
: []
|
||||
}
|
||||
@@ -293,6 +301,8 @@ const ProjectFlockChickinDetail = ({
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/\b\w/g, (char) => char.toUpperCase())}
|
||||
/>
|
||||
) : projectFlock?.approval?.step_number === 1 ? (
|
||||
<PillBadge color='red' content={'Tidak Dapat Chick In'} />
|
||||
) : (
|
||||
<PillBadge color='gray' content={'Belum Chick In'} />
|
||||
);
|
||||
@@ -310,6 +320,7 @@ const ProjectFlockChickinDetail = ({
|
||||
handleChickinClick(props.row.original);
|
||||
}}
|
||||
className='p-1'
|
||||
disabled={projectFlock?.approval?.step_number === 1}
|
||||
>
|
||||
<Icon
|
||||
icon='mdi:home-import-outline'
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { Icon } from '@iconify/react';
|
||||
import { useFormik } from 'formik';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { use, useEffect, useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import useSWR, { KeyedMutator } from 'swr';
|
||||
import {
|
||||
ProjectFlockFormSchema,
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
import {
|
||||
ProjectFlockApprovalPayload,
|
||||
CreateProjectFlockPayload,
|
||||
PeriodFlock,
|
||||
ProjectFlock,
|
||||
} from '@/types/api/production/project-flock';
|
||||
import toast from 'react-hot-toast';
|
||||
@@ -34,23 +33,19 @@ import TextInput from '@/components/input/TextInput';
|
||||
import { Kandang } from '@/types/api/master-data/kandang';
|
||||
import Collapse from '@/components/Collapse';
|
||||
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
||||
import { BaseApiResponse, BaseGroupedApproval } from '@/types/api/api-general';
|
||||
import { BaseApiResponse } from '@/types/api/api-general';
|
||||
import { APPROVAL_WORKFLOWS, FLOCK_CATEGORY_OPTIONS } from '@/config/constant';
|
||||
import { useModal } from '@/components/Modal';
|
||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||
import ProjectFlockKandangTable from './ProjectFlockKandangTable';
|
||||
import ApprovalSteps from '@/components/pages/ApprovalSteps';
|
||||
import Steps from '@/components/steps/Steps';
|
||||
import StepItem from '@/components/steps/StepItem';
|
||||
import Tooltip from '@/components/Tooltip';
|
||||
import { id, is } from 'react-day-picker/locale';
|
||||
import { formatDate } from '@/lib/helper';
|
||||
import ApprovalSteps, {
|
||||
useApprovalSteps,
|
||||
} from '@/components/pages/ApprovalSteps';
|
||||
import Card from '@/components/Card';
|
||||
|
||||
interface ProjectFlockFormProps {
|
||||
formType?: 'add' | 'edit' | 'detail';
|
||||
initialValues?: ProjectFlock;
|
||||
initialApprovals?: BaseGroupedApproval[];
|
||||
refreshProjectFlocks?: KeyedMutator<
|
||||
BaseApiResponse<ProjectFlock> | undefined
|
||||
>;
|
||||
@@ -59,16 +54,11 @@ interface ProjectFlockFormProps {
|
||||
const ProjectFlockForm = ({
|
||||
formType = 'add',
|
||||
initialValues,
|
||||
initialApprovals,
|
||||
refreshProjectFlocks,
|
||||
}: ProjectFlockFormProps) => {
|
||||
// State
|
||||
const router = useRouter();
|
||||
|
||||
const projectFlockSteps = APPROVAL_WORKFLOWS.find(
|
||||
(step) => step.key === 'PROJECT_FLOCKS'
|
||||
);
|
||||
|
||||
const [projectFlockFormErrorMessage, setProjectFlockFormErrorMessage] =
|
||||
useState('');
|
||||
const [selectedArea, setSelectedArea] = useState('');
|
||||
@@ -120,34 +110,28 @@ const ProjectFlockForm = ({
|
||||
}, [initialValues]);
|
||||
|
||||
// Fetch Data
|
||||
const {
|
||||
rawData: flocks,
|
||||
isLoadingOptions: isLoadingFlocks,
|
||||
options: optionsFlock,
|
||||
} = useSelect(FlockApi.basePath, 'id', 'name');
|
||||
const { isLoadingOptions: isLoadingFlocks, options: optionsFlock } =
|
||||
useSelect(FlockApi.basePath, 'id', 'name');
|
||||
|
||||
const {
|
||||
options: optionsArea,
|
||||
isLoadingOptions: isLoadingAreas,
|
||||
rawData: areas,
|
||||
} = useSelect(AreaApi.basePath, 'id', 'name');
|
||||
const { options: optionsArea, isLoadingOptions: isLoadingAreas } = useSelect(
|
||||
AreaApi.basePath,
|
||||
'id',
|
||||
'name'
|
||||
);
|
||||
|
||||
const {
|
||||
options: optionsLocation,
|
||||
isLoadingOptions: isLoadingLocations,
|
||||
rawData: locations,
|
||||
} = useSelect(LocationApi.basePath, 'id', 'name', '', {
|
||||
area_id:
|
||||
selectedArea != ''
|
||||
? selectedArea
|
||||
: ((initialValues?.area?.id ?? '') as string),
|
||||
});
|
||||
const { options: optionsLocation, isLoadingOptions: isLoadingLocations } =
|
||||
useSelect(LocationApi.basePath, 'id', 'name', '', {
|
||||
area_id:
|
||||
selectedArea != ''
|
||||
? selectedArea
|
||||
: ((initialValues?.area?.id ?? '') as string),
|
||||
});
|
||||
|
||||
const {
|
||||
options: optionsFcr,
|
||||
isLoadingOptions: isLoadingFcrs,
|
||||
rawData: fcrs,
|
||||
} = useSelect(FcrApi.basePath, 'id', 'name');
|
||||
const { options: optionsFcr, isLoadingOptions: isLoadingFcrs } = useSelect(
|
||||
FcrApi.basePath,
|
||||
'id',
|
||||
'name'
|
||||
);
|
||||
|
||||
const kandangUrl = `${KandangApi.basePath}?${new URLSearchParams({
|
||||
search: '',
|
||||
@@ -164,6 +148,16 @@ const ProjectFlockForm = ({
|
||||
(id: string) => ProjectFlockApi.getNextPeriod(id)
|
||||
);
|
||||
|
||||
const {
|
||||
approvals,
|
||||
isLoading: approvalsLoading,
|
||||
refresh: refreshApprovals,
|
||||
} = useApprovalSteps({
|
||||
moduleUrl: `/production/project-flocks/${initialValues?.id}`,
|
||||
moduleName: 'PROJECT_FLOCKS',
|
||||
moduleId: initialValues?.id.toString() ?? '',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isResponseSuccess(kandang)) {
|
||||
if (selectedLocation) {
|
||||
@@ -516,6 +510,7 @@ const ProjectFlockForm = ({
|
||||
if (isResponseError(approveProjectFlockRes)) {
|
||||
toast.error(approveProjectFlockRes?.message as string);
|
||||
}
|
||||
refreshApprovals();
|
||||
confirmModal.closeModal();
|
||||
setIsApproveLoading(false);
|
||||
};
|
||||
@@ -558,79 +553,8 @@ const ProjectFlockForm = ({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{formType == 'detail' && initialApprovals && (
|
||||
<div className='w-full flex items-center gap-2 my-4'>
|
||||
<Steps className='w-full'>
|
||||
{projectFlockSteps?.steps.map((step, idx) => {
|
||||
const approvalLogs = initialApprovals.find(
|
||||
(approve) => approve.step_number == step.step_number
|
||||
);
|
||||
return (
|
||||
<StepItem
|
||||
key={step.step_number}
|
||||
color={
|
||||
step.step_number <=
|
||||
(initialValues?.approval.step_number ?? 0)
|
||||
? 'success'
|
||||
: undefined
|
||||
}
|
||||
icon={
|
||||
<Tooltip
|
||||
color={
|
||||
step.step_number <=
|
||||
(initialValues?.approval.step_number ?? 0)
|
||||
? 'success'
|
||||
: undefined
|
||||
}
|
||||
position='bottom'
|
||||
content={
|
||||
<ul>
|
||||
{approvalLogs &&
|
||||
approvalLogs?.approvals?.map((approval, idx) => {
|
||||
return (
|
||||
<li className='mb-2' key={`key-logs-${idx}`}>
|
||||
<div className='flex flex-col w-full text-start text-base'>
|
||||
<span>Status: {approval.step_name}</span>
|
||||
<span>
|
||||
Oleh: {approval.action_by.name}
|
||||
</span>
|
||||
<span>
|
||||
Tanggal:{' '}
|
||||
{formatDate(
|
||||
approval.action_at,
|
||||
'DD-MM-yyyy HH:mm:ss'
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
{step.step_number <=
|
||||
(initialValues?.approval.step_number ?? 0) ? (
|
||||
<Icon
|
||||
icon='material-symbols:check-rounded'
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
icon='material-symbols:check-rounded'
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
)}
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
{step.step_name}
|
||||
</StepItem>
|
||||
);
|
||||
})}
|
||||
</Steps>
|
||||
</div>
|
||||
{approvals && !approvalsLoading && (
|
||||
<ApprovalSteps approvals={approvals} />
|
||||
)}
|
||||
{formType == 'detail' && (
|
||||
<div className='w-full flex flex-col sm:flex-row gap-2 py-4'>
|
||||
@@ -675,32 +599,12 @@ const ProjectFlockForm = ({
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Icon icon='mdi:home-import-outline' width={18} height={18} />
|
||||
Chickin
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Card
|
||||
className={{
|
||||
body: 'text-primary',
|
||||
}}
|
||||
>
|
||||
{JSON.stringify(formik.values)}
|
||||
</Card>
|
||||
<Card
|
||||
className={{
|
||||
body: 'text-success',
|
||||
}}
|
||||
>
|
||||
{JSON.stringify(formik.initialValues)}
|
||||
</Card>
|
||||
<Card
|
||||
className={{
|
||||
body: 'text-error',
|
||||
}}
|
||||
>
|
||||
{JSON.stringify(formik.errors)}
|
||||
</Card>
|
||||
<form
|
||||
className='w-auto h-auto'
|
||||
onSubmit={formik.handleSubmit}
|
||||
|
||||
@@ -36,7 +36,6 @@ const ProjectFlockKandangTable = ({
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{JSON.stringify(initialKandangIdSet)}
|
||||
<Table<Kandang>
|
||||
data={listKandang}
|
||||
columns={[
|
||||
|
||||
Reference in New Issue
Block a user