refactor teacher and user meta management UI by updating form components, replacing COL_TEACHERS with COL_USER_METAS where applicable, adding development environment checks, improving type definitions for user meta including billing address, and fixing parameter naming inconsistencies in form handlers
```
This commit is contained in:
louiscklaw
2025-05-13 13:27:41 +08:00
parent 09ded06dd2
commit a441e3e52d
4 changed files with 72 additions and 10 deletions

View File

@@ -1,10 +1,12 @@
'use client'; 'use client';
// src/components/dashboard/teacher/teacher-edit-form.tsx
//
import * as React from 'react'; import * as React from 'react';
import RouterLink from 'next/link'; import RouterLink from 'next/link';
import { useParams, useRouter } from 'next/navigation'; import { useParams, useRouter } from 'next/navigation';
// //
import { COL_TEACHERS, COL_USER_METAS } from '@/constants'; import { COL_USER_METAS } from '@/constants';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
// //
@@ -32,6 +34,7 @@ import { useTranslation } from 'react-i18next';
import { z as zod } from 'zod'; import { z as zod } from 'zod';
import { paths } from '@/paths'; import { paths } from '@/paths';
import isDevelopment from '@/lib/check-is-development';
import { logger } from '@/lib/default-logger'; import { logger } from '@/lib/default-logger';
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64'; import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
import { pb } from '@/lib/pb'; import { pb } from '@/lib/pb';
@@ -40,7 +43,6 @@ import FormLoading from '@/components/loading';
// import ErrorDisplay from '../../error'; // import ErrorDisplay from '../../error';
import ErrorDisplay from '../error'; import ErrorDisplay from '../error';
import isDevelopment from '@/lib/check-is-development';
// TODO: review this // TODO: review this
const schema = zod.object({ const schema = zod.object({

View File

@@ -32,6 +32,7 @@ import { useTranslation } from 'react-i18next';
import { z as zod } from 'zod'; import { z as zod } from 'zod';
import { paths } from '@/paths'; import { paths } from '@/paths';
import isDevelopment from '@/lib/check-is-development';
import { logger } from '@/lib/default-logger'; import { logger } from '@/lib/default-logger';
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64'; import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
import { pb } from '@/lib/pb'; import { pb } from '@/lib/pb';
@@ -40,7 +41,6 @@ import FormLoading from '@/components/loading';
// import ErrorDisplay from '../../error'; // import ErrorDisplay from '../../error';
import ErrorDisplay from '../error'; import ErrorDisplay from '../error';
import isDevelopment from '@/lib/check-is-development';
// TODO: review this // TODO: review this
const schema = zod.object({ const schema = zod.object({

View File

@@ -1,8 +1,55 @@
'use client'; 'use client';
import type { BillingAddress } from '@/db/billingAddress/type';
// RULES: sorting direction for teacher lists // RULES: sorting direction for teacher lists
export type SortDir = 'asc' | 'desc'; export type SortDir = 'asc' | 'desc';
// obsoleted
// export interface BillingAddress {
// city: string;
// country: string;
// line1: string;
// line2: string;
// state: string;
// zipCode: string;
// //
// id: string;
// collectionId: string;
// collectionName: string;
// updated: string;
// created: string;
// }
export interface DBUserMeta {
name: string;
//
// NOTE: obslete "avatar" and use "avatar_file"
avatar?: string;
avatar_file?: string;
//
email: string;
phone: string;
quota: number;
company: string;
//
// billingAddress: BillingAddress[] | [];
expand: { billingAddress?: BillingAddress[] };
// status is obsoleted, replace by state
status: 'pending' | 'active' | 'blocked';
state: 'pending' | 'active' | 'blocked';
//
timezone: string;
language: string;
currency: string;
//
id: string;
created: string;
updated?: string;
collectionId: string;
}
// RULES: core teacher data structure // RULES: core teacher data structure
export interface UserMeta { export interface UserMeta {
name: string; name: string;
@@ -14,10 +61,18 @@ export interface UserMeta {
email: string; email: string;
phone?: string; phone?: string;
quota: number; quota: number;
company?: string;
//
billingAddress: BillingAddress | Record<string, never>;
// status is obsoleted, replace by state // status is obsoleted, replace by state
status: 'pending' | 'active' | 'blocked'; status: 'pending' | 'active' | 'blocked';
state: 'pending' | 'active' | 'blocked'; state: 'pending' | 'active' | 'blocked';
//
timezone: string;
language: string;
currency: string;
// //
id: string; id: string;
createdAt: Date; createdAt: Date;

View File

@@ -1,10 +1,15 @@
'use client'; 'use client';
// src/components/dashboard/user_meta/user-meta-edit-form.tsx
//
import * as React from 'react'; import * as React from 'react';
import RouterLink from 'next/link'; import RouterLink from 'next/link';
import { useParams, useRouter } from 'next/navigation'; import { useParams, useRouter } from 'next/navigation';
// //
import { COL_TEACHERS, COL_USER_METAS } from '@/constants'; import { COL_CUSTOMERS, COL_USER_METAS } from '@/constants';
import { UpdateBillingAddressById } from '@/db/billingAddress/UpdateById';
import { getUserMetaById } from '@/db/UserMetas/GetById';
import { UpdateUserMetaById } from '@/db/UserMetas/UpdateById';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
// //
@@ -32,6 +37,7 @@ import { useTranslation } from 'react-i18next';
import { z as zod } from 'zod'; import { z as zod } from 'zod';
import { paths } from '@/paths'; import { paths } from '@/paths';
import isDevelopment from '@/lib/check-is-development';
import { logger } from '@/lib/default-logger'; import { logger } from '@/lib/default-logger';
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64'; import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
import { pb } from '@/lib/pb'; import { pb } from '@/lib/pb';
@@ -40,7 +46,6 @@ import FormLoading from '@/components/loading';
// import ErrorDisplay from '../../error'; // import ErrorDisplay from '../../error';
import ErrorDisplay from '../error'; import ErrorDisplay from '../error';
import isDevelopment from '@/lib/check-is-development';
// TODO: review this // TODO: review this
const schema = zod.object({ const schema = zod.object({
@@ -89,7 +94,7 @@ export function UserMetaEditForm(): React.JSX.Element {
const router = useRouter(); const router = useRouter();
const { t } = useTranslation(['lp_categories']); const { t } = useTranslation(['lp_categories']);
const { id: teacherId } = useParams<{ id: string }>(); const { id: userMetaId } = useParams<{ id: string }>();
// //
const [isUpdating, setIsUpdating] = React.useState<boolean>(false); const [isUpdating, setIsUpdating] = React.useState<boolean>(false);
const [showLoading, setShowLoading] = React.useState<boolean>(false); const [showLoading, setShowLoading] = React.useState<boolean>(false);
@@ -123,7 +128,7 @@ export function UserMetaEditForm(): React.JSX.Element {
}; };
try { try {
await pb.collection(COL_USER_METAS).update(teacherId, updateData); await pb.collection(COL_USER_METAS).update(userMetaId, updateData);
toast.success('Teacher updated successfully'); toast.success('Teacher updated successfully');
router.push(paths.dashboard.teachers.list); router.push(paths.dashboard.teachers.list);
} catch (error) { } catch (error) {
@@ -133,7 +138,7 @@ export function UserMetaEditForm(): React.JSX.Element {
setIsUpdating(false); setIsUpdating(false);
} }
}, },
[teacherId, router] [userMetaId, router]
); );
const avatarInputRef = React.useRef<HTMLInputElement>(null); const avatarInputRef = React.useRef<HTMLInputElement>(null);
@@ -186,9 +191,9 @@ export function UserMetaEditForm(): React.JSX.Element {
); );
React.useEffect(() => { React.useEffect(() => {
void loadExistingData(teacherId); void loadExistingData(userMetaId);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [teacherId]); }, [userMetaId]);
if (showLoading) return <FormLoading />; if (showLoading) return <FormLoading />;
if (showError.show) if (showError.show)