update,
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import GetAllCount from '@/db/LessonCategories/GetAllCount';
|
||||
import GetHiddenCount from '@/db/LessonCategories/GetHiddenCount';
|
||||
import GetVisibleCount from '@/db/LessonCategories/GetVisibleCount';
|
||||
import GetAllCount from '@/db/Vocabularies/GetAllCount';
|
||||
import GetHiddenCount from '@/db/Vocabularies/GetHiddenCount';
|
||||
import GetVisibleCount from '@/db/Vocabularies/GetVisibleCount';
|
||||
import Button from '@mui/material/Button';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Divider from '@mui/material/Divider';
|
||||
|
@@ -5,8 +5,7 @@ import * as React from 'react';
|
||||
import { useSelection } from '@/hooks/use-selection';
|
||||
import type { Selection } from '@/hooks/use-selection';
|
||||
|
||||
import { Vocabulary } from './type';
|
||||
|
||||
import type { Vocabulary } from './type';
|
||||
|
||||
function noop(): void {
|
||||
return undefined;
|
||||
|
@@ -5,21 +5,14 @@ import RouterLink from 'next/link';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import LinearProgress from '@mui/material/LinearProgress';
|
||||
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 { Images as ImagesIcon } from '@phosphor-icons/react/dist/ssr/Images';
|
||||
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';
|
||||
@@ -29,16 +22,8 @@ import type { ColumnDef } from '@/components/core/data-table';
|
||||
import ConfirmDeleteModal from './confirm-delete-modal';
|
||||
import { useVocabulariesSelection } from './vocabularies-selection-context';
|
||||
import type { Vocabulary } from './type';
|
||||
import { listLessonCategories } from '@/db/LessonCategories/listLessonCategories';
|
||||
import { LessonCategory } from '@/db/LessonCategories/type';
|
||||
import { Logger } from '@/lib/logger';
|
||||
import { logger } from '@/lib/default-logger';
|
||||
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||
|
||||
function columns(
|
||||
handleDeleteClick: (testId: string) => void,
|
||||
lessonCategories: { id: string; label: string }[]
|
||||
): ColumnDef<Vocabulary>[] {
|
||||
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Vocabulary>[] {
|
||||
return [
|
||||
{
|
||||
formatter: (row): React.JSX.Element => (
|
||||
@@ -173,20 +158,6 @@ export function VocabulariesTable({ rows, reloadRows }: VocabulariesTableProps):
|
||||
setIdToDelete(testId);
|
||||
}
|
||||
|
||||
let [lessonCategories, setLessonCategories] = React.useState<{}>({});
|
||||
|
||||
async function tempFunc(): Promise<void> {
|
||||
try {
|
||||
const tempCategories = await listLessonCategories();
|
||||
console.log(tempCategories);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
}
|
||||
}
|
||||
React.useEffect(() => {
|
||||
void tempFunc;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ConfirmDeleteModal
|
||||
|
@@ -2,75 +2,85 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import RouterLink from 'next/link';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { COL_VOCABULARIES } from '@/constants';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { Avatar, Divider } from '@mui/material';
|
||||
// import Avatar from '@mui/material/Avatar';
|
||||
import { Avatar, Divider, MenuItem } from '@mui/material';
|
||||
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 FormControl from '@mui/material/FormControl';
|
||||
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 { fileToBase64 } from '@/lib/file-to-base64';
|
||||
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
|
||||
import { pb } from '@/lib/pb';
|
||||
import { Option } from '@/components/core/option';
|
||||
|
||||
import { TextEditor } from '@/components/core/text-editor/text-editor';
|
||||
import { toast } from '@/components/core/toaster';
|
||||
import FormLoading from '@/components/loading';
|
||||
|
||||
import ErrorDisplay from '../error';
|
||||
import type { EditFormProps } from './type';
|
||||
import { listLessonCategories } from '@/db/LessonCategories/listLessonCategories';
|
||||
import isDevelopment from '@/lib/check-is-development';
|
||||
|
||||
const schema = zod.object({
|
||||
image: zod.union([zod.array(zod.any()), zod.string()]).optional(),
|
||||
sound: zod.union([zod.array(zod.any()), zod.string()]).optional(),
|
||||
word: zod.string().min(1, 'Word is required').max(255),
|
||||
word_c: zod.string().min(1, 'Chinese word is required').max(255),
|
||||
sample_e: zod.string().optional(),
|
||||
sample_c: zod.string().optional(),
|
||||
cat_id: zod.string().min(1, 'Category ID is required'),
|
||||
category: zod.string().optional(),
|
||||
lesson_type_id: zod.string().optional(),
|
||||
// NOTE: for image handling
|
||||
avatar: zod.string().optional(),
|
||||
name: zod.string().min(1, 'Name is required').max(255),
|
||||
email: zod.string().email('Must be a valid email').min(1, 'Email is required').max(255),
|
||||
phone: zod.string().min(1, 'Phone is required').max(15),
|
||||
company: zod.string().max(255),
|
||||
billingAddress: zod.object({
|
||||
country: zod.string().min(1, 'Country is required').max(255),
|
||||
state: zod.string().min(1, 'State is required').max(255),
|
||||
city: zod.string().min(1, 'City is required').max(255),
|
||||
zipCode: zod.string().min(1, 'Zip code is required').max(255),
|
||||
line1: zod.string().min(1, 'Street line 1 is required').max(255),
|
||||
line2: zod.string().max(255).optional(),
|
||||
}),
|
||||
taxId: zod.string().max(255).optional(),
|
||||
timezone: zod.string().min(1, 'Timezone is required').max(255),
|
||||
language: zod.string().min(1, 'Language is required').max(255),
|
||||
currency: zod.string().min(1, 'Currency is required').max(255),
|
||||
visible: zod.string(),
|
||||
});
|
||||
|
||||
type Values = zod.infer<typeof schema>;
|
||||
|
||||
const defaultValues = {
|
||||
avatar: '',
|
||||
name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company: '',
|
||||
billingAddress: { country: '', state: '', city: '', zipCode: '', line1: '', line2: '' },
|
||||
taxId: '',
|
||||
timezone: 'new_york',
|
||||
language: 'en',
|
||||
currency: 'USD',
|
||||
image: undefined,
|
||||
sound: undefined,
|
||||
word: '',
|
||||
word_c: '',
|
||||
sample_e: '',
|
||||
sample_c: '',
|
||||
cat_id: '',
|
||||
category: '',
|
||||
lesson_type_id: '',
|
||||
visible: 'visible',
|
||||
} satisfies Values;
|
||||
|
||||
export function VocabularyCreateForm(): React.JSX.Element {
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation(['common', 'lesson_category']);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { cat_id: catId } = useParams<{ cat_id: string }>();
|
||||
|
||||
const [isCreating, setIsCreating] = React.useState<boolean>(false);
|
||||
const [showLoading, setShowLoading] = React.useState<boolean>(false);
|
||||
//
|
||||
const [showError, setShowError] = React.useState({ show: false, detail: '' });
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -83,15 +93,33 @@ export function VocabularyCreateForm(): React.JSX.Element {
|
||||
const onSubmit = React.useCallback(
|
||||
async (values: Values): Promise<void> => {
|
||||
setIsCreating(true);
|
||||
|
||||
const tempUpdate: EditFormProps = {
|
||||
image: values.avatar ? [await base64ToFile(values.avatar)] : null,
|
||||
sound: '',
|
||||
word: values.word,
|
||||
word_c: values.word_c,
|
||||
sample_e: values.sample_e || '',
|
||||
sample_c: values.sample_c || '',
|
||||
cat_id: values.cat_id,
|
||||
category: '',
|
||||
lesson_type_id: '',
|
||||
};
|
||||
|
||||
try {
|
||||
// Make API request
|
||||
toast.success('Customer updated');
|
||||
router.push(paths.dashboard.lesson_categories.details('1'));
|
||||
const result = await pb.collection(COL_VOCABULARIES).create(tempUpdate);
|
||||
logger.debug(result);
|
||||
toast.success(t('create.success'));
|
||||
// router.push(paths.dashboard.lesson_categories.details('1'));
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
toast.error('Something went wrong!');
|
||||
toast.error(t('create.failed'));
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
}
|
||||
},
|
||||
// t is not necessary here
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[router]
|
||||
);
|
||||
|
||||
@@ -110,6 +138,43 @@ export function VocabularyCreateForm(): React.JSX.Element {
|
||||
[setValue]
|
||||
);
|
||||
|
||||
const [categoriesOption, setCategoriesOption] = React.useState<{ value: string; label: string }[]>([]);
|
||||
const loadCategories = React.useCallback(async () => {
|
||||
try {
|
||||
const categories = await listLessonCategories();
|
||||
|
||||
logger.debug(categories);
|
||||
|
||||
setCategoriesOption(
|
||||
categories.map((c) => {
|
||||
return { label: c.cat_name || '??', value: c.id };
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
toast.error(t('list.error'));
|
||||
}
|
||||
}, [catId]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setShowLoading(true);
|
||||
void loadCategories();
|
||||
//
|
||||
setShowLoading(false);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [catId]);
|
||||
|
||||
if (showLoading) return <FormLoading />;
|
||||
if (showError.show)
|
||||
return (
|
||||
<ErrorDisplay
|
||||
message={t('error.unable-to-process-request')}
|
||||
code="500"
|
||||
details={showError.detail}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Card>
|
||||
@@ -183,84 +248,125 @@ export function VocabularyCreateForm(): React.JSX.Element {
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
disabled={isCreating}
|
||||
control={control}
|
||||
name="name"
|
||||
name="word"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.name)}
|
||||
disabled={isCreating}
|
||||
error={Boolean(errors.word)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel required>{t('create.name')}</InputLabel>
|
||||
<InputLabel required>{t('create.word')}</InputLabel>
|
||||
<OutlinedInput {...field} />
|
||||
{errors.name ? <FormHelperText>{errors.name.message}</FormHelperText> : null}
|
||||
{errors.word ? <FormHelperText>{errors.word.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
{/* */}
|
||||
<Grid
|
||||
md={6}
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
disabled={isCreating}
|
||||
control={control}
|
||||
name="word_c"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.word_c)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel required>{t('create.word_c')}</InputLabel>
|
||||
<OutlinedInput {...field} />
|
||||
{errors.word_c ? <FormHelperText>{errors.word_c.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
{/* */}
|
||||
<Grid
|
||||
md={6}
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
disabled={isCreating}
|
||||
control={control}
|
||||
name="cat_id"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.cat_id)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel>{t('create.cat_id')}</InputLabel>
|
||||
<Select {...field}>
|
||||
{categoriesOption.map((co, i) => (
|
||||
<Option
|
||||
key={i}
|
||||
value={co.value}
|
||||
>
|
||||
{co.label}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
{/* */}
|
||||
<Grid
|
||||
md={6}
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
disabled={isCreating}
|
||||
control={control}
|
||||
name="sound"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.sound)}
|
||||
fullWidth
|
||||
>
|
||||
{/* TODO: sound file selection is not implemented */}
|
||||
<InputLabel required>{t('create.sound_file')} - (Not implemented)</InputLabel>
|
||||
<OutlinedInput {...field} />
|
||||
{errors.sound ? <FormHelperText>{errors.sound.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid
|
||||
md={6}
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="email"
|
||||
name="visible"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.email)}
|
||||
error={Boolean(errors.visible)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel required>Email address</InputLabel>
|
||||
<OutlinedInput
|
||||
{...field}
|
||||
type="email"
|
||||
/>
|
||||
{errors.email ? <FormHelperText>{errors.email.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
md={6}
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="phone"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.phone)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel required>Phone number</InputLabel>
|
||||
<OutlinedInput {...field} />
|
||||
{errors.phone ? <FormHelperText>{errors.phone.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
md={6}
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name="company"
|
||||
render={({ field }) => (
|
||||
<FormControl
|
||||
error={Boolean(errors.company)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel>Company</InputLabel>
|
||||
<OutlinedInput {...field} />
|
||||
{errors.company ? <FormHelperText>{errors.company.message}</FormHelperText> : null}
|
||||
<InputLabel>{t('create.visible')}</InputLabel>
|
||||
<Select {...field}>
|
||||
<MenuItem value="visible">visible</MenuItem>
|
||||
<MenuItem value="hidden">hidden</MenuItem>
|
||||
</Select>
|
||||
|
||||
{errors.visible ? <FormHelperText>{errors.visible.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
|
||||
{/* */}
|
||||
|
||||
<Stack spacing={3}>
|
||||
<Typography variant="h6">{t('create.detail-information')}</Typography>
|
||||
<Typography variant="h6">{t('create.sample-sentence')}</Typography>
|
||||
<Grid
|
||||
container
|
||||
spacing={3}
|
||||
@@ -270,23 +376,22 @@ export function VocabularyCreateForm(): React.JSX.Element {
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
disabled={isCreating}
|
||||
control={control}
|
||||
name="billingAddress.country"
|
||||
name="sample_e"
|
||||
render={({ field }) => (
|
||||
<Box>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
color="text-secondary"
|
||||
>
|
||||
{t('create.description')}
|
||||
</Typography>
|
||||
<Box sx={{ mt: '8px', '& .tiptap-container': { height: '400px' } }}>
|
||||
<TextEditor
|
||||
content=""
|
||||
placeholder="Write something"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<FormControl
|
||||
error={Boolean(errors.sample_e)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel>{t('create.sample_e')}</InputLabel>
|
||||
<OutlinedInput
|
||||
{...field}
|
||||
multiline
|
||||
rows={4}
|
||||
/>
|
||||
{errors.sample_e ? <FormHelperText>{errors.sample_e.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
@@ -295,35 +400,35 @@ export function VocabularyCreateForm(): React.JSX.Element {
|
||||
xs={12}
|
||||
>
|
||||
<Controller
|
||||
disabled={isCreating}
|
||||
control={control}
|
||||
name="billingAddress.state"
|
||||
name="sample_c"
|
||||
render={({ field }) => (
|
||||
<Box>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
color="text.secondary"
|
||||
>
|
||||
{t('create.remarks')}
|
||||
</Typography>
|
||||
<Box sx={{ mt: '8px', '& .tiptap-container': { height: '400px' } }}>
|
||||
<TextEditor
|
||||
content=""
|
||||
placeholder="Write something"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<FormControl
|
||||
error={Boolean(errors.sample_c)}
|
||||
fullWidth
|
||||
>
|
||||
<InputLabel>{t('create.sample_c')}</InputLabel>
|
||||
<OutlinedInput
|
||||
{...field}
|
||||
multiline
|
||||
rows={4}
|
||||
/>
|
||||
{errors.sample_c ? <FormHelperText>{errors.sample_c.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Stack>
|
||||
{/* */}
|
||||
</Stack>
|
||||
</CardContent>
|
||||
<CardActions sx={{ justifyContent: 'flex-end' }}>
|
||||
<Button
|
||||
color="secondary"
|
||||
component={RouterLink}
|
||||
href={paths.dashboard.lesson_categories.list}
|
||||
href={paths.dashboard.vocabularies.list}
|
||||
>
|
||||
{t('create.cancelButton')}
|
||||
</Button>
|
||||
@@ -337,6 +442,9 @@ export function VocabularyCreateForm(): React.JSX.Element {
|
||||
{t('create.createButton')}
|
||||
</LoadingButton>
|
||||
</CardActions>
|
||||
<Box sx={{ display: isDevelopment ? 'block' : 'none' }}>
|
||||
<pre>{JSON.stringify(errors, null, 2)}</pre>
|
||||
</Box>
|
||||
</Card>
|
||||
</form>
|
||||
);
|
||||
|
@@ -6,8 +6,7 @@ import { useParams, useRouter } from 'next/navigation';
|
||||
import { COL_VOCABULARIES } from '@/constants';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { Avatar, Divider, MenuItem } from '@mui/material';
|
||||
// import Avatar from '@mui/material/Avatar';
|
||||
import { Avatar, Divider } from '@mui/material';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Card from '@mui/material/Card';
|
||||
@@ -23,26 +22,20 @@ 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 type { RecordModel } from 'pocketbase';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z as zod } from 'zod';
|
||||
|
||||
import { paths } from '@/paths';
|
||||
import { dayjs } from '@/lib/dayjs';
|
||||
import { logger } from '@/lib/default-logger';
|
||||
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
|
||||
import { pb } from '@/lib/pb';
|
||||
import { Option } from '@/components/core/option';
|
||||
import { TextEditor } from '@/components/core/text-editor/text-editor';
|
||||
import { toast } from '@/components/core/toaster';
|
||||
import FormLoading from '@/components/loading';
|
||||
|
||||
import ErrorDisplay from '../error';
|
||||
import { defaultLessonCategory } from './_constants';
|
||||
import type { EditFormProps } from './type';
|
||||
import getVocabularyById from '@/db/Vocabularies/GetById';
|
||||
import getAllLessonCategories from '@/db/LessonCategories/GetAll';
|
||||
import { listLessonCategories } from '@/db/LessonCategories/listLessonCategories';
|
||||
import isDevelopment from '@/lib/check-is-development';
|
||||
|
||||
@@ -55,7 +48,7 @@ const schema = zod.object({
|
||||
sample_c: zod.string().optional(),
|
||||
cat_id: zod.string().min(1, 'Category ID is required'),
|
||||
category: zod.string().optional(),
|
||||
lesson_type_id: zod.string().min(1, 'Lesson type ID is required'),
|
||||
lesson_type_id: zod.string().optional(),
|
||||
// NOTE: for image handling
|
||||
avatar: zod.string().optional(),
|
||||
});
|
||||
@@ -111,7 +104,6 @@ export function VocabularyEditForm(): React.JSX.Element {
|
||||
};
|
||||
//
|
||||
try {
|
||||
console.log({ tempUpdate });
|
||||
const result = await pb.collection(COL_VOCABULARIES).update(catId, tempUpdate);
|
||||
logger.debug(result);
|
||||
toast.success(t('edit.success'));
|
||||
@@ -173,7 +165,7 @@ export function VocabularyEditForm(): React.JSX.Element {
|
||||
[catId]
|
||||
);
|
||||
|
||||
let [categoriesOption, setCategoriesOption] = React.useState<{ value: string; label: string }[]>([]);
|
||||
const [categoriesOption, setCategoriesOption] = React.useState<{ value: string; label: string }[]>([]);
|
||||
const loadCategories = React.useCallback(async () => {
|
||||
try {
|
||||
const categories = await listLessonCategories();
|
||||
@@ -193,10 +185,8 @@ export function VocabularyEditForm(): React.JSX.Element {
|
||||
|
||||
React.useEffect(() => {
|
||||
setShowLoading(true);
|
||||
|
||||
void loadCategories();
|
||||
void loadExistingData(catId);
|
||||
|
||||
setShowLoading(false);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
Reference in New Issue
Block a user