mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-24 23:35:45 +00:00
refactor(FE): change project flock form, detail and chickin view using drawer
This commit is contained in:
@@ -12,8 +12,6 @@ const DetailInventoryAdjustment = () => {
|
|||||||
|
|
||||||
// Ambil data dari router state
|
// Ambil data dari router state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Router State');
|
|
||||||
console.log(window.history.state);
|
|
||||||
const state = window.history.state?.usr as
|
const state = window.history.state?.usr as
|
||||||
| { inventoryAdjustment?: InventoryAdjustment }
|
| { inventoryAdjustment?: InventoryAdjustment }
|
||||||
| undefined;
|
| undefined;
|
||||||
@@ -26,9 +24,6 @@ const DetailInventoryAdjustment = () => {
|
|||||||
|
|
||||||
const finalData = inventoryAdjustment;
|
const finalData = inventoryAdjustment;
|
||||||
|
|
||||||
console.log('Final Data');
|
|
||||||
console.log(finalData);
|
|
||||||
|
|
||||||
if (!finalData) {
|
if (!finalData) {
|
||||||
return (
|
return (
|
||||||
<div className='w-full flex flex-row justify-center items-center p-4'>
|
<div className='w-full flex flex-row justify-center items-center p-4'>
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm';
|
import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm';
|
||||||
|
import React, { useImperativeHandle } from 'react';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
const AddProjectFlock = () => {
|
const AddProjectFlock = () => {
|
||||||
|
// useImperativeHandle(ref, () => ({
|
||||||
|
// validate() {
|
||||||
|
// toast.success('Validating');
|
||||||
|
// return false;
|
||||||
|
// },
|
||||||
|
// }));
|
||||||
return (
|
return (
|
||||||
<section className='w-full p-4 flex flex-row justify-center'>
|
<section className='w-full p-4 flex flex-row justify-center'>
|
||||||
<ProjectFlockForm formType='add' />
|
<ProjectFlockForm formType='add' />
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
|
import Drawer from '@/components/Drawer';
|
||||||
|
import React, { ReactNode } from 'react';
|
||||||
|
import ProjectFlockTable from '@/components/pages/production/project-flock/ProjectFlockTable';
|
||||||
|
|
||||||
|
export default function ProjectFlockLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const isAdd = pathname.endsWith('/add');
|
||||||
|
const isEdit = pathname.includes('/detail/edit');
|
||||||
|
const isDetail = pathname.includes('/detail');
|
||||||
|
const isChickin = pathname.includes('/chickin/add/kandang');
|
||||||
|
|
||||||
|
const isOpen = isAdd || isEdit || isDetail || isChickin;
|
||||||
|
|
||||||
|
// const childRef = useRef<ProjectFlockFormRef>(null);
|
||||||
|
|
||||||
|
const handleBackdropClick = () => {
|
||||||
|
// const isValid = childRef.current?.validate(); // 🔥 trigger validation child
|
||||||
|
|
||||||
|
// if (!isValid) {
|
||||||
|
// toast.error('Form belum valid, Drawer tidak bisa close');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
router.push('/production/project-flock');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* List page always rendered */}
|
||||||
|
<div>
|
||||||
|
<ProjectFlockTable />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Render Drawer only on /add */}
|
||||||
|
<Drawer
|
||||||
|
open={isOpen}
|
||||||
|
setOpen={(v) => {
|
||||||
|
if (!v) router.push('/production/project-flock');
|
||||||
|
}}
|
||||||
|
closeOnBackdropClick={false}
|
||||||
|
onBackdropClick={handleBackdropClick}
|
||||||
|
variant='right'
|
||||||
|
sidebarContent={isOpen && <div className='p-4'>{children}</div>}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import ProjectFlockTable from '@/components/pages/production/project-flock/Proje
|
|||||||
|
|
||||||
const ProjectFlock = () => {
|
const ProjectFlock = () => {
|
||||||
return (
|
return (
|
||||||
<section className='w-full p-4'>
|
<section className='size-full p-4'>
|
||||||
<ProjectFlockTable />
|
<ProjectFlockTable />
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
+103
-8
@@ -10,28 +10,102 @@ interface DrawerProps {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: (newOpenState: boolean) => void;
|
setOpen: (newOpenState: boolean) => void;
|
||||||
openOnLarge?: boolean;
|
openOnLarge?: boolean;
|
||||||
|
variant?: 'sidebar' | 'left' | 'right';
|
||||||
|
zIndex?: string;
|
||||||
|
className?: DrawerClassName;
|
||||||
|
onBackdropClick?: () => void;
|
||||||
|
closeOnBackdropClick?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DrawerClassName = {
|
||||||
|
drawer?: string;
|
||||||
|
drawerContent?: string;
|
||||||
|
drawerSide?: string;
|
||||||
|
drawerOverlay?: string;
|
||||||
|
drawerSidebarContent?: string;
|
||||||
|
};
|
||||||
|
|
||||||
const Drawer = ({
|
const Drawer = ({
|
||||||
children,
|
children,
|
||||||
sidebarContent,
|
sidebarContent,
|
||||||
open,
|
open,
|
||||||
setOpen,
|
setOpen,
|
||||||
openOnLarge,
|
openOnLarge,
|
||||||
|
variant = 'sidebar',
|
||||||
|
zIndex = '20',
|
||||||
|
className,
|
||||||
|
onBackdropClick,
|
||||||
|
closeOnBackdropClick = true,
|
||||||
}: DrawerProps) => {
|
}: DrawerProps) => {
|
||||||
|
const getDrawerClassNames = (): DrawerClassName => {
|
||||||
|
const baseClassNames = {
|
||||||
|
drawer: 'drawer',
|
||||||
|
drawerContent: 'drawer-content',
|
||||||
|
drawerSide: 'drawer-side',
|
||||||
|
drawerOverlay: 'drawer-overlay',
|
||||||
|
drawerSidebarContent: 'min-h-full bg-base-100',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (variant === 'sidebar') {
|
||||||
|
return {
|
||||||
|
...baseClassNames,
|
||||||
|
drawerSidebarContent: cn(
|
||||||
|
baseClassNames.drawerSidebarContent,
|
||||||
|
'w-full max-w-[300px] lg:w-[300px]'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
} else if (variant === 'right') {
|
||||||
|
return {
|
||||||
|
...baseClassNames,
|
||||||
|
drawer: cn(baseClassNames.drawer, 'drawer-end'),
|
||||||
|
drawerSide: cn(
|
||||||
|
baseClassNames.drawerSide,
|
||||||
|
'border-l border-solid border-gray-200 drawer-side w-screen top-0 right-0 fixed z-21'
|
||||||
|
),
|
||||||
|
drawerSidebarContent: cn(
|
||||||
|
baseClassNames.drawerSidebarContent,
|
||||||
|
'w-full min-w-120 sm:w-fit'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
} else if (variant === 'left') {
|
||||||
|
return {
|
||||||
|
...baseClassNames,
|
||||||
|
drawerSide: cn(
|
||||||
|
baseClassNames.drawerSide,
|
||||||
|
'border-l border-solid border-gray-200 drawer-side w-screen top-0 right-0 fixed z-21'
|
||||||
|
),
|
||||||
|
drawerSidebarContent: cn(
|
||||||
|
baseClassNames.drawerSidebarContent,
|
||||||
|
'w-full min-w-120 sm:w-fit'
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return baseClassNames; // Fallback for default or unknown variant
|
||||||
|
};
|
||||||
|
|
||||||
|
const varianClassName = getDrawerClassNames();
|
||||||
|
|
||||||
const toggleDrawer = () => {
|
const toggleDrawer = () => {
|
||||||
setOpen(!open);
|
setOpen(!open);
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeDrawer = () => {
|
const closeDrawer = () => {
|
||||||
setOpen(false);
|
if (closeOnBackdropClick) {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
onBackdropClick && onBackdropClick();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn('drawer', {
|
className={cn(
|
||||||
'lg:drawer-open': openOnLarge,
|
'drawer',
|
||||||
})}
|
{
|
||||||
|
'lg:drawer-open': openOnLarge,
|
||||||
|
},
|
||||||
|
varianClassName?.drawer,
|
||||||
|
className?.drawer
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
@@ -40,16 +114,37 @@ const Drawer = ({
|
|||||||
className='drawer-toggle'
|
className='drawer-toggle'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='drawer-content'>{children}</div>
|
{/* Drawer Content */}
|
||||||
|
<div
|
||||||
|
className={cn(varianClassName?.drawerContent, className?.drawerContent)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='drawer-side border-r border-solid border-gray-200 z-20'>
|
{/* Drawer Side */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
varianClassName?.drawerSide,
|
||||||
|
className?.drawerSide,
|
||||||
|
zIndex
|
||||||
|
)}
|
||||||
|
>
|
||||||
<label
|
<label
|
||||||
aria-label='close sidebar'
|
aria-label='close sidebar'
|
||||||
className='drawer-overlay'
|
className={cn(
|
||||||
|
varianClassName?.drawerOverlay,
|
||||||
|
className?.drawerOverlay
|
||||||
|
)}
|
||||||
onClick={closeDrawer}
|
onClick={closeDrawer}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='min-h-full w-full max-w-[300px] lg:w-[300px] bg-base-100'>
|
{/* Sidebar Content */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
varianClassName?.drawerSidebarContent,
|
||||||
|
className?.drawerContent
|
||||||
|
)}
|
||||||
|
>
|
||||||
{sidebarContent}
|
{sidebarContent}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -156,8 +156,6 @@ export const recalculate = (
|
|||||||
field: string,
|
field: string,
|
||||||
values: ProductCalculationFields
|
values: ProductCalculationFields
|
||||||
) => {
|
) => {
|
||||||
console.log('Values');
|
|
||||||
console.log(values);
|
|
||||||
const { qty, unit_price, total_price, avg_weight, total_weight } = values;
|
const { qty, unit_price, total_price, avg_weight, total_weight } = values;
|
||||||
const result: Partial<ProductCalculationFields> = {};
|
const result: Partial<ProductCalculationFields> = {};
|
||||||
if (field == 'unit_price' || field == 'total_price' || field == 'qty') {
|
if (field == 'unit_price' || field == 'total_price' || field == 'qty') {
|
||||||
@@ -174,8 +172,6 @@ export const recalculate = (
|
|||||||
result.avg_weight = Number(total_weight) / Number(qty);
|
result.avg_weight = Number(total_weight) / Number(qty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('Result');
|
|
||||||
console.log(result);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
export const getSubmitField = (values: ProductCalculationFields) => {
|
export const getSubmitField = (values: ProductCalculationFields) => {
|
||||||
@@ -327,8 +323,6 @@ const MarketingForm = ({
|
|||||||
})
|
})
|
||||||
.filter((item) => Boolean(item)),
|
.filter((item) => Boolean(item)),
|
||||||
} as UpdateDeliveryOrderPayload);
|
} as UpdateDeliveryOrderPayload);
|
||||||
console.log('PAYLOAD');
|
|
||||||
console.log(payload);
|
|
||||||
switch (formType) {
|
switch (formType) {
|
||||||
case 'add':
|
case 'add':
|
||||||
await createMarketingHandler(payload as CreateSalesOrderPayload);
|
await createMarketingHandler(payload as CreateSalesOrderPayload);
|
||||||
@@ -352,7 +346,6 @@ const MarketingForm = ({
|
|||||||
// ================== FORM REPEATER HANDLER ==================
|
// ================== FORM REPEATER HANDLER ==================
|
||||||
const createMarketingHandler = async (values: CreateSalesOrderPayload) => {
|
const createMarketingHandler = async (values: CreateSalesOrderPayload) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log(values);
|
|
||||||
const createMarketingRes = await SalesOrderApi.create(values);
|
const createMarketingRes = await SalesOrderApi.create(values);
|
||||||
if (isResponseSuccess(createMarketingRes)) {
|
if (isResponseSuccess(createMarketingRes)) {
|
||||||
toast.success(createMarketingRes?.message as string);
|
toast.success(createMarketingRes?.message as string);
|
||||||
@@ -365,7 +358,6 @@ const MarketingForm = ({
|
|||||||
};
|
};
|
||||||
const updateMarketingHandler = async (values: UpdateSalesOrderPayload) => {
|
const updateMarketingHandler = async (values: UpdateSalesOrderPayload) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log(values);
|
|
||||||
const updateMarketingRes = await SalesOrderApi.update(
|
const updateMarketingRes = await SalesOrderApi.update(
|
||||||
initialValues?.id as number,
|
initialValues?.id as number,
|
||||||
values
|
values
|
||||||
@@ -381,10 +373,8 @@ const MarketingForm = ({
|
|||||||
};
|
};
|
||||||
const createDeliveryHandler = async (values: CreateDeliveryOrderPayload) => {
|
const createDeliveryHandler = async (values: CreateDeliveryOrderPayload) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log(initialValues?.id);
|
|
||||||
const createDeliveryRes = await DeliveryOrderApi.create(values);
|
const createDeliveryRes = await DeliveryOrderApi.create(values);
|
||||||
if (isResponseSuccess(createDeliveryRes)) {
|
if (isResponseSuccess(createDeliveryRes)) {
|
||||||
console.log(createDeliveryRes);
|
|
||||||
toast.success(createDeliveryRes?.message as string);
|
toast.success(createDeliveryRes?.message as string);
|
||||||
setDeliveryOrderValues(
|
setDeliveryOrderValues(
|
||||||
createDeliveryRes.data?.delivery_order?.flatMap((delivery) =>
|
createDeliveryRes.data?.delivery_order?.flatMap((delivery) =>
|
||||||
@@ -397,20 +387,17 @@ const MarketingForm = ({
|
|||||||
router.push(`/marketing/detail?marketingId=${initialValues?.id}`);
|
router.push(`/marketing/detail?marketingId=${initialValues?.id}`);
|
||||||
}
|
}
|
||||||
if (isResponseError(createDeliveryRes)) {
|
if (isResponseError(createDeliveryRes)) {
|
||||||
console.log(createDeliveryRes);
|
|
||||||
toast.error(createDeliveryRes?.message as string);
|
toast.error(createDeliveryRes?.message as string);
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
const updateDeliveryHandler = async (values: UpdateDeliveryOrderPayload) => {
|
const updateDeliveryHandler = async (values: UpdateDeliveryOrderPayload) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log(initialValues?.id);
|
|
||||||
const updateDeliveryRes = await DeliveryOrderApi.update(
|
const updateDeliveryRes = await DeliveryOrderApi.update(
|
||||||
initialValues?.id as number,
|
initialValues?.id as number,
|
||||||
values
|
values
|
||||||
);
|
);
|
||||||
if (isResponseSuccess(updateDeliveryRes)) {
|
if (isResponseSuccess(updateDeliveryRes)) {
|
||||||
console.log(updateDeliveryRes);
|
|
||||||
toast.success(updateDeliveryRes?.message as string);
|
toast.success(updateDeliveryRes?.message as string);
|
||||||
setDeliveryOrderValues(
|
setDeliveryOrderValues(
|
||||||
mergeSOwithDO(
|
mergeSOwithDO(
|
||||||
@@ -426,7 +413,6 @@ const MarketingForm = ({
|
|||||||
router.push(`/marketing/detail?marketingId=${initialValues?.id}`);
|
router.push(`/marketing/detail?marketingId=${initialValues?.id}`);
|
||||||
}
|
}
|
||||||
if (isResponseError(updateDeliveryRes)) {
|
if (isResponseError(updateDeliveryRes)) {
|
||||||
console.log(updateDeliveryRes);
|
|
||||||
toast.error(updateDeliveryRes?.message as string);
|
toast.error(updateDeliveryRes?.message as string);
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -435,16 +421,13 @@ const MarketingForm = ({
|
|||||||
// ================== MARKETING HANDLER ==================
|
// ================== MARKETING HANDLER ==================
|
||||||
const deleteMarketingHandler = async () => {
|
const deleteMarketingHandler = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log(initialValues?.id);
|
|
||||||
const deleteMarketingRes = await MarketingApi.delete(
|
const deleteMarketingRes = await MarketingApi.delete(
|
||||||
initialValues?.id as number
|
initialValues?.id as number
|
||||||
);
|
);
|
||||||
if (isResponseSuccess(deleteMarketingRes)) {
|
if (isResponseSuccess(deleteMarketingRes)) {
|
||||||
console.log(deleteMarketingRes);
|
|
||||||
toast.success(deleteMarketingRes?.message as string);
|
toast.success(deleteMarketingRes?.message as string);
|
||||||
}
|
}
|
||||||
if (isResponseError(deleteMarketingRes)) {
|
if (isResponseError(deleteMarketingRes)) {
|
||||||
console.log(deleteMarketingRes);
|
|
||||||
toast.error(deleteMarketingRes?.message as string);
|
toast.error(deleteMarketingRes?.message as string);
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|||||||
@@ -306,7 +306,6 @@ const SupplierForm = ({
|
|||||||
label='Hatchery'
|
label='Hatchery'
|
||||||
value={hatcheryOptionsValues}
|
value={hatcheryOptionsValues}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
console.log(val); // pastikan val = array of { value, label }
|
|
||||||
setHatcheryOptionValues(val as OptionType[]);
|
setHatcheryOptionValues(val as OptionType[]);
|
||||||
}}
|
}}
|
||||||
isError={
|
isError={
|
||||||
|
|||||||
@@ -16,15 +16,11 @@ import { cn } from '@/lib/helper';
|
|||||||
import { AreaApi, KandangApi, LocationApi } from '@/services/api/master-data';
|
import { AreaApi, KandangApi, LocationApi } from '@/services/api/master-data';
|
||||||
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
import { BaseApiResponse } from '@/types/api/api-general';
|
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
import {
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
ProjectFlockApprovalPayload,
|
|
||||||
ProjectFlock,
|
|
||||||
} from '@/types/api/production/project-flock';
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { CellContext, SortingState } from '@tanstack/react-table';
|
import { CellContext, SortingState } from '@tanstack/react-table';
|
||||||
import { ChangeEventHandler, useState } from 'react';
|
import { ChangeEventHandler, useRef, useState } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
@@ -266,10 +262,10 @@ const ProjectFlockTable = () => {
|
|||||||
<div className='w-full flex flex-col justify-between items-end gap-2'>
|
<div className='w-full flex flex-col justify-between items-end gap-2'>
|
||||||
<div className='flex flex-col sm:flex-row gap-3 w-full'>
|
<div className='flex flex-col sm:flex-row gap-3 w-full'>
|
||||||
<Button
|
<Button
|
||||||
href='/production/project-flock/add'
|
|
||||||
variant='outline'
|
variant='outline'
|
||||||
color='primary'
|
color='primary'
|
||||||
className='w-full sm:w-fit'
|
className='w-full sm:w-fit'
|
||||||
|
href='/production/project-flock/add'
|
||||||
>
|
>
|
||||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||||
Tambah
|
Tambah
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import {
|
|||||||
UpdateProjectFlockFormSchema,
|
UpdateProjectFlockFormSchema,
|
||||||
} from '@/components/pages/production/project-flock/form/ProjectFlockForm.schema';
|
} from '@/components/pages/production/project-flock/form/ProjectFlockForm.schema';
|
||||||
import {
|
import {
|
||||||
ProjectFlockApprovalPayload,
|
|
||||||
CreateProjectFlockPayload,
|
CreateProjectFlockPayload,
|
||||||
ProjectFlock,
|
ProjectFlock,
|
||||||
} from '@/types/api/production/project-flock';
|
} from '@/types/api/production/project-flock';
|
||||||
@@ -43,6 +42,7 @@ import ApprovalSteps, {
|
|||||||
import { PROJECT_FLOCK_APPROVAL_LINE } from '@/config/approval-line';
|
import { PROJECT_FLOCK_APPROVAL_LINE } from '@/config/approval-line';
|
||||||
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
import NumberInput from '@/components/input/NumberInput';
|
||||||
|
import Card from '@/components/Card';
|
||||||
|
|
||||||
interface ProjectFlockFormProps {
|
interface ProjectFlockFormProps {
|
||||||
formType?: 'add' | 'edit' | 'detail';
|
formType?: 'add' | 'edit' | 'detail';
|
||||||
@@ -259,6 +259,7 @@ const ProjectFlockForm = ({
|
|||||||
|
|
||||||
if (isResponseSuccess(createProjectFlockRes)) {
|
if (isResponseSuccess(createProjectFlockRes)) {
|
||||||
toast.success(createProjectFlockRes?.message as string);
|
toast.success(createProjectFlockRes?.message as string);
|
||||||
|
handleReset();
|
||||||
router.push('/production/project-flock');
|
router.push('/production/project-flock');
|
||||||
}
|
}
|
||||||
if (isResponseError(createProjectFlockRes)) {
|
if (isResponseError(createProjectFlockRes)) {
|
||||||
@@ -276,6 +277,7 @@ const ProjectFlockForm = ({
|
|||||||
|
|
||||||
if (isResponseSuccess(updateProjectFlockRes)) {
|
if (isResponseSuccess(updateProjectFlockRes)) {
|
||||||
toast.success(updateProjectFlockRes?.message as string);
|
toast.success(updateProjectFlockRes?.message as string);
|
||||||
|
handleReset();
|
||||||
router.push('/production/project-flock');
|
router.push('/production/project-flock');
|
||||||
}
|
}
|
||||||
if (isResponseError(updateProjectFlockRes)) {
|
if (isResponseError(updateProjectFlockRes)) {
|
||||||
@@ -283,6 +285,15 @@ const ProjectFlockForm = ({
|
|||||||
toast.error(updateProjectFlockRes?.message as string);
|
toast.error(updateProjectFlockRes?.message as string);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const handleReset = () => {
|
||||||
|
formik.resetForm();
|
||||||
|
setSelectedArea('');
|
||||||
|
setSelectedLocation('');
|
||||||
|
setDisabledLocation(true);
|
||||||
|
setOpenSelectKandangs(false);
|
||||||
|
setOptionsKandang([]);
|
||||||
|
formikSetValues(formikInitialValues);
|
||||||
|
};
|
||||||
|
|
||||||
// Formik InitialValue
|
// Formik InitialValue
|
||||||
const formikInitialValues = useMemo<ProjectFlockFormValues>(() => {
|
const formikInitialValues = useMemo<ProjectFlockFormValues>(() => {
|
||||||
@@ -557,6 +568,16 @@ const ProjectFlockForm = ({
|
|||||||
const inputPeriod =
|
const inputPeriod =
|
||||||
(initialValues?.period ?? selectedPeriod == 0) ? 1 : selectedPeriod;
|
(initialValues?.period ?? selectedPeriod == 0) ? 1 : selectedPeriod;
|
||||||
|
|
||||||
|
// expose method validate() ke parent
|
||||||
|
// TODO: Buat Store untuk kirim props formik.isValid ke parent (layout.tsx)
|
||||||
|
// useImperativeHandle(ref, () => ({
|
||||||
|
// validate() {
|
||||||
|
// formik.validateForm();
|
||||||
|
// const isValid = formik.isValid;
|
||||||
|
// return isValid;
|
||||||
|
// },
|
||||||
|
// }));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='w-full'>
|
<section className='w-full'>
|
||||||
@@ -653,158 +674,139 @@ const ProjectFlockForm = ({
|
|||||||
onSubmit={formik.handleSubmit}
|
onSubmit={formik.handleSubmit}
|
||||||
onReset={formik.handleReset}
|
onReset={formik.handleReset}
|
||||||
>
|
>
|
||||||
<div className='card bg-base-100 shadow w-full mb-6'>
|
<Card
|
||||||
<div className='card-body'>
|
title='Informasi Umum'
|
||||||
<div className='card-title mb-4'>Informasi Umum</div>
|
variant='bordered'
|
||||||
<div className='grid sm:grid-cols-2 gap-4'>
|
className={{
|
||||||
<SelectInput
|
wrapper: 'w-full mb-4',
|
||||||
required
|
}}
|
||||||
label='Area'
|
>
|
||||||
value={formik.values.area as OptionType}
|
<div className='grid sm:grid-cols-2 gap-4'>
|
||||||
onChange={areaChangeHandler}
|
<SelectInput
|
||||||
options={optionsArea}
|
required
|
||||||
isLoading={isLoadingAreas}
|
label='Area'
|
||||||
isError={
|
value={formik.values.area as OptionType}
|
||||||
formik.touched.area_id && Boolean(formik.errors.area_id)
|
onChange={areaChangeHandler}
|
||||||
}
|
options={optionsArea}
|
||||||
errorMessage={formik.errors.area_id as string}
|
isLoading={isLoadingAreas}
|
||||||
isClearable
|
isError={
|
||||||
isDisabled={formType === 'detail'}
|
formik.touched.area_id && Boolean(formik.errors.area_id)
|
||||||
/>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Flock'
|
|
||||||
value={
|
|
||||||
formik.values.flock_name
|
|
||||||
? ({
|
|
||||||
label: formik.values.flock_name,
|
|
||||||
value: optionsFlock.find((flock) => {
|
|
||||||
return flock.label === formik.values.flock_name;
|
|
||||||
})?.value,
|
|
||||||
} as OptionType)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
onChange={(val) => {
|
|
||||||
optionChangeHandler(val, 'flock');
|
|
||||||
setSelectedFlock((val as OptionType)?.label);
|
|
||||||
formik.setFieldValue(
|
|
||||||
'flock_name',
|
|
||||||
(val as OptionType)?.label
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
options={optionsFlock}
|
|
||||||
isLoading={isLoadingFlocks}
|
|
||||||
isError={
|
|
||||||
formik.touched.flock_name &&
|
|
||||||
Boolean(formik.errors.flock_name)
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.flock_name as string}
|
|
||||||
isClearable
|
|
||||||
isDisabled={formType === 'detail'}
|
|
||||||
/>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Lokasi'
|
|
||||||
value={formik.values.location as OptionType}
|
|
||||||
onChange={locationChangeHandler}
|
|
||||||
options={
|
|
||||||
selectedArea != '' || initialValues?.area?.id
|
|
||||||
? optionsLocation
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
isLoading={isLoadingLocations}
|
|
||||||
isError={
|
|
||||||
formik.touched.location_id &&
|
|
||||||
Boolean(formik.errors.location_id)
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.location_id as string}
|
|
||||||
isClearable
|
|
||||||
isDisabled={formType === 'detail' || disabledLocation}
|
|
||||||
/>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='FCR'
|
|
||||||
value={formik.values.fcr as OptionType}
|
|
||||||
onChange={(val) => {
|
|
||||||
optionChangeHandler(val, 'fcr');
|
|
||||||
}}
|
|
||||||
options={optionsFcr}
|
|
||||||
isLoading={isLoadingFcrs}
|
|
||||||
isError={
|
|
||||||
formik.touched.fcr_id && Boolean(formik.errors.fcr_id)
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.fcr_id as string}
|
|
||||||
isClearable
|
|
||||||
isDisabled={formType === 'detail'}
|
|
||||||
/>
|
|
||||||
<SelectInput
|
|
||||||
required
|
|
||||||
label='Kategori'
|
|
||||||
value={formik.values.category_option as OptionType}
|
|
||||||
onChange={categoryChangeHandler}
|
|
||||||
options={FLOCK_CATEGORY_OPTIONS}
|
|
||||||
isError={
|
|
||||||
formik.touched.category && Boolean(formik.errors.category)
|
|
||||||
}
|
|
||||||
errorMessage={formik.errors.category as string}
|
|
||||||
isClearable
|
|
||||||
isDisabled={formType === 'detail'}
|
|
||||||
/>
|
|
||||||
<NumberInput
|
|
||||||
name='period'
|
|
||||||
label='Periode'
|
|
||||||
disabled
|
|
||||||
readOnly
|
|
||||||
placeholder='Period'
|
|
||||||
value={selectedLocation ? inputPeriod : ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='card bg-base-100 shadow w-full'>
|
|
||||||
<div className='card-body'>
|
|
||||||
<Collapse
|
|
||||||
title={
|
|
||||||
<div className='card-actions justify-between w-full'>
|
|
||||||
<div className='card-title'>Pilih Kandang</div>
|
|
||||||
<Button
|
|
||||||
variant='link'
|
|
||||||
className={`text-primary rotate-${
|
|
||||||
openSelectKandangs ? '180' : '0'
|
|
||||||
} transition-transform hover:text-inherit me-3`}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:keyboard-arrow-down'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
className='sm:w-full'
|
errorMessage={formik.errors.area_id as string}
|
||||||
titleClassName='w-full p-0!'
|
isClearable
|
||||||
onOpenChange={setOpenSelectKandangs}
|
isDisabled={formType === 'detail'}
|
||||||
open={openSelectKandangs}
|
/>
|
||||||
>
|
<SelectInput
|
||||||
<div className='overflow-x-auto'>
|
required
|
||||||
{isLoadingKandang && (
|
label='Flock'
|
||||||
<span className='loading loading-dots loading-xl'></span>
|
value={
|
||||||
)}
|
formik.values.flock_name
|
||||||
<ProjectFlockKandangTable
|
? ({
|
||||||
listPeriods={
|
label: formik.values.flock_name,
|
||||||
isResponseSuccess(periodFlocks) ? periodFlocks.data : []
|
value: optionsFlock.find((flock) => {
|
||||||
}
|
return flock.label === formik.values.flock_name;
|
||||||
listKandang={optionsKandang}
|
})?.value,
|
||||||
rowSelection={rowSelection}
|
} as OptionType)
|
||||||
setRowSelection={setRowSelection}
|
: undefined
|
||||||
selectedIds={formik.values.kandang_ids}
|
}
|
||||||
formType={formType}
|
onChange={(val) => {
|
||||||
initialValues={initialValues}
|
optionChangeHandler(val, 'flock');
|
||||||
/>
|
setSelectedFlock((val as OptionType)?.label);
|
||||||
</div>
|
formik.setFieldValue(
|
||||||
</Collapse>
|
'flock_name',
|
||||||
|
(val as OptionType)?.label
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
options={optionsFlock}
|
||||||
|
isLoading={isLoadingFlocks}
|
||||||
|
isError={
|
||||||
|
formik.touched.flock_name && Boolean(formik.errors.flock_name)
|
||||||
|
}
|
||||||
|
errorMessage={formik.errors.flock_name as string}
|
||||||
|
isClearable
|
||||||
|
isDisabled={formType === 'detail'}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
required
|
||||||
|
label='Lokasi'
|
||||||
|
value={formik.values.location as OptionType}
|
||||||
|
onChange={locationChangeHandler}
|
||||||
|
options={
|
||||||
|
selectedArea != '' || initialValues?.area?.id
|
||||||
|
? optionsLocation
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
isLoading={isLoadingLocations}
|
||||||
|
isError={
|
||||||
|
formik.touched.location_id &&
|
||||||
|
Boolean(formik.errors.location_id)
|
||||||
|
}
|
||||||
|
errorMessage={formik.errors.location_id as string}
|
||||||
|
isClearable
|
||||||
|
isDisabled={formType === 'detail' || disabledLocation}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
required
|
||||||
|
label='FCR'
|
||||||
|
value={formik.values.fcr as OptionType}
|
||||||
|
onChange={(val) => {
|
||||||
|
optionChangeHandler(val, 'fcr');
|
||||||
|
}}
|
||||||
|
options={optionsFcr}
|
||||||
|
isLoading={isLoadingFcrs}
|
||||||
|
isError={formik.touched.fcr_id && Boolean(formik.errors.fcr_id)}
|
||||||
|
errorMessage={formik.errors.fcr_id as string}
|
||||||
|
isClearable
|
||||||
|
isDisabled={formType === 'detail'}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
required
|
||||||
|
label='Kategori'
|
||||||
|
value={formik.values.category_option as OptionType}
|
||||||
|
onChange={categoryChangeHandler}
|
||||||
|
options={FLOCK_CATEGORY_OPTIONS}
|
||||||
|
isError={
|
||||||
|
formik.touched.category && Boolean(formik.errors.category)
|
||||||
|
}
|
||||||
|
errorMessage={formik.errors.category as string}
|
||||||
|
isClearable
|
||||||
|
isDisabled={formType === 'detail'}
|
||||||
|
/>
|
||||||
|
<NumberInput
|
||||||
|
name='period'
|
||||||
|
label='Periode'
|
||||||
|
disabled
|
||||||
|
readOnly
|
||||||
|
placeholder='Period'
|
||||||
|
value={selectedLocation ? inputPeriod : ''}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
|
<Card
|
||||||
|
collapsible
|
||||||
|
title='Pilih Kandang'
|
||||||
|
variant='bordered'
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto duration-300 ease-in-out'>
|
||||||
|
{isLoadingKandang && (
|
||||||
|
<span className='loading loading-dots loading-xl'></span>
|
||||||
|
)}
|
||||||
|
<ProjectFlockKandangTable
|
||||||
|
listPeriods={
|
||||||
|
isResponseSuccess(periodFlocks) ? periodFlocks.data : []
|
||||||
|
}
|
||||||
|
listKandang={optionsKandang}
|
||||||
|
rowSelection={rowSelection}
|
||||||
|
setRowSelection={setRowSelection}
|
||||||
|
selectedIds={formik.values.kandang_ids}
|
||||||
|
formType={formType}
|
||||||
|
initialValues={initialValues}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<div className='flex flex-row justify-center gap-2 flex-wrap my-6'>
|
<div className='flex flex-row justify-center gap-2 flex-wrap my-6'>
|
||||||
{formType !== 'detail' && (
|
{formType !== 'detail' && (
|
||||||
@@ -912,4 +914,6 @@ const ProjectFlockForm = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ProjectFlockForm.displayName = 'ProjectFlockForm';
|
||||||
|
|
||||||
export default ProjectFlockForm;
|
export default ProjectFlockForm;
|
||||||
|
|||||||
@@ -144,8 +144,6 @@ const ProjectFlockKandangTable = ({
|
|||||||
accessorFn: (row) => row.location?.name,
|
accessorFn: (row) => row.location?.name,
|
||||||
header: 'Periode',
|
header: 'Periode',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
console.log('listPeriods');
|
|
||||||
console.log(listPeriods);
|
|
||||||
const period =
|
const period =
|
||||||
listPeriods.length > 0
|
listPeriods.length > 0
|
||||||
? listPeriods.find((p) => p.id == props.row.original.id)
|
? listPeriods.find((p) => p.id == props.row.original.id)
|
||||||
|
|||||||
@@ -793,8 +793,6 @@ export class ExpenseApiService extends BaseApiService<
|
|||||||
sentPayload.set(pair[0], pair[1]);
|
sentPayload.set(pair[0], pair[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log({ sentPayload });
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 200,
|
code: 200,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@@ -815,8 +813,6 @@ export class ExpenseApiService extends BaseApiService<
|
|||||||
sentPayload.set(pair[0], pair[1]);
|
sentPayload.set(pair[0], pair[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log({ sentPayload });
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: 200,
|
code: 200,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
|
|||||||
Reference in New Issue
Block a user