From 07d338b4852a3542552017d607f30b36e82b3746 Mon Sep 17 00:00:00 2001 From: louiscklaw Date: Wed, 16 Apr 2025 01:15:34 +0800 Subject: [PATCH] update build ok, --- .../src/app/dashboard/lesson_types/page.tsx | 26 ++- .../lesson_type/confirm-delete-modal.tsx | 104 +++++++++++ .../lesson_type/lesson-types-pagination.tsx | 30 ++++ .../lesson_type/lesson-types-table.tsx | 162 ++++++++++++++++++ 4 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 002_source/cms/src/components/dashboard/lesson_type/confirm-delete-modal.tsx create mode 100644 002_source/cms/src/components/dashboard/lesson_type/lesson-types-pagination.tsx create mode 100644 002_source/cms/src/components/dashboard/lesson_type/lesson-types-table.tsx diff --git a/002_source/cms/src/app/dashboard/lesson_types/page.tsx b/002_source/cms/src/app/dashboard/lesson_types/page.tsx index 8ae82b5..ebfcd46 100644 --- a/002_source/cms/src/app/dashboard/lesson_types/page.tsx +++ b/002_source/cms/src/app/dashboard/lesson_types/page.tsx @@ -15,9 +15,12 @@ import { paths } from '@/paths'; import { logger } from '@/lib/default-logger'; import { toast } from '@/components/core/toaster'; 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 { 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 { searchParams: { @@ -50,6 +53,10 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element { // }); + const reloadRows = () => { + console.log('reload rows'); + }; + return ( + + + + + + + + + + + ); diff --git a/002_source/cms/src/components/dashboard/lesson_type/confirm-delete-modal.tsx b/002_source/cms/src/components/dashboard/lesson_type/confirm-delete-modal.tsx new file mode 100644 index 0000000..a5c2075 --- /dev/null +++ b/002_source/cms/src/components/dashboard/lesson_type/confirm-delete-modal.tsx @@ -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 ( +
+ + + + + + + + + + + {t('Delete Lesson Type ?')} + + {t('Are you sure you want to delete lesson type ?')} + + + + + { + handleUserConfirmDelete(); + }} + loading={isDeleteing} + > + {t('Delete')} + + + + + + + + +
+ ); +} diff --git a/002_source/cms/src/components/dashboard/lesson_type/lesson-types-pagination.tsx b/002_source/cms/src/components/dashboard/lesson_type/lesson-types-pagination.tsx new file mode 100644 index 0000000..a124e14 --- /dev/null +++ b/002_source/cms/src/components/dashboard/lesson_type/lesson-types-pagination.tsx @@ -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 ( + + ); +} diff --git a/002_source/cms/src/components/dashboard/lesson_type/lesson-types-table.tsx b/002_source/cms/src/components/dashboard/lesson_type/lesson-types-table.tsx new file mode 100644 index 0000000..63541b8 --- /dev/null +++ b/002_source/cms/src/components/dashboard/lesson_type/lesson-types-table.tsx @@ -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[] { + return [ + { + formatter: (row): React.JSX.Element => ( + +
+ + {row.name} + +
+
+ ), + 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: }, + blocked: { label: 'Blocked', icon: }, + pending: { label: 'Pending', icon: }, + visible: { + label: t('visible'), + icon: , + }, + hidden: { + label: t('hidden'), + icon: , + }, + } as const; + + const { label, icon } = mapping[row.visible] ?? { label: 'Unknown', icon: null }; + + return ( + + ); + }, + 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 => ( + + + + + { + handleDeleteClick(row.id); + }} + > + + + + ), + 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 ( + + + + columns={columns(handleDeleteClick)} + onDeselectAll={deselectAll} + onDeselectOne={(_, row) => { + deselectOne(row.id); + }} + onSelectAll={selectAll} + onSelectOne={(_, row) => { + selectOne(row.id); + }} + rows={rows} + selectable + selected={selected} + /> + {!rows.length ? ( + + + {t('No lesson types found')} + + + ) : null} + + ); +}