fixing refresh & sorting manage groups

This commit is contained in:
Raja Oktafrianto
2025-04-21 18:24:56 +07:00
parent ca0e8f33b8
commit 103b7bb750
3 changed files with 143 additions and 42 deletions

View File

@ -1,5 +1,8 @@
import { KeenIcon } from '@/components'; import { KeenIcon } from '@/components';
import { Button } from '@/components/ui/button';
import { ColumnDef } from '@tanstack/react-table'; import { ColumnDef } from '@tanstack/react-table';
import { ArrowUpDown } from 'lucide-react';
import moment from 'moment';
export type Group = { export type Group = {
no: number; no: number;
@ -12,27 +15,81 @@ export type Group = {
export const getColumns = (handleUpdate: (data: any) => void): ColumnDef<Group>[] => [ export const getColumns = (handleUpdate: (data: any) => void): ColumnDef<Group>[] => [
{ {
accessorKey: 'no', accessorKey: 'no',
header: 'ID' header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
ID
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
}
}, },
{ {
accessorKey: 'created_at', accessorKey: 'created_at',
header: 'Created Date', header: ({ column }) => {
cell: ({ row }) => new Date(row.original.created_at).toLocaleDateString() return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Created Date
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
},
cell: ({ row }) => moment(row.original.created_at).format('YYYY-MM-DD HH:mm:ss')
}, },
{ {
accessorKey: 'name', accessorKey: 'name',
header: 'Name' header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Name
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
}
}, },
{ {
accessorKey: 'status', accessorKey: 'status',
header: 'Status' header: 'Status',
cell: ({ row }) => {
const isActive = row.original.status === 'Y';
return (
<span
className={`px-2 py-1 text-xs font-semibold rounded-full ${
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
}`}
>
{isActive ? 'Active' : 'inactive'}
</span>
);
}
}, },
{ {
accessorKey: 'description', accessorKey: 'description',
header: 'Description' header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Description
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
);
}
}, },
{ {
id: 'actions', id: 'actions',
header: 'Actions',
cell: ({ row }) => { cell: ({ row }) => {
const dataMembers = row.original; const dataMembers = row.original;

View File

@ -1,8 +1,20 @@
import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import React, { useState } from 'react';
const ListToolBar = ({ createGroup }: { createGroup: () => void }) => { interface ListToolBarProps {
const { table, reload } = useDataGrid(); createGroup: () => void;
onReload: () => void;
isReloading: boolean;
}
const ListToolBar = ({ createGroup, onReload, isReloading }: ListToolBarProps) => {
const { table } = useDataGrid();
const [usernameFilter, setUsernameFilter] = useState('');
const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setUsernameFilter(e.target.value);
table.getColumn('name')?.setFilterValue(e.target.value);
};
return ( return (
<div className="card-header flex-wrap gap-2 border-b-0 px-5"> <div className="card-header flex-wrap gap-2 border-b-0 px-5">
@ -14,29 +26,25 @@ const ListToolBar = ({ createGroup }: { createGroup: () => void }) => {
<input <input
type="text" type="text"
placeholder="Search users" placeholder="Search users"
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''} value={usernameFilter}
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} onChange={handleUsernameChange}
className="input input-sm w-40"
/> />
</label> </label>
{/* <DefaultTooltip title={'Filter'} placement={'top'}>
<Button
variant="outline"
className="h-7.5 disabled:bg-gray-400"
// disabled={isLoading}
// onClick={handleFilterData}
>
{loadingButton === 'filter' ? <ContentLoader /> : <KeenIcon icon="filter" />}
<KeenIcon icon="filter" />
</Button>
</DefaultTooltip> */}
</div> </div>
<div className="flex gap-3 items-center"> <div className="flex gap-3 items-center">
<Button variant="outline" className="h-7.5 text-[0.8rem]" onClick={createGroup}> <Button variant="outline" className="h-7.5 text-[0.8rem]" onClick={createGroup}>
Add Data Add Data
</Button> </Button>
<DefaultTooltip title={'Refresh'} placement={'top'}> <DefaultTooltip title={isReloading ? 'Refreshing...' : 'Refresh'} placement={'top'}>
<Button variant="outline" className="h-7.5" onClick={() => reload()}> <Button variant="outline" className="h-7.5" onClick={onReload} disabled={isReloading}>
<KeenIcon icon="arrows-circle" /> {isReloading ? (
<div className="animate-spin">
<KeenIcon icon="arrows-circle" />
</div>
) : (
<KeenIcon icon="arrows-circle" />
)}
</Button> </Button>
</DefaultTooltip> </DefaultTooltip>
</div> </div>

View File

@ -24,8 +24,10 @@ import CloseIcon from '@mui/icons-material/Close';
import Divider from '@mui/material/Divider'; import Divider from '@mui/material/Divider';
import ConfirmDialog from '@/components/confirm'; import ConfirmDialog from '@/components/confirm';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { Container, DataGridProvider } from '@/components'; import { Container, DataGridProvider, LoaderTransparant } from '@/components';
import { ListToolBar } from './ListToolbar'; import { ListToolBar } from './ListToolbar';
import { RefreshCw } from 'lucide-react';
import { setgroups } from 'process';
// import { DialogHeader } from '@/components/ui/dialog'; // import { DialogHeader } from '@/components/ui/dialog';
// import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; // import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
const BASE_URL = apiConfig.service_customer; const BASE_URL = apiConfig.service_customer;
@ -42,37 +44,52 @@ let initGroup = {
const ManageGroups = () => { const ManageGroups = () => {
const [isDialogOpen, setIsDialogOpen] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [dataGroup, setDataGroup] = useState([]); const [dataGroup, setDataGroup] = useState([]);
const [formData, setFormData] = useState(initGroup); const [formData, setFormData] = useState(initGroup);
const [pageIndex, setPageIndex] = useState(1); const [pageIndex, setPageIndex] = useState(1);
const [pageSize, setPageSize] = useState(10); const [pageSize, setPageSize] = useState(10);
const [dialogType, setDialogType] = useState(''); const [dialogType, setDialogType] = useState('');
const [dialogOpen, setDialogOpen] = useState(false); const [dialogOpen, setDialogOpen] = useState(false);
const [isReloading, setIsReloading] = useState(false);
// const closeDialog = () => {
// setIsDialogOpen(false);
// setgroups(initGroup);
// };
useEffect(() => { useEffect(() => {
setLoading(true);
fetchGroups(); fetchGroups();
setLoading(false);
}, []); }, []);
async function fetchGroups() { async function fetchGroups(): Promise<void> {
try { try {
let groups = await axios.get(`${BASE_URL}/groups/list`, { let groups = await axios.get(`${BASE_URL}/groups/list`, {
params: { params: {
limit: pageSize, limit: 20,
page: pageIndex, page: 1,
with_deleted: false, with_deleted: false,
order_field: 'name', order_field: 'created_at',
order_direction: 'ASC' order_direction: 'DESC'
} }
}); });
let temp = 1; let temp = 1;
let resGroups = groups.data.data.list.map((el: any) => { let resGroups = groups.data.data.list.map((el: any) => {
el.no = temp++; el.no = temp++;
if (el.date_birth) {
const d = new Date(el.date_birth);
el.date_birth = d.toLocaleString('sv-SE');
}
return el; return el;
}) });
setDataGroup(resGroups); setDataGroup(resGroups);
} catch (error: any) { } catch (error: any) {
alert(error.message); alert(error.message);
console.log(error); console.log(error);
} finally {
setLoading(false);
setIsReloading(false);
} }
} }
@ -127,6 +144,11 @@ const ManageGroups = () => {
setDialogOpen(true); setDialogOpen(true);
}; };
const handleReload = () => {
setIsReloading(true);
fetchGroups();
};
const handleYes = async () => { const handleYes = async () => {
try { try {
if (dialogType === 'create') { if (dialogType === 'create') {
@ -153,12 +175,19 @@ const ManageGroups = () => {
console.log(error); console.log(error);
toast.error(error.message); toast.error(error.message);
} finally { } finally {
await fetchGroups();
setDialogOpen(false); setDialogOpen(false);
closeDialog(); closeDialog();
await fetchGroups();
setLoading(false);
} }
}; };
function setShowAddDialog(el: any) {
setIsDialogOpen(el);
}
if (loading) return <LoaderTransparant />;
return ( return (
<> <>
<Helmet> <Helmet>
@ -191,21 +220,28 @@ const ManageGroups = () => {
</Link> </Link>
</Breadcrumbs> </Breadcrumbs>
{/* <div className="w-full overflow-x-auto px-4"> */} {/* <div className="w-full overflow-x-auto px-4"> */}
<div className="grid gap-5 lg:gap-7.5 mt-5">
{/* <DataTable <div className="grid gap-5 lg:gap-7.5 mt-5 relative">
data={dataGroup} {isReloading && (
columns={columns} <div className="fixed inset-0 flex items-center justify-center z-50 bg-white/70">
createData={createGroup} <div className="flex flex-col items-center">
onUpdate={handleUpdate} <RefreshCw className="animate-spin h-8 w-8 text-slate-500 mb-2" />
onDelete={null} <span className="text-slate-500 font-medium">Refreshing data...</span>
/> */} </div>
</div>
)}
<DataGridProvider <DataGridProvider
data={dataGroup} data={dataGroup}
columns={getColumns(handleUpdate)} columns={getColumns(handleUpdate)}
pagination={{ size: 25 }} pagination={{ size: 25 }}
toolbar={<ListToolBar createGroup={createGroup} />} toolbar={
<ListToolBar
createGroup={createGroup}
onReload={handleReload}
isReloading={isReloading}
/>
}
layout={{ card: true }} layout={{ card: true }}
sorting={[{ id: 'created_at', desc: true }]}
serverSide={false} serverSide={false}
onRowSelectionChange={(selected, table: any) => { onRowSelectionChange={(selected, table: any) => {
const selectedRow = table.getSelectedRowModel().rows[0]; const selectedRow = table.getSelectedRowModel().rows[0];