update build ok,

This commit is contained in:
louiscklaw
2025-04-16 02:09:11 +08:00
parent f49e6acef3
commit 3b8aa890d2
3 changed files with 269 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
import { dayjs } from '@/lib/dayjs';
import type { LessonType } from '@/components/dashboard/lesson_type/ILessonType';
// import { helloworld } from '@/components/dashboard/lesson_type/helloworld';
// export const metadata = { title: `List | Customers | Dashboard | ${config.site.name}` } satisfies Metadata;
export const lessonTypesSampleData = [
{
id: 'USR-005',
name: 'Fran Perez',
type: 'vocabulary',
pos: 1,
visible: 'visible',
avatar: '/assets/avatar-5.png',
email: 'fran.perez@domain.com',
phone: '(815) 704-0045',
quota: 50,
status: 'active',
createdAt: dayjs().subtract(1, 'hour').toDate(),
},
{
id: 'USR-004',
name: 'Penjani Inyene',
type: 'connectives',
pos: 1,
visible: 'visible',
avatar: '/assets/avatar-4.png',
email: 'penjani.inyene@domain.com',
phone: '(803) 937-8925',
quota: 100,
status: 'active',
createdAt: dayjs().subtract(3, 'hour').toDate(),
},
] satisfies LessonType[];
export const lessonTypesData = (): LessonType[] => {
return lessonTypesSampleData;
};

View File

@@ -0,0 +1,3 @@
const helloworld = 'helloworld';
export { helloworld };

View File

