mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
Merge branch 'development' into 'staging'
Development See merge request mbugroup/lti-web-client!331
This commit is contained in:
@@ -7,7 +7,6 @@ import ClosingDetail from '@/components/pages/closing/ClosingDetailTabs';
|
|||||||
|
|
||||||
import { ClosingApi } from '@/services/api/closing';
|
import { ClosingApi } from '@/services/api/closing';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { FlockApi } from '@/services/api/master-data';
|
|
||||||
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
||||||
import { ProjectFlockKandangApi } from '@/services/api/production';
|
import { ProjectFlockKandangApi } from '@/services/api/production';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import useSWR from 'swr';
|
|||||||
import { FinanceApi } from '@/services/api/finance';
|
import { FinanceApi } from '@/services/api/finance';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import FormFinanceAdd from '@/components/pages/finance/add/FormFinanceAdd';
|
import FormFinanceAdd from '@/components/pages/finance/add/FormFinanceAdd';
|
||||||
import FormFinanceAddInitialBalance from '@/components/pages/finance/add/initial-balance/FormFinanceAddInitialBalance';
|
|
||||||
|
|
||||||
const EditFinanceTransactionPage = () => {
|
const EditFinanceTransactionPage = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import FinanceDetail from '@/components/pages/finance/FinanceDetail';
|
|||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { FinanceApi } from '@/services/api/finance';
|
import { FinanceApi } from '@/services/api/finance';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
|
|
||||||
const FinanceDetailPage = () => {
|
const FinanceDetailPage = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
+1
-2
@@ -3,10 +3,9 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import { useAuth } from '@/services/hooks/useAuth';
|
import { useAuth } from '@/services/hooks/useAuth';
|
||||||
import { redirectToSSO } from '@/lib/auth-helper';
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const { user, isLoadingUser } = useAuth();
|
const { isLoadingUser } = useAuth();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
'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 React from 'react';
|
||||||
import toast from 'react-hot-toast';
|
// import React, { useImperativeHandle } from 'react';
|
||||||
|
|
||||||
const AddProjectFlock = () => {
|
const AddProjectFlock = () => {
|
||||||
// useImperativeHandle(ref, () => ({
|
// useImperativeHandle(ref, () => ({
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ const ProjectFlockEdit = () => {
|
|||||||
|
|
||||||
const projectFlockId = searchParams.get('projectFlockId');
|
const projectFlockId = searchParams.get('projectFlockId');
|
||||||
|
|
||||||
const {
|
const { data: projectFlock, isLoading: isLoadingProjectFlock } = useSWR(
|
||||||
data: projectFlock,
|
projectFlockId,
|
||||||
isLoading: isLoadingProjectFlock,
|
(id: number) => ProjectFlockApi.getSingle(id)
|
||||||
mutate: refreshProjectFlocks,
|
);
|
||||||
} = useSWR(projectFlockId, (id: number) => ProjectFlockApi.getSingle(id));
|
|
||||||
|
|
||||||
if (!projectFlockId) {
|
if (!projectFlockId) {
|
||||||
router.back();
|
router.back();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import ProjectFlockDetail from '@/components/pages/production/project-flock/detail/ProjectFlockDetail';
|
import ProjectFlockDetail from '@/components/pages/production/project-flock/detail/ProjectFlockDetail';
|
||||||
import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm';
|
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
@@ -13,11 +12,10 @@ const ProjectFlockDetailPage = () => {
|
|||||||
|
|
||||||
const projectFlockId = searchParams.get('projectFlockId');
|
const projectFlockId = searchParams.get('projectFlockId');
|
||||||
|
|
||||||
const {
|
const { data: projectFlock, isLoading: isLoadingProjectFlock } = useSWR(
|
||||||
data: projectFlock,
|
projectFlockId,
|
||||||
isLoading: isLoadingProjectFlock,
|
(id: number) => ProjectFlockApi.getSingle(id)
|
||||||
mutate: refreshProjectFlock,
|
);
|
||||||
} = useSWR(projectFlockId, (id: number) => ProjectFlockApi.getSingle(id));
|
|
||||||
|
|
||||||
if (!projectFlockId) {
|
if (!projectFlockId) {
|
||||||
router.back();
|
router.back();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
|
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
@@ -13,7 +12,6 @@ import PermissionNotFound from '@/components/helper/PermissionNotFound';
|
|||||||
|
|
||||||
import { useUiStore } from '@/stores/ui/ui.store';
|
import { useUiStore } from '@/stores/ui/ui.store';
|
||||||
import { MAIN_DRAWER_LINKS } from '@/config/constant';
|
import { MAIN_DRAWER_LINKS } from '@/config/constant';
|
||||||
import { isPathActive } from '@/lib/helper';
|
|
||||||
import { ROUTE_PERMISSIONS } from '@/config/route-permission';
|
import { ROUTE_PERMISSIONS } from '@/config/route-permission';
|
||||||
import { useAuth } from '@/services/hooks/useAuth';
|
import { useAuth } from '@/services/hooks/useAuth';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { HTMLAttributes, ReactNode, useEffect, useState } from 'react';
|
import { HTMLAttributes, ReactNode, useState } from 'react';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
|
|
||||||
export interface TabItem {
|
export interface TabItem {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import IconSkeleton from '@/components/helper/skeleton/IconSkeleton';
|
import IconSkeleton from '@/components/helper/skeleton/IconSkeleton';
|
||||||
import { Icon } from '@iconify/react';
|
|
||||||
|
|
||||||
const DataStateSkeleton = ({
|
const DataStateSkeleton = ({
|
||||||
icon,
|
icon,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { ChangeEvent } from 'react';
|
|||||||
import {
|
import {
|
||||||
PatternFormat,
|
PatternFormat,
|
||||||
NumberFormatBase,
|
NumberFormatBase,
|
||||||
NumberFormatBaseProps,
|
|
||||||
OnValueChange,
|
OnValueChange,
|
||||||
} from 'react-number-format';
|
} from 'react-number-format';
|
||||||
import TextInput, { TextInputProps } from '@/components/input/TextInput';
|
import TextInput, { TextInputProps } from '@/components/input/TextInput';
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
|
|||||||
closeOnBackdrop={closeOnBackdrop}
|
closeOnBackdrop={closeOnBackdrop}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
...primaryButton,
|
...primaryButton,
|
||||||
onClick: (e) => {
|
onClick: () => {
|
||||||
if (primaryButton && primaryButton?.onClick) {
|
if (primaryButton && primaryButton?.onClick) {
|
||||||
primaryButton?.onClick?.(notes);
|
primaryButton?.onClick?.(notes);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { cn, formatCurrency, formatDate, formatNumber } from '@/lib/helper';
|
import { cn, formatCurrency, formatDate, formatNumber } from '@/lib/helper';
|
||||||
import { ClosingApi } from '@/services/api/closing';
|
import { ClosingApi } from '@/services/api/closing';
|
||||||
@@ -38,7 +38,7 @@ const OverheadClosingTable = ({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: overheadKandang, isLoading: isLoadingOverheadKandang } = useSWR(
|
const { data: overheadKandang } = useSWR(
|
||||||
kandangId
|
kandangId
|
||||||
? `${ClosingApi.basePath}/${projectFlockId}/${kandangId}/overhead`
|
? `${ClosingApi.basePath}/${projectFlockId}/${kandangId}/overhead`
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ export const generateDashboardPDF = async ({
|
|||||||
pdf.save(fileName);
|
pdf.save(fileName);
|
||||||
|
|
||||||
toast.success('PDF exported successfully!', { id: 'export-pdf' });
|
toast.success('PDF exported successfully!', { id: 'export-pdf' });
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Failed to export PDF. Please try again.', {
|
toast.error('Failed to export PDF. Please try again.', {
|
||||||
id: 'export-pdf',
|
id: 'export-pdf',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { CellContext } from '@tanstack/react-table';
|
import { CellContext } from '@tanstack/react-table';
|
||||||
import { useSearchParams } from 'next/navigation';
|
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
|
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ const FormFinanceAddInitialBalance = ({
|
|||||||
// ===== Formik =====
|
// ===== Formik =====
|
||||||
const formikInitialValues = useMemo((): InitialBalanceFormValues => {
|
const formikInitialValues = useMemo((): InitialBalanceFormValues => {
|
||||||
// Type assertion to handle potential initial_balance_type field
|
// Type assertion to handle potential initial_balance_type field
|
||||||
const extendedInitialValues = initialValues as Finance & {
|
// const extendedInitialValues = initialValues as Finance & {
|
||||||
initial_balance_type?: string;
|
// initial_balance_type?: string;
|
||||||
};
|
// };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
party_type_option:
|
party_type_option:
|
||||||
@@ -122,8 +122,6 @@ const FormFinanceAddInitialBalance = ({
|
|||||||
options: bankOptions,
|
options: bankOptions,
|
||||||
rawData: bankRawData,
|
rawData: bankRawData,
|
||||||
isLoadingOptions: isLoadingBankOptions,
|
isLoadingOptions: isLoadingBankOptions,
|
||||||
setInputValue: setBankInputValue,
|
|
||||||
loadMore: loadMoreBankOptions,
|
|
||||||
} = useSelect<Bank>(BankApi.basePath, 'id', 'name');
|
} = useSelect<Bank>(BankApi.basePath, 'id', 'name');
|
||||||
|
|
||||||
// ===== Helper Functions =====
|
// ===== Helper Functions =====
|
||||||
|
|||||||
@@ -28,10 +28,7 @@ import { useCallback, useMemo, useState } from 'react';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import Alert from '@/components/Alert';
|
import Alert from '@/components/Alert';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import {
|
import { FINANCE_INJECTION_TYPE_OPTIONS } from '@/config/constant';
|
||||||
FINANCE_INJECTION_STATUS,
|
|
||||||
FINANCE_INJECTION_TYPE_OPTIONS,
|
|
||||||
} from '@/config/constant';
|
|
||||||
|
|
||||||
interface FormFinanceInjectionProps {
|
interface FormFinanceInjectionProps {
|
||||||
type?: 'add' | 'edit';
|
type?: 'add' | 'edit';
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { Icon } from '@iconify/react';
|
|||||||
import { ColumnDef, ColumnSort, SortingState } from '@tanstack/react-table';
|
import { ColumnDef, ColumnSort, SortingState } from '@tanstack/react-table';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
|
|
||||||
|
|
||||||
const InventoryAdjustmentTable = () => {
|
const InventoryAdjustmentTable = () => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
InventoryAdjustmentFormSchema,
|
InventoryAdjustmentFormSchema,
|
||||||
InventoryAdjustmentFormValues,
|
InventoryAdjustmentFormValues,
|
||||||
} from '@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.schema';
|
} from '@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm.schema';
|
||||||
import useSWR from 'swr';
|
|
||||||
import {
|
import {
|
||||||
ProductApi,
|
ProductApi,
|
||||||
ProductCategoryApi,
|
ProductCategoryApi,
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import { toast } from 'react-hot-toast';
|
|||||||
import { MovementApi } from '@/services/api/inventory';
|
import { MovementApi } from '@/services/api/inventory';
|
||||||
import FileInput from '@/components/input/FileInput';
|
import FileInput from '@/components/input/FileInput';
|
||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import Badge from '@/components/Badge';
|
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import { S3_PUBLIC_BASE_URL } from '@/config/constant';
|
import { S3_PUBLIC_BASE_URL } from '@/config/constant';
|
||||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
||||||
|
|||||||
@@ -15,12 +15,7 @@ import { InventoryProductApi } from '@/services/api/inventory';
|
|||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
import { InventoryProduct } from '@/types/api/inventory/product';
|
import { InventoryProduct } from '@/types/api/inventory/product';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import {
|
import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
|
||||||
CellContext,
|
|
||||||
ColumnDef,
|
|
||||||
Row,
|
|
||||||
SortingState,
|
|
||||||
} from '@tanstack/react-table';
|
|
||||||
import { ChangeEventHandler, useMemo, useState } from 'react';
|
import { ChangeEventHandler, useMemo, useState } from 'react';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { formatNumber } from '@/lib/helper';
|
import { formatNumber } from '@/lib/helper';
|
||||||
import {
|
import { ProductWarehouseStock } from '@/types/api/inventory/product';
|
||||||
InventoryProduct,
|
|
||||||
ProductWarehouseStock,
|
|
||||||
} from '@/types/api/inventory/product';
|
|
||||||
|
|
||||||
const StockProductWarehouseTable = ({
|
const StockProductWarehouseTable = ({
|
||||||
productWarehouseStock,
|
productWarehouseStock,
|
||||||
|
|||||||
@@ -48,11 +48,7 @@ import RequirePermission from '@/components/helper/RequirePermission';
|
|||||||
const MemoizedDeliveryOrderProductTable = memo(DeliveryOrderProductTable);
|
const MemoizedDeliveryOrderProductTable = memo(DeliveryOrderProductTable);
|
||||||
const MemoizedDeliveryOrderProductForm = memo(DeliveryOrderProductForm);
|
const MemoizedDeliveryOrderProductForm = memo(DeliveryOrderProductForm);
|
||||||
|
|
||||||
const DeliveryOrderFormModal = ({
|
const DeliveryOrderFormModal = ({}: { initialValues?: Marketing }) => {
|
||||||
initialValues,
|
|
||||||
}: {
|
|
||||||
initialValues?: Marketing;
|
|
||||||
}) => {
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
@@ -76,19 +72,14 @@ const DeliveryOrderFormModal = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data: marketing, isLoading: isLoadingMarketing } = useSWR(
|
const { data: marketing } = useSWR(
|
||||||
isModalActionForForm && marketingId
|
isModalActionForForm && marketingId
|
||||||
? `detail-marketing-${marketingId}`
|
? `detail-marketing-${marketingId}`
|
||||||
: undefined,
|
: undefined,
|
||||||
() => MarketingApi.getSingle(Number(marketingId))
|
() => MarketingApi.getSingle(Number(marketingId))
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const { rawDataApprovals, refresh: refreshApproval } = useApprovalSteps({
|
||||||
approvals,
|
|
||||||
rawDataApprovals,
|
|
||||||
isLoading: isLoadingApproval,
|
|
||||||
refresh: refreshApproval,
|
|
||||||
} = useApprovalSteps({
|
|
||||||
latestApproval: isResponseSuccess(marketing)
|
latestApproval: isResponseSuccess(marketing)
|
||||||
? marketing?.data.latest_approval
|
? marketing?.data.latest_approval
|
||||||
: undefined,
|
: undefined,
|
||||||
@@ -284,29 +275,10 @@ const DeliveryOrderFormModal = ({
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const memoSalesOrder = formik.values.sales_order;
|
|
||||||
|
|
||||||
// ================== HANDLER ==================
|
// ================== HANDLER ==================
|
||||||
const nextButtonHandler = () => {
|
|
||||||
setStep(step + 1);
|
|
||||||
};
|
|
||||||
const prevButtonHandler = () => {
|
const prevButtonHandler = () => {
|
||||||
setStep(step - 1);
|
setStep(step - 1);
|
||||||
};
|
};
|
||||||
const handleChangeCustomer = useCallback(
|
|
||||||
(val: OptionType | OptionType[] | null) => {
|
|
||||||
formik.setFieldValue('customer_id', (val as OptionType)?.value);
|
|
||||||
formik.setFieldValue('customer', val as OptionType);
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
const handleChangeSalesPerson = useCallback(
|
|
||||||
(val: OptionType | OptionType[] | null) => {
|
|
||||||
formik.setFieldValue('sales_person_id', (val as OptionType)?.value);
|
|
||||||
formik.setFieldValue('sales_person', val as OptionType);
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
const rejectMarketingHandler = async (notes: string) => {
|
const rejectMarketingHandler = async (notes: string) => {
|
||||||
if (!marketingId) {
|
if (!marketingId) {
|
||||||
toast.error(`Tidak ada data yang valid untuk di reject.`);
|
toast.error(`Tidak ada data yang valid untuk di reject.`);
|
||||||
@@ -507,18 +479,18 @@ const DeliveryOrderFormModal = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ================== MEMOIZED ==================
|
// ================== MEMOIZED ==================
|
||||||
const isNextButtonDisabled = useMemo(() => {
|
// const isNextButtonDisabled = useMemo(() => {
|
||||||
if (step === 1) {
|
// if (step === 1) {
|
||||||
return Boolean(
|
// return Boolean(
|
||||||
!formik.values.customer_id ||
|
// !formik.values.customer_id ||
|
||||||
!formik.values.sales_person_id ||
|
// !formik.values.sales_person_id ||
|
||||||
!formik.values.so_date ||
|
// !formik.values.so_date ||
|
||||||
!formik.values.notes
|
// !formik.values.notes
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}, [step, formik.values]);
|
// }, [step, formik.values]);
|
||||||
const deliveryRejected = useMemo(() => {
|
const deliveryRejected = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
isResponseSuccess(marketing) &&
|
isResponseSuccess(marketing) &&
|
||||||
@@ -877,7 +849,7 @@ const DeliveryOrderFormModal = ({
|
|||||||
text: 'Oke',
|
text: 'Oke',
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
className: 'rounded-lg',
|
className: 'rounded-lg',
|
||||||
onClick: (e) => {
|
onClick: () => {
|
||||||
closeModalHandler();
|
closeModalHandler();
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ import { useMemo, useState } from 'react';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import { useAuth } from '@/services/hooks/useAuth';
|
|
||||||
import ButtonFilter from '@/components/helper/ButtonFilter';
|
|
||||||
import Dropdown from '@/components/Dropdown';
|
import Dropdown from '@/components/Dropdown';
|
||||||
import PopoverButton from '@/components/popover/PopoverButton';
|
import PopoverButton from '@/components/popover/PopoverButton';
|
||||||
import PopoverContent from '@/components/popover/PopoverContent';
|
import PopoverContent from '@/components/popover/PopoverContent';
|
||||||
@@ -136,7 +134,7 @@ const RowsOptionsMenu = ({
|
|||||||
onClick={deleteClickHandler}
|
onClick={deleteClickHandler}
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
color='none'
|
color='none'
|
||||||
className='relative p-3 overflow-hidden justify-start text-sm font-semibold w-full text-error before:content-[""] before:absolute before:h-0.25 before:p-3 before:top-0 before:left-0 before:right-0 before:border-t before:border-base-content/5'
|
className='relative p-3 overflow-hidden justify-start text-sm font-semibold w-full text-error before:content-[""] before:absolute before:h-px before:p-3 before:top-0 before:left-0 before:right-0 before:border-t before:border-base-content/5'
|
||||||
>
|
>
|
||||||
<Icon icon='heroicons:trash' width={20} height={20} />
|
<Icon icon='heroicons:trash' width={20} height={20} />
|
||||||
Delete Item
|
Delete Item
|
||||||
@@ -149,14 +147,11 @@ const RowsOptionsMenu = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MarketingTable = () => {
|
const MarketingTable = () => {
|
||||||
const [search, setSearch] = useState('');
|
|
||||||
|
|
||||||
const [approveAction, setApproveAction] = useState<'APPROVED' | 'REJECTED'>(
|
const [approveAction, setApproveAction] = useState<'APPROVED' | 'REJECTED'>(
|
||||||
'APPROVED'
|
'APPROVED'
|
||||||
);
|
);
|
||||||
const [selectedItem, setSelectedItem] = useState<Marketing | null>(null);
|
const [selectedItem, setSelectedItem] = useState<Marketing | null>(null);
|
||||||
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||||
const { permissionCheck } = useAuth();
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const deleteModal = useModal();
|
const deleteModal = useModal();
|
||||||
@@ -219,6 +214,32 @@ const MarketingTable = () => {
|
|||||||
updateFilter('customer_id', '');
|
updateFilter('customer_id', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ===== ACTIVE FILTERS COUNT =====
|
||||||
|
const activeFiltersCount = useMemo(() => {
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
// Product filter
|
||||||
|
if (tableFilterState.product_ids) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status filter
|
||||||
|
if (tableFilterState.status) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customer filter
|
||||||
|
if (tableFilterState.customer_id) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}, [
|
||||||
|
tableFilterState.product_ids,
|
||||||
|
tableFilterState.status,
|
||||||
|
tableFilterState.customer_id,
|
||||||
|
]);
|
||||||
|
|
||||||
const approveClickHandler = () => {
|
const approveClickHandler = () => {
|
||||||
setApproveAction('APPROVED');
|
setApproveAction('APPROVED');
|
||||||
confirmationModal.openModal();
|
confirmationModal.openModal();
|
||||||
@@ -530,7 +551,7 @@ const MarketingTable = () => {
|
|||||||
</RequirePermission>
|
</RequirePermission>
|
||||||
{idsToProcess.length > 0 && (
|
{idsToProcess.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className='divider divider-horizontal w-0.25 p-0 m-0 bg-base-content/10 text-base-content/10 before:bg-base-content/10 before:w-0.25 after:bg-base-content/10 after:w-0.25'></div>
|
<div className='divider divider-horizontal w-px p-0 m-0 bg-base-content/10 text-base-content/10 before:bg-base-content/10 before:w-px after:bg-base-content/10 after:w-px'></div>
|
||||||
<RequirePermission permissions='lti.marketing.sales_order.approve'>
|
<RequirePermission permissions='lti.marketing.sales_order.approve'>
|
||||||
<Button
|
<Button
|
||||||
color='error'
|
color='error'
|
||||||
@@ -567,16 +588,28 @@ const MarketingTable = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-row gap-3'>
|
<div className='flex flex-row gap-3'>
|
||||||
<ButtonFilter
|
<Button
|
||||||
values={(() => {
|
variant='outline'
|
||||||
const { page, pageSize, ...rest } = tableFilterState;
|
color='none'
|
||||||
return rest;
|
|
||||||
})()}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
filterModal.openModal();
|
filterModal.openModal();
|
||||||
}}
|
}}
|
||||||
className='rounded-lg px-3 py-2.5'
|
className={cn(
|
||||||
/>
|
'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
|
||||||
|
{
|
||||||
|
'border-primary-gradient text-primary':
|
||||||
|
activeFiltersCount > 0,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Icon icon='heroicons:funnel' width={20} height={20} />
|
||||||
|
Filter
|
||||||
|
{activeFiltersCount > 0 && (
|
||||||
|
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
|
||||||
|
{activeFiltersCount}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
direction='bottom'
|
direction='bottom'
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ const SalesOrderFormModal = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data: marketing, isLoading: isLoadingMarketing } = useSWR(
|
const { data: marketing } = useSWR(
|
||||||
isModalActionForForm && marketingId
|
isModalActionForForm && marketingId
|
||||||
? `detail-marketing-${marketingId}`
|
? `detail-marketing-${marketingId}`
|
||||||
: undefined,
|
: undefined,
|
||||||
@@ -750,7 +750,7 @@ const SalesOrderFormModal = ({
|
|||||||
text: 'Oke',
|
text: 'Oke',
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
className: 'rounded-lg',
|
className: 'rounded-lg',
|
||||||
onClick: (e) => {
|
onClick: () => {
|
||||||
closeModalHandler();
|
closeModalHandler();
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ const DeliveryOrderProductForm = ({
|
|||||||
salesOrders,
|
salesOrders,
|
||||||
initialValues,
|
initialValues,
|
||||||
exisitingValues,
|
exisitingValues,
|
||||||
onSubmitForm,
|
|
||||||
onUpdateForm,
|
onUpdateForm,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: {
|
}: {
|
||||||
@@ -96,12 +95,12 @@ const DeliveryOrderProductForm = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Options Week dari minggu 1 - 22
|
// Options Week dari minggu 1 - 22
|
||||||
const optionsWeek = useMemo(() => {
|
// const optionsWeek = useMemo(() => {
|
||||||
return Array.from({ length: 22 }, (_, i) => ({
|
// return Array.from({ length: 22 }, (_, i) => ({
|
||||||
value: i + 1,
|
// value: i + 1,
|
||||||
label: `Week ${i + 1}`,
|
// label: `Week ${i + 1}`,
|
||||||
}));
|
// }));
|
||||||
}, []);
|
// }, []);
|
||||||
|
|
||||||
const options = exisitingValues
|
const options = exisitingValues
|
||||||
?.map((item) => {
|
?.map((item) => {
|
||||||
|
|||||||
@@ -139,12 +139,12 @@ const SalesOrderProductForm = ({
|
|||||||
} = useSelect<Kandang>(WarehouseApi.basePath, 'id', 'name');
|
} = useSelect<Kandang>(WarehouseApi.basePath, 'id', 'name');
|
||||||
|
|
||||||
// Options Week dari minggu 1 - 22
|
// Options Week dari minggu 1 - 22
|
||||||
const optionsWeek = useMemo(() => {
|
// const optionsWeek = useMemo(() => {
|
||||||
return Array.from({ length: 22 }, (_, i) => ({
|
// return Array.from({ length: 22 }, (_, i) => ({
|
||||||
value: i + 1,
|
// value: i + 1,
|
||||||
label: `Week ${i + 1}`,
|
// label: `Week ${i + 1}`,
|
||||||
}));
|
// }));
|
||||||
}, []);
|
// }, []);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
options: warehouseSourceOptions,
|
options: warehouseSourceOptions,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const DeliveryOrderExport = ({
|
|||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(url);
|
||||||
}, 150);
|
}, 150);
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Failed to generate PDF. Please try again.');
|
toast.error('Failed to generate PDF. Please try again.');
|
||||||
} finally {
|
} finally {
|
||||||
setIsGeneratingPDF(false);
|
setIsGeneratingPDF(false);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import { Marketing } from '@/types/api/marketing/marketing';
|
import { Marketing } from '@/types/api/marketing/marketing';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { Document, Image, Page, pdf, Text, View } from '@react-pdf/renderer';
|
import { Document, Page, pdf, Text, View } from '@react-pdf/renderer';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { formatDate, formatNumber } from '@/lib/helper';
|
import { formatDate, formatNumber } from '@/lib/helper';
|
||||||
import pdfStyles from '@/components/pages/marketing/pdf/styles/MarketingPDFStyles';
|
import pdfStyles from '@/components/pages/marketing/pdf/styles/MarketingPDFStyles';
|
||||||
@@ -43,7 +43,7 @@ const SalesOrderExport = ({ data }: SalesOrderExportProps) => {
|
|||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(url);
|
||||||
}, 150);
|
}, 150);
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Failed to generate PDF. Please try again.');
|
toast.error('Failed to generate PDF. Please try again.');
|
||||||
} finally {
|
} finally {
|
||||||
setIsGeneratingPDF(false);
|
setIsGeneratingPDF(false);
|
||||||
@@ -162,7 +162,7 @@ const PDFDocument = ({ data }: { data: Marketing }) => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{data?.sales_order?.map((item, index) => {
|
{data?.sales_order?.map((item, index) => {
|
||||||
const isLastItem = index === (data?.sales_order?.length || 0) - 1;
|
// const isLastItem = index === (data?.sales_order?.length || 0) - 1;
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useModal } from '@/components/Modal';
|
import { useModal } from '@/components/Modal';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import { CustomerApi } from '@/services/api/master-data';
|
import { CustomerApi } from '@/services/api/master-data';
|
||||||
import {
|
import {
|
||||||
CreateCustomerPayload,
|
CreateCustomerPayload,
|
||||||
@@ -27,7 +27,6 @@ import SelectInput, {
|
|||||||
OptionType,
|
OptionType,
|
||||||
useSelect,
|
useSelect,
|
||||||
} from '@/components/input/SelectInput';
|
} from '@/components/input/SelectInput';
|
||||||
import useSWR from 'swr';
|
|
||||||
import { UserApi } from '@/services/api/user';
|
import { UserApi } from '@/services/api/user';
|
||||||
import { TYPE_OPTIONS } from '@/config/constant';
|
import { TYPE_OPTIONS } from '@/config/constant';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
@@ -22,7 +21,7 @@ import {
|
|||||||
KandangFormValues,
|
KandangFormValues,
|
||||||
UpdateKandangFormSchema,
|
UpdateKandangFormSchema,
|
||||||
} from '@/components/pages/master-data/kandang/form/KandangForm.schema';
|
} from '@/components/pages/master-data/kandang/form/KandangForm.schema';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import {
|
import {
|
||||||
Kandang,
|
Kandang,
|
||||||
CreateKandangPayload,
|
CreateKandangPayload,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
@@ -22,7 +21,7 @@ import {
|
|||||||
LocationFormValues,
|
LocationFormValues,
|
||||||
UpdateLocationFormSchema,
|
UpdateLocationFormSchema,
|
||||||
} from '@/components/pages/master-data/location/form/LocationForm.schema';
|
} from '@/components/pages/master-data/location/form/LocationForm.schema';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import {
|
import {
|
||||||
Location,
|
Location,
|
||||||
CreateLocationPayload,
|
CreateLocationPayload,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
@@ -22,7 +21,7 @@ import {
|
|||||||
NonstockFormValues,
|
NonstockFormValues,
|
||||||
UpdateNonstockFormSchema,
|
UpdateNonstockFormSchema,
|
||||||
} from '@/components/pages/master-data/nonstock/form/NonstockForm.schema';
|
} from '@/components/pages/master-data/nonstock/form/NonstockForm.schema';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import {
|
import {
|
||||||
Nonstock,
|
Nonstock,
|
||||||
CreateNonstockPayload,
|
CreateNonstockPayload,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
|
||||||
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
||||||
import { ProductionStandard } from '@/types/api/master-data/production-standard';
|
import { ProductionStandard } from '@/types/api/master-data/production-standard';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
@@ -82,14 +81,11 @@ const ProductionStandardTable = () => {
|
|||||||
>(undefined);
|
>(undefined);
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
const {
|
const { data: productionStandards, mutate: refreshProductionStandards } =
|
||||||
data: productionStandards,
|
useSWR(
|
||||||
isLoading: productionStandardsLoading,
|
`${ProductionStandardApi.basePath}`,
|
||||||
mutate: refreshProductionStandards,
|
ProductionStandardApi.getAllFetcher
|
||||||
} = useSWR(
|
);
|
||||||
`${ProductionStandardApi.basePath}`,
|
|
||||||
ProductionStandardApi.getAllFetcher
|
|
||||||
);
|
|
||||||
|
|
||||||
const confirmationModalDeleteClickHandler = async () => {
|
const confirmationModalDeleteClickHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { toast } from 'react-hot-toast';
|
import { toast } from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
@@ -22,7 +21,7 @@ import {
|
|||||||
WarehouseFormValues,
|
WarehouseFormValues,
|
||||||
UpdateWarehouseFormSchema,
|
UpdateWarehouseFormSchema,
|
||||||
} from '@/components/pages/master-data/warehouse/form/WarehouseForm.schema';
|
} from '@/components/pages/master-data/warehouse/form/WarehouseForm.schema';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import {
|
import {
|
||||||
Warehouse,
|
Warehouse,
|
||||||
CreateWarehousePayload,
|
CreateWarehousePayload,
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import { FormHeader } from '@/components/helper/form/FormHeader';
|
|
||||||
import Table from '@/components/Table';
|
|
||||||
import { formatNumber } from '@/lib/helper';
|
import { formatNumber } from '@/lib/helper';
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
|
||||||
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
import Tabs from '@/components/Tabs';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import ApprovalSteps, {
|
import ApprovalSteps, {
|
||||||
useApprovalSteps,
|
useApprovalSteps,
|
||||||
@@ -15,7 +11,6 @@ import ChickinFormView from '@/components/pages/production/chickin/form/tabs/Chi
|
|||||||
import ChickinLogsView from '@/components/pages/production/chickin/form/tabs/ChickLogsView';
|
import ChickinLogsView from '@/components/pages/production/chickin/form/tabs/ChickLogsView';
|
||||||
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Badge from '@/components/Badge';
|
|
||||||
import StatusBadge from '@/components/helper/StatusBadge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import { CHICKINS_APPROVAL_LINE } from '@/config/approval-line';
|
import { CHICKINS_APPROVAL_LINE } from '@/config/approval-line';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import Table from '@/components/Table';
|
|
||||||
import {
|
import {
|
||||||
ChickinFormValues,
|
ChickinFormValues,
|
||||||
ChickinRequestFormValues,
|
|
||||||
ChickinSchema,
|
ChickinSchema,
|
||||||
} from '@/components/pages/production/chickin/form/ChickinForm.schema';
|
} from '@/components/pages/production/chickin/form/ChickinForm.schema';
|
||||||
import DateInput from '@/components/input/DateInput';
|
import DateInput from '@/components/input/DateInput';
|
||||||
|
|||||||
@@ -60,11 +60,7 @@ const ProjectFlockConfirmationModal = ({
|
|||||||
: '',
|
: '',
|
||||||
limit: '500',
|
limit: '500',
|
||||||
}).toString()}`;
|
}).toString()}`;
|
||||||
const {
|
const { data: kandang } = useSWR(kandangUrl, KandangApi.getAllFetcher);
|
||||||
data: kandang,
|
|
||||||
isLoading: isLoadingKandang,
|
|
||||||
mutate: refreshKandang,
|
|
||||||
} = useSWR(kandangUrl, KandangApi.getAllFetcher);
|
|
||||||
|
|
||||||
const notesChangeHandler: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
|
const notesChangeHandler: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
|
||||||
setNotes(e.target.value);
|
setNotes(e.target.value);
|
||||||
@@ -85,7 +81,7 @@ const ProjectFlockConfirmationModal = ({
|
|||||||
text: primaryButton?.text ?? 'Oke',
|
text: primaryButton?.text ?? 'Oke',
|
||||||
color: primaryButton?.color ?? 'primary',
|
color: primaryButton?.color ?? 'primary',
|
||||||
className: 'rounded-lg',
|
className: 'rounded-lg',
|
||||||
onClick: (e) => {
|
onClick: () => {
|
||||||
if (withNote) {
|
if (withNote) {
|
||||||
primaryButton?.onClick?.(notes);
|
primaryButton?.onClick?.(notes);
|
||||||
} else if (primaryButton && primaryButton?.onClick) {
|
} else if (primaryButton && primaryButton?.onClick) {
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Badge from '@/components/Badge';
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import FloatingActionsButton from '@/components/FloatingActionsButton';
|
|
||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
||||||
import SelectInput, {
|
import { OptionType, useSelect } from '@/components/input/SelectInput';
|
||||||
OptionType,
|
|
||||||
useSelect,
|
|
||||||
} from '@/components/input/SelectInput';
|
|
||||||
import { useModal } from '@/components/Modal';
|
import { useModal } from '@/components/Modal';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import Dropdown from '@/components/Dropdown';
|
import Dropdown from '@/components/Dropdown';
|
||||||
import { ROWS_OPTIONS } from '@/config/constant';
|
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { cn, formatDate, formatTitleCase } from '@/lib/helper';
|
import { cn, formatDate } 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';
|
||||||
@@ -37,6 +31,7 @@ import ProjectFlockConfirmationModal from './ProjectFlockConfirmationModal';
|
|||||||
import { useProjectFlockStore } from '@/stores/production/project-flock/project-flock.store';
|
import { useProjectFlockStore } from '@/stores/production/project-flock/project-flock.store';
|
||||||
import { ProjectFlockFormValues } from './form/ProjectFlockForm.schema';
|
import { ProjectFlockFormValues } from './form/ProjectFlockForm.schema';
|
||||||
import { useChickinStore } from '@/stores/production/chickin/chickin.store';
|
import { useChickinStore } from '@/stores/production/chickin/chickin.store';
|
||||||
|
import { useProjectFlockClosingStore } from '@/stores/production/project-flock-closing/project-flock-closing.store';
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
props,
|
props,
|
||||||
@@ -182,19 +177,12 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
.filter((id) => rowSelection[id])
|
.filter((id) => rowSelection[id])
|
||||||
.map((id) => parseInt(id));
|
.map((id) => parseInt(id));
|
||||||
|
|
||||||
const [selectedArea, setSelectedArea] = useState<OptionType | null>(null);
|
|
||||||
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const [selectedKandang, setSelectedKandang] = useState<OptionType | null>(
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const [periodInputValue, setPeriodInputValue] = useState<number | null>(null);
|
|
||||||
const [sorting, setSorting] = useState<SortingState>([]);
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
const deleteModal = useModal();
|
const deleteModal = useModal();
|
||||||
const confirmModal = useModal();
|
const confirmModal = useModal();
|
||||||
const successModal = useModal();
|
const successModal = useModal();
|
||||||
const chickinApproveModal = useModal();
|
const chickinApproveModal = useModal();
|
||||||
|
const closingModal = useModal();
|
||||||
const [approvalAction, setApprovalAction] = useState<'APPROVED' | 'REJECTED'>(
|
const [approvalAction, setApprovalAction] = useState<'APPROVED' | 'REJECTED'>(
|
||||||
'APPROVED'
|
'APPROVED'
|
||||||
);
|
);
|
||||||
@@ -210,6 +198,15 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
setChickinApproveLoading,
|
setChickinApproveLoading,
|
||||||
} = useChickinStore();
|
} = useChickinStore();
|
||||||
|
|
||||||
|
const {
|
||||||
|
isClosingModalOpen,
|
||||||
|
isKandangClosed,
|
||||||
|
isClosingLoading,
|
||||||
|
closingCallback,
|
||||||
|
closeClosingModal,
|
||||||
|
setClosingLoading,
|
||||||
|
} = useProjectFlockClosingStore();
|
||||||
|
|
||||||
// ===== Fetch Data =====
|
// ===== Fetch Data =====
|
||||||
const {
|
const {
|
||||||
data: projectFlocks,
|
data: projectFlocks,
|
||||||
@@ -221,26 +218,6 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
{ revalidateOnMount: true }
|
{ revalidateOnMount: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
// ===== Fetch Data Select =====
|
|
||||||
const {
|
|
||||||
options: optionsArea,
|
|
||||||
isLoadingOptions: isLoadingArea,
|
|
||||||
setInputValue: setAreaSelectInputValue,
|
|
||||||
loadMore: loadMoreArea,
|
|
||||||
} = useSelect(AreaApi.basePath, 'id', 'name');
|
|
||||||
const {
|
|
||||||
options: optionsLocation,
|
|
||||||
isLoadingOptions: isLoadingLocation,
|
|
||||||
setInputValue: setLocationSelectInputValue,
|
|
||||||
loadMore: loadMoreLocation,
|
|
||||||
} = useSelect(LocationApi.basePath, 'id', 'name');
|
|
||||||
const {
|
|
||||||
options: optionsKandang,
|
|
||||||
isLoadingOptions: isLoadingKandang,
|
|
||||||
setInputValue: setKandangSelectInputValue,
|
|
||||||
loadMore: loadMoreKandang,
|
|
||||||
} = useSelect(KandangApi.basePath, 'id', 'name');
|
|
||||||
|
|
||||||
// ====== HANDLER ======
|
// ====== HANDLER ======
|
||||||
const confirmationModalDeleteClickHandler = async () => {
|
const confirmationModalDeleteClickHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
@@ -309,6 +286,14 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
}
|
}
|
||||||
}, [isChickinApproveModalOpen, chickinApproveModal]);
|
}, [isChickinApproveModalOpen, chickinApproveModal]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isClosingModalOpen) {
|
||||||
|
closingModal.openModal();
|
||||||
|
} else {
|
||||||
|
closingModal.closeModal();
|
||||||
|
}
|
||||||
|
}, [isClosingModalOpen, closingModal]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
successModal.openModal();
|
successModal.openModal();
|
||||||
@@ -1025,6 +1010,45 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
isLoading: isChickinApproveLoading,
|
isLoading: isChickinApproveLoading,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Project Flock Closing Modal */}
|
||||||
|
<ConfirmationModal
|
||||||
|
ref={closingModal.ref}
|
||||||
|
type='error'
|
||||||
|
text={
|
||||||
|
!isKandangClosed
|
||||||
|
? 'Apakah kamu yakin ingin mengakhiri project ini ? *Pastikan persediaan produk di gudang terkait sudah kosong, dan BOP sudah selesai'
|
||||||
|
: 'Apakah kamu yakin ingin membuka kembali project ini ? *Project ini akan kembali ke status aktif'
|
||||||
|
}
|
||||||
|
className={{
|
||||||
|
modal: 'z-9999',
|
||||||
|
}}
|
||||||
|
secondaryButton={{
|
||||||
|
text: 'Tidak',
|
||||||
|
onClick: () => {
|
||||||
|
closeClosingModal();
|
||||||
|
closingModal.closeModal();
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
primaryButton={{
|
||||||
|
text: 'Ya',
|
||||||
|
color: 'error',
|
||||||
|
isLoading: isClosingLoading,
|
||||||
|
onClick: async () => {
|
||||||
|
if (closingCallback) {
|
||||||
|
setClosingLoading(true);
|
||||||
|
try {
|
||||||
|
await closingCallback(!isKandangClosed ? 'close' : 'unclose');
|
||||||
|
} finally {
|
||||||
|
setClosingLoading(false);
|
||||||
|
closeClosingModal();
|
||||||
|
closingModal.closeModal();
|
||||||
|
refreshProjectFlocks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import Button from '@/components/Button';
|
|||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import Badge from '@/components/Badge';
|
|
||||||
import StatusBadge from '@/components/helper/StatusBadge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import { formatDate, formatNumber, formatTitleCase } from '@/lib/helper';
|
import { formatDate, formatNumber, formatTitleCase } from '@/lib/helper';
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
@@ -17,12 +16,10 @@ import { Icon } from '@iconify/react';
|
|||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { ProjectFlockKandangApi } from '@/services/api/production/project-flock-kandang';
|
import { ProjectFlockKandangApi } from '@/services/api/production/project-flock-kandang';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { useModal } from '@/components/Modal';
|
import { useProjectFlockClosingStore } from '@/stores/production/project-flock-closing/project-flock-closing.store';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import { useMemo } from 'react';
|
||||||
import { useMemo, useState } from 'react';
|
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { ApprovalApi } from '@/services/api/approval';
|
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import { Color } from '@/types/theme';
|
import { Color } from '@/types/theme';
|
||||||
|
|
||||||
@@ -53,56 +50,46 @@ const ProjectFlockClosingForm = ({
|
|||||||
projectFlockKandang: ProjectFlockKandang;
|
projectFlockKandang: ProjectFlockKandang;
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const closeModal = useModal();
|
|
||||||
|
|
||||||
const [isClosingLoading, setIsClosingLoading] = useState(false);
|
const { openClosingModal } = useProjectFlockClosingStore();
|
||||||
|
|
||||||
const { data: closingData, isLoading } = useSWR(
|
const { data: closingData, isLoading } = useSWR(
|
||||||
`${ProjectFlockKandangApi.basePath}/${projectFlockKandang.id}/closing`,
|
`${ProjectFlockKandangApi.basePath}/${projectFlockKandang.id}/closing`,
|
||||||
() => ProjectFlockKandangApi.checkClosing(projectFlockKandang.id)
|
() => ProjectFlockKandangApi.checkClosing(projectFlockKandang.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: projectFlockKandangApprovals } = useSWR(
|
|
||||||
`${ApprovalApi.basePath}?module_name=PROJECT_FLOCK_KANDANGS&module_id=${projectFlockKandang.id}`,
|
|
||||||
() =>
|
|
||||||
ApprovalApi.getAllFetcher(
|
|
||||||
`${ApprovalApi.basePath}?module_name=PROJECT_FLOCK_KANDANGS&module_id=${projectFlockKandang.id}`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const isKandangClosed = useMemo(() => {
|
const isKandangClosed = useMemo(() => {
|
||||||
return projectFlockKandang.kandang?.status === 'NON_ACTIVE';
|
return projectFlockKandang.kandang?.status === 'NON_ACTIVE';
|
||||||
}, [projectFlockKandang]);
|
}, [projectFlockKandang]);
|
||||||
|
|
||||||
const isCanClose = useMemo(() => {
|
const handleCloseClick = () => {
|
||||||
return isResponseSuccess(projectFlockKandangApprovals)
|
const closingCallback = async (action: 'close' | 'unclose') => {
|
||||||
? projectFlockKandangApprovals?.data?.[0]?.step_number <= 2
|
const deleteProjectFlockRes = await ProjectFlockKandangApi.closing(
|
||||||
: true;
|
projectFlockKandang?.id as number,
|
||||||
}, [projectFlockKandangApprovals]);
|
{
|
||||||
|
closed_date:
|
||||||
const confirmationModalCloseClickHandler = async () => {
|
action === 'close' ? formatDate(new Date(), 'YYYY-MM-DD') : '',
|
||||||
setIsClosingLoading(true);
|
action,
|
||||||
const deleteProjectFlockRes = await ProjectFlockKandangApi.closing(
|
}
|
||||||
projectFlockKandang?.id as number,
|
|
||||||
{
|
|
||||||
closed_date: !isKandangClosed
|
|
||||||
? formatDate(new Date(), 'YYYY-MM-DD')
|
|
||||||
: '',
|
|
||||||
action: !isKandangClosed ? 'close' : 'unclose',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isResponseSuccess(deleteProjectFlockRes)) {
|
|
||||||
toast.success(deleteProjectFlockRes?.message as string);
|
|
||||||
router.push(
|
|
||||||
`/production/project-flock/detail?projectFlockId=${projectFlock.id}`
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
if (isResponseError(deleteProjectFlockRes)) {
|
if (isResponseSuccess(deleteProjectFlockRes)) {
|
||||||
toast.error(deleteProjectFlockRes?.message as string);
|
toast.success(deleteProjectFlockRes?.message as string);
|
||||||
}
|
router.push(
|
||||||
setIsClosingLoading(false);
|
`/production/project-flock/detail?projectFlockId=${projectFlock.id}`
|
||||||
closeModal.closeModal();
|
);
|
||||||
|
}
|
||||||
|
if (isResponseError(deleteProjectFlockRes)) {
|
||||||
|
toast.error(deleteProjectFlockRes?.message as string);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
openClosingModal(
|
||||||
|
projectFlockKandang,
|
||||||
|
projectFlock.id,
|
||||||
|
isKandangClosed,
|
||||||
|
closingCallback
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const errorStock = useMemo(() => {
|
// const errorStock = useMemo(() => {
|
||||||
@@ -334,7 +321,7 @@ const ProjectFlockClosingForm = ({
|
|||||||
color='error'
|
color='error'
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
disabled={!isCanCloseValid}
|
disabled={!isCanCloseValid}
|
||||||
onClick={() => closeModal.openModal()}
|
onClick={handleCloseClick}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon={
|
icon={
|
||||||
@@ -347,25 +334,6 @@ const ProjectFlockClosingForm = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</RequirePermission>
|
</RequirePermission>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ConfirmationModal
|
|
||||||
ref={closeModal.ref}
|
|
||||||
type='error'
|
|
||||||
text={
|
|
||||||
!isKandangClosed
|
|
||||||
? 'Apakah kamu yakin ingin mengakhiri project ini ? *Pastikan persediaan produk di gudang terkait sudah kosong, dan BOP sudah selesai'
|
|
||||||
: 'Apakah kamu yakin ingin membuka kembali project ini ? *Project ini akan kembali ke status aktif'
|
|
||||||
}
|
|
||||||
secondaryButton={{
|
|
||||||
text: 'Tidak',
|
|
||||||
}}
|
|
||||||
primaryButton={{
|
|
||||||
text: 'Ya',
|
|
||||||
color: 'error',
|
|
||||||
isLoading: isClosingLoading,
|
|
||||||
onClick: confirmationModalCloseClickHandler,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import Badge from '@/components/Badge';
|
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import { RadioGroup, RadioGroupItem } from '@/components/input/RadioInput';
|
import { RadioGroup, RadioGroupItem } from '@/components/input/RadioInput';
|
||||||
@@ -42,19 +41,6 @@ const ProjectFlockDetail = ({
|
|||||||
(kandang) => kandang.id === Number(selectedKandangId)
|
(kandang) => kandang.id === Number(selectedKandangId)
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: projectFlockKandang, isLoading: projectFlockKandangLoading } =
|
|
||||||
useSWR(
|
|
||||||
selectedKandangId
|
|
||||||
? `${ProjectFlockKandangApi.basePath}/get-detail/${selectedKandangId}`
|
|
||||||
: null,
|
|
||||||
selectedKandangId
|
|
||||||
? () =>
|
|
||||||
ProjectFlockKandangApi.getSingle(
|
|
||||||
Number(selectedKandang?.project_flock_kandang_id)
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data: projectFlockApprovalResponse } = useSWR(
|
const { data: projectFlockApprovalResponse } = useSWR(
|
||||||
projectFlock.id ? ['approval-project-flock', projectFlock.id] : undefined,
|
projectFlock.id ? ['approval-project-flock', projectFlock.id] : undefined,
|
||||||
([, id]) => ProjectFlockApi.getApprovalLineHistory(Number(id))
|
([, id]) => ProjectFlockApi.getApprovalLineHistory(Number(id))
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import { FLOCK_CATEGORY_OPTIONS } from '@/config/constant';
|
|||||||
import { useModal } from '@/components/Modal';
|
import { useModal } from '@/components/Modal';
|
||||||
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
import ConfirmationModal from '@/components/modal/ConfirmationModal';
|
||||||
import NumberInput from '@/components/input/NumberInput';
|
import NumberInput from '@/components/input/NumberInput';
|
||||||
import Card from '@/components/Card';
|
|
||||||
import ProjectFlockKandangTable from '@/components/pages/production/project-flock/form/ProjectFlockKandangTable';
|
import ProjectFlockKandangTable from '@/components/pages/production/project-flock/form/ProjectFlockKandangTable';
|
||||||
import { Nonstock } from '@/types/api/master-data/nonstock';
|
import { Nonstock } from '@/types/api/master-data/nonstock';
|
||||||
import { useUiStore } from '@/stores/ui/ui.store';
|
import { useUiStore } from '@/stores/ui/ui.store';
|
||||||
@@ -209,7 +208,6 @@ export const ProjectFlockFormConfirmationTable = ({
|
|||||||
const ProjectFlockForm = ({
|
const ProjectFlockForm = ({
|
||||||
formType = 'add',
|
formType = 'add',
|
||||||
initialValues,
|
initialValues,
|
||||||
refreshProjectFlocks,
|
|
||||||
}: ProjectFlockFormProps) => {
|
}: ProjectFlockFormProps) => {
|
||||||
// State
|
// State
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -228,7 +226,7 @@ const ProjectFlockForm = ({
|
|||||||
const [disabledLocation, setDisabledLocation] = useState(
|
const [disabledLocation, setDisabledLocation] = useState(
|
||||||
initialValues?.location?.id ? false : true
|
initialValues?.location?.id ? false : true
|
||||||
);
|
);
|
||||||
const [openSelectKandangs, setOpenSelectKandangs] = useState(
|
const [, setOpenSelectKandangs] = useState(
|
||||||
initialValues?.kandangs && initialValues?.kandangs?.length > 0
|
initialValues?.kandangs && initialValues?.kandangs?.length > 0
|
||||||
);
|
);
|
||||||
const [optionsKandang, setOptionsKandang] = useState<Kandang[]>(
|
const [optionsKandang, setOptionsKandang] = useState<Kandang[]>(
|
||||||
@@ -475,9 +473,9 @@ const ProjectFlockForm = ({
|
|||||||
formikSetValues(formikInitialValues);
|
formikSetValues(formikInitialValues);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [formikLastValues, setFormikLastValues] = useState<
|
const [, setFormikLastValues] = useState<ProjectFlockFormValues | undefined>(
|
||||||
ProjectFlockFormValues | undefined
|
undefined
|
||||||
>(undefined);
|
);
|
||||||
|
|
||||||
// Formik InitialValue
|
// Formik InitialValue
|
||||||
const formikInitialValues = useMemo<ProjectFlockFormValues>(() => {
|
const formikInitialValues = useMemo<ProjectFlockFormValues>(() => {
|
||||||
@@ -486,9 +484,9 @@ const ProjectFlockForm = ({
|
|||||||
0,
|
0,
|
||||||
initialValues?.flock_name?.lastIndexOf(' ')
|
initialValues?.flock_name?.lastIndexOf(' ')
|
||||||
) ?? '';
|
) ?? '';
|
||||||
const optionFind = optionsFlock.find((flock) => {
|
// const optionFind = optionsFlock.find((flock) => {
|
||||||
return flock.label == trimFlock;
|
// return flock.label == trimFlock;
|
||||||
}) as OptionType;
|
// }) as OptionType;
|
||||||
return {
|
return {
|
||||||
flock:
|
flock:
|
||||||
optionsFlock.find((flock) => {
|
optionsFlock.find((flock) => {
|
||||||
|
|||||||
@@ -1,28 +1,21 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Badge from '@/components/Badge';
|
|
||||||
import Card from '@/components/Card';
|
import Card from '@/components/Card';
|
||||||
import StatusBadge from '@/components/helper/StatusBadge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import PillBadge from '@/components/PillBadge';
|
|
||||||
import Table from '@/components/Table';
|
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
import {
|
import {
|
||||||
ProjectFlock,
|
ProjectFlock,
|
||||||
ProjectFlockPeriods,
|
ProjectFlockPeriods,
|
||||||
} from '@/types/api/production/project-flock';
|
} from '@/types/api/production/project-flock';
|
||||||
import { Icon } from '@iconify/react';
|
import { OnChangeFn } from '@tanstack/react-table';
|
||||||
import { OnChangeFn, Row } from '@tanstack/react-table';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
const ProjectFlockKandangTable = ({
|
const ProjectFlockKandangTable = ({
|
||||||
listPeriods,
|
|
||||||
listKandang,
|
listKandang,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
setRowSelection,
|
setRowSelection,
|
||||||
selectedIds,
|
selectedIds,
|
||||||
initialValues,
|
|
||||||
formType = 'add',
|
formType = 'add',
|
||||||
}: {
|
}: {
|
||||||
listPeriods: ProjectFlockPeriods;
|
listPeriods: ProjectFlockPeriods;
|
||||||
|
|||||||
+2
-2
@@ -55,7 +55,7 @@ const TransferToLayingConfirmationModalTable = ({
|
|||||||
transferToLayingId
|
transferToLayingId
|
||||||
? ['detail-transfer-to-laying', String(transferToLayingId)]
|
? ['detail-transfer-to-laying', String(transferToLayingId)]
|
||||||
: undefined,
|
: undefined,
|
||||||
([_, id]) => TransferToLayingApi.getSingle(Number(id))
|
([id]) => TransferToLayingApi.getSingle(Number(id))
|
||||||
);
|
);
|
||||||
|
|
||||||
const confirmationTableColumns: ColumnDef<TransferToLayingConfirmationTableDataType>[] =
|
const confirmationTableColumns: ColumnDef<TransferToLayingConfirmationTableDataType>[] =
|
||||||
@@ -230,7 +230,7 @@ const TransferToLayingConfirmationModal = ({
|
|||||||
text: primaryButton?.text ?? 'Oke',
|
text: primaryButton?.text ?? 'Oke',
|
||||||
color: primaryButton?.color ?? 'primary',
|
color: primaryButton?.color ?? 'primary',
|
||||||
className: 'rounded-lg',
|
className: 'rounded-lg',
|
||||||
onClick: (e) => {
|
onClick: () => {
|
||||||
if (withNote) {
|
if (withNote) {
|
||||||
primaryButton?.onClick?.(notes);
|
primaryButton?.onClick?.(notes);
|
||||||
} else if (primaryButton && primaryButton?.onClick) {
|
} else if (primaryButton && primaryButton?.onClick) {
|
||||||
|
|||||||
@@ -40,10 +40,7 @@ const TransferToLayingDetailModal = () => {
|
|||||||
? transferToLayingResponse.data
|
? transferToLayingResponse.data
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const {
|
const { data: transferToLayingApprovalResponse } = useSWR(
|
||||||
data: transferToLayingApprovalResponse,
|
|
||||||
isLoading: isLoadingTransferToLayingApproval,
|
|
||||||
} = useSWR(
|
|
||||||
transferToLayingId
|
transferToLayingId
|
||||||
? ['approval-transfer-to-laying', transferToLayingId]
|
? ['approval-transfer-to-laying', transferToLayingId]
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|||||||
@@ -60,13 +60,12 @@ const TransferToLayingFormModal = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data: transferToLaying, isLoading: isLoadingTransferToLaying } =
|
const { data: transferToLaying } = useSWR(
|
||||||
useSWR(
|
isModalActionForForm && transferToLayingId
|
||||||
isModalActionForForm && transferToLayingId
|
? ['detail-transfer-to-laying', transferToLayingId]
|
||||||
? ['detail-transfer-to-laying', transferToLayingId]
|
: undefined,
|
||||||
: undefined,
|
([, id]) => TransferToLayingApi.getSingle(Number(id))
|
||||||
([, id]) => TransferToLayingApi.getSingle(Number(id))
|
);
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Step 1: General Information
|
* Step 1: General Information
|
||||||
@@ -83,6 +82,9 @@ const TransferToLayingFormModal = () => {
|
|||||||
TransferToLayingFormValues | undefined
|
TransferToLayingFormValues | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
|
const [formErrorMessage, setFormErrorMessage] = useState<string | null>(null);
|
||||||
|
const [submittedActionType, setSubmittedActionType] = useState<
|
||||||
|
'add' | 'edit' | null
|
||||||
|
>(null);
|
||||||
|
|
||||||
// Flock Source
|
// Flock Source
|
||||||
const {
|
const {
|
||||||
@@ -175,7 +177,7 @@ const TransferToLayingFormModal = () => {
|
|||||||
[router]
|
[router]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [formikInitialValues, setFormikInitialValues] = useState(
|
const [formikInitialValues] = useState(
|
||||||
getTransferToLayingFormInitialValues()
|
getTransferToLayingFormInitialValues()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -203,6 +205,7 @@ const TransferToLayingFormModal = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setFormikLastValues(values);
|
setFormikLastValues(values);
|
||||||
|
setSubmittedActionType(modalAction as 'add' | 'edit');
|
||||||
|
|
||||||
switch (modalAction) {
|
switch (modalAction) {
|
||||||
case 'add':
|
case 'add':
|
||||||
@@ -234,10 +237,7 @@ const TransferToLayingFormModal = () => {
|
|||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const {
|
const { data: flockSourceKandangsAvailability } = useSWR(
|
||||||
data: flockSourceKandangsAvailability,
|
|
||||||
isLoading: isLoadingFlockSourceKandangsAvailability,
|
|
||||||
} = useSWR(
|
|
||||||
formik.values.flockSource
|
formik.values.flockSource
|
||||||
? [
|
? [
|
||||||
'transfer-to-laying',
|
'transfer-to-laying',
|
||||||
@@ -293,10 +293,7 @@ const TransferToLayingFormModal = () => {
|
|||||||
return { available: countAvailable, unavailable: countUnavailable };
|
return { available: countAvailable, unavailable: countUnavailable };
|
||||||
}, [mappedFlockSourceKandangsAvailability]);
|
}, [mappedFlockSourceKandangsAvailability]);
|
||||||
|
|
||||||
const {
|
const { data: flockDestinationKandangsMaxTargetQty } = useSWR(
|
||||||
data: flockDestinationKandangsMaxTargetQty,
|
|
||||||
isLoading: isLoadingFlockDestinationKandangsMaxTargetQty,
|
|
||||||
} = useSWR(
|
|
||||||
formik.values.flockDestination
|
formik.values.flockDestination
|
||||||
? [
|
? [
|
||||||
'transfer-to-laying',
|
'transfer-to-laying',
|
||||||
@@ -1059,10 +1056,21 @@ const TransferToLayingFormModal = () => {
|
|||||||
<TransferToLayingConfirmationModal
|
<TransferToLayingConfirmationModal
|
||||||
ref={successModal.ref}
|
ref={successModal.ref}
|
||||||
type='success'
|
type='success'
|
||||||
text='Data Berhasil Ditambahkan'
|
text={
|
||||||
subtitleText='Data transfer to laying telah berhasil disimpan.'
|
submittedActionType === 'edit'
|
||||||
|
? 'Data Berhasil Diperbarui'
|
||||||
|
: 'Data Berhasil Ditambahkan'
|
||||||
|
}
|
||||||
|
subtitleText={
|
||||||
|
submittedActionType === 'edit'
|
||||||
|
? 'Data transfer to laying telah berhasil diperbarui.'
|
||||||
|
: 'Data transfer to laying telah berhasil disimpan.'
|
||||||
|
}
|
||||||
transferToLayingForm={formikLastValues}
|
transferToLayingForm={formikLastValues}
|
||||||
onClose={() => setFormikLastValues(undefined)}
|
onClose={() => {
|
||||||
|
setFormikLastValues(undefined);
|
||||||
|
setSubmittedActionType(null);
|
||||||
|
}}
|
||||||
secondaryButton={undefined}
|
secondaryButton={undefined}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -680,6 +680,7 @@ const TransferToLayingsTable = () => {
|
|||||||
subtitleText='Are you sure you want to delete this data? '
|
subtitleText='Are you sure you want to delete this data? '
|
||||||
transferToLayingIds={selectedRowIds}
|
transferToLayingIds={selectedRowIds}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
|
text: 'Delete',
|
||||||
isLoading: isDeleteLoading,
|
isLoading: isDeleteLoading,
|
||||||
color: 'error',
|
color: 'error',
|
||||||
onClick: confirmationModalDeleteClickHandler,
|
onClick: confirmationModalDeleteClickHandler,
|
||||||
@@ -704,6 +705,7 @@ const TransferToLayingsTable = () => {
|
|||||||
withNote
|
withNote
|
||||||
noteLabel='Notes Approval'
|
noteLabel='Notes Approval'
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
|
text: 'Approve',
|
||||||
isLoading: isApproveLoading,
|
isLoading: isApproveLoading,
|
||||||
onClick: confirmationModalApproveClickHandler,
|
onClick: confirmationModalApproveClickHandler,
|
||||||
}}
|
}}
|
||||||
@@ -735,6 +737,7 @@ const TransferToLayingsTable = () => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
|
text: 'Reject',
|
||||||
isLoading: isRejectLoading,
|
isLoading: isRejectLoading,
|
||||||
color: 'error',
|
color: 'error',
|
||||||
onClick: confirmationModalRejectClickHandler,
|
onClick: confirmationModalRejectClickHandler,
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ import * as Yup from 'yup';
|
|||||||
import { TransferToLaying } from '@/types/api/production/transfer-to-laying';
|
import { TransferToLaying } from '@/types/api/production/transfer-to-laying';
|
||||||
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying';
|
||||||
import { formatDate, formatNumber } from '@/lib/helper';
|
import { formatDate, formatNumber } from '@/lib/helper';
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
|
||||||
import { ProjectFlockApi } from '@/services/api/production/project-flock';
|
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
|
||||||
|
|
||||||
type TransferToLayingFormSchemaType = {
|
type TransferToLayingFormSchemaType = {
|
||||||
transfer_date?: string;
|
transfer_date?: string;
|
||||||
|
|||||||
@@ -203,16 +203,19 @@ const UniformityForm = ({
|
|||||||
|
|
||||||
// ===== RECORDINGS DATA (FOR WEEK CALCULATION) =====
|
// ===== RECORDINGS DATA (FOR WEEK CALCULATION) =====
|
||||||
const recordingsUrl = useMemo(() => {
|
const recordingsUrl = useMemo(() => {
|
||||||
|
if (!projectFlockKandangLookup?.project_flock_kandang_id) return null;
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
|
project_flock_kandang_id:
|
||||||
|
projectFlockKandangLookup.project_flock_kandang_id.toString(),
|
||||||
});
|
});
|
||||||
return `${RecordingApi.basePath}?${params.toString()}`;
|
return `${RecordingApi.basePath}?${params.toString()}`;
|
||||||
}, []);
|
}, [projectFlockKandangLookup?.project_flock_kandang_id]);
|
||||||
|
|
||||||
const { data: recordingsData } = useSWR(
|
const { data: recordingsData } = useSWR(
|
||||||
recordingsUrl,
|
recordingsUrl,
|
||||||
RecordingApi.getAllFetcher
|
recordingsUrl ? RecordingApi.getAllFetcher : null
|
||||||
);
|
);
|
||||||
|
|
||||||
// ===== FORM CONFIGURATION =====
|
// ===== FORM CONFIGURATION =====
|
||||||
@@ -400,50 +403,46 @@ const UniformityForm = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
projectFlockKandangLookup?.chick_in_date &&
|
projectFlockKandangLookup?.chick_in_date &&
|
||||||
projectFlockKandangLookup?.project_flock_kandang_id &&
|
projectFlockKandangLookup?.project_flock_kandang_id
|
||||||
isResponseSuccess(recordingsData) &&
|
|
||||||
recordingsData.data
|
|
||||||
) {
|
) {
|
||||||
const matchingRecordings = recordingsData.data.filter(
|
const chickInDate = new Date(projectFlockKandangLookup.chick_in_date);
|
||||||
(recording: Recording) =>
|
chickInDate.setHours(0, 0, 0, 0);
|
||||||
recording.project_flock?.project_flock_kandang_id ===
|
|
||||||
projectFlockKandangLookup.project_flock_kandang_id
|
|
||||||
);
|
|
||||||
|
|
||||||
matchingRecordings.sort(
|
let initialWeek = 18;
|
||||||
(a: Recording, b: Recording) =>
|
|
||||||
new Date(a.record_datetime).getTime() -
|
|
||||||
new Date(b.record_datetime).getTime()
|
|
||||||
);
|
|
||||||
|
|
||||||
const earliestRecording = matchingRecordings[0];
|
if (
|
||||||
|
isResponseSuccess(recordingsData) &&
|
||||||
|
recordingsData.data &&
|
||||||
|
recordingsData.data.length > 0
|
||||||
|
) {
|
||||||
|
const sortedRecordings = [...recordingsData.data].sort(
|
||||||
|
(a: Recording, b: Recording) =>
|
||||||
|
new Date(a.record_datetime).getTime() -
|
||||||
|
new Date(b.record_datetime).getTime()
|
||||||
|
);
|
||||||
|
|
||||||
if (earliestRecording) {
|
const earliestRecording = sortedRecordings[0];
|
||||||
const chickInDate = new Date(projectFlockKandangLookup.chick_in_date);
|
if (earliestRecording?.project_flock?.production_standart?.week) {
|
||||||
chickInDate.setHours(0, 0, 0, 0);
|
initialWeek =
|
||||||
|
earliestRecording.project_flock.production_standart.week;
|
||||||
const earliestRecordDate = new Date(earliestRecording.record_datetime);
|
|
||||||
earliestRecordDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const initialWeek =
|
|
||||||
earliestRecording.project_flock?.production_standart?.week || 18;
|
|
||||||
|
|
||||||
if (formik.values.date) {
|
|
||||||
const selectedDate = new Date(formik.values.date);
|
|
||||||
selectedDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const daysDiff = Math.floor(
|
|
||||||
(selectedDate.getTime() - chickInDate.getTime()) /
|
|
||||||
(1000 * 60 * 60 * 24)
|
|
||||||
);
|
|
||||||
|
|
||||||
const weeksDiff = Math.floor(daysDiff / 7);
|
|
||||||
|
|
||||||
formik.setFieldValue('week', initialWeek + weeksDiff);
|
|
||||||
} else {
|
|
||||||
formik.setFieldValue('week', initialWeek);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (formik.values.date) {
|
||||||
|
const selectedDate = new Date(formik.values.date);
|
||||||
|
selectedDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
const daysDiff = Math.floor(
|
||||||
|
(selectedDate.getTime() - chickInDate.getTime()) /
|
||||||
|
(1000 * 60 * 60 * 24)
|
||||||
|
);
|
||||||
|
|
||||||
|
const weeksDiff = Math.floor(daysDiff / 7);
|
||||||
|
|
||||||
|
formik.setFieldValue('week', initialWeek + weeksDiff);
|
||||||
|
} else {
|
||||||
|
formik.setFieldValue('week', initialWeek);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
projectFlockKandangLookup?.chick_in_date,
|
projectFlockKandangLookup?.chick_in_date,
|
||||||
|
|||||||
@@ -153,11 +153,9 @@ const PurchaseOrderAcceptApprovalForm = ({
|
|||||||
|
|
||||||
// ===== SELECT INPUT DATA =====
|
// ===== SELECT INPUT DATA =====
|
||||||
const {
|
const {
|
||||||
setInputValue: setExpeditionsSelectInputValue,
|
|
||||||
options: expeditionVendors,
|
options: expeditionVendors,
|
||||||
isLoadingOptions: isLoadingExpeditions,
|
isLoadingOptions: isLoadingExpeditions,
|
||||||
loadMore: loadMoreExpeditions,
|
loadMore: loadMoreExpeditions,
|
||||||
hasMore: hasMoreExpeditions,
|
|
||||||
} = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search', {
|
} = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search', {
|
||||||
category: 'BOP',
|
category: 'BOP',
|
||||||
flag: 'EKSPEDISI',
|
flag: 'EKSPEDISI',
|
||||||
@@ -343,19 +341,6 @@ const PurchaseOrderAcceptApprovalForm = ({
|
|||||||
) => {
|
) => {
|
||||||
const numValue = typeof value === 'string' ? parseFloat(value) || 0 : value;
|
const numValue = typeof value === 'string' ? parseFloat(value) || 0 : value;
|
||||||
formik.setFieldValue(`items.${idx}.${field}`, numValue);
|
formik.setFieldValue(`items.${idx}.${field}`, numValue);
|
||||||
|
|
||||||
if (field === 'received_qty' || field === 'transport_per_item') {
|
|
||||||
const receivedQty =
|
|
||||||
field === 'received_qty'
|
|
||||||
? numValue
|
|
||||||
: parseFloat(formik.values.items?.[idx]?.received_qty as string) || 0;
|
|
||||||
const transportPerItem =
|
|
||||||
field === 'transport_per_item'
|
|
||||||
? numValue
|
|
||||||
: parseFloat(
|
|
||||||
formik.values.items?.[idx]?.transport_per_item as string
|
|
||||||
) || 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const PurchaseRequestForm = ({
|
|||||||
const deleteModal = useModal();
|
const deleteModal = useModal();
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
const [locationSelectInputValue, setLocationSelectInputValue] = useState('');
|
const [, setLocationSelectInputValue] = useState('');
|
||||||
const [selectedPurchaseItems, setSelectedPurchaseItems] = useState<number[]>(
|
const [selectedPurchaseItems, setSelectedPurchaseItems] = useState<number[]>(
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
@@ -149,7 +149,6 @@ const PurchaseRequestForm = ({
|
|||||||
isLoadingOptions: isLoadingSuppliers,
|
isLoadingOptions: isLoadingSuppliers,
|
||||||
rawData: supplierRawData,
|
rawData: supplierRawData,
|
||||||
loadMore: loadMoreSuppliers,
|
loadMore: loadMoreSuppliers,
|
||||||
hasMore: hasMoreSuppliers,
|
|
||||||
} = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search', {
|
} = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search', {
|
||||||
category: 'SAPRONAK',
|
category: 'SAPRONAK',
|
||||||
});
|
});
|
||||||
@@ -164,7 +163,6 @@ const PurchaseRequestForm = ({
|
|||||||
options: locationOptions,
|
options: locationOptions,
|
||||||
isLoadingOptions: isLoadingLocations,
|
isLoadingOptions: isLoadingLocations,
|
||||||
loadMore: loadMoreLocations,
|
loadMore: loadMoreLocations,
|
||||||
hasMore: hasMoreLocations,
|
|
||||||
} = useSelect(LocationApi.basePath, 'id', 'name', '', {
|
} = useSelect(LocationApi.basePath, 'id', 'name', '', {
|
||||||
area_id:
|
area_id:
|
||||||
selectedArea != ''
|
selectedArea != ''
|
||||||
@@ -173,12 +171,10 @@ const PurchaseRequestForm = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
inputValue: warehouseSelectInputValue,
|
|
||||||
setInputValue: setWarehouseSelectInputValue,
|
setInputValue: setWarehouseSelectInputValue,
|
||||||
options: warehouseOptions,
|
options: warehouseOptions,
|
||||||
isLoadingOptions: isLoadingWarehouses,
|
isLoadingOptions: isLoadingWarehouses,
|
||||||
loadMore: loadMoreWarehouses,
|
loadMore: loadMoreWarehouses,
|
||||||
hasMore: hasMoreWarehouses,
|
|
||||||
} = useSelect(WarehouseApi.basePath, 'id', 'name', 'search', {
|
} = useSelect(WarehouseApi.basePath, 'id', 'name', 'search', {
|
||||||
area_id:
|
area_id:
|
||||||
selectedArea != ''
|
selectedArea != ''
|
||||||
@@ -651,7 +647,7 @@ const PurchaseRequestForm = ({
|
|||||||
{formik.values.items?.map((item, idx) => (
|
{formik.values.items?.map((item, idx) => (
|
||||||
<tr key={`purchase-item-${idx}`}>
|
<tr key={`purchase-item-${idx}`}>
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
<td className='!align-middle'>
|
<td className='align-middle!'>
|
||||||
<CheckboxInput
|
<CheckboxInput
|
||||||
name={`purchase-item-${idx}`}
|
name={`purchase-item-${idx}`}
|
||||||
checked={selectedPurchaseItems.includes(idx)}
|
checked={selectedPurchaseItems.includes(idx)}
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ interface PurchaseOrderDetailProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PurchaseOrderDetail = ({
|
const PurchaseOrderDetail = ({
|
||||||
type = 'detail',
|
|
||||||
initialValues,
|
initialValues,
|
||||||
refetchData,
|
refetchData,
|
||||||
}: PurchaseOrderDetailProps) => {
|
}: PurchaseOrderDetailProps) => {
|
||||||
@@ -1042,7 +1041,7 @@ const PurchaseOrderDetail = ({
|
|||||||
ref={staffApprovalModal.ref}
|
ref={staffApprovalModal.ref}
|
||||||
closeOnBackdrop
|
closeOnBackdrop
|
||||||
className={{
|
className={{
|
||||||
modalBox: 'w-full max-w-screen-2xl max-h-[90vh] overflow-y-auto',
|
modalBox: 'w-full max-w-2xl max-h-[90vh] overflow-y-auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PurchaseOrderStaffApprovalForm
|
<PurchaseOrderStaffApprovalForm
|
||||||
@@ -1061,7 +1060,7 @@ const PurchaseOrderDetail = ({
|
|||||||
ref={acceptApprovalModal.ref}
|
ref={acceptApprovalModal.ref}
|
||||||
closeOnBackdrop
|
closeOnBackdrop
|
||||||
className={{
|
className={{
|
||||||
modalBox: 'w-full max-w-screen-2xl max-h-[90vh] overflow-y-auto',
|
modalBox: 'w-full max-w-2xl max-h-[90vh] overflow-y-auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PurchaseOrderAcceptApprovalForm
|
<PurchaseOrderAcceptApprovalForm
|
||||||
@@ -1079,7 +1078,7 @@ const PurchaseOrderDetail = ({
|
|||||||
ref={editModal.ref}
|
ref={editModal.ref}
|
||||||
closeOnBackdrop
|
closeOnBackdrop
|
||||||
className={{
|
className={{
|
||||||
modalBox: 'w-full max-w-screen-2xl max-h-[90vh] overflow-y-auto',
|
modalBox: 'w-full max-w-2xl max-h-[90vh] overflow-y-auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PurchaseOrderStaffApprovalForm
|
<PurchaseOrderStaffApprovalForm
|
||||||
@@ -1098,7 +1097,7 @@ const PurchaseOrderDetail = ({
|
|||||||
ref={penerimaanBarangModal.ref}
|
ref={penerimaanBarangModal.ref}
|
||||||
closeOnBackdrop
|
closeOnBackdrop
|
||||||
className={{
|
className={{
|
||||||
modalBox: 'w-full max-w-screen-2xl max-h-[90vh] overflow-y-auto',
|
modalBox: 'w-full max-w-2xl max-h-[90vh] overflow-y-auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PurchaseOrderAcceptApprovalForm
|
<PurchaseOrderAcceptApprovalForm
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
import { ReportExpense } from '@/types/api/report/report-expense';
|
import { ReportExpense } from '@/types/api/report/report-expense';
|
||||||
import { formatCurrency, formatDate } from '@/lib/helper';
|
import { formatDate } from '@/lib/helper';
|
||||||
|
|
||||||
export const generateReportExpenseExcel = async (
|
export const generateReportExpenseExcel = async (
|
||||||
data: ReportExpense[]
|
data: ReportExpense[]
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const getTableColumns = (
|
|||||||
header: 'No',
|
header: 'No',
|
||||||
flex: 0.5,
|
flex: 0.5,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cell: ({ row, index }) => index + 1,
|
cell: ({ index }) => index + 1,
|
||||||
footer: 'Total',
|
footer: 'Total',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const getTableColumns = (total?: DebtSupplier['total']): PdfColumn[] => {
|
|||||||
header: 'No',
|
header: 'No',
|
||||||
flex: 0.5,
|
flex: 0.5,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cell: ({ row, index }) => index + 1,
|
cell: ({ index }) => index + 1,
|
||||||
footer: 'Total',
|
footer: 'Total',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import ExcelJS from 'exceljs';
|
import ExcelJS from 'exceljs';
|
||||||
import { formatDate } from '@/lib/helper';
|
import { formatDate } from '@/lib/helper';
|
||||||
import { DebtRow, DebtSupplier } from '@/types/api/report/debt-supplier';
|
import { DebtSupplier } from '@/types/api/report/debt-supplier';
|
||||||
|
|
||||||
interface DebtSupplierExportExcelParams {
|
interface DebtSupplierExportExcelParams {
|
||||||
data: DebtSupplier[];
|
data: DebtSupplier[];
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
|
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { DebtRow } from '@/types/api/report/debt-supplier';
|
import { DebtRow } from '@/types/api/report/debt-supplier';
|
||||||
import { Icon } from '@iconify/react';
|
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
|
||||||
const DebtSupplierSkeleton = ({
|
const DebtSupplierSkeleton = ({
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
|
|||||||
filterModal.closeModal();
|
filterModal.closeModal();
|
||||||
setIsSubmitted(true);
|
setIsSubmitted(true);
|
||||||
},
|
},
|
||||||
onReset: (values) => {
|
onReset: () => {
|
||||||
setFilterParams({
|
setFilterParams({
|
||||||
start_date: undefined,
|
start_date: undefined,
|
||||||
end_date: undefined,
|
end_date: undefined,
|
||||||
@@ -170,10 +170,6 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
|
|||||||
: [],
|
: [],
|
||||||
[debtSupplier]
|
[debtSupplier]
|
||||||
);
|
);
|
||||||
const meta =
|
|
||||||
isResponseSuccess(debtSupplier) && debtSupplier?.meta
|
|
||||||
? debtSupplier.meta
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// ===== EXPORT DATA FETCHER =====
|
// ===== EXPORT DATA FETCHER =====
|
||||||
const debtSupplierExport = useCallback(async (): Promise<
|
const debtSupplierExport = useCallback(async (): Promise<
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const getTableColumns = (
|
|||||||
header: 'No',
|
header: 'No',
|
||||||
flex: 0.5,
|
flex: 0.5,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cell: ({ row, index }) => index + 1,
|
cell: ({ index }) => index + 1,
|
||||||
footer: 'Total',
|
footer: 'Total',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -336,11 +336,6 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
|
|||||||
[purchasePerSupplier]
|
[purchasePerSupplier]
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta =
|
|
||||||
isResponseSuccess(purchasePerSupplier) && purchasePerSupplier?.meta
|
|
||||||
? purchasePerSupplier.meta
|
|
||||||
: null;
|
|
||||||
|
|
||||||
// ===== EXPORT DATA FETCHER =====
|
// ===== EXPORT DATA FETCHER =====
|
||||||
const logisticPurchasePerSupplierExport = useCallback(async (): Promise<
|
const logisticPurchasePerSupplierExport = useCallback(async (): Promise<
|
||||||
LogisticPurchasePerSupplierReport[] | null
|
LogisticPurchasePerSupplierReport[] | null
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const getTableColumns = (
|
|||||||
header: 'No',
|
header: 'No',
|
||||||
flex: 0.5,
|
flex: 0.5,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cell: ({ row, index }) => index + 1,
|
cell: ({ index }) => index + 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'so_date',
|
key: 'so_date',
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ const getDetailColumns = (
|
|||||||
header: 'No',
|
header: 'No',
|
||||||
flex: 0.5,
|
flex: 0.5,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
cell: ({ row, index }) => index + 1,
|
cell: ({ index }) => index + 1,
|
||||||
footer: 'TOTAL',
|
footer: 'TOTAL',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -324,11 +324,6 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
|
|||||||
[hppPerKandang]
|
[hppPerKandang]
|
||||||
);
|
);
|
||||||
|
|
||||||
const period =
|
|
||||||
isResponseSuccess(hppPerKandang) && hppPerKandang?.data?.period
|
|
||||||
? hppPerKandang.data.period
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
// ===== EXPORT DATA FETCHER =====
|
// ===== EXPORT DATA FETCHER =====
|
||||||
const hppPerKandangExport =
|
const hppPerKandangExport =
|
||||||
useCallback(async (): Promise<HppPerKandangReport | null> => {
|
useCallback(async (): Promise<HppPerKandangReport | null> => {
|
||||||
|
|||||||
-1
@@ -28,7 +28,6 @@ const ProductionResultProjectFlockKandangTable = ({
|
|||||||
setPage,
|
setPage,
|
||||||
setPageSize,
|
setPageSize,
|
||||||
toQueryString: getTableFilterQueryString,
|
toQueryString: getTableFilterQueryString,
|
||||||
reset: resetFilter,
|
|
||||||
} = useTableFilter({
|
} = useTableFilter({
|
||||||
initial: {
|
initial: {
|
||||||
filter_by: '',
|
filter_by: '',
|
||||||
|
|||||||
@@ -46,15 +46,15 @@ export function DatePicker({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatDateInput = (dateStr: string) => {
|
// const formatDateInput = (dateStr: string) => {
|
||||||
if (!dateStr) return '';
|
// if (!dateStr) return '';
|
||||||
const d = new Date(dateStr + 'T00:00:00');
|
// const d = new Date(dateStr + 'T00:00:00');
|
||||||
return d.toLocaleDateString('en-GB', {
|
// return d.toLocaleDateString('en-GB', {
|
||||||
day: '2-digit',
|
// day: '2-digit',
|
||||||
month: '2-digit',
|
// month: '2-digit',
|
||||||
year: 'numeric',
|
// year: 'numeric',
|
||||||
});
|
// });
|
||||||
};
|
// };
|
||||||
|
|
||||||
const displayFormatter = formatDisplay || defaultFormatDisplay;
|
const displayFormatter = formatDisplay || defaultFormatDisplay;
|
||||||
|
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ import {
|
|||||||
} from '@/figma-make/components/base/popover';
|
} from '@/figma-make/components/base/popover';
|
||||||
import { Input } from '@/figma-make/components/base/input';
|
import { Input } from '@/figma-make/components/base/input';
|
||||||
|
|
||||||
interface DateRange {
|
|
||||||
from: string;
|
|
||||||
to: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DateRangePickerProps {
|
interface DateRangePickerProps {
|
||||||
dateFrom: string;
|
dateFrom: string;
|
||||||
dateTo: string;
|
dateTo: string;
|
||||||
|
|||||||
@@ -86,17 +86,18 @@ export function DailyChecklistContent() {
|
|||||||
searchParams.get('category') || ''
|
searchParams.get('category') || ''
|
||||||
);
|
);
|
||||||
|
|
||||||
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
const { options: kandangOptions } = useSelect(
|
||||||
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
KandangApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const { data: phases } = useSWR<
|
||||||
data: phases,
|
|
||||||
isLoading: isLoadingPhases,
|
|
||||||
mutate: refreshPhases,
|
|
||||||
} = useSWR<
|
|
||||||
BaseApiResponse<Phase[] | undefined>,
|
BaseApiResponse<Phase[] | undefined>,
|
||||||
AxiosError<BaseApiResponse>,
|
AxiosError<BaseApiResponse>,
|
||||||
SWRHttpKey
|
SWRHttpKey
|
||||||
@@ -104,11 +105,7 @@ export function DailyChecklistContent() {
|
|||||||
keepPreviousData: true,
|
keepPreviousData: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { data: employeesRes } = useSWR(
|
||||||
data: employeesRes,
|
|
||||||
isLoading: isLoadingEmployees,
|
|
||||||
mutate: refreshEmployees,
|
|
||||||
} = useSWR(
|
|
||||||
`${EmployeeApi.basePath}?page=1&limit=500&kandang_id=${kandangId}&is_active=true`,
|
`${EmployeeApi.basePath}?page=1&limit=500&kandang_id=${kandangId}&is_active=true`,
|
||||||
EmployeeApi.getAllFetcher,
|
EmployeeApi.getAllFetcher,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,12 +16,7 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/figma-make/components/base/select';
|
} from '@/figma-make/components/base/select';
|
||||||
import { Badge } from '@/figma-make/components/base/badge';
|
import { Badge } from '@/figma-make/components/base/badge';
|
||||||
import {
|
import { Users, AlertCircle, Info } from 'lucide-react';
|
||||||
Calendar as CalendarIcon,
|
|
||||||
Users,
|
|
||||||
AlertCircle,
|
|
||||||
Info,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import { DateRangePicker } from '@/figma-make/components/base/date-range-picker';
|
import { DateRangePicker } from '@/figma-make/components/base/date-range-picker';
|
||||||
import {
|
import {
|
||||||
BarChart,
|
BarChart,
|
||||||
@@ -71,11 +66,7 @@ export function Dashboard() {
|
|||||||
const [kandangFilter, setKandangFilter] = useState('ALL');
|
const [kandangFilter, setKandangFilter] = useState('ALL');
|
||||||
const [categoryFilter, setCategoryFilter] = useState('ALL');
|
const [categoryFilter, setCategoryFilter] = useState('ALL');
|
||||||
|
|
||||||
const {
|
const { data: summaryResponse, isLoading: isLoadingSummary } = useSWR<
|
||||||
data: summaryResponse,
|
|
||||||
isLoading: isLoadingSummary,
|
|
||||||
mutate: refreshSummary,
|
|
||||||
} = useSWR<
|
|
||||||
BaseApiResponse<DailyChecklistSummary | undefined>,
|
BaseApiResponse<DailyChecklistSummary | undefined>,
|
||||||
AxiosError<BaseApiResponse>,
|
AxiosError<BaseApiResponse>,
|
||||||
SWRHttpKey
|
SWRHttpKey
|
||||||
@@ -86,11 +77,16 @@ export function Dashboard() {
|
|||||||
httpClientFetcher
|
httpClientFetcher
|
||||||
);
|
);
|
||||||
|
|
||||||
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
const { options: kandangOptions } = useSelect(
|
||||||
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
KandangApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const kandangColorMap: { [key: string]: string } = {};
|
const kandangColorMap: { [key: string]: string } = {};
|
||||||
(kandangOptions || []).forEach((k, index) => {
|
(kandangOptions || []).forEach((k, index) => {
|
||||||
|
|||||||
@@ -38,11 +38,6 @@ import { KandangApi } from '@/services/api/master-data';
|
|||||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
|
|
||||||
interface Kandang {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const STATUS_OPTIONS = [
|
const STATUS_OPTIONS = [
|
||||||
{ value: 'ALL', label: 'Semua Status' },
|
{ value: 'ALL', label: 'Semua Status' },
|
||||||
{ value: 'DRAFT', label: 'Draft' },
|
{ value: 'DRAFT', label: 'Draft' },
|
||||||
@@ -98,11 +93,16 @@ export function ListDailyChecklistContent() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
const { options: kandangOptions } = useSelect(
|
||||||
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
KandangApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const checklistList = isResponseSuccess(checklistListRes)
|
const checklistList = isResponseSuccess(checklistListRes)
|
||||||
? checklistListRes.data || []
|
? checklistListRes.data || []
|
||||||
|
|||||||
+14
-17
@@ -17,7 +17,7 @@ import {
|
|||||||
DialogFooter,
|
DialogFooter,
|
||||||
} from '@/figma-make/components/base/dialog';
|
} from '@/figma-make/components/base/dialog';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { notFound, useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { DailyChecklistApi } from '@/services/api/daily-checklist/daily-checklist';
|
import { DailyChecklistApi } from '@/services/api/daily-checklist/daily-checklist';
|
||||||
import { isResponseError } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
@@ -90,16 +90,16 @@ interface ChecklistData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AssignmentQueryResult {
|
// interface AssignmentQueryResult {
|
||||||
task_id: number;
|
// task_id: number;
|
||||||
employee_id: string;
|
// employee_id: string;
|
||||||
checked: boolean;
|
// checked: boolean;
|
||||||
note: string | null;
|
// note: string | null;
|
||||||
employees: {
|
// employees: {
|
||||||
id: number;
|
// id: number;
|
||||||
name: string;
|
// name: string;
|
||||||
} | null;
|
// } | null;
|
||||||
}
|
// }
|
||||||
|
|
||||||
const CATEGORY_LABELS: { [key: string]: string } = {
|
const CATEGORY_LABELS: { [key: string]: string } = {
|
||||||
pullet_open: 'Pullet Open',
|
pullet_open: 'Pullet Open',
|
||||||
@@ -124,7 +124,7 @@ export function DetailDailyChecklistContent() {
|
|||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [header, setHeader] = useState<ChecklistHeader | null>(null);
|
const [header, setHeader] = useState<ChecklistHeader | null>(null);
|
||||||
const [detailRows, setDetailRows] = useState<ChecklistDetailRow[]>([]);
|
const [, setDetailRows] = useState<ChecklistDetailRow[]>([]);
|
||||||
const [phaseGroups, setPhaseGroups] = useState<PhaseGroup[]>([]);
|
const [phaseGroups, setPhaseGroups] = useState<PhaseGroup[]>([]);
|
||||||
const [employees, setEmployees] = useState<{ id: string; name: string }[]>(
|
const [employees, setEmployees] = useState<{ id: string; name: string }[]>(
|
||||||
[]
|
[]
|
||||||
@@ -381,7 +381,7 @@ export function DetailDailyChecklistContent() {
|
|||||||
// Convert to array and group by time_type
|
// Convert to array and group by time_type
|
||||||
const grouped: PhaseGroup[] = [];
|
const grouped: PhaseGroup[] = [];
|
||||||
|
|
||||||
phaseMap.forEach((phaseData, phaseId) => {
|
phaseMap.forEach((phaseData) => {
|
||||||
const timeGroups: {
|
const timeGroups: {
|
||||||
[timeType: string]: {
|
[timeType: string]: {
|
||||||
activities: {
|
activities: {
|
||||||
@@ -570,9 +570,6 @@ export function DetailDailyChecklistContent() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isReadOnly =
|
|
||||||
header.status === 'APPROVED' || header.status === 'REJECTED';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='min-h-screen'>
|
<div className='min-h-screen'>
|
||||||
<div className='p-6'>
|
<div className='p-6'>
|
||||||
@@ -680,7 +677,7 @@ export function DetailDailyChecklistContent() {
|
|||||||
{header.status === 'REJECTED' && header.reject_reason && (
|
{header.status === 'REJECTED' && header.reject_reason && (
|
||||||
<div className='mt-6 pt-6 border-t border-gray-200'>
|
<div className='mt-6 pt-6 border-t border-gray-200'>
|
||||||
<div className='flex items-start gap-3 p-4 bg-red-50 border border-red-200 rounded-lg'>
|
<div className='flex items-start gap-3 p-4 bg-red-50 border border-red-200 rounded-lg'>
|
||||||
<AlertCircle className='w-5 h-5 text-red-600 mt-0.5 flex-shrink-0' />
|
<AlertCircle className='w-5 h-5 text-red-600 mt-0.5 shrink-0' />
|
||||||
<div>
|
<div>
|
||||||
<Label className='text-sm font-medium text-red-900'>
|
<Label className='text-sm font-medium text-red-900'>
|
||||||
Alasan Reject
|
Alasan Reject
|
||||||
|
|||||||
@@ -69,11 +69,7 @@ export function MasterAktivitasContent() {
|
|||||||
const [selectedCategory, setSelectedCategory] = useState<string>('');
|
const [selectedCategory, setSelectedCategory] = useState<string>('');
|
||||||
const [selectedPhase, setSelectedPhase] = useState<Phase | null>(null);
|
const [selectedPhase, setSelectedPhase] = useState<Phase | null>(null);
|
||||||
|
|
||||||
const {
|
const { data: phases, mutate: refreshPhases } = useSWR<
|
||||||
data: phases,
|
|
||||||
isLoading: isLoadingPhases,
|
|
||||||
mutate: refreshPhases,
|
|
||||||
} = useSWR<
|
|
||||||
BaseApiResponse<Phase[] | undefined>,
|
BaseApiResponse<Phase[] | undefined>,
|
||||||
AxiosError<BaseApiResponse>,
|
AxiosError<BaseApiResponse>,
|
||||||
SWRHttpKey
|
SWRHttpKey
|
||||||
@@ -87,11 +83,7 @@ export function MasterAktivitasContent() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const { data: phaseActivities, mutate: refreshPhaseActivities } = useSWR<
|
||||||
data: phaseActivities,
|
|
||||||
isLoading: isLoadingPhaseActivities,
|
|
||||||
mutate: refreshPhaseActivities,
|
|
||||||
} = useSWR<
|
|
||||||
BaseApiResponse<PhaseActivity[] | undefined>,
|
BaseApiResponse<PhaseActivity[] | undefined>,
|
||||||
AxiosError<BaseApiResponse>,
|
AxiosError<BaseApiResponse>,
|
||||||
SWRHttpKey
|
SWRHttpKey
|
||||||
@@ -630,7 +622,7 @@ export function MasterAktivitasContent() {
|
|||||||
<th className='text-left py-3.5 px-6 text-sm font-semibold text-gray-700'>
|
<th className='text-left py-3.5 px-6 text-sm font-semibold text-gray-700'>
|
||||||
Nama Aktivitas
|
Nama Aktivitas
|
||||||
</th>
|
</th>
|
||||||
<th className='text-center py-3.5 px-6 text-sm font-semibold text-gray-700 w-[80px]'>
|
<th className='text-center py-3.5 px-6 text-sm font-semibold text-gray-700 w-20'>
|
||||||
Aksi
|
Aksi
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
+1
-5
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Plus, MoreVertical, Pencil, Trash2 } from 'lucide-react';
|
import { Plus, MoreVertical, Pencil, Trash2 } from 'lucide-react';
|
||||||
import { Card, CardContent } from '@/figma-make/components/base/card';
|
import { Card, CardContent } from '@/figma-make/components/base/card';
|
||||||
import { Button } from '@/figma-make/components/base/button';
|
import { Button } from '@/figma-make/components/base/button';
|
||||||
@@ -295,10 +295,6 @@ export function MasterConfigurationContent() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExport = (format: string) => {
|
|
||||||
toast.success(`Data berhasil diekspor ke ${format}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isLoadingDailyChecklistConfigurations && !dailyChecklistConfigurations) {
|
if (isLoadingDailyChecklistConfigurations && !dailyChecklistConfigurations) {
|
||||||
return (
|
return (
|
||||||
<div className='min-h-screen'>
|
<div className='min-h-screen'>
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import {
|
import { Plus, MoreVertical, Pencil, Trash2, Search } from 'lucide-react';
|
||||||
Plus,
|
|
||||||
Download,
|
|
||||||
ChevronDown,
|
|
||||||
MoreVertical,
|
|
||||||
Pencil,
|
|
||||||
Trash2,
|
|
||||||
Search,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import { Card, CardContent } from '@/figma-make/components/base/card';
|
import { Card, CardContent } from '@/figma-make/components/base/card';
|
||||||
import { Button } from '@/figma-make/components/base/button';
|
import { Button } from '@/figma-make/components/base/button';
|
||||||
import { Label } from '@/figma-make/components/base/label';
|
import { Label } from '@/figma-make/components/base/label';
|
||||||
@@ -93,11 +85,16 @@ export function MasterEmployeeContent() {
|
|||||||
keepPreviousData: true,
|
keepPreviousData: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
const { options: kandangOptions } = useSelect(
|
||||||
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
KandangApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||||
@@ -373,7 +370,7 @@ export function MasterEmployeeContent() {
|
|||||||
updateFilter('status', value === 'all' ? '' : value);
|
updateFilter('status', value === 'all' ? '' : value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger className='w-[160px] border-gray-200'>
|
<SelectTrigger className='w-40 border-gray-200'>
|
||||||
<SelectValue placeholder='Semua Status' />
|
<SelectValue placeholder='Semua Status' />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Card, CardContent } from '@/figma-make/components/base/card';
|
import { Card, CardContent } from '@/figma-make/components/base/card';
|
||||||
import { Badge } from '@/figma-make/components/base/badge';
|
|
||||||
import { Label } from '@/figma-make/components/base/label';
|
import { Label } from '@/figma-make/components/base/label';
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
@@ -11,8 +10,6 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from '@/figma-make/components/base/select';
|
} from '@/figma-make/components/base/select';
|
||||||
import { toast } from 'sonner';
|
|
||||||
import { useRouter } from 'next/navigation';
|
|
||||||
import { useSelect } from '@/components/input/SelectInput';
|
import { useSelect } from '@/components/input/SelectInput';
|
||||||
import { AreaApi, KandangApi, LocationApi } from '@/services/api/master-data';
|
import { AreaApi, KandangApi, LocationApi } from '@/services/api/master-data';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -26,7 +23,6 @@ import { isResponseSuccess } from '@/lib/api-helper';
|
|||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
import { cn } from '@/lib/helper';
|
import { cn } from '@/lib/helper';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { report } from 'process';
|
|
||||||
import { PhaseApi } from '@/services/api/daily-checklist/phase';
|
import { PhaseApi } from '@/services/api/daily-checklist/phase';
|
||||||
import { EmployeeApi } from '@/services/api/daily-checklist/employee';
|
import { EmployeeApi } from '@/services/api/daily-checklist/employee';
|
||||||
import { Button } from '@/figma-make/components/base/button';
|
import { Button } from '@/figma-make/components/base/button';
|
||||||
@@ -66,8 +62,6 @@ const YEAR_OPTIONS = [
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
export function DailyChecklistReportsContent() {
|
export function DailyChecklistReportsContent() {
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const currentMonth = useMemo(() => new Date().getMonth() + 1, []);
|
const currentMonth = useMemo(() => new Date().getMonth() + 1, []);
|
||||||
const currentYear = useMemo(() => new Date().getFullYear(), []);
|
const currentYear = useMemo(() => new Date().getFullYear(), []);
|
||||||
|
|
||||||
@@ -100,11 +94,7 @@ export function DailyChecklistReportsContent() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const { data: reportResponse, isLoading: isLoadingReport } = useSWR<
|
||||||
data: reportResponse,
|
|
||||||
isLoading: isLoadingReport,
|
|
||||||
mutate: refreshReport,
|
|
||||||
} = useSWR<
|
|
||||||
BaseApiResponse<DailyChecklistReport[] | undefined>,
|
BaseApiResponse<DailyChecklistReport[] | undefined>,
|
||||||
AxiosError<BaseApiResponse>,
|
AxiosError<BaseApiResponse>,
|
||||||
SWRHttpKey
|
SWRHttpKey
|
||||||
@@ -116,7 +106,7 @@ export function DailyChecklistReportsContent() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { options: areaOptions, isLoadingOptions: isLoadingAreas } = useSelect(
|
const { options: areaOptions } = useSelect(
|
||||||
AreaApi.basePath,
|
AreaApi.basePath,
|
||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
@@ -127,33 +117,53 @@ export function DailyChecklistReportsContent() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const { options: locationOptions, isLoadingOptions: isLoadingLocations } =
|
const { options: locationOptions } = useSelect(
|
||||||
useSelect(LocationApi.basePath, 'id', 'name', 'search', {
|
LocationApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
area_id: tableFilterState.area_id,
|
area_id: tableFilterState.area_id,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } =
|
const { options: kandangOptions } = useSelect(
|
||||||
useSelect(KandangApi.basePath, 'id', 'name', 'search', {
|
KandangApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
area_id: tableFilterState.area_id,
|
area_id: tableFilterState.area_id,
|
||||||
location_id: tableFilterState.location_id,
|
location_id: tableFilterState.location_id,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { options: phaseOptions, isLoadingOptions: isLoadingPhases } =
|
const { options: phaseOptions } = useSelect(
|
||||||
useSelect(PhaseApi.basePath, 'id', 'name', 'search', {
|
PhaseApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '100',
|
limit: '100',
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { options: employeeOptions, isLoadingOptions: isLoadingEmployees } =
|
const { options: employeeOptions } = useSelect(
|
||||||
useSelect(EmployeeApi.basePath, 'id', 'name', 'search', {
|
EmployeeApi.basePath,
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'search',
|
||||||
|
{
|
||||||
page: '1',
|
page: '1',
|
||||||
limit: '500',
|
limit: '500',
|
||||||
kandang_id: tableFilterState.kandang_id,
|
kandang_id: tableFilterState.kandang_id,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const currentMonthMaxDay = new Date(
|
const currentMonthMaxDay = new Date(
|
||||||
Number(tableFilterState.tahun),
|
Number(tableFilterState.tahun),
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
} from '@/types/api/daily-checklist/daily-checklist';
|
} from '@/types/api/daily-checklist/daily-checklist';
|
||||||
import { isResponseError } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { formatDate } from '@/lib/helper';
|
|
||||||
|
|
||||||
export class DailyChecklistApiService extends BaseApiService<
|
export class DailyChecklistApiService extends BaseApiService<
|
||||||
DailyChecklist,
|
DailyChecklist,
|
||||||
@@ -316,7 +315,7 @@ export class DailyChecklistApiService extends BaseApiService<
|
|||||||
wb,
|
wb,
|
||||||
`laporan-daily-checklist-${params.get('tahun')}-${params.get('bulan')}.xlsx`
|
`laporan-daily-checklist-${params.get('tahun')}-${params.get('bulan')}.xlsx`
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Gagal melakukan export daily checklist! Coba lagi.');
|
toast.error('Gagal melakukan export daily checklist! Coba lagi.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { sleep } from '@/lib/helper';
|
|
||||||
import { BaseApiService } from '@/services/api/base';
|
import { BaseApiService } from '@/services/api/base';
|
||||||
import { BaseApiResponse, GroupedApprovals } from '@/types/api/api-general';
|
import { BaseApiResponse, GroupedApprovals } from '@/types/api/api-general';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -17,12 +17,6 @@ import { formatCurrency, formatDate, formatTitleCase } from '@/lib/helper';
|
|||||||
* 💡 Helper untuk membuat respons dummy
|
* 💡 Helper untuk membuat respons dummy
|
||||||
* @param data Data yang akan dimasukkan ke dalam body respons
|
* @param data Data yang akan dimasukkan ke dalam body respons
|
||||||
*/
|
*/
|
||||||
const createDummyResponse = <T>(data: T): BaseApiResponse<T> => ({
|
|
||||||
code: 200,
|
|
||||||
status: 'success',
|
|
||||||
message: 'Data retrieved successfully (MOCK)',
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
|
|
||||||
export class SalesOrderService extends BaseApiService<
|
export class SalesOrderService extends BaseApiService<
|
||||||
Marketing,
|
Marketing,
|
||||||
@@ -168,7 +162,7 @@ class MarketingExportService extends BaseApiService<
|
|||||||
|
|
||||||
// triggers download in browser
|
// triggers download in browser
|
||||||
XLSX.writeFile(wb, 'marketing.xlsx');
|
XLSX.writeFile(wb, 'marketing.xlsx');
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Gagal melakukan export marketing! Coba lagi.');
|
toast.error('Gagal melakukan export marketing! Coba lagi.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ export class TransferToLayingService extends BaseApiService<
|
|||||||
});
|
});
|
||||||
|
|
||||||
return mappedFlockKandangsAvailableQty;
|
return mappedFlockKandangsAvailableQty;
|
||||||
} catch (error) {
|
} catch {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ export class TransferToLayingService extends BaseApiService<
|
|||||||
});
|
});
|
||||||
|
|
||||||
return mappedFlockKandangsMaxTargetQty;
|
return mappedFlockKandangsMaxTargetQty;
|
||||||
} catch (error) {
|
} catch {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,7 @@ export class TransferToLayingService extends BaseApiService<
|
|||||||
|
|
||||||
// triggers download in browser
|
// triggers download in browser
|
||||||
XLSX.writeFile(wb, 'transfer-ke-laying.xlsx');
|
XLSX.writeFile(wb, 'transfer-ke-laying.xlsx');
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Gagal melakukan export transfer to laying! Coba lagi.');
|
toast.error('Gagal melakukan export transfer to laying! Coba lagi.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { BaseApiService } from '@/services/api/base';
|
import { BaseApiService } from '@/services/api/base';
|
||||||
import { httpClient, httpClientFetcher } from '@/services/http/client';
|
import { httpClientFetcher } from '@/services/http/client';
|
||||||
import { BaseApiResponse } from '@/types/api/api-general';
|
import { BaseApiResponse } from '@/types/api/api-general';
|
||||||
import { ReportExpense } from '@/types/api/report/report-expense';
|
import { ReportExpense } from '@/types/api/report/report-expense';
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export class ReportExpenseApiService extends BaseApiService<
|
export class ReportExpenseApiService extends BaseApiService<
|
||||||
ReportExpense,
|
ReportExpense,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
DailyMarketingReport,
|
DailyMarketingReport,
|
||||||
DailyMarketingReportResponse,
|
DailyMarketingReportResponse,
|
||||||
} from '@/types/api/report/marketing';
|
} from '@/types/api/report/marketing';
|
||||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseError } from '@/lib/api-helper';
|
||||||
import { formatDate } from '@/lib/helper';
|
import { formatDate } from '@/lib/helper';
|
||||||
|
|
||||||
export class MarketingReportApiService extends BaseApiService<
|
export class MarketingReportApiService extends BaseApiService<
|
||||||
@@ -68,7 +68,7 @@ export class MarketingReportApiService extends BaseApiService<
|
|||||||
|
|
||||||
// triggers download in browser
|
// triggers download in browser
|
||||||
XLSX.writeFile(wb, 'laporan-penjualan-harian.xlsx');
|
XLSX.writeFile(wb, 'laporan-penjualan-harian.xlsx');
|
||||||
} catch (error) {
|
} catch {
|
||||||
toast.error('Gagal melakukan export penjualan harian! Coba lagi.');
|
toast.error('Gagal melakukan export penjualan harian! Coba lagi.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { create } from 'zustand';
|
||||||
|
import { devtools } from 'zustand/middleware';
|
||||||
|
import { createProjectFlockClosingSlice } from '@/stores/production/project-flock-closing/slices/project-flock-closing.slice';
|
||||||
|
import { ProjectFlockClosingSlice } from '@/stores/production/project-flock-closing/slices/project-flock-closing.slice';
|
||||||
|
|
||||||
|
export type ProjectFlockClosingStore = ProjectFlockClosingSlice;
|
||||||
|
|
||||||
|
export const useProjectFlockClosingStore = create<ProjectFlockClosingStore>()(
|
||||||
|
devtools(
|
||||||
|
(...args) => ({
|
||||||
|
...createProjectFlockClosingSlice(...args),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: 'ProjectFlockClosingStore',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import { StateCreator } from 'zustand';
|
||||||
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
|
|
||||||
|
export type ProjectFlockClosingSlice = {
|
||||||
|
// State
|
||||||
|
isClosingModalOpen: boolean;
|
||||||
|
selectedProjectFlockKandang: ProjectFlockKandang | null;
|
||||||
|
projectFlockId: number | null;
|
||||||
|
isKandangClosed: boolean;
|
||||||
|
isClosingLoading: boolean;
|
||||||
|
closingCallback: ((action: 'close' | 'unclose') => Promise<void>) | null;
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
openClosingModal: (
|
||||||
|
data: ProjectFlockKandang,
|
||||||
|
projectFlockId: number,
|
||||||
|
isClosed: boolean,
|
||||||
|
callback: (action: 'close' | 'unclose') => Promise<void>
|
||||||
|
) => void;
|
||||||
|
closeClosingModal: () => void;
|
||||||
|
setClosingLoading: (loading: boolean) => void;
|
||||||
|
resetClosing: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createProjectFlockClosingSlice: StateCreator<
|
||||||
|
ProjectFlockClosingSlice,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
ProjectFlockClosingSlice
|
||||||
|
> = (set) => ({
|
||||||
|
// Initial state
|
||||||
|
isClosingModalOpen: false,
|
||||||
|
selectedProjectFlockKandang: null,
|
||||||
|
projectFlockId: null,
|
||||||
|
isKandangClosed: false,
|
||||||
|
isClosingLoading: false,
|
||||||
|
closingCallback: null,
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
openClosingModal: (data, projectFlockId, isClosed, callback) =>
|
||||||
|
set({
|
||||||
|
isClosingModalOpen: true,
|
||||||
|
selectedProjectFlockKandang: data,
|
||||||
|
projectFlockId,
|
||||||
|
isKandangClosed: isClosed,
|
||||||
|
closingCallback: callback,
|
||||||
|
}),
|
||||||
|
|
||||||
|
closeClosingModal: () =>
|
||||||
|
set({
|
||||||
|
isClosingModalOpen: false,
|
||||||
|
selectedProjectFlockKandang: null,
|
||||||
|
projectFlockId: null,
|
||||||
|
isKandangClosed: false,
|
||||||
|
closingCallback: null,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setClosingLoading: (loading) => set({ isClosingLoading: loading }),
|
||||||
|
|
||||||
|
resetClosing: () =>
|
||||||
|
set({
|
||||||
|
isClosingModalOpen: false,
|
||||||
|
selectedProjectFlockKandang: null,
|
||||||
|
projectFlockId: null,
|
||||||
|
isKandangClosed: false,
|
||||||
|
isClosingLoading: false,
|
||||||
|
closingCallback: null,
|
||||||
|
}),
|
||||||
|
});
|
||||||
Vendored
-3
@@ -1,6 +1,3 @@
|
|||||||
import { Area } from '@/types/api/master-data/area';
|
|
||||||
import { Flock } from '@/types/api/master-data/flock';
|
|
||||||
import { Location } from '@/types/api/master-data/location';
|
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
import { Product } from '@type/api/master-data/product';
|
import { Product } from '@type/api/master-data/product';
|
||||||
import { Customer } from '@type/api/master-data/customer';
|
import { Customer } from '@type/api/master-data/customer';
|
||||||
|
|||||||
-2
@@ -1,6 +1,4 @@
|
|||||||
import { BaseMetadata } from '@/types/api/api-general';
|
import { BaseMetadata } from '@/types/api/api-general';
|
||||||
import { BaseLocation } from '@/types/api/master-data/location';
|
|
||||||
import { BaseUser } from '@/types/api/user';
|
|
||||||
import { BaseKandang } from '@/types/api/master-data/kandang';
|
import { BaseKandang } from '@/types/api/master-data/kandang';
|
||||||
|
|
||||||
export type BaseEmployee = {
|
export type BaseEmployee = {
|
||||||
|
|||||||
-2
@@ -1,5 +1,3 @@
|
|||||||
import { SuccessApiResponse } from '@/types/api/api-general';
|
|
||||||
|
|
||||||
export interface Dashboard {
|
export interface Dashboard {
|
||||||
statistics_data: DashboardStatisticsData[];
|
statistics_data: DashboardStatisticsData[];
|
||||||
charts: DashboardComparisonCharts | DashboardOverviewCharts;
|
charts: DashboardComparisonCharts | DashboardOverviewCharts;
|
||||||
|
|||||||
Vendored
+3
-5
@@ -1,9 +1,7 @@
|
|||||||
import { BaseApproval, BaseMetadata } from '@/types/api/api-general';
|
import { BaseApproval, BaseMetadata } from '@/types/api/api-general';
|
||||||
import { BaseLocation, Location } from '@/types/api/master-data/location';
|
import { BaseLocation } from '@/types/api/master-data/location';
|
||||||
import { BaseKandang, Kandang } from '@/types/api/master-data/kandang';
|
import { BaseSupplier } from '@/types/api/master-data/supplier';
|
||||||
import { BaseSupplier, Supplier } from '@/types/api/master-data/supplier';
|
import { BaseNonstock } from '@/types/api/master-data/nonstock';
|
||||||
import { BaseNonstock, Nonstock } from '@/types/api/master-data/nonstock';
|
|
||||||
import { BaseUser } from '@/types/api/user';
|
|
||||||
|
|
||||||
export type BaseExpense = {
|
export type BaseExpense = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
Vendored
-1
@@ -1,5 +1,4 @@
|
|||||||
import { BaseMetadata, CreatedUser } from '@/types/api/api-general';
|
import { BaseMetadata, CreatedUser } from '@/types/api/api-general';
|
||||||
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
|
||||||
import { ProductCategory } from '@/types/api/master-data/product-category';
|
import { ProductCategory } from '@/types/api/master-data/product-category';
|
||||||
import { Supplier } from '@/types/api/master-data/supplier';
|
import { Supplier } from '@/types/api/master-data/supplier';
|
||||||
import { Uom } from '@/types/api/master-data/uom';
|
import { Uom } from '@/types/api/master-data/uom';
|
||||||
|
|||||||
-1
@@ -6,7 +6,6 @@ import {
|
|||||||
} from '@/types/api/api-general';
|
} from '@/types/api/api-general';
|
||||||
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
import { id } from 'react-day-picker/locale';
|
|
||||||
import { Warehouse } from '@/types/api/master-data/warehouse';
|
import { Warehouse } from '@/types/api/master-data/warehouse';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { BaseApiResponse, BaseMetadata, flags } from '@/types/api/api-general';
|
import { BaseMetadata, flags } from '@/types/api/api-general';
|
||||||
import { BaseUom } from '@/types/api/master-data/uom';
|
import { BaseUom } from '@/types/api/master-data/uom';
|
||||||
import { BaseSupplier } from '@/types/api/master-data/supplier';
|
import { BaseSupplier } from '@/types/api/master-data/supplier';
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import { BaseMetadata } from '@/types/api/api-general';
|
import { BaseMetadata } from '@/types/api/api-general';
|
||||||
import { Uom } from '@/types/api/master-data/uom';
|
import { Uom } from '@/types/api/master-data/uom';
|
||||||
import { ProductCategory } from '@/types/api/master-data/product-category';
|
import { ProductCategory } from '@/types/api/master-data/product-category';
|
||||||
import { BaseSupplier, Supplier } from '@/types/api/master-data/supplier';
|
import { BaseSupplier } from '@/types/api/master-data/supplier';
|
||||||
|
|
||||||
export type BaseProduct = {
|
export type BaseProduct = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
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 { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
||||||
import { Supplier } from '@/types/api/master-data/supplier';
|
|
||||||
import { BaseApproval } from '@/types/api/api-general';
|
import { BaseApproval } from '@/types/api/api-general';
|
||||||
|
|
||||||
export type BaseProjectFlockKandang = {
|
export type BaseProjectFlockKandang = {
|
||||||
|
|||||||
+2
-7
@@ -1,10 +1,5 @@
|
|||||||
import {
|
import { BaseMetadata, CreatedUser } from '@/types/api/api-general';
|
||||||
BaseApiResponse,
|
import { BaseKandang } from '@/types/api/master-data/kandang';
|
||||||
BaseMetadata,
|
|
||||||
CreatedUser,
|
|
||||||
flags,
|
|
||||||
} from '@/types/api/api-general';
|
|
||||||
import { BaseKandang, Kandang } from '@/types/api/master-data/kandang';
|
|
||||||
import { WarehouseType } from '@/types/api/master-data/warehouse';
|
import { WarehouseType } from '@/types/api/master-data/warehouse';
|
||||||
|
|
||||||
export type BaseTransferToLaying = {
|
export type BaseTransferToLaying = {
|
||||||
|
|||||||
Vendored
+1
-4
@@ -1,13 +1,10 @@
|
|||||||
import { BaseApiResponse, BaseMetadata } from '@/types/api/api-general';
|
import { BaseApiResponse, BaseMetadata } from '@/types/api/api-general';
|
||||||
import { BaseCustomer, Customer } from '@/types/api/master-data/customer';
|
import { BaseCustomer } from '@/types/api/master-data/customer';
|
||||||
import {
|
import {
|
||||||
BaseWarehouseArea,
|
BaseWarehouseArea,
|
||||||
BaseWarehouseKandang,
|
BaseWarehouseKandang,
|
||||||
BaseWarehouseLocation,
|
BaseWarehouseLocation,
|
||||||
Warehouse,
|
|
||||||
} from '@/types/api/master-data/warehouse';
|
} from '@/types/api/master-data/warehouse';
|
||||||
import { Location } from '@/types/api/master-data/location';
|
|
||||||
import { Area } from '@/types/api/master-data/area';
|
|
||||||
import { BaseProduct } from '@/types/api/master-data/product';
|
import { BaseProduct } from '@/types/api/master-data/product';
|
||||||
import { BaseUser } from '@/types/api/user';
|
import { BaseUser } from '@/types/api/user';
|
||||||
|
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
import { BaseApproval, CreatedUser } from '@/types/api/api-general';
|
import { BaseApproval, CreatedUser } from '@/types/api/api-general';
|
||||||
import { Supplier } from '@/types/api/master-data/supplier';
|
import { Supplier } from '@/types/api/master-data/supplier';
|
||||||
import { Location } from '@/types/api/master-data/location';
|
|
||||||
import { Nonstock } from '@/types/api/master-data/nonstock';
|
import { Nonstock } from '@/types/api/master-data/nonstock';
|
||||||
import { Kandang } from '@/types/api/master-data/kandang';
|
import { Kandang } from '@/types/api/master-data/kandang';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user