updat build ok,

This commit is contained in:
louiscklaw
2025-04-16 12:22:39 +08:00
parent 3569518c0b
commit 08e5677c0b
6 changed files with 108 additions and 31 deletions

View File

@@ -1,3 +1,9 @@
need to fix local storage error
page right (next page) button is not working
in the middle of clone lesson type to lesson category
- [ ] listing page
- [ ] delete button on each row
- [ ] create page
- [ ] edit
- [ ] delete

View File

@@ -1,6 +1,9 @@
'use client';
import * as React from 'react';
import { useRouter } from 'next/navigation';
import { COL_LESSON_CATEGORIES } from '@/constants';
import { LoadingButton } from '@mui/lab';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
@@ -8,13 +11,24 @@ import Divider from '@mui/material/Divider';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { Plus as PlusIcon } from '@phosphor-icons/react/dist/ssr/Plus';
import type { ListResult, RecordModel } from 'pocketbase';
import { useTranslation } from 'react-i18next';
import type { LessonCategory } from '@/components/dashboard/lesson_category/interfaces';
import { paths } from '@/paths';
import { logger } from '@/lib/default-logger';
import { pb } from '@/lib/pb';
import { toast } from '@/components/core/toaster';
import {
defaultLessonCategory,
type emptyLessonCategory,
type LessonCategory,
} from '@/components/dashboard/lesson_category/interfaces';
import { LessonCategoriesFilters } from '@/components/dashboard/lesson_category/lesson-categories-filters';
import type { Filters } from '@/components/dashboard/lesson_category/lesson-categories-filters';
import { LessonCategoriesPagination } from '@/components/dashboard/lesson_category/lesson-categories-pagination';
import { LessonCategoriesSelectionProvider } from '@/components/dashboard/lesson_category/lesson-categories-selection-context';
import { LessonCategoriesTable } from '@/components/dashboard/lesson_category/lesson-categories-table';
import FormLoading from '@/components/loading';
import { lessonCategoriesSampleData } from './lesson-categories-sample-data';
@@ -23,19 +37,51 @@ interface PageProps {
email?: string;
phone?: string;
sortDir?: 'asc' | 'desc';
status?: string;
name?: string;
visible?: string;
type?: string;
spStatus?: string;
spName?: string;
spVisible?: string;
spType?: string;
//
};
}
export default function Page({ searchParams }: PageProps): React.JSX.Element {
const { email, phone, sortDir, status } = searchParams;
const { t } = useTranslation();
const { email, phone, sortDir, spStatus } = searchParams;
const router = useRouter();
const [recordCount, setRecordCount] = React.useState<number>(0);
const [rowsPerPage, setRowsPerPage] = React.useState<number>(5);
const [currentPage, setCurrentPage] = React.useState<number>(1);
const sortedLessonCategories = applySort(lessonCategoriesSampleData, sortDir);
const filteredLessonCategories = applyFilters(sortedLessonCategories, { email, phone, status });
const filteredLessonCategories = applyFilters(sortedLessonCategories, { email, phone, status: spStatus });
//
const [isLoadingAddPage, setIsLoadingAddPage] = React.useState<boolean>(false);
const [lessonCategoriesData, setLessonCategoriesData] = React.useState<LessonCategory[]>([]);
const reloadRows = () => {
pb.collection(COL_LESSON_CATEGORIES)
.getList(currentPage, rowsPerPage, {})
.then((lessonCategories: ListResult<RecordModel>) => {
// console.log(lessonTypes);
const { items, page, perPage, totalItems, totalPages } = lessonCategories;
const tempLessonCategories: LessonCategory[] = items.map((item) => {
return { ...defaultLessonCategory, ...item };
});
setLessonCategoriesData(tempLessonCategories);
setRecordCount(totalItems);
})
.catch((err) => {
logger.error(err);
toast(t('dashboard.lessonTypes.list.error'));
});
};
React.useEffect(() => {
reloadRows();
}, []);
if (lessonCategoriesData.length < 1) return <FormLoading />;
return (
<Box
@@ -49,17 +95,25 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
<Stack spacing={4}>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={3} sx={{ alignItems: 'flex-start' }}>
<Box sx={{ flex: '1 1 auto' }}>
<Typography variant="h4">Lesson Categories</Typography>
<Typography variant="h4">{t('Lesson Categories')}</Typography>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button startIcon={<PlusIcon />} variant="contained">
Add
</Button>
<LoadingButton
loading={isLoadingAddPage}
onClick={(): void => {
setIsLoadingAddPage(true);
router.push(paths.dashboard.lesson_categories.create);
}}
startIcon={<PlusIcon />}
variant="contained"
>
{t('dashboard.lessonCategories.add')}
</LoadingButton>
</Box>
</Stack>
<LessonCategoriesSelectionProvider lessonCategories={filteredLessonCategories}>
<Card>
<LessonCategoriesFilters filters={{ email, phone, status }} sortDir={sortDir} />
<LessonCategoriesFilters filters={{ email, phone, status: spStatus }} sortDir={sortDir} />
<Divider />
<Box sx={{ overflowX: 'auto' }}>
<LessonCategoriesTable rows={filteredLessonCategories} />

View File

@@ -11,7 +11,6 @@ import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { Plus as PlusIcon } from '@phosphor-icons/react/dist/ssr/Plus';
import type { ListResult, RecordModel } from 'pocketbase';
import PocketBase from 'pocketbase';
import { useTranslation } from 'react-i18next';
import { paths } from '@/paths';
@@ -88,19 +87,6 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
logger.error(err);
toast(t('dashboard.lessonTypes.list.error'));
});
// pb.collection(COL_LESSON_TYPES)
// .getFullList()
// .then((lessonTypes: RecordModel[]) => {
// const tempLessonTypes: LessonType[] = lessonTypes.map((lt) => {
// return safeAssignment(lt);
// });
// setLessonTypesData(tempLessonTypes);
// })
// .catch((err) => {
// logger.error(err);
// toast(t('dashboard.lessonTypes.list.error'));
// });
};
React.useEffect(() => {
@@ -178,7 +164,7 @@ function applySort(row: LessonType[], sortDir: 'asc' | 'desc' | undefined): Less
function applyFilters(
row: LessonType[],
{ email, phone, spStatus: status, spName: name, spVisible: visible }: Filters
{ email, phone, spStatus: status, spName: name, spVisible }: Filters
): LessonType[] {
return row.filter((item) => {
if (email) {
@@ -205,8 +191,8 @@ function applyFilters(
}
}
if (visible) {
if (!item.visible?.toLowerCase().includes(visible.toLowerCase())) {
if (spVisible) {
if (!item.visible?.toLowerCase().includes(spVisible.toLowerCase())) {
return false;
}
}

View File

@@ -1,4 +1,18 @@
import { dayjs } from '@/lib/dayjs';
export interface LessonCategory {
id: string;
isEmpty?: boolean;
name: string;
avatar?: string;
email: string;
phone?: string;
quota: number;
status: 'pending' | 'active' | 'blocked' | 'NA';
createdAt: Date;
}
export interface DBLessonCategory {
id: string;
name: string;
avatar?: string;
@@ -8,3 +22,18 @@ export interface LessonCategory {
status: 'pending' | 'active' | 'blocked';
createdAt: Date;
}
export const defaultLessonCategory: LessonCategory = {
isEmpty: true,
id: '',
name: '',
email: '',
quota: -Infinity,
status: 'NA',
createdAt: dayjs('2099-01-01').toDate(),
};
export const emptyLessonCategory: LessonCategory = {
...defaultLessonCategory,
isEmpty: true,
};

View File

@@ -20,7 +20,7 @@ import { dayjs } from '@/lib/dayjs';
import { DataTable } from '@/components/core/data-table';
import type { ColumnDef } from '@/components/core/data-table';
import { LessonCategory } from './interfaces';
import type { LessonCategory } from './interfaces';
import { useLessonCategoriesSelection } from './lesson-categories-selection-context';
const columns = [
@@ -73,6 +73,7 @@ const columns = [
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 };

View File

@@ -1,5 +1,6 @@
const COL_LESSON_TYPES = 'LessonsTypes';
const COL_LESSON_CATEGORIES = 'LessonsCategories';
const NO_VALUE = 'NO_VALUE';
const NO_NUM = -Infinity;
export { COL_LESSON_TYPES, NO_VALUE, NO_NUM };
export { COL_LESSON_TYPES, NO_VALUE, NO_NUM, COL_LESSON_CATEGORIES };