mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 15:25:46 +00:00
Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/hotfix/restu
This commit is contained in:
@@ -0,0 +1,174 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { ChangeEventHandler, useEffect, useState } from 'react';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { Icon } from '@iconify/react';
|
||||||
|
import Table from '@/components/Table';
|
||||||
|
import Card from '@/components/Card';
|
||||||
|
import Collapse from '@/components/Collapse';
|
||||||
|
|
||||||
|
import { cn, formatNumber } from '@/lib/helper';
|
||||||
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
|
import { ClosingApi } from '@/services/api/closing';
|
||||||
|
import { ClosingIncomingSapronakSummary } from '@/types/api/closing';
|
||||||
|
|
||||||
|
interface ClosingIncomingSapronaksSummaryTableProps {
|
||||||
|
projectFlockId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClosingIncomingSapronaksSummaryTable = ({
|
||||||
|
projectFlockId,
|
||||||
|
}: ClosingIncomingSapronaksSummaryTableProps) => {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const kandangId = searchParams.get('kandangId');
|
||||||
|
|
||||||
|
const {
|
||||||
|
state: tableFilterState,
|
||||||
|
updateFilter,
|
||||||
|
setPage,
|
||||||
|
setPageSize,
|
||||||
|
toQueryString: getTableFilterQueryString,
|
||||||
|
} = useTableFilter({
|
||||||
|
initial: {
|
||||||
|
search: '',
|
||||||
|
nameSort: '',
|
||||||
|
},
|
||||||
|
paramMap: {
|
||||||
|
page: 'page',
|
||||||
|
pageSize: 'limit',
|
||||||
|
nameSort: 'sort_name',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: incomingSapronakSummaries,
|
||||||
|
isLoading: isLoadingIncomingSapronakSummaries,
|
||||||
|
} = useSWR(
|
||||||
|
`${ClosingApi.basePath}/${projectFlockId}/sapronak/summary${getTableFilterQueryString()}&type=incoming&kandang_id=${kandangId ? `${kandangId}` : ''}`,
|
||||||
|
ClosingApi.getAllIncomingSapronakSummaryFetcher,
|
||||||
|
{
|
||||||
|
keepPreviousData: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(true);
|
||||||
|
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||||
|
|
||||||
|
const incomingSapronaksColumns: ColumnDef<ClosingIncomingSapronakSummary>[] =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
header: '#',
|
||||||
|
cell: (props) => props.row.index + 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'category',
|
||||||
|
header: 'Kategori',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'total_qty',
|
||||||
|
header: 'Total Kuantitas',
|
||||||
|
cell: (props) =>
|
||||||
|
`${formatNumber(props.row.original.total_qty)} ${props.row.original.uom.name}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
updateFilter('search', e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// track sorting
|
||||||
|
useEffect(() => {
|
||||||
|
const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
|
||||||
|
|
||||||
|
if (!isNameSorted) {
|
||||||
|
updateFilter('nameSort', '');
|
||||||
|
} else {
|
||||||
|
updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
|
||||||
|
}
|
||||||
|
}, [sorting, updateFilter]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) {
|
||||||
|
setOpen(
|
||||||
|
isResponseSuccess(incomingSapronakSummaries)
|
||||||
|
? incomingSapronakSummaries.data.length > 0
|
||||||
|
: false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [incomingSapronakSummaries, isResponseSuccess]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full',
|
||||||
|
body: 'p-4 shadow',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Collapse
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
title={
|
||||||
|
<div className='card-actions p-4 justify-between items-center w-full'>
|
||||||
|
<div className='card-title'>Ringkasan Sapronak Masuk</div>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
icon='material-symbols:keyboard-arrow-down'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
className={cn('text-primary transition-transform', {
|
||||||
|
'-rotate-180': open,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
className='w-full!'
|
||||||
|
titleClassName='w-full p-0!'
|
||||||
|
>
|
||||||
|
<div className='w-full p-0'>
|
||||||
|
<Table<ClosingIncomingSapronakSummary>
|
||||||
|
data={
|
||||||
|
isResponseSuccess(incomingSapronakSummaries)
|
||||||
|
? incomingSapronakSummaries?.data
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
columns={incomingSapronaksColumns}
|
||||||
|
pageSize={tableFilterState.pageSize}
|
||||||
|
onPageSizeChange={setPageSize}
|
||||||
|
rowOptions={[10, 20, 50, 100]}
|
||||||
|
page={
|
||||||
|
isResponseSuccess(incomingSapronakSummaries)
|
||||||
|
? incomingSapronakSummaries?.meta?.page
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
totalItems={
|
||||||
|
isResponseSuccess(incomingSapronakSummaries)
|
||||||
|
? incomingSapronakSummaries?.meta?.total_results
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
onPageChange={setPage}
|
||||||
|
isLoading={isLoadingIncomingSapronakSummaries}
|
||||||
|
sorting={sorting}
|
||||||
|
setSorting={setSorting}
|
||||||
|
rowSelection={rowSelection}
|
||||||
|
setRowSelection={setRowSelection}
|
||||||
|
className={{
|
||||||
|
containerClassName: cn({
|
||||||
|
'w-full mb-20':
|
||||||
|
isResponseSuccess(incomingSapronakSummaries) &&
|
||||||
|
incomingSapronakSummaries?.data?.length === 0,
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClosingIncomingSapronaksSummaryTable;
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { ChangeEventHandler, useEffect, useState } from 'react';
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
import useSWR from 'swr';
|
||||||
|
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { Icon } from '@iconify/react';
|
||||||
|
import Table from '@/components/Table';
|
||||||
|
import Card from '@/components/Card';
|
||||||
|
import Collapse from '@/components/Collapse';
|
||||||
|
|
||||||
|
import { cn, formatNumber } from '@/lib/helper';
|
||||||
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
|
import { ClosingApi } from '@/services/api/closing';
|
||||||
|
import { ClosingOutgoingSapronakSummary } from '@/types/api/closing';
|
||||||
|
|
||||||
|
interface ClosingOutgoingSapronaksSummaryTableProps {
|
||||||
|
projectFlockId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClosingOutgoingSapronaksSummaryTable = ({
|
||||||
|
projectFlockId,
|
||||||
|
}: ClosingOutgoingSapronaksSummaryTableProps) => {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const kandangId = searchParams.get('kandangId');
|
||||||
|
|
||||||
|
const {
|
||||||
|
state: tableFilterState,
|
||||||
|
updateFilter,
|
||||||
|
setPage,
|
||||||
|
setPageSize,
|
||||||
|
toQueryString: getTableFilterQueryString,
|
||||||
|
} = useTableFilter({
|
||||||
|
initial: {
|
||||||
|
search: '',
|
||||||
|
nameSort: '',
|
||||||
|
},
|
||||||
|
paramMap: {
|
||||||
|
page: 'page',
|
||||||
|
pageSize: 'limit',
|
||||||
|
nameSort: 'sort_name',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: outgoingSapronakSummaries,
|
||||||
|
isLoading: isLoadingOutgoingSapronakSummaries,
|
||||||
|
} = useSWR(
|
||||||
|
`${ClosingApi.basePath}/${projectFlockId}/sapronak/summary${getTableFilterQueryString()}&type=outgoing&kandang_id=${kandangId ? `${kandangId}` : ''}`,
|
||||||
|
ClosingApi.getAllIncomingSapronakSummaryFetcher,
|
||||||
|
{
|
||||||
|
keepPreviousData: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(true);
|
||||||
|
|
||||||
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||||
|
|
||||||
|
const outgoingSapronaksColumns: ColumnDef<ClosingOutgoingSapronakSummary>[] =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
header: '#',
|
||||||
|
cell: (props) => props.row.index + 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'category',
|
||||||
|
header: 'Kategori',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'total_qty',
|
||||||
|
header: 'Total Kuantitas',
|
||||||
|
cell: (props) =>
|
||||||
|
`${formatNumber(props.row.original.total_qty)} ${props.row.original.uom.name}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
updateFilter('search', e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// track sorting
|
||||||
|
useEffect(() => {
|
||||||
|
const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
|
||||||
|
|
||||||
|
if (!isNameSorted) {
|
||||||
|
updateFilter('nameSort', '');
|
||||||
|
} else {
|
||||||
|
updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
|
||||||
|
}
|
||||||
|
}, [sorting, updateFilter]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) {
|
||||||
|
setOpen(
|
||||||
|
isResponseSuccess(outgoingSapronakSummaries)
|
||||||
|
? outgoingSapronakSummaries.data.length > 0
|
||||||
|
: false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [outgoingSapronakSummaries, isResponseSuccess]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full',
|
||||||
|
body: 'p-4 shadow',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Collapse
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
title={
|
||||||
|
<div className='card-actions p-4 justify-between items-center w-full'>
|
||||||
|
<div className='card-title'>Ringkasan Sapronak Keluar</div>
|
||||||
|
|
||||||
|
<Icon
|
||||||
|
icon='material-symbols:keyboard-arrow-down'
|
||||||
|
width={24}
|
||||||
|
height={24}
|
||||||
|
className={cn('text-primary transition-transform', {
|
||||||
|
'-rotate-180': open,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
className='w-full!'
|
||||||
|
titleClassName='w-full p-0!'
|
||||||
|
>
|
||||||
|
<div className='w-full p-0'>
|
||||||
|
<Table<ClosingOutgoingSapronakSummary>
|
||||||
|
data={
|
||||||
|
isResponseSuccess(outgoingSapronakSummaries)
|
||||||
|
? outgoingSapronakSummaries?.data
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
columns={outgoingSapronaksColumns}
|
||||||
|
pageSize={tableFilterState.pageSize}
|
||||||
|
onPageSizeChange={setPageSize}
|
||||||
|
rowOptions={[10, 20, 50, 100]}
|
||||||
|
page={
|
||||||
|
isResponseSuccess(outgoingSapronakSummaries)
|
||||||
|
? outgoingSapronakSummaries?.meta?.page
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
totalItems={
|
||||||
|
isResponseSuccess(outgoingSapronakSummaries)
|
||||||
|
? outgoingSapronakSummaries?.meta?.total_results
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
onPageChange={setPage}
|
||||||
|
isLoading={isLoadingOutgoingSapronakSummaries}
|
||||||
|
sorting={sorting}
|
||||||
|
setSorting={setSorting}
|
||||||
|
rowSelection={rowSelection}
|
||||||
|
setRowSelection={setRowSelection}
|
||||||
|
className={{
|
||||||
|
containerClassName: cn({
|
||||||
|
'w-full mb-20':
|
||||||
|
isResponseSuccess(outgoingSapronakSummaries) &&
|
||||||
|
outgoingSapronakSummaries?.data?.length === 0,
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClosingOutgoingSapronaksSummaryTable;
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import ClosingIncomingSapronaksTable from '@/components/pages/closing/ClosingIncomingSapronaksTable';
|
import ClosingIncomingSapronaksTable from '@/components/pages/closing/ClosingIncomingSapronaksTable';
|
||||||
import ClosingOutgoingSapronaksTable from '@/components/pages/closing/ClosingOutgoingSapronaksTable';
|
import ClosingOutgoingSapronaksTable from '@/components/pages/closing/ClosingOutgoingSapronaksTable';
|
||||||
|
import ClosingIncomingSapronaksSummaryTable from '@/components/pages/closing/ClosingIncomingSapronaksSummaryTable';
|
||||||
|
import ClosingOutgoingSapronaksSummaryTable from './ClosingOutgoingSapronaksSummaryTable';
|
||||||
|
|
||||||
interface ClosingSapronakTableProps {
|
interface ClosingSapronakTableProps {
|
||||||
projectFlockId?: number;
|
projectFlockId?: number;
|
||||||
@@ -16,7 +18,15 @@ const ClosingSapronakTabContent = ({
|
|||||||
<>
|
<>
|
||||||
<ClosingIncomingSapronaksTable projectFlockId={projectFlockId} />
|
<ClosingIncomingSapronaksTable projectFlockId={projectFlockId} />
|
||||||
|
|
||||||
|
<ClosingIncomingSapronaksSummaryTable
|
||||||
|
projectFlockId={projectFlockId}
|
||||||
|
/>
|
||||||
|
|
||||||
<ClosingOutgoingSapronaksTable projectFlockId={projectFlockId} />
|
<ClosingOutgoingSapronaksTable projectFlockId={projectFlockId} />
|
||||||
|
|
||||||
|
<ClosingOutgoingSapronaksSummaryTable
|
||||||
|
projectFlockId={projectFlockId}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ import {
|
|||||||
GROWING_RECORDING_APPROVAL_LINE,
|
GROWING_RECORDING_APPROVAL_LINE,
|
||||||
LAYING_RECORDING_APPROVAL_LINE,
|
LAYING_RECORDING_APPROVAL_LINE,
|
||||||
} from '@/config/approval-line';
|
} from '@/config/approval-line';
|
||||||
|
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
||||||
|
|
||||||
interface RecordingFormProps {
|
interface RecordingFormProps {
|
||||||
type?: 'add' | 'edit' | 'detail';
|
type?: 'add' | 'edit' | 'detail';
|
||||||
@@ -227,7 +228,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const [, setApprovalNotes] = useState('');
|
const [, setApprovalNotes] = useState('');
|
||||||
const [recordingFormErrorMessage, setRecordingFormErrorMessage] =
|
const [recordingFormErrorMessage, setRecordingFormErrorMessage] =
|
||||||
useState('');
|
useState('');
|
||||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
const [, setNewRecordingData] = useState<Recording | null>(null);
|
const [, setNewRecordingData] = useState<Recording | null>(null);
|
||||||
const [nextDayRecording, setNextDayRecording] =
|
const [nextDayRecording, setNextDayRecording] =
|
||||||
@@ -905,10 +905,58 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
baseValues = getRecordingGrowingFormInitialValues(initialValues);
|
baseValues = getRecordingGrowingFormInitialValues(initialValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'add') {
|
||||||
|
baseValues.location = selectedLocation
|
||||||
|
? {
|
||||||
|
value: Number(selectedLocation.value),
|
||||||
|
label: selectedLocation.label,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
baseValues.location_id = selectedLocation
|
||||||
|
? Number(selectedLocation.value)
|
||||||
|
: 0;
|
||||||
|
baseValues.project_flock = selectedProjectFlock
|
||||||
|
? {
|
||||||
|
value: Number(selectedProjectFlock.value),
|
||||||
|
label: selectedProjectFlock.label,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
baseValues.project_flock_id = selectedProjectFlock
|
||||||
|
? Number(selectedProjectFlock.value)
|
||||||
|
: 0;
|
||||||
|
baseValues.kandang = selectedKandang
|
||||||
|
? {
|
||||||
|
value: Number(selectedKandang.value),
|
||||||
|
label: selectedKandang.label,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
baseValues.kandang_id = selectedKandang
|
||||||
|
? Number(selectedKandang.value)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) {
|
if (projectFlockKandangDetail && (type === 'edit' || type === 'detail')) {
|
||||||
baseValues.project_flock_kandang = {
|
baseValues = {
|
||||||
value: projectFlockKandangDetail.project_flock.id,
|
...baseValues,
|
||||||
label: projectFlockKandangDetail.project_flock.flock_name || '',
|
project_flock_kandang: {
|
||||||
|
value: projectFlockKandangDetail.project_flock?.id,
|
||||||
|
label: projectFlockKandangDetail.project_flock?.flock_name || '',
|
||||||
|
},
|
||||||
|
project_flock: {
|
||||||
|
value: projectFlockKandangDetail.project_flock?.id,
|
||||||
|
label: projectFlockKandangDetail.project_flock?.flock_name || '',
|
||||||
|
},
|
||||||
|
project_flock_id: projectFlockKandangDetail.project_flock?.id,
|
||||||
|
location: {
|
||||||
|
value: projectFlockKandangDetail.project_flock?.location?.id,
|
||||||
|
label: projectFlockKandangDetail.project_flock?.location?.name || '',
|
||||||
|
},
|
||||||
|
location_id: projectFlockKandangDetail.project_flock?.location?.id,
|
||||||
|
kandang: {
|
||||||
|
value: projectFlockKandangDetail.kandang?.id,
|
||||||
|
label: projectFlockKandangDetail.kandang?.name || '',
|
||||||
|
},
|
||||||
|
kandang_id: projectFlockKandangDetail.kandang?.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -995,22 +1043,6 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleValidateForm = async () => {
|
|
||||||
const errors = await formik.validateForm();
|
|
||||||
|
|
||||||
if (Object.keys(errors).length > 0) {
|
|
||||||
const errorMessages = getUniqueFormikErrors(errors);
|
|
||||||
setFormErrorList(errorMessages);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
|
||||||
e.preventDefault();
|
|
||||||
handleValidateForm();
|
|
||||||
formik.handleSubmit(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ===== HELPER FUNCTIONS =====
|
// ===== HELPER FUNCTIONS =====
|
||||||
const getAvailableStock = useCallback(
|
const getAvailableStock = useCallback(
|
||||||
(productWarehouseId: number) => {
|
(productWarehouseId: number) => {
|
||||||
@@ -1266,6 +1298,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
[formik, duplicateErrorShown]
|
[formik, duplicateErrorShown]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { formErrorList, handleFormSubmit, close } = useFormikErrorList(formik);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (projectFlockKandangLookup?.project_flock_kandang_id) {
|
if (projectFlockKandangLookup?.project_flock_kandang_id) {
|
||||||
const projectFlockKandangId =
|
const projectFlockKandangId =
|
||||||
@@ -1655,12 +1689,15 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
{/* Error List Alert */}
|
{/* Error List Alert */}
|
||||||
{formErrorList.length > 0 && (
|
{formErrorList.length > 0 && (
|
||||||
<AlertErrorList
|
<AlertErrorList formErrorList={formErrorList} onClose={close} />
|
||||||
formErrorList={formErrorList}
|
|
||||||
onClose={() => setFormErrorList([])}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className='text-xs text-error'>
|
||||||
|
{JSON.stringify(formik.errors)}
|
||||||
|
</div>
|
||||||
|
<div className='text-xs text-success'>
|
||||||
|
{JSON.stringify(formik.values)}
|
||||||
|
</div>
|
||||||
{/* Basic Info Card */}
|
{/* Basic Info Card */}
|
||||||
{(type === 'add' || type === 'edit') && (
|
{(type === 'add' || type === 'edit') && (
|
||||||
<Card
|
<Card
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import {
|
|||||||
ClosingSapronakCalculation,
|
ClosingSapronakCalculation,
|
||||||
ClosingProductionData,
|
ClosingProductionData,
|
||||||
ClosingHppExpedition,
|
ClosingHppExpedition,
|
||||||
|
ClosingIncomingSapronakSummary,
|
||||||
|
ClosingOutgoingSapronakSummary,
|
||||||
} from '@/types/api/closing';
|
} from '@/types/api/closing';
|
||||||
import { BaseApiResponse } from '@/types/api/api-general';
|
import { BaseApiResponse } from '@/types/api/api-general';
|
||||||
import { httpClient, httpClientFetcher } from '@/services/http/client';
|
import { httpClient, httpClientFetcher } from '@/services/http/client';
|
||||||
@@ -62,6 +64,14 @@ export class ClosingApiService extends BaseApiService<Closing, null, null> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAllIncomingSapronakSummaryFetcher(
|
||||||
|
endpoint: string
|
||||||
|
): Promise<BaseApiResponse<ClosingIncomingSapronakSummary[]>> {
|
||||||
|
return await httpClientFetcher<
|
||||||
|
BaseApiResponse<ClosingIncomingSapronakSummary[]>
|
||||||
|
>(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
async getAllOutgoingSapronakFetcher(
|
async getAllOutgoingSapronakFetcher(
|
||||||
endpoint: string
|
endpoint: string
|
||||||
): Promise<BaseApiResponse<ClosingOutgoingSapronak[]>> {
|
): Promise<BaseApiResponse<ClosingOutgoingSapronak[]>> {
|
||||||
@@ -70,6 +80,14 @@ export class ClosingApiService extends BaseApiService<Closing, null, null> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAllOutgoingSapronakSummaryFetcher(
|
||||||
|
endpoint: string
|
||||||
|
): Promise<BaseApiResponse<ClosingOutgoingSapronakSummary[]>> {
|
||||||
|
return await httpClientFetcher<
|
||||||
|
BaseApiResponse<ClosingOutgoingSapronakSummary[]>
|
||||||
|
>(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
async getGeneralInfo(
|
async getGeneralInfo(
|
||||||
id: number
|
id: number
|
||||||
): Promise<BaseApiResponse<ClosingGeneralInformation> | undefined> {
|
): Promise<BaseApiResponse<ClosingGeneralInformation> | undefined> {
|
||||||
|
|||||||
Vendored
+9
@@ -11,6 +11,7 @@ import { Product } from '@type/api/master-data/product';
|
|||||||
import { Customer } from '@type/api/master-data/customer';
|
import { Customer } from '@type/api/master-data/customer';
|
||||||
import { BaseMetadata } from '@/types/api/api-general';
|
import { BaseMetadata } from '@/types/api/api-general';
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
|
import { BaseUom } from '@/types/api/master-data/uom';
|
||||||
|
|
||||||
export type BaseSales = {
|
export type BaseSales = {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -104,8 +105,16 @@ export type ClosingIncomingSapronak = {
|
|||||||
notes: string;
|
notes: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ClosingIncomingSapronakSummary = {
|
||||||
|
category: string;
|
||||||
|
total_qty: number;
|
||||||
|
uom: BaseUom;
|
||||||
|
};
|
||||||
|
|
||||||
export type ClosingOutgoingSapronak = ClosingIncomingSapronak;
|
export type ClosingOutgoingSapronak = ClosingIncomingSapronak;
|
||||||
|
|
||||||
|
export type ClosingOutgoingSapronakSummary = ClosingIncomingSapronakSummary;
|
||||||
|
|
||||||
export type ClosingProductionData = {
|
export type ClosingProductionData = {
|
||||||
purchase: {
|
purchase: {
|
||||||
initial_population: number;
|
initial_population: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user