mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
refactor(FE-106-91-339-238): Slicing UI Chickin DOC Refactored
This commit is contained in:
@@ -87,7 +87,7 @@ const ChickinTable = () => {
|
||||
<div className='flex flex-col gap-2 mb-4'>
|
||||
<div className='w-full flex flex-col sm:flex-row justify-between items-end sm:items-center gap-2'>
|
||||
<Button
|
||||
href='/production/chickin/add?projectFlockId=1'
|
||||
href='/production/project-flock/chickin/add?projectFlockId=1'
|
||||
variant='outline'
|
||||
color='primary'
|
||||
className='w-full sm:w-fit'
|
||||
@@ -260,14 +260,14 @@ const ChickinTable = () => {
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
<ChickinForm
|
||||
{/* <ChickinForm
|
||||
initialValues={selectedChickin}
|
||||
formType='edit'
|
||||
afterSubmit={() => {
|
||||
refreshChickins();
|
||||
chickinModal.closeModal();
|
||||
}}
|
||||
/>
|
||||
/> */}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
@@ -287,7 +287,7 @@ const RowOptionsMenu = ({
|
||||
return (
|
||||
<RowOptionsMenuWrapper type={type}>
|
||||
<Button
|
||||
href={`/production/chickin/detail?chickinId=${props.row.original.id}`}
|
||||
href={`/production/project-flock/chickin/detail?chickinId=${props.row.original.id}`}
|
||||
variant='ghost'
|
||||
color='primary'
|
||||
className='justify-start text-sm'
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export const ChickinFormSchema = Yup.object({
|
||||
chick_in_date: Yup.string().required('Tanggal masuk wajib diisi!'),
|
||||
note: Yup.string().required('Catatan wajib diisi!'),
|
||||
quantity: Yup.number()
|
||||
.min(1, 'Jumlah wajib diisi!')
|
||||
.required('Jumlah wajib diisi!'),
|
||||
});
|
||||
|
||||
export type ChickinFormValues = Yup.InferType<typeof ChickinFormSchema>;
|
||||
|
||||
export const UpdateChickinFormSchema = ChickinFormSchema;
|
||||
import { Product } from '@/types/api/master-data/product';
|
||||
import { Supplier } from '@/types/api/master-data/supplier';
|
||||
|
||||
@@ -1,220 +1,227 @@
|
||||
'use client';
|
||||
|
||||
import Button from '@/components/Button';
|
||||
import {
|
||||
Chickin,
|
||||
CreateChickinPayload,
|
||||
UpdateChickinPayload,
|
||||
} from '@/types/api/production/chickin';
|
||||
import {
|
||||
ChickinFormSchema,
|
||||
ChickinFormValues,
|
||||
UpdateChickinFormSchema,
|
||||
} from '@/components/pages/production/chickin/form/ChickinForm.schema';
|
||||
import { use, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useFormik } from 'formik';
|
||||
import { ChickinApi } from '@/services/api/production';
|
||||
import Card from '@/components/Card';
|
||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||
import DateInput from '@/components/input/DateInput';
|
||||
import { isResponseError } from '@/lib/api-helper';
|
||||
import toast from 'react-hot-toast';
|
||||
import { Icon } from '@iconify/react';
|
||||
import TextArea from '@/components/input/TextArea';
|
||||
import TextInput from '@/components/input/TextInput';
|
||||
import FileInput from '@/components/input/FileInput';
|
||||
import NumberInput from '@/components/input/NumberInput';
|
||||
import SelectInput from '@/components/input/SelectInput';
|
||||
import TextInput from '@/components/input/TextInput';
|
||||
import Table from '@/components/Table';
|
||||
import { formatNumber } from '@/lib/helper';
|
||||
import { Kandang } from '@/types/api/master-data/kandang';
|
||||
import {
|
||||
AvailableQty,
|
||||
ProjectFlockKandang,
|
||||
} from '@/types/api/production/project-flock-kandang';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
interface ChickinFormProps {
|
||||
formType?: 'add' | 'detail' | 'edit';
|
||||
initialValues?: Chickin;
|
||||
afterSubmit?: () => void;
|
||||
}
|
||||
|
||||
const ChickinForm = ({
|
||||
const ChickinFormKandang = ({
|
||||
formType = 'add',
|
||||
initialValues,
|
||||
afterSubmit,
|
||||
}: ChickinFormProps) => {
|
||||
// Helper Function
|
||||
const formatDateForInput = (dateString?: string): string => {
|
||||
if (!dateString) return '';
|
||||
return new Date(dateString).toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
// State
|
||||
const [chickinFormErrorMessage, setChickinFormErrorMessage] = useState('');
|
||||
|
||||
// Initial Value
|
||||
const formikInitialValue = useMemo<ChickinFormValues>(() => {
|
||||
return {
|
||||
chick_in_date: formatDateForInput(initialValues?.chick_in_date) ?? '',
|
||||
note: initialValues?.note ?? '',
|
||||
quantity:
|
||||
initialValues?.quantity ??
|
||||
initialValues?.project_flock_kandang?.available_quantity ??
|
||||
0,
|
||||
};
|
||||
}, [initialValues]);
|
||||
|
||||
// Handle Submit Function
|
||||
const handleCreate = useCallback(
|
||||
async (
|
||||
payload: CreateChickinPayload,
|
||||
afterSubmit: (() => void) | undefined
|
||||
) => {
|
||||
const res = await ChickinApi.create(payload);
|
||||
if (isResponseError(res)) {
|
||||
setChickinFormErrorMessage(res.message);
|
||||
return;
|
||||
}
|
||||
toast.success(res?.message as string);
|
||||
afterSubmit?.();
|
||||
},
|
||||
[]
|
||||
);
|
||||
const handleUpdate = useCallback(
|
||||
async (
|
||||
payload: UpdateChickinPayload,
|
||||
afterSubmit: (() => void) | undefined
|
||||
) => {
|
||||
const res = await ChickinApi.update(payload.id, payload);
|
||||
if (isResponseError(res)) {
|
||||
setChickinFormErrorMessage(res.message);
|
||||
return;
|
||||
}
|
||||
toast.success(res?.message as string);
|
||||
afterSubmit?.();
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// Formik
|
||||
const formik = useFormik<ChickinFormValues>({
|
||||
initialValues: formikInitialValue,
|
||||
enableReinitialize: true,
|
||||
validationSchema:
|
||||
formType === 'edit' ? UpdateChickinFormSchema : ChickinFormSchema,
|
||||
onSubmit: async (values) => {
|
||||
// reset error message
|
||||
setChickinFormErrorMessage('');
|
||||
|
||||
if (
|
||||
initialValues?.project_flock_kandang?.id == undefined ||
|
||||
(formType == 'edit' && initialValues?.id == undefined)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create payload
|
||||
const payload = {
|
||||
chick_in_date: values.chick_in_date,
|
||||
project_flock_kandang_id: initialValues?.project_flock_kandang?.id,
|
||||
note: values.note,
|
||||
quantity: values.quantity,
|
||||
id: initialValues.id ?? 0,
|
||||
};
|
||||
|
||||
// cek type form yang disubmit
|
||||
console.log(formType);
|
||||
switch (formType) {
|
||||
case 'add':
|
||||
handleCreate(payload, afterSubmit);
|
||||
break;
|
||||
case 'edit':
|
||||
handleUpdate(payload, afterSubmit);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Initialize Formik
|
||||
const { setValues: formikSetValues } = formik;
|
||||
useEffect(() => {
|
||||
formikSetValues(formikInitialValue);
|
||||
}, [formikSetValues, formikInitialValue]);
|
||||
|
||||
}: {
|
||||
formType?: 'add' | 'detail' | 'edit';
|
||||
initialValues: ProjectFlockKandang;
|
||||
afterSubmit?: () => void;
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<form
|
||||
className='min-h-48 flex flex-col gap-4'
|
||||
onSubmit={formik.handleSubmit}
|
||||
onReset={formik.handleReset}
|
||||
<div className='flex flex-col gap-4'>
|
||||
<FormHeader
|
||||
type='add'
|
||||
title='Chick In DOC'
|
||||
backUrl={`/production/project-flock/chickin/add?projectFlockId=${initialValues.project_flock.id}`}
|
||||
/>
|
||||
<Card
|
||||
title='Informasi Kandang'
|
||||
className={{
|
||||
wrapper: 'w-full bg-white mt-4',
|
||||
}}
|
||||
>
|
||||
<DateInput
|
||||
value={formik.values.chick_in_date}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
name='chick_in_date'
|
||||
label='Tanggal Chickin'
|
||||
required
|
||||
isError={
|
||||
formik.touched.chick_in_date && Boolean(formik.errors.chick_in_date)
|
||||
<Table<Kandang>
|
||||
emptyContent={
|
||||
<div className='w-full p-5 text-center'>
|
||||
<span className='text-lg opacity-50'>
|
||||
Informasi Kandang belum tersedia...
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
errorMessage={formik.errors.chick_in_date}
|
||||
data={[initialValues.kandang]}
|
||||
columns={[
|
||||
{
|
||||
header: 'Area',
|
||||
accessorFn: () => initialValues.project_flock?.area.name || '-',
|
||||
},
|
||||
{
|
||||
header: 'Lokasi',
|
||||
accessorFn: () =>
|
||||
initialValues.project_flock?.location.name || '-',
|
||||
},
|
||||
{
|
||||
header: 'Flock',
|
||||
accessorFn: () => initialValues.project_flock?.flock.name || '-',
|
||||
},
|
||||
{
|
||||
header: 'Kandang',
|
||||
accessorFn: (row) => row?.name || '-',
|
||||
},
|
||||
{
|
||||
header: 'Kapasitas',
|
||||
accessorFn: (row) =>
|
||||
(row?.capacity && formatNumber(row?.capacity)) || '-',
|
||||
},
|
||||
{
|
||||
header: 'Penanggung Jawab',
|
||||
accessorFn: (row) => row?.pic?.name || '-',
|
||||
},
|
||||
]}
|
||||
className={{
|
||||
tableWrapperClassName: 'overflow-x-auto min-h-full!',
|
||||
tableClassName: 'font-inter w-full table-auto min-h-full!',
|
||||
headerRowClassName: 'border-b border-b-gray-200',
|
||||
headerColumnClassName:
|
||||
'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
|
||||
bodyRowClassName: 'border-b border-b-gray-200',
|
||||
bodyColumnClassName:
|
||||
'px-6 py-3 last:flex last:flex-row last:justify-end',
|
||||
paginationClassName: 'hidden',
|
||||
}}
|
||||
/>
|
||||
<NumberInput
|
||||
value={formik.values.quantity}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
name='quantity'
|
||||
label='Jumlah (Ekor)'
|
||||
required
|
||||
isError={
|
||||
(formik.touched.quantity && Boolean(formik.errors.quantity)) ||
|
||||
formik.values.quantity == 0
|
||||
</Card>
|
||||
<Card
|
||||
title='Informasi Chick In DOC'
|
||||
className={{
|
||||
wrapper: 'w-full bg-white',
|
||||
}}
|
||||
>
|
||||
<Table<AvailableQty>
|
||||
data={initialValues.available_qtys || []}
|
||||
columns={[
|
||||
{
|
||||
accessorFn: (row) => row.chick_in_date,
|
||||
header: 'Tanggal Chick In',
|
||||
cell(props) {
|
||||
return (
|
||||
<DateInput
|
||||
name='chick_in_date[]'
|
||||
value={props.row.original.chick_in_date}
|
||||
onChange={(e) => {
|
||||
props.row.original.chick_in_date = e.target.value;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.po_number,
|
||||
header: 'No. Surat Jalan',
|
||||
cell(props) {
|
||||
return (
|
||||
<TextInput
|
||||
name='po_number[]'
|
||||
value={props.row.original.po_number}
|
||||
onChange={(e) => {
|
||||
props.row.original.po_number = e.target.value;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
header: 'Dokumen Surat Jalan',
|
||||
cell(props) {
|
||||
return (
|
||||
<FileInput
|
||||
name='document_path[]'
|
||||
onChange={(e) => {
|
||||
props.row.original.document_path = e.target.value;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.supplier?.name,
|
||||
header: 'Supplier',
|
||||
cell(props) {
|
||||
return (
|
||||
<SelectInput
|
||||
value={
|
||||
props.row.original.supplier?.name &&
|
||||
props.row.original.supplier?.id
|
||||
? {
|
||||
label: props.row.original.supplier.name,
|
||||
value: props.row.original.supplier.id,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
options={[]}
|
||||
isDisabled
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.product_warehouse.product.name,
|
||||
header: 'Produk',
|
||||
cell(props) {
|
||||
return (
|
||||
<SelectInput
|
||||
value={{
|
||||
label: props.row.original.product_warehouse.product.name,
|
||||
value: props.row.original.product_warehouse.product.id,
|
||||
}}
|
||||
options={[]}
|
||||
isDisabled
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorFn: (row) => row.product_warehouse.quantity,
|
||||
header: 'Jumlah (ekor)',
|
||||
cell(props) {
|
||||
return (
|
||||
<NumberInput
|
||||
name='qty[]'
|
||||
value={props.row.original.product_warehouse.quantity}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
className={{
|
||||
tableWrapperClassName: 'overflow-x-auto min-h-full!',
|
||||
tableClassName: 'font-inter w-full table-auto min-h-full!',
|
||||
headerRowClassName: 'border-b border-b-gray-200',
|
||||
headerColumnClassName:
|
||||
'px-2 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
|
||||
bodyRowClassName: 'border-b border-b-gray-200',
|
||||
bodyColumnClassName:
|
||||
'px-2 py-2 last:flex last:flex-row last:justify-end',
|
||||
paginationClassName: 'hidden',
|
||||
}}
|
||||
emptyContent={
|
||||
<div className='w-full p-5 text-center'>
|
||||
<span className='text-lg opacity-50'>
|
||||
Isi persediaan DOC untuk kandang belum tersedia...
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
errorMessage={
|
||||
formik.values.quantity == 0
|
||||
? 'Masukan Persediaan Day Old Chick terlebih dahulu.'
|
||||
: formik.errors.quantity
|
||||
}
|
||||
readOnly
|
||||
/>
|
||||
<TextArea
|
||||
required
|
||||
label='Catatan'
|
||||
name='note'
|
||||
placeholder='Masukan catatan chickin'
|
||||
value={formik.values.note}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
isError={formik.touched.note && Boolean(formik.errors.note)}
|
||||
errorMessage={formik.errors.note}
|
||||
/>
|
||||
{initialValues?.project_flock_kandang?.id == undefined && (
|
||||
<p className='text-error'>Project Flock Kandang tidak ditemukan.</p>
|
||||
)}
|
||||
{chickinFormErrorMessage && (
|
||||
<div
|
||||
role='alert'
|
||||
className='alert alert-error'
|
||||
onClick={() => {
|
||||
setChickinFormErrorMessage('');
|
||||
}}
|
||||
>
|
||||
<Icon icon='mdi:times' />
|
||||
<span>{chickinFormErrorMessage}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className='flex justify-center mt-auto gap-2'>
|
||||
<Button color='warning' type='reset'>
|
||||
Reset
|
||||
</Button>
|
||||
<Button
|
||||
type='submit'
|
||||
isLoading={formik.isSubmitting}
|
||||
disabled={
|
||||
!formik.isValid ||
|
||||
formik.isSubmitting ||
|
||||
!initialValues?.project_flock_kandang?.id
|
||||
}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
</Card>
|
||||
<div className='flex flex-row justify-center gap-3'>
|
||||
<Button type='reset' color='warning'>
|
||||
Reset
|
||||
</Button>
|
||||
<Button type='submit' color='primary'>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChickinForm;
|
||||
export default ChickinFormKandang;
|
||||
|
||||
Reference in New Issue
Block a user