update build ok,
This commit is contained in:
@@ -15,9 +15,12 @@ import { paths } from '@/paths';
|
|||||||
import { logger } from '@/lib/default-logger';
|
import { logger } from '@/lib/default-logger';
|
||||||
import { toast } from '@/components/core/toaster';
|
import { toast } from '@/components/core/toaster';
|
||||||
import type { LessonType } from '@/components/dashboard/lesson_type/ILessonType';
|
import type { LessonType } from '@/components/dashboard/lesson_type/ILessonType';
|
||||||
|
import { LessonTypesFilters } from '@/components/dashboard/lesson_type/lesson-types-filters';
|
||||||
import type { Filters } from '@/components/dashboard/lesson_type/lesson-types-filters';
|
import type { Filters } from '@/components/dashboard/lesson_type/lesson-types-filters';
|
||||||
|
import { LessonTypesPagination } from '@/components/dashboard/lesson_type/lesson-types-pagination';
|
||||||
|
import { LessonTypesSelectionProvider } from '@/components/dashboard/lesson_type/lesson-types-selection-context';
|
||||||
|
import { LessonTypesTable } from '@/components/dashboard/lesson_type/lesson-types-table';
|
||||||
|
import FormLoading from '@/components/loading';
|
||||||
|
|
||||||
interface PageProps {
|
interface PageProps {
|
||||||
searchParams: {
|
searchParams: {
|
||||||
@@ -50,6 +53,10 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
|
|||||||
//
|
//
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const reloadRows = () => {
|
||||||
|
console.log('reload rows');
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -79,6 +86,21 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
|
|||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<LessonTypesSelectionProvider lessonTypes={filteredLessonTypes}>
|
||||||
|
<Card>
|
||||||
|
<LessonTypesFilters
|
||||||
|
filters={{ email, phone, status, name, visible, type }}
|
||||||
|
fullData={lessonTypesData}
|
||||||
|
sortDir={sortDir}
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
<Box sx={{ overflowX: 'auto' }}>
|
||||||
|
<LessonTypesTable reloadRows={reloadRows} rows={filteredLessonTypes} />
|
||||||
|
</Box>
|
||||||
|
<Divider />
|
||||||
|
<LessonTypesPagination count={filteredLessonTypes.length + 100} page={0} />
|
||||||
|
</Card>
|
||||||
|
</LessonTypesSelectionProvider>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@@ -0,0 +1,104 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import { LoadingButton } from '@mui/lab';
|
||||||
|
import { Button, Container, Modal, Paper } from '@mui/material';
|
||||||
|
import Avatar from '@mui/material/Avatar';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Stack from '@mui/material/Stack';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import { Note as NoteIcon } from '@phosphor-icons/react/dist/ssr/Note';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
// import { deleteLessonType } from './http-actions';
|
||||||
|
|
||||||
|
export default function ConfirmDeleteModal({
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
idToDelete,
|
||||||
|
reloadRows,
|
||||||
|
}: {
|
||||||
|
open: boolean;
|
||||||
|
setOpen: (b: boolean) => void;
|
||||||
|
idToDelete: string;
|
||||||
|
reloadRows: () => void;
|
||||||
|
}): React.JSX.Element {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
// const handleClose = () => setOpen(false);
|
||||||
|
function handleClose(): void {
|
||||||
|
setOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [isDeleteing, setIsDeleteing] = React.useState(false);
|
||||||
|
const style = {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUserConfirmDelete = (): void => {
|
||||||
|
if (idToDelete) {
|
||||||
|
setIsDeleteing(true);
|
||||||
|
// deleteLessonType(idToDelete)
|
||||||
|
// .then(() => {
|
||||||
|
// reloadRows();
|
||||||
|
// handleClose();
|
||||||
|
// })
|
||||||
|
// .catch((err) => {
|
||||||
|
// // console.error(err);
|
||||||
|
// setIsDeleteing(false);
|
||||||
|
// })
|
||||||
|
// .finally(() => {
|
||||||
|
// setIsDeleteing(false);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Modal
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
aria-labelledby="modal-modal-title"
|
||||||
|
aria-describedby="modal-modal-description"
|
||||||
|
>
|
||||||
|
<Box sx={style}>
|
||||||
|
<Container maxWidth="sm">
|
||||||
|
<Paper sx={{ border: '1px solid var(--mui-palette-divider)', boxShadow: 'var(--mui-shadows-16)' }}>
|
||||||
|
<Stack direction="row" spacing={2} sx={{ display: 'flex', p: 3 }}>
|
||||||
|
<Avatar sx={{ bgcolor: 'var(--mui-palette-error-50)', color: 'var(--mui-palette-error-main)' }}>
|
||||||
|
<NoteIcon fontSize="var(--Icon-fontSize)" />
|
||||||
|
</Avatar>
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<Stack spacing={1}>
|
||||||
|
<Typography variant="h5">{t('Delete Lesson Type ?')}</Typography>
|
||||||
|
<Typography color="text.secondary" variant="body2">
|
||||||
|
{t('Are you sure you want to delete lesson type ?')}
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
<Stack direction="row" spacing={2} sx={{ justifyContent: 'flex-end' }}>
|
||||||
|
<Button color="secondary" onClick={handleClose}>
|
||||||
|
{t('Cancel')}
|
||||||
|
</Button>
|
||||||
|
<LoadingButton
|
||||||
|
color="error"
|
||||||
|
variant="contained"
|
||||||
|
onClick={(e) => {
|
||||||
|
handleUserConfirmDelete();
|
||||||
|
}}
|
||||||
|
loading={isDeleteing}
|
||||||
|
>
|
||||||
|
{t('Delete')}
|
||||||
|
</LoadingButton>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Container>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import TablePagination from '@mui/material/TablePagination';
|
||||||
|
|
||||||
|
function noop(): void {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LessonTypesPaginationProps {
|
||||||
|
count: number;
|
||||||
|
page: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LessonTypesPagination({ count, page }: LessonTypesPaginationProps): React.JSX.Element {
|
||||||
|
// You should implement the pagination using a similar logic as the filters.
|
||||||
|
// Note that when page change, you should keep the filter search params.
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TablePagination
|
||||||
|
component="div"
|
||||||
|
count={count}
|
||||||
|
onPageChange={noop}
|
||||||
|
onRowsPerPageChange={noop}
|
||||||
|
page={page}
|
||||||
|
rowsPerPage={5}
|
||||||
|
rowsPerPageOptions={[5, 10, 25]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@@ -0,0 +1,162 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import RouterLink from 'next/link';
|
||||||
|
import { Button } from '@mui/material';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Chip from '@mui/material/Chip';
|
||||||
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
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 { 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 { i18n } from '@/lib/i18n';
|
||||||
|
import { DataTable } from '@/components/core/data-table';
|
||||||
|
import type { ColumnDef } from '@/components/core/data-table';
|
||||||
|
|
||||||
|
import ConfirmDeleteModal from './confirm-delete-modal';
|
||||||
|
import type { LessonType } from './ILessonType';
|
||||||
|
import { useLessonTypesSelection } from './lesson-types-selection-context';
|
||||||
|
|
||||||
|
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<LessonType>[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
formatter: (row): React.JSX.Element => (
|
||||||
|
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
color="inherit"
|
||||||
|
component={RouterLink}
|
||||||
|
href={paths.dashboard.lesson_types.details('1')}
|
||||||
|
sx={{ whiteSpace: 'nowrap' }}
|
||||||
|
variant="subtitle2"
|
||||||
|
>
|
||||||
|
{row.name}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</Stack>
|
||||||
|
),
|
||||||
|
name: 'Name',
|
||||||
|
width: '250px',
|
||||||
|
},
|
||||||
|
{ field: 'type', name: 'Lesson type', width: '150px' },
|
||||||
|
{ field: 'pos', name: 'Lesson position', width: '150px' },
|
||||||
|
{
|
||||||
|
formatter: (row): React.JSX.Element => {
|
||||||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
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" /> },
|
||||||
|
visible: {
|
||||||
|
label: t('visible'),
|
||||||
|
icon: <ClockIcon color="var(--mui-palette-success-main)" weight="fill" />,
|
||||||
|
},
|
||||||
|
hidden: {
|
||||||
|
label: t('hidden'),
|
||||||
|
icon: <ClockIcon color="var(--mui-palette-warning-main)" weight="fill" />,
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const { label, icon } = mapping[row.visible] ?? { 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" />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
name: 'visible',
|
||||||
|
width: '150px',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
formatter(row) {
|
||||||
|
return dayjs(row.createdAt).format('MMM D, YYYY h:mm A');
|
||||||
|
},
|
||||||
|
name: 'Created at',
|
||||||
|
width: '200px',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
formatter: (row): React.JSX.Element => (
|
||||||
|
<Stack direction="row" spacing={1}>
|
||||||
|
<IconButton component={RouterLink} href={paths.dashboard.lesson_types.details(row.id)}>
|
||||||
|
<PencilSimpleIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
color="error"
|
||||||
|
onClick={() => {
|
||||||
|
handleDeleteClick(row.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TrashSimpleIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Stack>
|
||||||
|
),
|
||||||
|
name: 'Actions',
|
||||||
|
width: '100px',
|
||||||
|
align: 'right',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LessonTypesTableProps {
|
||||||
|
rows: LessonType[];
|
||||||
|
reloadRows: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LessonTypesTable({ rows, reloadRows }: LessonTypesTableProps): React.JSX.Element {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { deselectAll, deselectOne, selectAll, selectOne, selected } = useLessonTypesSelection();
|
||||||
|
|
||||||
|
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<LessonType>
|
||||||
|
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 types found')}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user