242 lines
7.0 KiB
TypeScript
242 lines
7.0 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import RouterLink from 'next/link';
|
|
import { LoadingButton } from '@mui/lab';
|
|
import Avatar from '@mui/material/Avatar';
|
|
import Box from '@mui/material/Box';
|
|
import Button from '@mui/material/Button';
|
|
import LinearProgress from '@mui/material/LinearProgress';
|
|
import Link from '@mui/material/Link';
|
|
import Stack from '@mui/material/Stack';
|
|
import Typography from '@mui/material/Typography';
|
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
|
import { Clock as ClockIcon } from '@phosphor-icons/react/dist/ssr/Clock';
|
|
import { Images as ImagesIcon } from '@phosphor-icons/react/dist/ssr/Images';
|
|
import { Minus as MinusIcon } from '@phosphor-icons/react/dist/ssr/Minus';
|
|
import { PencilSimple as PencilSimpleIcon } from '@phosphor-icons/react/dist/ssr/PencilSimple';
|
|
import { TrashSimple as TrashSimpleIcon } from '@phosphor-icons/react/dist/ssr/TrashSimple';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { toast } from 'sonner';
|
|
|
|
import { paths } from '@/paths';
|
|
import { dayjs } from '@/lib/dayjs';
|
|
import { DataTable } from '@/components/core/data-table';
|
|
import type { ColumnDef } from '@/components/core/data-table';
|
|
|
|
import ConfirmDeleteModal from './confirm-delete-modal';
|
|
import { useLpCategoriesSelection } from './lp-questions-selection-context';
|
|
import type { LpQuestion } from './type';
|
|
|
|
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<LpQuestion>[] {
|
|
return [
|
|
{
|
|
formatter: (row): React.JSX.Element => (
|
|
<Stack
|
|
direction="row"
|
|
spacing={1}
|
|
sx={{ alignItems: 'center' }}
|
|
>
|
|
<Link
|
|
color="inherit"
|
|
component={RouterLink}
|
|
href={paths.dashboard.lp_questions.details(row.id)}
|
|
sx={{ whiteSpace: 'nowrap' }}
|
|
variant="subtitle2"
|
|
>
|
|
<Stack
|
|
direction="row"
|
|
spacing={1}
|
|
sx={{ alignItems: 'center' }}
|
|
>
|
|
<Avatar
|
|
src={`http://127.0.0.1:8090/api/files/${row.collectionId}/${row.id}/${row.cat_image}`}
|
|
variant="rounded"
|
|
>
|
|
<ImagesIcon size={32} />
|
|
</Avatar>{' '}
|
|
<div>
|
|
<Box sx={{ whiteSpace: 'nowrap' }}>{row.cat_name}</Box>
|
|
<Typography
|
|
color="text.secondary"
|
|
variant="body2"
|
|
>
|
|
slug: {row.cat_name}
|
|
</Typography>
|
|
</div>
|
|
</Stack>
|
|
</Link>
|
|
</Stack>
|
|
),
|
|
name: 'Name',
|
|
width: '200px',
|
|
},
|
|
{
|
|
formatter: (row): React.JSX.Element => (
|
|
<Stack
|
|
direction="row"
|
|
spacing={2}
|
|
sx={{ alignItems: 'center' }}
|
|
>
|
|
<LinearProgress
|
|
sx={{ flex: '1 1 auto' }}
|
|
value={row.quota}
|
|
variant="determinate"
|
|
/>
|
|
<Typography
|
|
color="text.secondary"
|
|
variant="body2"
|
|
>
|
|
{new Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 2 }).format(row.quota / 100)}
|
|
</Typography>
|
|
</Stack>
|
|
),
|
|
// NOTE: please refer to translation.json here
|
|
name: 'word-count',
|
|
width: '100px',
|
|
},
|
|
{
|
|
formatter: (row): React.JSX.Element => {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
|
|
const mapping = {
|
|
active: {
|
|
label: 'Active',
|
|
icon: (
|
|
<CheckCircleIcon
|
|
color="var(--mui-palette-success-main)"
|
|
weight="fill"
|
|
/>
|
|
),
|
|
},
|
|
blocked: { label: 'Blocked', icon: <MinusIcon color="var(--mui-palette-error-main)" /> },
|
|
pending: {
|
|
label: 'Pending',
|
|
icon: (
|
|
<ClockIcon
|
|
color="var(--mui-palette-warning-main)"
|
|
weight="fill"
|
|
/>
|
|
),
|
|
},
|
|
NA: {
|
|
label: 'NA',
|
|
icon: (
|
|
<ClockIcon
|
|
color="var(--mui-palette-warning-main)"
|
|
weight="fill"
|
|
/>
|
|
),
|
|
},
|
|
} as const;
|
|
const { label, icon } = mapping[row.status] ?? { label: 'Unknown', icon: null };
|
|
|
|
return (
|
|
<Button
|
|
onClick={() => {
|
|
toast.error('sorry but not implementd');
|
|
}}
|
|
style={{ backgroundColor: 'transparent' }}
|
|
>
|
|
{/* <Chip icon={icon} label={label} size="small" variant="outlined" /> */}
|
|
{label}
|
|
</Button>
|
|
);
|
|
},
|
|
name: 'visible',
|
|
width: '150px',
|
|
},
|
|
{
|
|
formatter(row) {
|
|
return dayjs(row.createdAt).format('MMM D, YYYY');
|
|
},
|
|
name: 'Created at',
|
|
width: '100px',
|
|
},
|
|
{
|
|
formatter: (row): React.JSX.Element => (
|
|
<Stack
|
|
direction="row"
|
|
spacing={1}
|
|
>
|
|
<LoadingButton
|
|
//
|
|
color="secondary"
|
|
component={RouterLink}
|
|
href={paths.dashboard.lp_questions.details(row.id)}
|
|
>
|
|
<PencilSimpleIcon size={24} />
|
|
</LoadingButton>
|
|
<LoadingButton
|
|
color="error"
|
|
disabled={row.isEmpty}
|
|
onClick={() => {
|
|
handleDeleteClick(row.id);
|
|
}}
|
|
>
|
|
<TrashSimpleIcon size={24} />
|
|
</LoadingButton>
|
|
</Stack>
|
|
),
|
|
name: 'Actions',
|
|
hideName: true,
|
|
width: '100px',
|
|
align: 'right',
|
|
},
|
|
];
|
|
}
|
|
|
|
export interface LessonCategoriesTableProps {
|
|
rows: LpQuestion[];
|
|
reloadRows: () => void;
|
|
}
|
|
|
|
export function LpQuestionsTable({ rows, reloadRows }: LessonCategoriesTableProps): React.JSX.Element {
|
|
const { t } = useTranslation(['lp_questions']);
|
|
const { deselectAll, deselectOne, selectAll, selectOne, selected } = useLpCategoriesSelection();
|
|
|
|
const [idToDelete, setIdToDelete] = React.useState('');
|
|
const [open, setOpen] = React.useState(false);
|
|
|
|
function handleDeleteClick(testId: string): void {
|
|
setOpen(true);
|
|
setIdToDelete(testId);
|
|
}
|
|
|
|
return (
|
|
<React.Fragment>
|
|
<ConfirmDeleteModal
|
|
idToDelete={idToDelete}
|
|
open={open}
|
|
reloadRows={reloadRows}
|
|
setOpen={setOpen}
|
|
/>
|
|
<DataTable<LpQuestion>
|
|
columns={columns(handleDeleteClick)}
|
|
onDeselectAll={deselectAll}
|
|
onDeselectOne={(_, row) => {
|
|
deselectOne(row.id);
|
|
}}
|
|
onSelectAll={selectAll}
|
|
onSelectOne={(_, row) => {
|
|
selectOne(row.id);
|
|
}}
|
|
rows={rows}
|
|
selectable
|
|
selected={selected}
|
|
/>
|
|
{!rows.length ? (
|
|
<Box sx={{ p: 3 }}>
|
|
<Typography
|
|
color="text.secondary"
|
|
sx={{ textAlign: 'center' }}
|
|
variant="body2"
|
|
>
|
|
{t('no-lesson-categories-found')}
|
|
</Typography>
|
|
</Box>
|
|
) : null}
|
|
</React.Fragment>
|
|
);
|
|
}
|