refactor(FE-316): Refactor Uniformity table and status helpers

This commit is contained in:
rstubryan
2025-12-24 10:51:12 +07:00
parent 5fae7752f2
commit b9c1989cae
3 changed files with 201 additions and 168 deletions
@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import Card from '@/components/Card'; import Card from '@/components/Card';
import UniformityBarChart from './chart/UniformityBarChart'; import UniformityBarChart from '@/components/pages/uniformity/chart/UniformityBarChart';
import UniformityGaugeChart from './chart/UniformityGaugeChart'; import UniformityGaugeChart from '@/components/pages/uniformity/chart/UniformityGaugeChart';
interface BarChartData { interface BarChartData {
name: string; name: string;
@@ -1,6 +1,6 @@
'use client'; 'use client';
import React, { useCallback, useState, useEffect } from 'react'; import React, { useCallback, useState, useEffect, useMemo } from 'react';
import useSWR from 'swr'; import useSWR from 'swr';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table'; import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
@@ -22,16 +22,60 @@ import { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal'; import ConfirmationModal from '@/components/modal/ConfirmationModal';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import Card from '@/components/Card'; import Card from '@/components/Card';
import { Color } from '@/types/theme';
const statusColorMap: Record<string, Color> = {
APPROVED: 'success',
REJECTED: 'error',
CREATED: 'none',
};
const statusIndicatorColorMap: Record<string, string> = {
APPROVED: 'bg-success',
REJECTED: 'bg-error',
CREATED: 'bg-[#D9D9D9]',
};
const statusTextMap: Record<string, string> = {
APPROVED: 'Disetujui',
REJECTED: 'Ditolak',
CREATED: 'Pengajuan',
};
const getStatusColor = (status: string): Color => {
return statusColorMap[status] || 'info';
};
const getStatusIndicatorColor = (status: string): string => {
return statusIndicatorColorMap[status] || 'bg-info';
};
const getStatusText = (status: string): string => {
return statusTextMap[status] || status;
};
const isUniformityLocked = (uniformity: Uniformity): boolean => {
return uniformity.status === 'APPROVED' || uniformity.status === 'REJECTED';
};
const RowOptionsMenu = ({ const RowOptionsMenu = ({
type = 'dropdown', type = 'dropdown',
props, props,
deleteClickHandler, deleteClickHandler,
setSelectedUniformity,
openModal,
}: { }: {
type: 'dropdown' | 'collapse'; type: 'dropdown' | 'collapse';
props: CellContext<Uniformity, unknown>; props: CellContext<Uniformity, unknown>;
deleteClickHandler: () => void; deleteClickHandler: () => void;
setSelectedUniformity: (uniformity: Uniformity) => void;
openModal: () => void;
}) => { }) => {
const handleDeleteClick = useCallback(() => {
setSelectedUniformity(props.row.original);
openModal();
}, [props.row.original, setSelectedUniformity, openModal]);
return ( return (
<RowOptionsMenuWrapper type={type}> <RowOptionsMenuWrapper type={type}>
<Button <Button
@@ -53,7 +97,7 @@ const RowOptionsMenu = ({
Edit Edit
</Button> </Button>
<Button <Button
onClick={deleteClickHandler} onClick={handleDeleteClick}
variant='ghost' variant='ghost'
color='error' color='error'
className='justify-start text-sm text-error focus-visible:text-error-content hover:text-error-content' className='justify-start text-sm text-error focus-visible:text-error-content hover:text-error-content'
@@ -104,11 +148,7 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
UniformityApi.getAllFetcher UniformityApi.getAllFetcher
); );
const isUniformityLocked = useCallback((uniformity: Uniformity): boolean => { const singleDeleteHandler = useCallback(async () => {
return uniformity.status === 'APPROVED' || uniformity.status === 'REJECTED';
}, []);
const singleDeleteHandler = async () => {
setIsDeleteLoading(true); setIsDeleteLoading(true);
await UniformityApi.delete(selectedUniformity?.id as number); await UniformityApi.delete(selectedUniformity?.id as number);
@@ -117,7 +157,7 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
singleDeleteModal.closeModal(); singleDeleteModal.closeModal();
toast.success('Successfully delete Uniformity!'); toast.success('Successfully delete Uniformity!');
setIsDeleteLoading(false); setIsDeleteLoading(false);
}; }, [selectedUniformity?.id, refreshUniformities, singleDeleteModal]);
useEffect(() => { useEffect(() => {
if (isResponseSuccess(uniformities) && uniformities.data) { if (isResponseSuccess(uniformities) && uniformities.data) {
@@ -140,36 +180,11 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
setRowSelection(newSelection); setRowSelection(newSelection);
} }
} }
}, [uniformities, rowSelection, isUniformityLocked, setRowSelection]); }, [uniformities, rowSelection]);
const getStatusColor = (status: string) => {
switch (status) {
case 'APPROVED':
return 'success';
case 'REJECTED':
return 'error';
case 'CREATED':
return 'info';
default:
return 'info';
}
};
const getStatusText = (status: string) => {
switch (status) {
case 'APPROVED':
return 'Disetujui';
case 'REJECTED':
return 'Ditolak';
case 'CREATED':
return 'Pengajuan';
default:
return status;
}
};
// ===== TABLE COLUMNS DEFINITION ===== // ===== TABLE COLUMNS DEFINITION =====
const uniformityColumns: ColumnDef<Uniformity>[] = [ const uniformityColumns: ColumnDef<Uniformity>[] = useMemo(
() => [
{ {
id: 'select', id: 'select',
header: ({ table }) => { header: ({ table }) => {
@@ -254,9 +269,19 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
cell: (props) => { cell: (props) => {
const status = props.row.original.status; const status = props.row.original.status;
return ( return (
<Badge variant='soft' color={getStatusColor(status)}> <div className='w-full'>
<Badge
statusIndicator={true}
variant='soft'
color={getStatusColor(status)}
className={{
badge: `rounded-xl w-full justify-start border border-gray-200`,
status: getStatusIndicatorColor(status),
}}
>
{getStatusText(status)} {getStatusText(status)}
</Badge> </Badge>
</div>
); );
}, },
}, },
@@ -272,18 +297,14 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
id: 'actions', id: 'actions',
header: 'Aksi', header: 'Aksi',
cell: (props: CellContext<Uniformity, unknown>) => { cell: (props: CellContext<Uniformity, unknown>) => {
const currentPageSize = props.table.getPaginationRowModel().rows.length; const currentPageSize =
props.table.getPaginationRowModel().rows.length;
const currentPageRows = props.table.getPaginationRowModel().flatRows; const currentPageRows = props.table.getPaginationRowModel().flatRows;
const currentRowRelativeIndex = const currentRowRelativeIndex =
currentPageRows.findIndex((r) => r.id === props.row.id) + 1; currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2; const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
const deleteClickHandler = () => {
setSelectedUniformity(props.row.original);
singleDeleteModal.openModal();
};
return ( return (
<> <>
{currentPageSize > 2 && ( {currentPageSize > 2 && (
@@ -291,7 +312,12 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
<RowOptionsMenu <RowOptionsMenu
type='dropdown' type='dropdown'
props={props} props={props}
deleteClickHandler={deleteClickHandler} deleteClickHandler={() => {
setSelectedUniformity(props.row.original);
singleDeleteModal.openModal();
}}
setSelectedUniformity={setSelectedUniformity}
openModal={singleDeleteModal.openModal}
/> />
</RowDropdownOptions> </RowDropdownOptions>
)} )}
@@ -301,7 +327,12 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
<RowOptionsMenu <RowOptionsMenu
type='collapse' type='collapse'
props={props} props={props}
deleteClickHandler={deleteClickHandler} deleteClickHandler={() => {
setSelectedUniformity(props.row.original);
singleDeleteModal.openModal();
}}
setSelectedUniformity={setSelectedUniformity}
openModal={singleDeleteModal.openModal}
/> />
</RowCollapseOptions> </RowCollapseOptions>
)} )}
@@ -309,7 +340,9 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
); );
}, },
}, },
]; ],
[]
);
return ( return (
<> <>
+1 -1
View File
@@ -1,6 +1,6 @@
import { Location } from '@/types/api/location/location'; import { Location } from '@/types/api/location/location';
import { Kandang } from '@/types/api/kandang/kandang'; import { Kandang } from '@/types/api/kandang/kandang';
import { BaseMetadata } from '../api-general'; import { BaseMetadata } from '@/types/common/base-metadata';
export type Uniformity = BaseMetadata & { export type Uniformity = BaseMetadata & {
id: number; id: number;