update build ok,

This commit is contained in:
louiscklaw
2025-04-16 19:38:52 +08:00
parent 8bc4a37e8e
commit 0648bf5bfb
8 changed files with 130 additions and 75 deletions

View File

@@ -1,20 +1,19 @@
'use client'; 'use client';
import * as React from 'react'; import * as React from 'react';
import RouterLink from 'next/link'; import RouterLink from 'next/link';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Link from '@mui/material/Link'; import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack'; import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import { ArrowLeft as ArrowLeftIcon } from '@phosphor-icons/react/dist/ssr/ArrowLeft'; import { ArrowLeft as ArrowLeftIcon } from '@phosphor-icons/react/dist/ssr/ArrowLeft';
import { useTranslation } from 'react-i18next';
import { config } from '@/config';
import { paths } from '@/paths'; import { paths } from '@/paths';
import { CustomerCreateForm } from '@/components/dashboard/lesson_category/lesson-category-create-form'; import { LessonCategoryCreateForm } from '@/components/dashboard/lesson_category/lesson-category-create-form';
export default function Page(): React.JSX.Element { export default function Page(): React.JSX.Element {
const { t } = useTranslation();
return ( return (
<Box <Box
sx={{ sx={{
@@ -35,14 +34,14 @@ export default function Page(): React.JSX.Element {
variant="subtitle2" variant="subtitle2"
> >
<ArrowLeftIcon fontSize="var(--icon-fontSize-md)" /> <ArrowLeftIcon fontSize="var(--icon-fontSize-md)" />
Lesson Categories {t('dashboard.lessonCategories.title')}
</Link> </Link>
</div> </div>
<div> <div>
<Typography variant="h4">Create customer</Typography> <Typography variant="h4">{t('dashboard.lessonCategories.create.title')}</Typography>
</div> </div>
</Stack> </Stack>
<CustomerCreateForm /> <LessonCategoryCreateForm />
</Stack> </Stack>
</Box> </Box>
); );

View File

@@ -12,6 +12,12 @@ export const lessonCategoriesSampleData = [
quota: 50, quota: 50,
status: 'active', status: 'active',
createdAt: dayjs().subtract(1, 'hour').toDate(), createdAt: dayjs().subtract(1, 'hour').toDate(),
cat_name: '',
pos: 99,
visible: 'visible',
lesson_id: 'lid_00001',
description: '',
remarks: '',
}, },
{ {
id: 'USR-004', id: 'USR-004',
@@ -22,6 +28,12 @@ export const lessonCategoriesSampleData = [
quota: 100, quota: 100,
status: 'active', status: 'active',
createdAt: dayjs().subtract(3, 'hour').toDate(), createdAt: dayjs().subtract(3, 'hour').toDate(),
cat_name: '',
pos: 99,
visible: 'visible',
lesson_id: 'lid_00001',
description: '',
remarks: '',
}, },
{ {
id: 'USR-003', id: 'USR-003',
@@ -32,6 +44,12 @@ export const lessonCategoriesSampleData = [
quota: 10, quota: 10,
status: 'blocked', status: 'blocked',
createdAt: dayjs().subtract(1, 'hour').subtract(1, 'day').toDate(), createdAt: dayjs().subtract(1, 'hour').subtract(1, 'day').toDate(),
cat_name: '',
pos: 99,
visible: 'visible',
lesson_id: 'lid_00001',
description: '',
remarks: '',
}, },
{ {
id: 'USR-002', id: 'USR-002',
@@ -42,6 +60,12 @@ export const lessonCategoriesSampleData = [
quota: 0, quota: 0,
status: 'pending', status: 'pending',
createdAt: dayjs().subtract(7, 'hour').subtract(1, 'day').toDate(), createdAt: dayjs().subtract(7, 'hour').subtract(1, 'day').toDate(),
cat_name: '',
pos: 99,
visible: 'visible',
lesson_id: 'lid_00001',
description: '',
remarks: '',
}, },
{ {
id: 'USR-001', id: 'USR-001',
@@ -52,5 +76,11 @@ export const lessonCategoriesSampleData = [
quota: 50, quota: 50,
status: 'active', status: 'active',
createdAt: dayjs().subtract(2, 'hour').subtract(2, 'day').toDate(), createdAt: dayjs().subtract(2, 'hour').subtract(2, 'day').toDate(),
cat_name: '',
pos: 99,
visible: 'visible',
lesson_id: 'lid_00001',
description: '',
remarks: '',
}, },
] satisfies LessonCategory[]; ] satisfies LessonCategory[];

View File

@@ -5,7 +5,6 @@ import { useRouter } from 'next/navigation';
import { COL_LESSON_CATEGORIES } from '@/constants'; import { COL_LESSON_CATEGORIES } from '@/constants';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
import Divider from '@mui/material/Divider'; import Divider from '@mui/material/Divider';
import Stack from '@mui/material/Stack'; import Stack from '@mui/material/Stack';
@@ -19,8 +18,8 @@ import { logger } from '@/lib/default-logger';
import { pb } from '@/lib/pb'; import { pb } from '@/lib/pb';
import { toast } from '@/components/core/toaster'; import { toast } from '@/components/core/toaster';
import { import {
DBLessonCategory,
defaultLessonCategory, defaultLessonCategory,
type emptyLessonCategory,
type LessonCategory, type LessonCategory,
} from '@/components/dashboard/lesson_category/interfaces'; } from '@/components/dashboard/lesson_category/interfaces';
import { LessonCategoriesFilters } from '@/components/dashboard/lesson_category/lesson-categories-filters'; import { LessonCategoriesFilters } from '@/components/dashboard/lesson_category/lesson-categories-filters';
@@ -64,7 +63,7 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
.then((lessonCategories: ListResult<RecordModel>) => { .then((lessonCategories: ListResult<RecordModel>) => {
// console.log(lessonTypes); // console.log(lessonTypes);
const { items, page, perPage, totalItems, totalPages } = lessonCategories; const { items, page, perPage, totalItems, totalPages } = lessonCategories;
const tempLessonCategories: LessonCategory[] = items.map((item) => { const tempLessonCategories: DBLessonCategory[] = items.map((item) => {
return { ...defaultLessonCategory, ...item }; return { ...defaultLessonCategory, ...item };
}); });

View File

@@ -0,0 +1,12 @@
export function fileToBase64(file: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result as string);
};
reader.onerror = () => {
reject(new Error('Error converting file to base64'));
};
});
}

View File

@@ -1,11 +1,21 @@
import { dayjs } from '@/lib/dayjs'; import { dayjs } from '@/lib/dayjs';
export interface LessonCategory { export interface LessonCategory {
id: string;
isEmpty?: boolean; isEmpty?: boolean;
name: string; //
id: string;
cat_name: string;
cat_image_url?: string;
cat_image?: string;
pos: number;
visible: string;
lesson_id: string;
description: string;
remarks: string;
//
name?: string;
avatar?: string; avatar?: string;
email: string; email?: string;
phone?: string; phone?: string;
quota: number; quota: number;
status: 'pending' | 'active' | 'blocked' | 'NA'; status: 'pending' | 'active' | 'blocked' | 'NA';
@@ -14,26 +24,49 @@ export interface LessonCategory {
export interface DBLessonCategory { export interface DBLessonCategory {
id: string; id: string;
name: string; cat_name: string;
avatar?: string; cat_image_url?: string;
email: string; cat_image?: string;
phone?: string; pos: number;
quota: number; visible: string;
status: 'pending' | 'active' | 'blocked'; lesson_id: string;
description: string;
remarks: string;
createdAt: Date; createdAt: Date;
status: string;
} }
export const defaultLessonCategory: LessonCategory = { export const defaultLessonCategory: LessonCategory = {
isEmpty: true, id: 'default-id',
id: '', cat_name: 'default-category-name',
name: '', cat_image_url: undefined,
email: '', cat_image: undefined,
quota: -Infinity, pos: 0,
status: 'NA', visible: 'hidden',
lesson_id: 'default-lesson-id',
description: 'default-description',
remarks: 'default-remarks',
createdAt: dayjs('2099-01-01').toDate(), createdAt: dayjs('2099-01-01').toDate(),
quota: 0,
status: 'NA',
}; };
export const emptyLessonCategory: LessonCategory = { export const emptyLessonCategory: LessonCategory = {
...defaultLessonCategory, ...defaultLessonCategory,
isEmpty: true, isEmpty: true,
}; };
export interface CreateForm {
name: string;
type: string;
pos: number;
visible: string;
}
export const LessonCategoryCreateFormDefault: CreateForm = {
name: '',
type: '',
pos: 1,
visible: 'visible',
};

View File

@@ -4,7 +4,8 @@ import * as React from 'react';
import RouterLink from 'next/link'; import RouterLink from 'next/link';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import Avatar from '@mui/material/Avatar'; import { Avatar } from '@mui/material';
// import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
@@ -22,6 +23,7 @@ import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import Grid from '@mui/material/Unstable_Grid2'; import Grid from '@mui/material/Unstable_Grid2';
import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera'; import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera';
// import axios from 'axios';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
import { z as zod } from 'zod'; import { z as zod } from 'zod';
@@ -30,18 +32,7 @@ import { logger } from '@/lib/default-logger';
import { Option } from '@/components/core/option'; import { Option } from '@/components/core/option';
import { toast } from '@/components/core/toaster'; import { toast } from '@/components/core/toaster';
function fileToBase64(file: Blob): Promise<string> { import { fileToBase64 } from './file-to-base64';
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
resolve(reader.result as string);
};
reader.onerror = () => {
reject(new Error('Error converting file to base64'));
};
});
}
const schema = zod.object({ const schema = zod.object({
avatar: zod.string().optional(), avatar: zod.string().optional(),
@@ -78,7 +69,7 @@ const defaultValues = {
currency: 'USD', currency: 'USD',
} satisfies Values; } satisfies Values;
export function CustomerCreateForm(): React.JSX.Element { export function LessonCategoryCreateForm(): React.JSX.Element {
const router = useRouter(); const router = useRouter();
const { const {

View File

@@ -17,14 +17,14 @@ export interface RestLessonTypeUpdateForm {
data: LessonTypeEditFormProps; data: LessonTypeEditFormProps;
} }
export interface LessonTypeCreateForm { export interface CreateForm {
name: string; name: string;
type: string; type: string;
pos: number; pos: number;
visible: string; visible: string;
} }
export const LessonTypeCreateFormDefault: LessonTypeCreateForm = { export const LessonTypeCreateFormDefault: CreateForm = {
name: '', name: '',
type: '', type: '',
pos: 1, pos: 1,

View File

@@ -24,8 +24,6 @@ import Select from '@mui/material/Select';
import Stack from '@mui/material/Stack'; import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import Grid from '@mui/material/Unstable_Grid2'; import Grid from '@mui/material/Unstable_Grid2';
import type { RecordModel } from 'pocketbase';
import PocketBase from 'pocketbase';
// import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera'; // import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera';
// import axios from 'axios'; // import axios from 'axios';
import { Controller, useForm } from 'react-hook-form'; import { Controller, useForm } from 'react-hook-form';
@@ -34,31 +32,15 @@ import { z as zod } from 'zod';
import { paths } from '@/paths'; import { paths } from '@/paths';
import { logger } from '@/lib/default-logger'; import { logger } from '@/lib/default-logger';
import { pb } from '@/lib/pb';
// import { Option } from '@/components/core/option'; // import { Option } from '@/components/core/option';
import { toast } from '@/components/core/toaster'; import { toast } from '@/components/core/toaster';
import { defaultLessonType, LessonTypeCreateForm, LessonTypeCreateFormDefault } from './interfaces';
import type { LessonType } from './ILessonType';
import { pb } from '@/lib/pb';
import { CreateForm, LessonTypeCreateFormDefault } from './interfaces';
// import { createLessonType } from './http-actions'; // import { createLessonType } from './http-actions';
// import { LessonTypeCreateForm, LessonTypeCreateFormDefault } from './interfaces'; // import { LessonTypeCreateForm, LessonTypeCreateFormDefault } from './interfaces';
// import { createLessonType } from './httpActions';
// function fileToBase64(file: Blob): Promise<string> {
// return new Promise((resolve, reject) => {
// const reader = new FileReader();
// reader.readAsDataURL(file);
// reader.onload = () => {
// resolve(reader.result as string);
// };
// reader.onerror = () => {
// reject(new Error('Error converting file to base64'));
// };
// });
// }
const schema = zod.object({ const schema = zod.object({
name: zod.string().min(1, 'Name is required').max(255), name: zod.string().min(1, 'Name is required').max(255),
type: zod.string().min(1, 'Name is required').max(255), type: zod.string().min(1, 'Name is required').max(255),
@@ -92,19 +74,22 @@ export function LessonTypeCreateForm(): React.JSX.Element {
async (values: Values): Promise<void> => { async (values: Values): Promise<void> => {
setIsCreating(true); setIsCreating(true);
const data: LessonTypeCreateForm = {...LessonTypeCreateFormDefault, ...values} const data: CreateForm = { ...LessonTypeCreateFormDefault, ...values };
pb.collection(COL_LESSON_TYPES).create(data).then((res)=>{ pb.collection(COL_LESSON_TYPES)
console.log(res) .create(data)
logger.debug(res); .then((res) => {
toast.success(t('dashboard.lessonTypes.update.success')); console.log(res);
setIsCreating(false); logger.debug(res);
router.push(paths.dashboard.lesson_types.list); toast.success(t('dashboard.lessonTypes.update.success'));
setIsCreating(false);
}).catch((err) => { router.push(paths.dashboard.lesson_types.list);
logger.error(err); })
toast.error('Something went wrong!'); .catch((err) => {
setIsCreating(false);}) logger.error(err);
toast.error('Something went wrong!');
setIsCreating(false);
});
// const tempCreate: LessonTypeCreateForm = LessonTypeCreateFormDefault; // const tempCreate: LessonTypeCreateForm = LessonTypeCreateFormDefault;
// tempCreate.name = values.name; // tempCreate.name = values.name;
@@ -158,7 +143,7 @@ export function LessonTypeCreateForm(): React.JSX.Element {
display: 'inline-flex', display: 'inline-flex',
p: '4px', p: '4px',
}} }}
/> />
<Stack spacing={1} sx={{ alignItems: 'flex-start' }}> <Stack spacing={1} sx={{ alignItems: 'flex-start' }}>
<Typography variant="subtitle1">{t('dashboard.lessonTypes.create.avatar')}</Typography> <Typography variant="subtitle1">{t('dashboard.lessonTypes.create.avatar')}</Typography>
<Typography variant="caption">{t('dashboard.lessonTypes.create.avatarRequirements')}</Typography> <Typography variant="caption">{t('dashboard.lessonTypes.create.avatarRequirements')}</Typography>
@@ -208,7 +193,13 @@ export function LessonTypeCreateForm(): React.JSX.Element {
render={({ field }) => ( render={({ field }) => (
<FormControl error={Boolean(errors.pos)} fullWidth> <FormControl error={Boolean(errors.pos)} fullWidth>
<InputLabel required>{t('dashboard.lessonTypes.create.position')}</InputLabel> <InputLabel required>{t('dashboard.lessonTypes.create.position')}</InputLabel>
<OutlinedInput {...field} onChange={e => {field.onChange(parseInt(e.target.value))} } type="number"/> <OutlinedInput
{...field}
onChange={(e) => {
field.onChange(parseInt(e.target.value));
}}
type="number"
/>
{errors.pos ? <FormHelperText>{errors.pos.message}</FormHelperText> : null} {errors.pos ? <FormHelperText>{errors.pos.message}</FormHelperText> : null}
</FormControl> </FormControl>
)} )}