@@ -0,0 +1,229 @@
'use client';
import * as React from 'react';
import RouterLink from 'next/link';
import { useRouter } from 'next/navigation';
import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab';
import { MenuItem } from '@mui/material';
// import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
// import Checkbox from '@mui/material/Checkbox';
import Divider from '@mui/material/Divider';
import FormControl from '@mui/material/FormControl';
// import FormControlLabel from '@mui/material/FormControlLabel';
import FormHelperText from '@mui/material/FormHelperText';
import InputLabel from '@mui/material/InputLabel';
import OutlinedInput from '@mui/material/OutlinedInput';
import Select from '@mui/material/Select';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import Grid from '@mui/material/Unstable_Grid2';
// import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera';
// import axios from 'axios';
import { Controller, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { z as zod } from 'zod';
import { paths } from '@/paths';
import { logger } from '@/lib/default-logger';
// import { Option } from '@/components/core/option';
import { toast } from '@/components/core/toaster';
// import { createLessonType } from './http-actions';
// 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({
name: zod.string().min(1, 'Name is required').max(255),
type: zod.string().min(1, 'Name is required').max(255),
pos: zod.string().min(1, 'Phone is required').max(15),
visible_to_user: zod.string().max(255),
});
type Values = zod.infer<typeof schema>;
const defaultValues = {
name: '',
type: '',
pos: '1',
visible_to_user: 'visible',
} satisfies Values;
export function LessonTypeCreateForm(): React.JSX.Element {
const router = useRouter();
const { t } = useTranslation();
const [isCreating, setIsCreating] = React.useState<boolean>(false);
const {
control,
handleSubmit,
formState: { errors, isSubmitting, isSubmitted },
setValue,
// watch,
} = useForm<Values>({ defaultValues, resolver: zodResolver(schema) });
const onSubmit = React.useCallback(
async (values: Values): Promise<void> => {
setIsCreating(true);
// const tempCreate: LessonTypeCreateForm = LessonTypeCreateFormDefault;
// tempCreate.name = values.name;
// tempCreate.type = values.type;
// tempCreate.pos = 1;
// tempCreate.visible = 'visible';
// createLessonType(tempCreate)
// .then((res) => {
// router.push(paths.dashboard.lesson_types.list);
// toast.success(t('dashboard.lessonTypes.create.success'));
// })
// .catch((err) => {
// logger.error(err);
// toast.error(t('dashboard.lessonTypes.create.error'));
// setIsCreating(false);
// });
},
[router]
);
const avatarInputRef = React.useRef<HTMLInputElement>(null);
// const avatar = watch('avatar');
const handleAvatarChange = React.useCallback(
async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
// const url = await fileToBase64(file);
// setValue('avatar', url);
}
},
[setValue]
);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Card>
<CardContent>
<Stack divider={<Divider />} spacing={4}>
<Stack spacing={3}>
<Typography variant="h6">{t('dashboard.lessonTypes.create.typeInformation')}</Typography>
<Grid container spacing={3}>
<Grid xs={12}>
<Stack direction="row" spacing={3} sx={{ alignItems: 'center' }}>
<Box
sx={{
border: '1px dashed var(--mui-palette-divider)',
borderRadius: '50%',
display: 'inline-flex',
p: '4px',
}}
></Box>
<Stack spacing={1} sx={{ alignItems: 'flex-start' }}>
<Typography variant="subtitle1">{t('dashboard.lessonTypes.create.avatar')}</Typography>
<Typography variant="caption">{t('dashboard.lessonTypes.create.avatarRequirements')}</Typography>
<Button
color="secondary"
onClick={() => {
avatarInputRef.current?.click();
}}
variant="outlined"
>
{t('dashboard.lessonTypes.create.select')}
</Button>
<input hidden onChange={handleAvatarChange} ref={avatarInputRef} type="file" />
</Stack>
</Stack>
</Grid>
<Grid md={6} xs={12}>
<Controller
control={control}
name="name"
render={({ field }) => (
<FormControl error={Boolean(errors.name)} fullWidth>
<InputLabel required>{t('dashboard.lessonTypes.create.name')}</InputLabel>
<OutlinedInput {...field} />
{errors.name ? <FormHelperText>{errors.name.message}</FormHelperText> : null}
</FormControl>
)}
/>
</Grid>
<Grid md={6} xs={12}>
<Controller
control={control}
name="type"
render={({ field }) => (
<FormControl error={Boolean(errors.type)} fullWidth>
<InputLabel required>{t('dashboard.lessonTypes.create.type')}</InputLabel>
<OutlinedInput {...field} />
{errors.type ? <FormHelperText>{errors.type.message}</FormHelperText> : null}
</FormControl>
)}
/>
</Grid>
<Grid md={6} xs={12}>
<Controller
control={control}
name="pos"
render={({ field }) => (
<FormControl error={Boolean(errors.pos)} fullWidth>
<InputLabel required>{t('dashboard.lessonTypes.create.position')}</InputLabel>
<OutlinedInput {...field} />
{errors.pos ? <FormHelperText>{errors.pos.message}</FormHelperText> : null}
</FormControl>
)}
/>
</Grid>
<Grid md={6} xs={12}>
<Controller
control={control}
name="visible_to_user"
render={({ field }) => (
<FormControl error={Boolean(errors.visible_to_user)} fullWidth>
<InputLabel>{t('dashboard.lessonTypes.create.visibleToUser')}</InputLabel>
<Select {...field}>
<MenuItem value="visible">visible</MenuItem>
<MenuItem value="hidden">hidden</MenuItem>
</Select>
{errors.visible_to_user ? (
<FormHelperText>{errors.visible_to_user.message}</FormHelperText>
) : null}
</FormControl>
)}
/>
</Grid>
</Grid>
</Stack>
</Stack>
</CardContent>
<CardActions sx={{ justifyContent: 'flex-end' }}>
<Button color="secondary" component={RouterLink} href={paths.dashboard.lesson_types.list}>
{t('dashboard.lessonTypes.create.cancelButton')}
</Button>
<LoadingButton disabled={isCreating} loading={isCreating} type="submit" variant="contained">
{t('dashboard.lessonTypes.create.createButton')}
</LoadingButton>
</CardActions>
</Card>
</form>
);
}