mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-106-91-339-238): Slicing UI Chickin DOC Refactored
This commit is contained in:
@@ -1,15 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
|
||||||
|
|
||||||
export default function AddChickinKandang() {
|
|
||||||
const router = useRouter();
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
const kandangId = searchParams.get('kandangId');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Tambah Chickin untuk Kandang ID: {kandangId}</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,426 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import Badge from '@/components/Badge';
|
|
||||||
import Button from '@/components/Button';
|
|
||||||
import Card from '@/components/Card';
|
|
||||||
import SelectInput, { OptionType } from '@/components/input/SelectInput';
|
|
||||||
import Modal, { useModal } from '@/components/Modal';
|
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
|
||||||
import ChickinForm from '@/components/pages/production/chickin/form/ChickinForm';
|
|
||||||
import PillBadge from '@/components/PillBadge';
|
|
||||||
import Table from '@/components/Table';
|
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|
||||||
import { cn } from '@/lib/helper';
|
|
||||||
import { ProjectFlockApi } from '@/services/api/production';
|
|
||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
|
||||||
import { BaseApiResponse } from '@/types/api/api-general';
|
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
|
||||||
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
|
||||||
import { Icon } from '@iconify/react';
|
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { is } from 'react-day-picker/locale';
|
|
||||||
|
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
const AddChickin = () => {
|
|
||||||
const router = useRouter();
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
const projectFlockId = searchParams.get('projectFlockId');
|
|
||||||
|
|
||||||
// Tables Props
|
|
||||||
const { state: tableFilterState } = useTableFilter({
|
|
||||||
initial: { search: '' },
|
|
||||||
paramMap: { page: 'page', pageSize: 'limit' },
|
|
||||||
});
|
|
||||||
|
|
||||||
// States
|
|
||||||
const [selectedKandang, setSelectedKandang] = useState<Kandang | undefined>(
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
const [projectFlockKandang, setProjectFlockKandang] =
|
|
||||||
useState<BaseApiResponse<ProjectFlockKandang>>();
|
|
||||||
const [isLoadingProjectFlockKandang, setIsLoadingProjectFlockKandang] =
|
|
||||||
useState(false);
|
|
||||||
const [searchProjectFlock, setSearchProjectFlock] = useState('');
|
|
||||||
const [selectedProjectFlock, setSelectedProjectFlock] =
|
|
||||||
useState<OptionType | null>(null);
|
|
||||||
|
|
||||||
// Fetch Data
|
|
||||||
const { data: projectFlock, isLoading: isLoadingProjectFlock } = useSWR(
|
|
||||||
projectFlockId ?? selectedProjectFlock?.value.toString(),
|
|
||||||
(id: number) => ProjectFlockApi.getSingle(id)
|
|
||||||
);
|
|
||||||
const { data: listProjectFlock, isLoading: isLoadingListProjectFlock } =
|
|
||||||
useSWR(
|
|
||||||
`${ProjectFlockApi.basePath}?${new URLSearchParams({
|
|
||||||
search: searchProjectFlock,
|
|
||||||
}).toString()}`,
|
|
||||||
ProjectFlockApi.getAllFetcher
|
|
||||||
);
|
|
||||||
|
|
||||||
const getProjectFlockKandangUrl = `/kandangs/lookup`;
|
|
||||||
// Mapping Options
|
|
||||||
const options = isResponseSuccess(listProjectFlock)
|
|
||||||
? listProjectFlock?.data.map((projectFlock) => {
|
|
||||||
return {
|
|
||||||
value: projectFlock.id,
|
|
||||||
label: `${projectFlock?.flock?.name} - Periode ${projectFlock?.period}`,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const chickinModal = useModal();
|
|
||||||
const alertModal = useModal();
|
|
||||||
|
|
||||||
// Handle Function
|
|
||||||
const handleChickinClick = async (kandang: Kandang) => {
|
|
||||||
setIsLoadingProjectFlockKandang(true);
|
|
||||||
setSelectedKandang(kandang);
|
|
||||||
const ProjectFlockKandangRes = await ProjectFlockApi.customRequest<
|
|
||||||
BaseApiResponse<ProjectFlockKandang>,
|
|
||||||
'GET'
|
|
||||||
>(getProjectFlockKandangUrl, {
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
project_flock_id: projectFlockId ?? selectedProjectFlock?.value ?? 0,
|
|
||||||
kandang_id: kandang.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (isResponseSuccess(ProjectFlockKandangRes)) {
|
|
||||||
setProjectFlockKandang(ProjectFlockKandangRes);
|
|
||||||
setIsLoadingProjectFlockKandang(false);
|
|
||||||
if (
|
|
||||||
ProjectFlockKandangRes.data.available_quantity &&
|
|
||||||
ProjectFlockKandangRes.data.available_quantity > 0
|
|
||||||
) {
|
|
||||||
chickinModal.openModal();
|
|
||||||
} else {
|
|
||||||
alertModal.openModal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const handleAfterSubmit = () => {
|
|
||||||
chickinModal.closeModal();
|
|
||||||
router.push('/production/chickin');
|
|
||||||
};
|
|
||||||
const handleChangeProjectFlock = (val: OptionType | null) => {
|
|
||||||
setSelectedProjectFlock(val);
|
|
||||||
if (projectFlockId) {
|
|
||||||
router.push('/production/chickin/add');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<>
|
|
||||||
<section className='w-full p-4'>
|
|
||||||
<header className='flex flex-col gap-4'>
|
|
||||||
<div className='flex flex-row justify-between items-center'>
|
|
||||||
<Button
|
|
||||||
href='/production/project-flock'
|
|
||||||
variant='link'
|
|
||||||
className='w-fit p-0 text-primary'
|
|
||||||
>
|
|
||||||
<Icon icon='uil:arrow-left' width={24} height={24} />
|
|
||||||
Kembali
|
|
||||||
</Button>
|
|
||||||
<h1 className='text-2xl font-semibold text-center'>
|
|
||||||
Daftar Kandang Project Flock
|
|
||||||
</h1>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex flex-col gap-4 w-full my-4'>
|
|
||||||
<div className='max-w-full sm:max-w-1/2 md:max-w-3/5 lg:max-w-2/5'>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Ganti Project Flock'
|
|
||||||
placeholder='Pilih Project Flock'
|
|
||||||
options={options}
|
|
||||||
onInputChange={(val) => {
|
|
||||||
setSearchProjectFlock(val);
|
|
||||||
}}
|
|
||||||
isLoading={isLoadingListProjectFlock}
|
|
||||||
value={
|
|
||||||
isResponseSuccess(projectFlock)
|
|
||||||
? {
|
|
||||||
label: `${projectFlock.data?.flock?.name}`,
|
|
||||||
value: projectFlock.data?.id,
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
onChange={(val) => {
|
|
||||||
handleChangeProjectFlock(val as OptionType);
|
|
||||||
}}
|
|
||||||
isSearchable
|
|
||||||
isClearable
|
|
||||||
startAdornment={
|
|
||||||
isResponseSuccess(projectFlock) && (
|
|
||||||
<Badge
|
|
||||||
variant='soft'
|
|
||||||
color='success'
|
|
||||||
size='sm'
|
|
||||||
className={{
|
|
||||||
badge: 'whitespace-nowrap font-semibold',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Periode {projectFlock.data?.period}
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<Card
|
|
||||||
title='Informasi Flock'
|
|
||||||
className={{
|
|
||||||
wrapper: 'w-full bg-white mb-3',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Table<ProjectFlock>
|
|
||||||
emptyContent={
|
|
||||||
<div className='w-full p-5 text-center'>
|
|
||||||
{projectFlockId && isResponseError(projectFlock) ? (
|
|
||||||
<span className='text-lg opacity-50'>
|
|
||||||
{projectFlock.message}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className='text-lg opacity-50'>
|
|
||||||
Pilih project flock terlebih dahulu...
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
data={isResponseSuccess(projectFlock) ? [projectFlock.data] : []}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
header: 'Area',
|
|
||||||
accessorKey: 'area.name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Lokasi',
|
|
||||||
accessorKey: 'location.name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Nama Flock',
|
|
||||||
accessorKey: 'flock.name',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Kategori',
|
|
||||||
accessorKey: 'category',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Status',
|
|
||||||
accessorKey: 'status',
|
|
||||||
cell: (props) => {
|
|
||||||
return props.row.original.approval.step_name ? (
|
|
||||||
<PillBadge
|
|
||||||
color={(() => {
|
|
||||||
switch (
|
|
||||||
props.row.original.approval.step_name.toUpperCase()
|
|
||||||
) {
|
|
||||||
case 'AKTIF':
|
|
||||||
return 'red';
|
|
||||||
case 'PENGAJUAN':
|
|
||||||
return 'green';
|
|
||||||
default:
|
|
||||||
return 'gray';
|
|
||||||
}
|
|
||||||
})()}
|
|
||||||
content={props.row.original.approval.step_name
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/_/g, ' ')
|
|
||||||
.replace(/\b\w/g, (char) => char.toUpperCase())}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
'-'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Periode',
|
|
||||||
accessorKey: 'period',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'FCR Layer',
|
|
||||||
accessorKey: 'fcr.name',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
page={undefined}
|
|
||||||
className={{
|
|
||||||
containerClassName: cn({
|
|
||||||
'mb-20':
|
|
||||||
isResponseSuccess(projectFlock) &&
|
|
||||||
projectFlock.data?.kandangs?.length === 0,
|
|
||||||
}),
|
|
||||||
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',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
<Card
|
|
||||||
title='Daftar Chickin'
|
|
||||||
className={{
|
|
||||||
wrapper: 'w-full bg-white',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Table<Kandang>
|
|
||||||
emptyContent={
|
|
||||||
<div className='w-full p-5 text-center'>
|
|
||||||
{projectFlockId && isResponseError(projectFlock) ? (
|
|
||||||
<span className='text-lg opacity-50'>
|
|
||||||
{projectFlock.message}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className='text-lg opacity-50'>
|
|
||||||
Pilih project flock terlebih dahulu...
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
data={
|
|
||||||
isResponseSuccess(projectFlock)
|
|
||||||
? projectFlock.data?.kandangs
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
header: '#',
|
|
||||||
cell: (props) =>
|
|
||||||
tableFilterState.pageSize * (tableFilterState.page - 1) +
|
|
||||||
props.row.index +
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: () =>
|
|
||||||
isResponseSuccess(projectFlock)
|
|
||||||
? projectFlock.data.area.name
|
|
||||||
: '',
|
|
||||||
header: 'Area',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorFn: () =>
|
|
||||||
isResponseSuccess(projectFlock)
|
|
||||||
? projectFlock.data.location.name
|
|
||||||
: '',
|
|
||||||
header: 'Lokasi',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'name',
|
|
||||||
header: 'Kandang',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'capacity',
|
|
||||||
header: 'Kapasitas',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'pic.name',
|
|
||||||
header: 'Penanggung Jawab',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Aksi',
|
|
||||||
cell: (props) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
color='success'
|
|
||||||
variant='outline'
|
|
||||||
onClick={() => {
|
|
||||||
handleChickinClick(props.row.original);
|
|
||||||
}}
|
|
||||||
disabled={isLoadingProjectFlockKandang}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon='mdi:home-import-outline'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
Chickin
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
page={undefined}
|
|
||||||
className={{
|
|
||||||
containerClassName: cn({
|
|
||||||
'mb-20':
|
|
||||||
isResponseSuccess(projectFlock) &&
|
|
||||||
projectFlock.data?.kandangs?.length === 0,
|
|
||||||
}),
|
|
||||||
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',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</section>
|
|
||||||
<Modal ref={chickinModal.ref}>
|
|
||||||
<div className='flex flex-row justify-between items-center'>
|
|
||||||
<h1 className='text-xl font-semibold text-center mb-6'>
|
|
||||||
Chickin Kandang - {selectedKandang?.name}
|
|
||||||
</h1>
|
|
||||||
<Button
|
|
||||||
color='error'
|
|
||||||
variant='link'
|
|
||||||
onClick={chickinModal.closeModal}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className='text-black'
|
|
||||||
icon='uil:times'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{isResponseSuccess(projectFlockKandang) &&
|
|
||||||
isResponseSuccess(projectFlock) &&
|
|
||||||
!isLoadingProjectFlockKandang && (
|
|
||||||
<ChickinForm
|
|
||||||
initialValues={{
|
|
||||||
project_flock_kandang: projectFlockKandang.data,
|
|
||||||
created_user: projectFlock.data?.created_user,
|
|
||||||
created_at: projectFlock.data?.created_at,
|
|
||||||
updated_at: projectFlock.data?.updated_at,
|
|
||||||
approval: projectFlock.data?.approval,
|
|
||||||
}}
|
|
||||||
afterSubmit={handleAfterSubmit}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Modal>
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={alertModal.ref}
|
|
||||||
type='info'
|
|
||||||
text={`Persediaan Day Old Chick pada kandang (${selectedKandang?.name}) belum ada, mohon isi terlebih dahulu di bagian Persediaan!`}
|
|
||||||
secondaryButton={undefined}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Ya',
|
|
||||||
color: 'info',
|
|
||||||
onClick: () => {
|
|
||||||
alertModal.closeModal();
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AddChickin;
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import ChickinForm from '@/components/pages/production/chickin/form/ChickinForm';
|
||||||
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
|
import { ProjectFlockKandangApi } from '@/services/api/production';
|
||||||
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
export default function AddChickinKandang() {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const projectFlockKandangId = searchParams.get('projectFlockKandangId');
|
||||||
|
const projectFlockId = searchParams.get('projectFlockId');
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const { data: projectFlockKandang, isLoading: isLoading } = useSWR(
|
||||||
|
projectFlockKandangId,
|
||||||
|
(id: number) => ProjectFlockKandangApi.getSingle(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!projectFlockKandangId) {
|
||||||
|
router.push(`/production/chickin/add?projectFlockId=${projectFlockId}`);
|
||||||
|
return (
|
||||||
|
<div className='w-full flex flex-row justify-center items-center p-4'>
|
||||||
|
<span className='loading loading-spinner loading-xl' />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLoading && !projectFlockKandang) {
|
||||||
|
router.replace('/404');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section className='w-full p-4'>
|
||||||
|
{isLoading && <span className='loading loading-spinner loading-xl' />}
|
||||||
|
{!isLoading &&
|
||||||
|
isResponseSuccess(projectFlockKandang) &&
|
||||||
|
projectFlockId && (
|
||||||
|
<ChickinForm initialValues={projectFlockKandang.data} />
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||||
|
import ProjectFlockChickinDetail from '@/components/pages/production/project-flock/chickin/ProjectFlockChickinDetail';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
|
||||||
|
const AddChickin = () => {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const projectFlockId = searchParams.get('projectFlockId');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section className='w-full p-4'>
|
||||||
|
<FormHeader
|
||||||
|
title='Daftar Kandang Project Flock'
|
||||||
|
backUrl='/production/project-flock'
|
||||||
|
/>
|
||||||
|
<ProjectFlockChickinDetail projectFlockId={Number(projectFlockId)} />
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddChickin;
|
||||||
-8
@@ -312,14 +312,6 @@ const DetailChickin = () => {
|
|||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<ChickinForm
|
|
||||||
initialValues={chickin?.data}
|
|
||||||
formType='edit'
|
|
||||||
afterSubmit={() => {
|
|
||||||
refreshChickin();
|
|
||||||
chickinModal.closeModal();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
@@ -2,15 +2,27 @@ import Button from '@/components/Button';
|
|||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
|
|
||||||
interface FormHeaderProps {
|
interface FormHeaderProps {
|
||||||
type: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
title: string;
|
title: string;
|
||||||
backUrl: string;
|
backUrl?: string;
|
||||||
|
onBackClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FormHeader = ({ type, title, backUrl }: FormHeaderProps) => {
|
export const FormHeader = ({
|
||||||
|
type,
|
||||||
|
title,
|
||||||
|
backUrl,
|
||||||
|
onBackClick,
|
||||||
|
}: FormHeaderProps) => {
|
||||||
return (
|
return (
|
||||||
<header className='flex flex-col gap-4'>
|
<header className='flex flex-col gap-4'>
|
||||||
<Button href={backUrl} variant='link' className='w-fit p-0 text-primary'>
|
<Button
|
||||||
|
type='button'
|
||||||
|
href={!onBackClick ? backUrl : undefined}
|
||||||
|
onClick={onBackClick}
|
||||||
|
variant='link'
|
||||||
|
className='w-fit p-0 text-primary'
|
||||||
|
>
|
||||||
<Icon icon='uil:arrow-left' width={24} height={24} />
|
<Icon icon='uil:arrow-left' width={24} height={24} />
|
||||||
Kembali
|
Kembali
|
||||||
</Button>
|
</Button>
|
||||||
@@ -18,6 +30,7 @@ export const FormHeader = ({ type, title, backUrl }: FormHeaderProps) => {
|
|||||||
{type === 'add' && `Tambah ${title}`}
|
{type === 'add' && `Tambah ${title}`}
|
||||||
{type === 'edit' && `Edit ${title}`}
|
{type === 'edit' && `Edit ${title}`}
|
||||||
{type === 'detail' && `Detail ${title}`}
|
{type === 'detail' && `Detail ${title}`}
|
||||||
|
{!type && title}
|
||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { TableRowSizeSelector } from '@/components/table/TableRowSizeSelector';
|
|||||||
import { TableToolbar } from '@/components/table/TableToolbar';
|
import { TableToolbar } from '@/components/table/TableToolbar';
|
||||||
import { ROWS_OPTIONS } from '@/config/constant';
|
import { ROWS_OPTIONS } from '@/config/constant';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { SalesOrder } from '@/types/api/marketing/marketing';
|
import { Marketing, MarketingProducts } from '@/types/api/marketing/marketing';
|
||||||
|
import { Customer } from '@/types/api/master-data/customer';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { CellContext } from '@tanstack/react-table';
|
import { CellContext } from '@tanstack/react-table';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
@@ -18,7 +19,7 @@ const RowsOptionsMenu = ({
|
|||||||
deleteClickHandler,
|
deleteClickHandler,
|
||||||
}: {
|
}: {
|
||||||
type: 'dropdown' | 'collapse';
|
type: 'dropdown' | 'collapse';
|
||||||
props: CellContext<SalesOrder, unknown>;
|
props: CellContext<Marketing, unknown>;
|
||||||
deleteClickHandler: () => void;
|
deleteClickHandler: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
@@ -111,7 +112,59 @@ const SalesOrderTable = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Table
|
<Table
|
||||||
data={[]}
|
data={[
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
so_number: 'SO-001',
|
||||||
|
so_date: '2024-01-01',
|
||||||
|
so_docs: 'Dokumen SO 1.pdf',
|
||||||
|
customer: {
|
||||||
|
id: 1,
|
||||||
|
name: 'Customer A',
|
||||||
|
} as Customer,
|
||||||
|
sales_person: {
|
||||||
|
id: 1,
|
||||||
|
name: 'Sales Person A',
|
||||||
|
},
|
||||||
|
notes: 'Catatan untuk SO 1',
|
||||||
|
grand_total: 1000000,
|
||||||
|
approval: {
|
||||||
|
step_name: 'Approved',
|
||||||
|
},
|
||||||
|
marketing_products: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
qty: 10,
|
||||||
|
unit_price: 100000,
|
||||||
|
avg_weigth: 1.5,
|
||||||
|
total_weight: 15,
|
||||||
|
total_price: 1000000,
|
||||||
|
product_warehouse: {
|
||||||
|
id: 1,
|
||||||
|
product: {
|
||||||
|
id: 1,
|
||||||
|
name: 'Product A',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as MarketingProducts,
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
qty: 5,
|
||||||
|
unit_price: 200000,
|
||||||
|
avg_weigth: 2.0,
|
||||||
|
total_weight: 10,
|
||||||
|
total_price: 1000000,
|
||||||
|
product_warehouse: {
|
||||||
|
id: 2,
|
||||||
|
product: {
|
||||||
|
id: 2,
|
||||||
|
name: 'Product B',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as MarketingProducts,
|
||||||
|
],
|
||||||
|
} as Marketing,
|
||||||
|
]}
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
header: '#',
|
header: '#',
|
||||||
@@ -122,7 +175,7 @@ const SalesOrderTable = () => {
|
|||||||
header: 'No. Order',
|
header: 'No. Order',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'tanggal',
|
accessorKey: 'so_date',
|
||||||
header: 'Tanggal',
|
header: 'Tanggal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -130,7 +183,7 @@ const SalesOrderTable = () => {
|
|||||||
header: 'Status',
|
header: 'Status',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'customer',
|
accessorKey: 'customer.name',
|
||||||
header: 'Customer',
|
header: 'Customer',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -138,8 +191,18 @@ const SalesOrderTable = () => {
|
|||||||
header: 'Grand Total',
|
header: 'Grand Total',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'product_details',
|
accessorKey: 'marketing_products.length',
|
||||||
header: 'Product Details',
|
header: 'Product Details',
|
||||||
|
cell: (props) => (
|
||||||
|
<ul className='list-disc list-inside'>
|
||||||
|
{props.row.original.marketing_products?.map((product) => (
|
||||||
|
<li key={product.id}>
|
||||||
|
{product.product_warehouse.product.name} - Qty:{' '}
|
||||||
|
{product.qty}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Aksi',
|
header: 'Aksi',
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ const ChickinTable = () => {
|
|||||||
<div className='flex flex-col gap-2 mb-4'>
|
<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'>
|
<div className='w-full flex flex-col sm:flex-row justify-between items-end sm:items-center gap-2'>
|
||||||
<Button
|
<Button
|
||||||
href='/production/chickin/add?projectFlockId=1'
|
href='/production/project-flock/chickin/add?projectFlockId=1'
|
||||||
variant='outline'
|
variant='outline'
|
||||||
color='primary'
|
color='primary'
|
||||||
className='w-full sm:w-fit'
|
className='w-full sm:w-fit'
|
||||||
@@ -260,14 +260,14 @@ const ChickinTable = () => {
|
|||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<ChickinForm
|
{/* <ChickinForm
|
||||||
initialValues={selectedChickin}
|
initialValues={selectedChickin}
|
||||||
formType='edit'
|
formType='edit'
|
||||||
afterSubmit={() => {
|
afterSubmit={() => {
|
||||||
refreshChickins();
|
refreshChickins();
|
||||||
chickinModal.closeModal();
|
chickinModal.closeModal();
|
||||||
}}
|
}}
|
||||||
/>
|
/> */}
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -287,7 +287,7 @@ const RowOptionsMenu = ({
|
|||||||
return (
|
return (
|
||||||
<RowOptionsMenuWrapper type={type}>
|
<RowOptionsMenuWrapper type={type}>
|
||||||
<Button
|
<Button
|
||||||
href={`/production/chickin/detail?chickinId=${props.row.original.id}`}
|
href={`/production/project-flock/chickin/detail?chickinId=${props.row.original.id}`}
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='primary'
|
color='primary'
|
||||||
className='justify-start text-sm'
|
className='justify-start text-sm'
|
||||||
|
|||||||
@@ -1,13 +1,3 @@
|
|||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
|
import { Product } from '@/types/api/master-data/product';
|
||||||
export const ChickinFormSchema = Yup.object({
|
import { Supplier } from '@/types/api/master-data/supplier';
|
||||||
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;
|
|
||||||
|
|||||||
@@ -1,220 +1,227 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import {
|
import Card from '@/components/Card';
|
||||||
Chickin,
|
import { FormHeader } from '@/components/helper/form/FormHeader';
|
||||||
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 DateInput from '@/components/input/DateInput';
|
import DateInput from '@/components/input/DateInput';
|
||||||
import { isResponseError } from '@/lib/api-helper';
|
import FileInput from '@/components/input/FileInput';
|
||||||
import toast from 'react-hot-toast';
|
|
||||||
import { Icon } from '@iconify/react';
|
|
||||||
import TextArea from '@/components/input/TextArea';
|
|
||||||
import TextInput from '@/components/input/TextInput';
|
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
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 {
|
const ChickinFormKandang = ({
|
||||||
formType?: 'add' | 'detail' | 'edit';
|
|
||||||
initialValues?: Chickin;
|
|
||||||
afterSubmit?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChickinForm = ({
|
|
||||||
formType = 'add',
|
formType = 'add',
|
||||||
initialValues,
|
initialValues,
|
||||||
afterSubmit,
|
afterSubmit,
|
||||||
}: ChickinFormProps) => {
|
}: {
|
||||||
// Helper Function
|
formType?: 'add' | 'detail' | 'edit';
|
||||||
const formatDateForInput = (dateString?: string): string => {
|
initialValues: ProjectFlockKandang;
|
||||||
if (!dateString) return '';
|
afterSubmit?: () => void;
|
||||||
return new Date(dateString).toISOString().split('T')[0];
|
}) => {
|
||||||
};
|
const router = useRouter();
|
||||||
|
|
||||||
// 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]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className='flex flex-col gap-4'>
|
||||||
<form
|
<FormHeader
|
||||||
className='min-h-48 flex flex-col gap-4'
|
type='add'
|
||||||
onSubmit={formik.handleSubmit}
|
title='Chick In DOC'
|
||||||
onReset={formik.handleReset}
|
backUrl={`/production/project-flock/chickin/add?projectFlockId=${initialValues.project_flock.id}`}
|
||||||
>
|
|
||||||
<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)
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.chick_in_date}
|
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<Card
|
||||||
value={formik.values.quantity}
|
title='Informasi Kandang'
|
||||||
onChange={formik.handleChange}
|
className={{
|
||||||
onBlur={formik.handleBlur}
|
wrapper: 'w-full bg-white mt-4',
|
||||||
name='quantity'
|
|
||||||
label='Jumlah (Ekor)'
|
|
||||||
required
|
|
||||||
isError={
|
|
||||||
(formik.touched.quantity && Boolean(formik.errors.quantity)) ||
|
|
||||||
formik.values.quantity == 0
|
|
||||||
}
|
|
||||||
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' />
|
<Table<Kandang>
|
||||||
<span>{chickinFormErrorMessage}</span>
|
emptyContent={
|
||||||
|
<div className='w-full p-5 text-center'>
|
||||||
|
<span className='text-lg opacity-50'>
|
||||||
|
Informasi Kandang belum tersedia...
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
}
|
||||||
<div className='flex justify-center mt-auto gap-2'>
|
data={[initialValues.kandang]}
|
||||||
<Button color='warning' type='reset'>
|
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',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</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>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
<div className='flex flex-row justify-center gap-3'>
|
||||||
|
<Button type='reset' color='warning'>
|
||||||
Reset
|
Reset
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button type='submit' color='primary'>
|
||||||
type='submit'
|
|
||||||
isLoading={formik.isSubmitting}
|
|
||||||
disabled={
|
|
||||||
!formik.isValid ||
|
|
||||||
formik.isSubmitting ||
|
|
||||||
!initialValues?.project_flock_kandang?.id
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChickinForm;
|
export default ChickinFormKandang;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
|||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
import RowCollapseOptions from '@/components/table/RowCollapseOptions';
|
||||||
import RowDropdownOptions from '@/components/table/RowDropdownOptions';
|
import RowDropdownOptions from '@/components/table/RowDropdownOptions';
|
||||||
import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
|
|
||||||
import { ROWS_OPTIONS } from '@/config/constant';
|
import { ROWS_OPTIONS } from '@/config/constant';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
@@ -60,7 +59,7 @@ const RowOptionsMenu = ({
|
|||||||
</Button>
|
</Button>
|
||||||
{props.row.original.approval.step_name === 'Aktif' && (
|
{props.row.original.approval.step_name === 'Aktif' && (
|
||||||
<Button
|
<Button
|
||||||
href={`/production/chickin/add?projectFlockId=${props.row.original.id}`}
|
href={`/production/project-flock/chickin/add?projectFlockId=${props.row.original.id}`}
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='success'
|
color='success'
|
||||||
className='justify-start text-sm'
|
className='justify-start text-sm'
|
||||||
@@ -84,13 +83,12 @@ const RowOptionsMenu = ({
|
|||||||
onClick={deleteClickHandler}
|
onClick={deleteClickHandler}
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='error'
|
color='error'
|
||||||
className='text-error hover:text-inherit'
|
className='text-error hover:text-inherit justify-start text-sm'
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon='material-symbols:delete-outline-rounded'
|
icon='material-symbols:delete-outline-rounded'
|
||||||
width={16}
|
width={16}
|
||||||
height={16}
|
height={16}
|
||||||
className='justify-start text-sm'
|
|
||||||
/>
|
/>
|
||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
@@ -499,7 +497,7 @@ const ProjectFlockTable = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currentPageSize > 1 && (
|
{currentPageSize > 2 && (
|
||||||
<RowDropdownOptions isLast2Rows={isLast2Rows}>
|
<RowDropdownOptions isLast2Rows={isLast2Rows}>
|
||||||
<RowOptionsMenu
|
<RowOptionsMenu
|
||||||
type='dropdown'
|
type='dropdown'
|
||||||
@@ -509,7 +507,7 @@ const ProjectFlockTable = () => {
|
|||||||
</RowDropdownOptions>
|
</RowDropdownOptions>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{currentPageSize <= 1 && (
|
{currentPageSize <= 2 && (
|
||||||
<RowCollapseOptions>
|
<RowCollapseOptions>
|
||||||
<RowOptionsMenu
|
<RowOptionsMenu
|
||||||
type='collapse'
|
type='collapse'
|
||||||
@@ -576,18 +574,6 @@ const ProjectFlockTable = () => {
|
|||||||
ref={confirmModal.ref}
|
ref={confirmModal.ref}
|
||||||
type='success'
|
type='success'
|
||||||
text={`Apakah anda yakin ingin reject data transfer ke laying ini (${selectedRowIds.length} data)?`}
|
text={`Apakah anda yakin ingin reject data transfer ke laying ini (${selectedRowIds.length} data)?`}
|
||||||
// text={
|
|
||||||
// selectedFlocks.length > 0
|
|
||||||
// ? `Apakah anda yakin ingin approve Project Flock berikut? (${selectedFlocks
|
|
||||||
// .map(
|
|
||||||
// (flock) =>
|
|
||||||
// `${flock.flock?.name ?? '(Tanpa nama)'} - ${
|
|
||||||
// flock.area?.name ?? '-'
|
|
||||||
// }`
|
|
||||||
// )
|
|
||||||
// .join(', ')})`
|
|
||||||
// : 'Tidak ada Project Flock yang dipilih.'
|
|
||||||
// }
|
|
||||||
secondaryButton={{
|
secondaryButton={{
|
||||||
text: 'Tidak',
|
text: 'Tidak',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Badge from '@/components/Badge';
|
||||||
|
import Button from '@/components/Button';
|
||||||
|
import Card from '@/components/Card';
|
||||||
|
import SelectInput, { OptionType } from '@/components/input/SelectInput';
|
||||||
|
import PillBadge from '@/components/PillBadge';
|
||||||
|
import Table from '@/components/Table';
|
||||||
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
|
import { cn } from '@/lib/helper';
|
||||||
|
import { ProjectFlockApi } from '@/services/api/production';
|
||||||
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
|
import { Icon } from '@iconify/react';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
const ProjectFlockChickinDetail = ({
|
||||||
|
projectFlockId,
|
||||||
|
}: {
|
||||||
|
projectFlockId: number | undefined;
|
||||||
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// Tables Props
|
||||||
|
const { state: tableFilterState } = useTableFilter({
|
||||||
|
initial: { search: '' },
|
||||||
|
paramMap: { page: 'page', pageSize: 'limit' },
|
||||||
|
});
|
||||||
|
|
||||||
|
// States
|
||||||
|
const [searchProjectFlock, setSearchProjectFlock] = useState('');
|
||||||
|
const [selectedProjectFlock, setSelectedProjectFlock] =
|
||||||
|
useState<OptionType | null>(null);
|
||||||
|
const [projectFlock, setProjectFlock] = useState<ProjectFlock>();
|
||||||
|
|
||||||
|
// Fetch Data
|
||||||
|
const { data: listProjectFlock, isLoading: isLoadingListProjectFlock } =
|
||||||
|
useSWR(
|
||||||
|
`${ProjectFlockApi.basePath}?${new URLSearchParams({
|
||||||
|
search: searchProjectFlock,
|
||||||
|
}).toString()}`,
|
||||||
|
ProjectFlockApi.getAllFetcher
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mapping Options
|
||||||
|
const options = isResponseSuccess(listProjectFlock)
|
||||||
|
? listProjectFlock?.data.map((projectFlock) => {
|
||||||
|
return {
|
||||||
|
value: projectFlock.id,
|
||||||
|
label: `${projectFlock?.flock?.name} - Periode ${projectFlock?.period}`,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
// Handle Function
|
||||||
|
const handleChickinClick = async (kandang: Kandang) => {
|
||||||
|
router.push(
|
||||||
|
`/production/project-flock/chickin/add/kandang?projectFlockKandangId=${kandang.project_flock_kandang_id}&projectFlockId=${projectFlockId ?? selectedProjectFlock?.value}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeProjectFlock = (val: OptionType | null) => {
|
||||||
|
setSelectedProjectFlock(val);
|
||||||
|
if (isResponseSuccess(listProjectFlock) && val) {
|
||||||
|
const selected = listProjectFlock.data.find(
|
||||||
|
(pf) => pf.id === Number(val.value)
|
||||||
|
);
|
||||||
|
setProjectFlock(selected);
|
||||||
|
} else {
|
||||||
|
setProjectFlock(undefined);
|
||||||
|
}
|
||||||
|
if (projectFlockId) {
|
||||||
|
router.push('/production/project-flock/chickin/add');
|
||||||
|
}
|
||||||
|
if (!val && projectFlockId) {
|
||||||
|
router.push('/production/project-flock/chickin/add');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (projectFlockId && isResponseSuccess(listProjectFlock)) {
|
||||||
|
setProjectFlock(
|
||||||
|
listProjectFlock.data.find((pf) => pf.id === Number(projectFlockId))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [projectFlockId, listProjectFlock]);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='flex flex-col gap-4 w-full my-4'>
|
||||||
|
<div className='max-w-full sm:max-w-1/2 md:max-w-3/5 lg:max-w-2/5'>
|
||||||
|
<SelectInput
|
||||||
|
required
|
||||||
|
label='Ganti Project Flock'
|
||||||
|
placeholder='Pilih Project Flock'
|
||||||
|
options={options}
|
||||||
|
onInputChange={(val) => {
|
||||||
|
setSearchProjectFlock(val);
|
||||||
|
}}
|
||||||
|
isLoading={isLoadingListProjectFlock}
|
||||||
|
value={
|
||||||
|
projectFlock
|
||||||
|
? {
|
||||||
|
label: `${projectFlock?.flock?.name}`,
|
||||||
|
value: projectFlock?.id,
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
onChange={(val) => {
|
||||||
|
handleChangeProjectFlock(val as OptionType | null);
|
||||||
|
}}
|
||||||
|
isSearchable
|
||||||
|
isClearable
|
||||||
|
startAdornment={
|
||||||
|
projectFlock && (
|
||||||
|
<Badge
|
||||||
|
variant='soft'
|
||||||
|
color='success'
|
||||||
|
size='sm'
|
||||||
|
className={{
|
||||||
|
badge: 'whitespace-nowrap font-semibold',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Periode {projectFlock?.period}
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Card
|
||||||
|
title='Informasi Flock'
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full bg-white mb-3',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Table<ProjectFlock>
|
||||||
|
emptyContent={
|
||||||
|
<div className='w-full p-5 text-center'>
|
||||||
|
<span className='text-lg opacity-50'>
|
||||||
|
Pilih project flock terlebih dahulu...
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
data={projectFlock ? [projectFlock] : []}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
header: 'Area',
|
||||||
|
accessorKey: 'area.name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Lokasi',
|
||||||
|
accessorKey: 'location.name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Nama Flock',
|
||||||
|
accessorKey: 'flock.name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Kategori',
|
||||||
|
accessorKey: 'category',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Status',
|
||||||
|
accessorKey: 'status',
|
||||||
|
cell: (props) => {
|
||||||
|
return props.row.original.approval?.step_name ? (
|
||||||
|
<PillBadge
|
||||||
|
color={(() => {
|
||||||
|
switch (
|
||||||
|
props.row.original.approval?.step_name.toUpperCase()
|
||||||
|
) {
|
||||||
|
case 'AKTIF':
|
||||||
|
return 'red';
|
||||||
|
case 'PENGAJUAN':
|
||||||
|
return 'green';
|
||||||
|
default:
|
||||||
|
return 'gray';
|
||||||
|
}
|
||||||
|
})()}
|
||||||
|
content={props.row.original.approval?.step_name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/_/g, ' ')
|
||||||
|
.replace(/\b\w/g, (char) => char.toUpperCase())}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
'-'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Periode',
|
||||||
|
accessorKey: 'period',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'FCR Layer',
|
||||||
|
accessorKey: 'fcr.name',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
page={undefined}
|
||||||
|
className={{
|
||||||
|
containerClassName: cn({
|
||||||
|
'mb-20': projectFlock && projectFlock.kandangs?.length === 0,
|
||||||
|
}),
|
||||||
|
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',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
title='Daftar Kandang'
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full bg-white',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Table<Kandang>
|
||||||
|
emptyContent={
|
||||||
|
<div className='w-full p-5 text-center'>
|
||||||
|
<span className='text-lg opacity-50'>
|
||||||
|
Pilih project flock terlebih dahulu...
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
data={projectFlock ? projectFlock.kandangs : []}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
header: '#',
|
||||||
|
cell: (props) =>
|
||||||
|
tableFilterState.pageSize * (tableFilterState.page - 1) +
|
||||||
|
props.row.index +
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: () => (projectFlock ? projectFlock.area.name : ''),
|
||||||
|
header: 'Area',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: () =>
|
||||||
|
projectFlock ? projectFlock.location.name : '',
|
||||||
|
header: 'Lokasi',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'name',
|
||||||
|
header: 'Kandang',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'capacity',
|
||||||
|
header: 'Kapasitas',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'pic.name',
|
||||||
|
header: 'Penanggung Jawab',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: 'Aksi',
|
||||||
|
cell: (props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
color='success'
|
||||||
|
variant='outline'
|
||||||
|
onClick={() => {
|
||||||
|
handleChickinClick(props.row.original);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon='mdi:home-import-outline'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
/>
|
||||||
|
Chickin
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
page={undefined}
|
||||||
|
className={{
|
||||||
|
containerClassName: cn({
|
||||||
|
'mb-20': projectFlock && projectFlock.kandangs?.length === 0,
|
||||||
|
}),
|
||||||
|
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',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProjectFlockChickinDetail;
|
||||||
@@ -77,7 +77,7 @@ const ProjectFlockForm = ({
|
|||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
const [isApproveLoading, setIsApproveLoading] = useState(false);
|
||||||
const [isApprovedDisabled, setIsApprovedDisabled] = useState(
|
const [isApprovedDisabled, setIsApprovedDisabled] = useState(
|
||||||
initialValues?.approval.step_name == 'Pengajuan' ? false : true
|
initialValues?.approval?.step_name == 'Pengajuan' ? false : true
|
||||||
);
|
);
|
||||||
const [isRejectedDisabled, setIsRejectedDisabled] =
|
const [isRejectedDisabled, setIsRejectedDisabled] =
|
||||||
useState(!isApprovedDisabled);
|
useState(!isApprovedDisabled);
|
||||||
@@ -726,7 +726,25 @@ const ProjectFlockForm = ({
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{formType != 'add' && (
|
{formType != 'add' && (
|
||||||
<div className='w-full'>
|
<div className='flex flex-row gap-2 mb-6'>
|
||||||
|
{formType != 'edit' && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
router.push(
|
||||||
|
`/production/project-flock/detail/edit?projectFlockId=${initialValues?.id}`
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
color='warning'
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon='mdi:pencil-outline'
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
className='justify-start text-sm'
|
||||||
|
/>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (initialValues?.id) {
|
if (initialValues?.id) {
|
||||||
|
|||||||
@@ -121,6 +121,10 @@ const ProjectFlockKandangTable = ({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.capacity,
|
||||||
|
header: 'Kapasitas',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.pic?.name,
|
accessorFn: (row) => row.pic?.name,
|
||||||
header: 'Penanggung Jawab',
|
header: 'Penanggung Jawab',
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ export const MAIN_DRAWER_LINKS: MAIN_DRAWER_MENU[] = [
|
|||||||
link: '/production/project-flock',
|
link: '/production/project-flock',
|
||||||
icon: 'material-symbols:list-alt-add-outline-rounded',
|
icon: 'material-symbols:list-alt-add-outline-rounded',
|
||||||
},
|
},
|
||||||
{
|
// { // DI HILANGKAN PADA VERSI REFACTORING
|
||||||
title: 'Chick In',
|
// title: 'Chick In',
|
||||||
link: '/production/chickin',
|
// link: '/production/chickin',
|
||||||
icon: 'mdi:home-import-outline',
|
// icon: 'mdi:home-import-outline',
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
title: 'Recording',
|
title: 'Recording',
|
||||||
link: '/production/recording',
|
link: '/production/recording',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BaseApiService } from './base';
|
import { BaseApiService } from '@/services/api/base';
|
||||||
import {
|
import {
|
||||||
CreateProjectFlockPayload,
|
CreateProjectFlockPayload,
|
||||||
ProjectFlock,
|
ProjectFlock,
|
||||||
@@ -14,12 +14,18 @@ import {
|
|||||||
CreateChickinPayload,
|
CreateChickinPayload,
|
||||||
UpdateChickinPayload,
|
UpdateChickinPayload,
|
||||||
} from '@/types/api/production/chickin';
|
} from '@/types/api/production/chickin';
|
||||||
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
|
|
||||||
export const ProjectFlockApi = new BaseApiService<
|
export const ProjectFlockApi = new BaseApiService<
|
||||||
ProjectFlock,
|
ProjectFlock,
|
||||||
CreateProjectFlockPayload,
|
CreateProjectFlockPayload,
|
||||||
UpdateProjectFlockPayload
|
UpdateProjectFlockPayload
|
||||||
>('/production/project_flocks');
|
>('/production/project_flocks');
|
||||||
|
export const ProjectFlockKandangApi = new BaseApiService<
|
||||||
|
ProjectFlockKandang,
|
||||||
|
unknown,
|
||||||
|
unknown
|
||||||
|
>('/production/project-flock-kandangs');
|
||||||
export const RecordingApi = new BaseApiService<
|
export const RecordingApi = new BaseApiService<
|
||||||
Recording,
|
Recording,
|
||||||
CreateRecordingPayload,
|
CreateRecordingPayload,
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
CreateProjectFlockPayload,
|
||||||
|
ProjectFlock,
|
||||||
|
UpdateProjectFlockPayload,
|
||||||
|
} from '@/types/api/production/project-flock';
|
||||||
|
import { BaseApiService } from '../base';
|
||||||
|
import { BaseApiResponse } from '@/types/api/api-general';
|
||||||
|
import { sleep } from '@/lib/helper';
|
||||||
|
import { httpClient } from '@/services/http/client';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export class ProjectFlockService extends BaseApiService<
|
||||||
|
ProjectFlock,
|
||||||
|
CreateProjectFlockPayload,
|
||||||
|
UpdateProjectFlockPayload
|
||||||
|
> {
|
||||||
|
constructor(basePath: string = '') {
|
||||||
|
super(basePath);
|
||||||
|
}
|
||||||
|
async getSingleProjectFlockKandang(): Promise<BaseApiResponse | undefined> {
|
||||||
|
try {
|
||||||
|
} catch (error) {
|
||||||
|
if (axios.isAxiosError<BaseApiResponse>(error)) {
|
||||||
|
return error.response?.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-5
@@ -15,6 +15,9 @@ export type BaseMarketing = {
|
|||||||
so_date: string;
|
so_date: string;
|
||||||
sales_person: CreatedUser;
|
sales_person: CreatedUser;
|
||||||
notes: string;
|
notes: string;
|
||||||
|
grand_total: number;
|
||||||
|
approval: BaseApproval;
|
||||||
|
marketing_products?: MarketingProducts[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MarketingProducts = {
|
export type MarketingProducts = {
|
||||||
@@ -22,18 +25,29 @@ export type MarketingProducts = {
|
|||||||
qty: number;
|
qty: number;
|
||||||
unit_price: number;
|
unit_price: number;
|
||||||
avg_weigth: number;
|
avg_weigth: number;
|
||||||
|
total_weight: number;
|
||||||
total_price: number;
|
total_price: number;
|
||||||
product_warehouse: ProductWarehouse;
|
product_warehouse: ProductWarehouse;
|
||||||
delivery_date?: string;
|
marketing_delivery_products?: MarketingDeliveryProducts;
|
||||||
vehicle_number?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SalesOrder = BaseMetadata & BaseMarketing;
|
export type MarketingDeliveryProducts = {
|
||||||
|
id: number;
|
||||||
|
qty: number;
|
||||||
|
unit_price: number;
|
||||||
|
avg_weigth: number;
|
||||||
|
total_weight: number;
|
||||||
|
total_price: number;
|
||||||
|
delivery_date: string;
|
||||||
|
vehicle_number: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type CreateSalesOrderPayload = {
|
export type Marketing = BaseMetadata & BaseMarketing;
|
||||||
|
|
||||||
|
export type CreateMarketingPayload = {
|
||||||
customer_id: number;
|
customer_id: number;
|
||||||
date: string;
|
date: string;
|
||||||
notes: string;
|
notes: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UpdateSalesOrderPayload = CreateSalesOrderPayload;
|
export type UpdateMarketingPayload = CreateMarketingPayload;
|
||||||
|
|||||||
+1
@@ -9,6 +9,7 @@ export type BaseKandang = {
|
|||||||
location: BaseLocation;
|
location: BaseLocation;
|
||||||
capacity: number;
|
capacity: number;
|
||||||
pic: BaseUser;
|
pic: BaseUser;
|
||||||
|
project_flock_kandang_id?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Kandang = BaseMetadata & BaseKandang;
|
export type Kandang = BaseMetadata & BaseKandang;
|
||||||
|
|||||||
+11
-1
@@ -1,5 +1,7 @@
|
|||||||
import { Kandang } from '@/type/master-data/kandang';
|
import { Kandang } from '@/type/master-data/kandang';
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
|
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
||||||
|
import { Supplier } from '../master-data/supplier';
|
||||||
|
|
||||||
export type BaseProjectFlockKandang = {
|
export type BaseProjectFlockKandang = {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -7,7 +9,15 @@ export type BaseProjectFlockKandang = {
|
|||||||
kandang_id: number;
|
kandang_id: number;
|
||||||
kandang: Kandang;
|
kandang: Kandang;
|
||||||
project_flock: ProjectFlock;
|
project_flock: ProjectFlock;
|
||||||
available_quantity?: number;
|
available_qtys?: AvailableQty[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AvailableQty = {
|
||||||
|
chick_in_date?: string;
|
||||||
|
po_number?: string;
|
||||||
|
document_path?: string;
|
||||||
|
supplier?: Supplier;
|
||||||
|
product_warehouse: ProductWarehouse;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ProjectFlockKandang = BaseProjectFlockKandang;
|
export type ProjectFlockKandang = BaseProjectFlockKandang;
|
||||||
|
|||||||
Reference in New Issue
Block a user