mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
440 lines
17 KiB
TypeScript
440 lines
17 KiB
TypeScript
import Badge from '@/components/Badge';
|
|
import Button from '@/components/Button';
|
|
import Card from '@/components/Card';
|
|
import { RadioGroup, RadioGroupItem } from '@/components/input/RadioInput';
|
|
import Tooltip from '@/components/Tooltip';
|
|
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
|
import {
|
|
formatCurrency,
|
|
formatDate,
|
|
formatNumber,
|
|
formatTitleCase,
|
|
} from '@/lib/helper';
|
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
|
import { Icon } from '@iconify/react';
|
|
import Link from 'next/link';
|
|
import { useRouter } from 'next/navigation';
|
|
import { useState } from 'react';
|
|
import { useModal } from '@/components/Modal';
|
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
|
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
|
import toast from 'react-hot-toast';
|
|
import ApprovalSteps, {
|
|
useApprovalSteps,
|
|
} from '@/components/pages/ApprovalSteps';
|
|
import { PROJECT_FLOCK_APPROVAL_LINE } from '@/config/approval-line';
|
|
|
|
const ProjectFlockDetail = ({
|
|
projectFlock,
|
|
}: {
|
|
projectFlock: ProjectFlock;
|
|
}) => {
|
|
const router = useRouter();
|
|
const deleteModal = useModal();
|
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
|
const [openBudgets, setOpenBudget] = useState(false);
|
|
const [selectedKandangId, setSelectedKamdangId] = useState<string | null>(
|
|
null
|
|
);
|
|
|
|
const selectedKandang = projectFlock.kandangs.find(
|
|
(kandang) => kandang.id === Number(selectedKandangId)
|
|
);
|
|
|
|
const {
|
|
approvals,
|
|
isLoading: approvalsLoading,
|
|
refresh: refreshApprovals,
|
|
} = useApprovalSteps({
|
|
latestApproval: projectFlock?.approval,
|
|
approvalLines: PROJECT_FLOCK_APPROVAL_LINE,
|
|
moduleName: 'PROJECT_FLOCKS',
|
|
moduleId: projectFlock?.id.toString() ?? '',
|
|
});
|
|
|
|
const confirmationModalDeleteClickHandler = async () => {
|
|
setIsDeleteLoading(true);
|
|
const deleteProjectFlockRes = await ProjectFlockApi.delete(
|
|
projectFlock?.id as number
|
|
);
|
|
|
|
if (isResponseSuccess(deleteProjectFlockRes)) {
|
|
toast.success(deleteProjectFlockRes?.message as string);
|
|
router.push('/production/project-flock');
|
|
}
|
|
if (isResponseError(deleteProjectFlockRes)) {
|
|
toast.error(deleteProjectFlockRes?.message as string);
|
|
}
|
|
setIsDeleteLoading(false);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<div className='h-full w-full flex flex-col gap-4'>
|
|
{/* Header */}
|
|
<DrawerHeader
|
|
leftIcon='mdi:close'
|
|
leftIconHref='/production/project-flock'
|
|
subtitle={`Created On ${formatDate(projectFlock.created_at, 'MMM DD, YYYY')}`}
|
|
>
|
|
<Link
|
|
href={`/production/project-flock/detail/edit?projectFlockId=${projectFlock.id}`}
|
|
className='p-0'
|
|
>
|
|
<Tooltip content='Edit' position='bottom'>
|
|
<Button variant='link' className='p-0 text-neutral'>
|
|
<Icon icon='mdi:square-edit-outline' width={20} height={20} />
|
|
</Button>
|
|
</Tooltip>
|
|
</Link>
|
|
<Button
|
|
variant='link'
|
|
className='p-0 text-error'
|
|
onClick={() => {
|
|
deleteModal.openModal();
|
|
}}
|
|
>
|
|
<Tooltip content='Hapus' position='bottom'>
|
|
<Icon icon='mdi:trash-can-outline' width={20} height={20} />
|
|
</Tooltip>
|
|
</Button>
|
|
</DrawerHeader>
|
|
|
|
{/* Informasi Umum */}
|
|
<div className='border-t-1 border-gray-300'>
|
|
<div className='p-4 flex flex-col gap-4'>
|
|
<h2 className='text-2xl font-semibold'>Informasi Umum</h2>
|
|
{/* Status Approval */}
|
|
{approvals && !approvalsLoading && (
|
|
<div className='text-sm my-3'>
|
|
<ApprovalSteps approvals={approvals} />
|
|
</div>
|
|
)}
|
|
{/* Badge Row */}
|
|
<div className='flex flex-row gap-2'>
|
|
<Badge
|
|
variant='soft'
|
|
color={
|
|
projectFlock.approval?.step_number == 1
|
|
? 'neutral'
|
|
: projectFlock.approval?.step_number == 2
|
|
? 'success'
|
|
: projectFlock.approval?.step_number >= 3
|
|
? 'error'
|
|
: undefined
|
|
}
|
|
className={{
|
|
badge: 'rounded-lg px-2',
|
|
}}
|
|
>
|
|
<Icon
|
|
icon='mdi:circle'
|
|
width={12}
|
|
height={12}
|
|
color={
|
|
projectFlock.approval?.step_number == 1
|
|
? 'neutral'
|
|
: projectFlock.approval?.step_number == 2
|
|
? 'success'
|
|
: projectFlock.approval?.step_number >= 3
|
|
? 'error'
|
|
: undefined
|
|
}
|
|
/>{' '}
|
|
{projectFlock.approval?.step_name}
|
|
</Badge>
|
|
<div className='divider divider-horizontal p-0 m-0'></div>
|
|
<Badge
|
|
color='neutral'
|
|
variant='soft'
|
|
className={{ badge: 'rounded-lg px-2' }}
|
|
>
|
|
<Icon icon='mdi:bookmark' width={12} height={12} />
|
|
{` ${formatTitleCase(projectFlock.category)}`}
|
|
</Badge>
|
|
</div>
|
|
{/* Information Grid */}
|
|
<div className='grid grid-cols-3 gap-4'>
|
|
<div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
|
|
<Icon width={14} height={14} icon='mdi:account' /> Submitted
|
|
</div>
|
|
<div className='col-span-2'>
|
|
<Badge
|
|
variant='soft'
|
|
color='neutral'
|
|
className={{
|
|
badge: 'rounded-lg px-2',
|
|
}}
|
|
>
|
|
<Icon icon='mdi:account-circle' width={14} height={14} />{' '}
|
|
{projectFlock.created_user.name}
|
|
</Badge>
|
|
</div>
|
|
|
|
{/* <div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
|
|
<Icon width={14} height={14} icon={'mdi:clock'} /> History
|
|
</div>
|
|
<div className='col-span-2'>
|
|
<Button variant='outline' className='py-1 text-sm'>
|
|
See History{' '}
|
|
<Icon
|
|
icon='mdi:arrow-top-right-thin'
|
|
width={11}
|
|
height={11}
|
|
/>
|
|
</Button>
|
|
</div> */}
|
|
|
|
{/* BARIS 1 */}
|
|
<div
|
|
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
|
|
relative
|
|
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
|
|
>
|
|
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Area
|
|
</div>
|
|
<div className='col-span-2'>{projectFlock.area.name}</div>
|
|
|
|
{/* BARIS 2 */}
|
|
<div
|
|
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
|
|
relative
|
|
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
|
|
>
|
|
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> Lokasi
|
|
</div>
|
|
<div className='col-span-2'>{projectFlock.location.name}</div>
|
|
|
|
<div
|
|
className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2
|
|
relative
|
|
before:content-[""] before:absolute before:left-[5px] before:top-[90%] before:bottom-[-100%] before:w-[1px] before:border-1 before:border-dashed before:border-gray-400'
|
|
>
|
|
<Icon width={14} height={14} icon='mdi:circle-slice-8' /> FCR
|
|
</div>
|
|
<div className='col-span-2'>{projectFlock.fcr.name}</div>
|
|
|
|
{/* BARIS 3 (Terakhir - TIDAK PERLU garis di bawahnya) */}
|
|
<div className='col-span-1 flex flex-row items-center text-gray-400 font-semibold gap-2'>
|
|
<Icon width={14} height={14} icon='mdi:circle-slice-8' />{' '}
|
|
Kategori
|
|
</div>
|
|
<div className='col-span-2'>
|
|
{formatTitleCase(projectFlock.category)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Kandang Aktif */}
|
|
<div className='border-t-1 border-gray-300'>
|
|
<div className='p-4 flex flex-col gap-4'>
|
|
<h2 className='text-2xl font-semibold'>Kandang Aktif</h2>
|
|
{/* Badge Row */}
|
|
<div className='flex flex-row gap-2'>
|
|
<Badge
|
|
variant='soft'
|
|
color={'success'}
|
|
className={{
|
|
badge: 'rounded-lg px-2',
|
|
}}
|
|
>
|
|
<Icon
|
|
icon='mdi:circle'
|
|
width={12}
|
|
height={12}
|
|
color={'success'}
|
|
/>{' '}
|
|
Kandang Aktif ({projectFlock.kandangs.length})
|
|
</Badge>
|
|
<div className='divider divider-horizontal p-0 m-0'></div>
|
|
<Badge
|
|
color='neutral'
|
|
variant='soft'
|
|
className={{ badge: 'rounded-lg px-2 cursor-pointer' }}
|
|
onClick={() => {
|
|
setOpenBudget(!openBudgets);
|
|
}}
|
|
>
|
|
{` ${formatCurrency(
|
|
(projectFlock.project_budgets ?? []).reduce(
|
|
(acc, curr) => acc + curr.price * curr.qty,
|
|
0
|
|
)
|
|
)}`}
|
|
<Icon
|
|
icon={`mdi:${openBudgets ? 'eye' : 'eye-off'}`}
|
|
width={12}
|
|
height={12}
|
|
/>
|
|
</Badge>
|
|
</div>
|
|
|
|
{/* Card List Project Budgets */}
|
|
{openBudgets &&
|
|
(projectFlock.project_budgets ?? []).map((budget) => (
|
|
<Card
|
|
key={budget.id}
|
|
variant='bordered'
|
|
className={{
|
|
wrapper: 'w-full',
|
|
body: 'p-3',
|
|
}}
|
|
>
|
|
<div className='flex flex-col gap-6'>
|
|
<div className='flex flex-row justify-between items-center'>
|
|
<div className='flex flex-row gap-2 items-center text-gray-400'>
|
|
<Icon icon={'mdi:tag'} width={14} height={14} />{' '}
|
|
<span>Jenis Produk</span>
|
|
</div>
|
|
<div className='text-end text-gray-500'>
|
|
{budget.nonstock?.name}
|
|
</div>
|
|
</div>
|
|
<div className='flex flex-row justify-between items-center'>
|
|
<div className='flex flex-row gap-2 items-center text-gray-400'>
|
|
<Icon icon={'mdi:tag'} width={14} height={14} />{' '}
|
|
<span>Nama Satuan</span>
|
|
</div>
|
|
<div className='text-end text-gray-500'>
|
|
{budget.nonstock?.uom.name}
|
|
</div>
|
|
</div>
|
|
<div className='flex flex-row justify-between items-center'>
|
|
<div className='flex flex-row gap-2 items-center text-gray-400'>
|
|
<Icon
|
|
icon={'mdi:file-multiple'}
|
|
width={14}
|
|
height={14}
|
|
/>{' '}
|
|
<span>Jumlah Pembelian</span>
|
|
</div>
|
|
<div className='text-end text-gray-500'>
|
|
{formatNumber(budget.qty)}
|
|
</div>
|
|
</div>
|
|
<div className='flex flex-row justify-between items-center'>
|
|
<div className='flex flex-row gap-2 items-center text-gray-400'>
|
|
<Icon icon={'mdi:file'} width={14} height={14} />{' '}
|
|
<span>Harga Satuan</span>
|
|
</div>
|
|
<div className='text-end text-gray-500'>
|
|
{formatCurrency(budget.price)}
|
|
</div>
|
|
</div>
|
|
<div className='flex flex-row justify-between items-center'>
|
|
<div className='flex flex-row gap-2 items-center text-gray-400'>
|
|
<Icon icon={'mdi:calculator'} width={14} height={14} />{' '}
|
|
<span>Total Harga</span>
|
|
</div>
|
|
<div className='text-end text-gray-500'>
|
|
{formatCurrency(budget.price * budget.qty)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
))}
|
|
|
|
{/* Card Kandangs */}
|
|
<Card
|
|
variant='bordered'
|
|
className={{
|
|
wrapper: 'w-full',
|
|
body: 'p-3',
|
|
}}
|
|
>
|
|
<RadioGroup
|
|
name='gender'
|
|
className={{
|
|
radioWrapper: 'grid grid-cols-1 gap-6',
|
|
}}
|
|
onChange={(e) => setSelectedKamdangId(e.target.value)}
|
|
value={selectedKandangId?.toString()}
|
|
size='md'
|
|
color='neutral'
|
|
disabled={projectFlock.approval.step_number == 1}
|
|
>
|
|
{projectFlock.kandangs.map((kandang) => (
|
|
<div
|
|
key={kandang.id}
|
|
className={`grid grid-cols-2 gap-6 cursor-pointer hover:text-gray-800`}
|
|
onClick={() =>
|
|
projectFlock.approval.step_number > 1 &&
|
|
setSelectedKamdangId(kandang.id.toString())
|
|
}
|
|
>
|
|
<RadioGroupItem
|
|
value={kandang.id.toString()}
|
|
label={kandang.name}
|
|
disabled={projectFlock.approval.step_number == 1}
|
|
/>
|
|
<div className='text-end'>
|
|
<Badge
|
|
className={{
|
|
badge: 'rounded-lg',
|
|
}}
|
|
>
|
|
Kapasitas {kandang.capacity} Ekor
|
|
</Badge>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</RadioGroup>
|
|
</Card>
|
|
<div className='grid grid-cols-4 gap-3'>
|
|
<Link
|
|
href={`/production/project-flock/chickin/add/kandang?projectFlockKandangId=${selectedKandang?.project_flock_kandang_id}&projectFlockId=${projectFlock.id}`}
|
|
className='m-0 p-0'
|
|
>
|
|
<Button
|
|
className='w-full px-2 py-1 text-sm'
|
|
variant='outline'
|
|
color='success'
|
|
disabled={
|
|
!selectedKandangId || projectFlock.approval.step_number == 1
|
|
}
|
|
>
|
|
Chickin <Icon icon='mdi:checkbox-marked-outline' />
|
|
</Button>
|
|
</Link>
|
|
<Link
|
|
href={`/production/project-flock/closing?projectFlockId=${projectFlock.id}&projectFlockKandangId=${selectedKandangId}`}
|
|
className='m-0 p-0'
|
|
>
|
|
<Button
|
|
className='w-full px-2 py-1 text-sm'
|
|
variant='outline'
|
|
color='error'
|
|
disabled={
|
|
!selectedKandangId || projectFlock.approval.step_number == 1
|
|
}
|
|
>
|
|
Close <Icon icon='mdi:checkbox-marked-circle-outline' />
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ConfirmationModal
|
|
ref={deleteModal.ref}
|
|
type='error'
|
|
text={`Apakah anda yakin ingin menghapus data Project Flock ini (${projectFlock?.flock_name} - ${projectFlock?.area?.name})?`}
|
|
secondaryButton={{
|
|
text: 'Tidak',
|
|
}}
|
|
primaryButton={{
|
|
text: 'Ya',
|
|
color: 'error',
|
|
isLoading: isDeleteLoading,
|
|
onClick: confirmationModalDeleteClickHandler,
|
|
}}
|
|
/>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ProjectFlockDetail;
|