I see this error with the app, reported by NextJS, please fix it. The er
This commit is contained in:
parent
7e09e249a7
commit
c63e4d3648
|
|
@ -18,7 +18,8 @@ import { useI18n, useCurrentLocale } from '@/locales/client';
|
|||
import { registerUser, updateUser } from '@/app/actions/user';
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(2, "Name must be at least 2 characters."),
|
||||
name: z.string().min(2, "Full name must be at least 2 characters."),
|
||||
nickname: z.string().optional(),
|
||||
email: z.string().email("Invalid email address."),
|
||||
role: z.enum(['User', 'Admin']),
|
||||
});
|
||||
|
|
@ -40,6 +41,7 @@ export default function UserForm({ initialData, isEditMode = false }: UserFormPr
|
|||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: initialData?.name || '',
|
||||
nickname: initialData?.nickname || '',
|
||||
email: initialData?.email || '',
|
||||
role: initialData?.role || 'User',
|
||||
},
|
||||
|
|
@ -85,7 +87,20 @@ export default function UserForm({ initialData, isEditMode = false }: UserFormPr
|
|||
name="name"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('admin.users.form_name_label')}</FormLabel>
|
||||
<FormLabel>{t('admin.users.form_full_name_label')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="e.g., John Doe" {...field} disabled={isSubmitting} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="nickname"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('admin.users.form_nickname_label')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="e.g., Johnny" {...field} disabled={isSubmitting} />
|
||||
</FormControl>
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ export default function AdminUserManagementPage() {
|
|||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>{t('admin.users.table_header_name')}</TableHead>
|
||||
<TableHead>{t('admin.users.table_header_full_name')}</TableHead>
|
||||
<TableHead>{t('admin.users.table_header_nickname')}</TableHead>
|
||||
<TableHead>{t('admin.users.table_header_email')}</TableHead>
|
||||
<TableHead>{t('admin.users.table_header_role')}</TableHead>
|
||||
<TableHead className="text-right">{t('admin.users.table_header_actions')}</TableHead>
|
||||
|
|
@ -112,6 +113,7 @@ export default function AdminUserManagementPage() {
|
|||
{users.map((user) => (
|
||||
<TableRow key={user.id}>
|
||||
<TableCell className="font-medium">{user.name}</TableCell>
|
||||
<TableCell>{user.nickname}</TableCell>
|
||||
<TableCell>{user.email}</TableCell>
|
||||
<TableCell>{user.role}</TableCell>
|
||||
<TableCell className="text-right space-x-2">
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
|
|||
|
||||
const mockUserProfile = {
|
||||
name: 'Alice Wonderland',
|
||||
nickname: 'Alice',
|
||||
email: 'alice@example.com',
|
||||
avatarUrl: 'https://placehold.co/100x100.png?text=AW',
|
||||
bio: "Lover of imaginative play and sharing joy. I have a collection of classic storybooks and dress-up costumes.",
|
||||
|
|
@ -29,6 +30,7 @@ export default function ProfilePage() {
|
|||
const changeLocale = useChangeLocale();
|
||||
|
||||
const [name, setName] = useState(mockUserProfile.name);
|
||||
const [nickname, setNickname] = useState(mockUserProfile.nickname);
|
||||
const [email, setEmail] = useState(mockUserProfile.email);
|
||||
const [avatarUrl, setAvatarUrl] = useState(mockUserProfile.avatarUrl);
|
||||
const [bio, setBio] = useState(mockUserProfile.bio);
|
||||
|
|
@ -52,7 +54,7 @@ export default function ProfilePage() {
|
|||
e.preventDefault();
|
||||
setIsLoading(true);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
console.log("Updating profile:", { name, avatarUrl, bio, phone, location });
|
||||
console.log("Updating profile:", { name, nickname, avatarUrl, bio, phone, location });
|
||||
toast({ title: t('dashboard.profile.save_button'), description: "Your profile information has been saved." });
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
|
@ -117,14 +119,19 @@ export default function ProfilePage() {
|
|||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="name">{t('dashboard.profile.full_name_label')}</Label>
|
||||
<Input id="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="Your Nickname" disabled={isLoading} />
|
||||
<Input id="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="Your Full Name" required disabled={isLoading} />
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="email">{t('dashboard.profile.email_label')}</Label>
|
||||
<Input id="email" type="email" value={email} readOnly disabled className="bg-muted/50 cursor-not-allowed" />
|
||||
<Label htmlFor="nickname">{t('dashboard.profile.nickname_label')}</Label>
|
||||
<Input id="nickname" value={nickname} onChange={(e) => setNickname(e.target.value)} placeholder="Your Nickname" disabled={isLoading} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="email">{t('dashboard.profile.email_label')}</Label>
|
||||
<Input id="email" type="email" value={email} readOnly disabled className="bg-muted/50 cursor-not-allowed" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="bio">{t('dashboard.profile.bio_label')}</Label>
|
||||
<Textarea id="bio" value={bio} onChange={(e) => setBio(e.target.value)} placeholder="Tell us a bit about yourself and your toys..." rows={3} disabled={isLoading}/>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export default function RegisterPage() {
|
|||
const locale = useCurrentLocale();
|
||||
|
||||
const [name, setName] = useState('');
|
||||
const [nickname, setNickname] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
|
|
@ -39,7 +40,7 @@ export default function RegisterPage() {
|
|||
return;
|
||||
}
|
||||
|
||||
const result = await registerUser({ name, email });
|
||||
const result = await registerUser({ name, nickname, email });
|
||||
|
||||
if (result.success && result.user) {
|
||||
// Mock login after successful registration
|
||||
|
|
@ -85,16 +86,27 @@ export default function RegisterPage() {
|
|||
<CardContent>
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name">{t('register.name_label')}</Label>
|
||||
<Label htmlFor="name">{t('register.full_name_label')}</Label>
|
||||
<Input
|
||||
id="name"
|
||||
type="text"
|
||||
placeholder="e.g., Johnny"
|
||||
placeholder="e.g., John Doe"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="nickname">{t('register.nickname_label')}</Label>
|
||||
<Input
|
||||
id="nickname"
|
||||
type="text"
|
||||
placeholder="e.g., Johnny"
|
||||
value={nickname}
|
||||
onChange={(e) => setNickname(e.target.value)}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email">{t('login.email_label')}</Label>
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ interface RegisterUserResult {
|
|||
user?: User;
|
||||
}
|
||||
|
||||
export async function registerUser(data: { name: string; email: string; password?: string, role?: 'Admin' | 'User' }): Promise<RegisterUserResult> {
|
||||
const { name, email, role = 'User' } = data;
|
||||
export async function registerUser(data: { name: string; nickname?: string; email: string; password?: string, role?: 'Admin' | 'User' }): Promise<RegisterUserResult> {
|
||||
const { name, nickname, email, role = 'User' } = data;
|
||||
|
||||
if (!name || !email) {
|
||||
return { success: false, message: 'Name and email are required.' };
|
||||
return { success: false, message: 'Full name and email are required.' };
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -29,6 +29,7 @@ export async function registerUser(data: { name: string; email: string; password
|
|||
const newUser: User = {
|
||||
id: `user-${randomUUID()}`,
|
||||
name,
|
||||
nickname,
|
||||
email,
|
||||
role: role,
|
||||
avatarUrl: '',
|
||||
|
|
@ -36,7 +37,7 @@ export async function registerUser(data: { name: string; email: string; password
|
|||
};
|
||||
|
||||
const stmt = db.prepare(
|
||||
'INSERT INTO users (id, name, email, role, avatarUrl, bio) VALUES (@id, @name, @email, @role, @avatarUrl, @bio)'
|
||||
'INSERT INTO users (id, name, nickname, email, role, avatarUrl, bio) VALUES (@id, @name, @nickname, @email, @role, @avatarUrl, @bio)'
|
||||
);
|
||||
|
||||
stmt.run(newUser);
|
||||
|
|
@ -67,12 +68,13 @@ export async function updateUser(user: User): Promise<UpdateUserResult> {
|
|||
}
|
||||
|
||||
const stmt = db.prepare(
|
||||
'UPDATE users SET name = @name, email = @email, role = @role, avatarUrl = @avatarUrl, bio = @bio WHERE id = @id'
|
||||
'UPDATE users SET name = @name, nickname = @nickname, email = @email, role = @role, avatarUrl = @avatarUrl, bio = @bio WHERE id = @id'
|
||||
);
|
||||
|
||||
stmt.run({
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
nickname: user.nickname ?? null,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
avatarUrl: user.avatarUrl ?? '',
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export function getOwnerProfile(ownerId: string) {
|
|||
// --- USER OPERATIONS ---
|
||||
|
||||
export function getAllUsers(): User[] {
|
||||
const stmt = db.prepare('SELECT id, name, email, role, avatarUrl, bio FROM users');
|
||||
const stmt = db.prepare('SELECT id, name, nickname, email, role, avatarUrl, bio FROM users');
|
||||
return stmt.all() as User[];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ function initDb() {
|
|||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
nickname TEXT,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
role TEXT,
|
||||
avatarUrl TEXT,
|
||||
|
|
@ -50,8 +51,8 @@ function initDb() {
|
|||
// Use INSERT OR IGNORE to only add data if the primary key doesn't exist.
|
||||
// This prevents errors on subsequent runs and adds missing users/toys without overwriting.
|
||||
const insertUser = db.prepare(`
|
||||
INSERT OR IGNORE INTO users (id, name, email, role, avatarUrl, bio)
|
||||
VALUES (@id, @name, @email, @role, @avatarUrl, @bio)
|
||||
INSERT OR IGNORE INTO users (id, name, nickname, email, role, avatarUrl, bio)
|
||||
VALUES (@id, @name, @nickname, @email, @role, @avatarUrl, @bio)
|
||||
`);
|
||||
|
||||
const insertToy = db.prepare(`
|
||||
|
|
@ -64,6 +65,7 @@ function initDb() {
|
|||
insertUser.run({
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
nickname: user.nickname ?? null,
|
||||
email: user.email,
|
||||
role: user.role ?? 'User',
|
||||
avatarUrl: user.avatarUrl ?? null,
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import { addDays, formatISO, subDays } from 'date-fns';
|
|||
const today = new Date();
|
||||
|
||||
export const rawUsers: User[] = [
|
||||
{ id: 'user1', name: 'Alice Wonderland', email: 'user@example.com', role: 'Admin', avatarUrl: 'https://placehold.co/100x100.png?text=AW', bio: "Lover of imaginative play and sharing joy. I have a collection of classic storybooks and dress-up costumes that my kids have outgrown but still have lots of life left in them!" },
|
||||
{ id: 'user2', name: 'Bob The Builder', email: 'user2@example.com', role: 'User', avatarUrl: 'https://placehold.co/100x100.png?text=BT', bio: "Can we fix it? Yes, we can! Sharing my collection of construction toys, tools, and playsets. Always happy to help another budding builder." },
|
||||
{ id: 'user3', name: 'Carol Danvers', email: 'user3@example.com', role: 'User', avatarUrl: 'https://placehold.co/100x100.png?text=CD', bio: "Higher, further, faster. Sharing toys that inspire adventure, courage, and exploration. My collection includes superhero action figures and space-themed playsets." },
|
||||
{ id: 'user4', name: 'Charlie Brown', email: 'user4@example.com', role: 'User' },
|
||||
{ id: 'user5', name: 'Diana Prince', email: 'user5@example.com', role: 'User' },
|
||||
{ id: 'user6', name: 'Edward Nigma', email: 'user6@example.com', role: 'User' },
|
||||
{ id: 'admin-main', name: 'Main Admin', email: 'admin@example.com', role: 'Admin' },
|
||||
{ id: 'user1', name: 'Alice Wonderland', nickname: 'Alice', email: 'user@example.com', role: 'Admin', avatarUrl: 'https://placehold.co/100x100.png?text=AW', bio: "Lover of imaginative play and sharing joy. I have a collection of classic storybooks and dress-up costumes that my kids have outgrown but still have lots of life left in them!" },
|
||||
{ id: 'user2', name: 'Bob The Builder', nickname: 'Bob', email: 'user2@example.com', role: 'User', avatarUrl: 'https://placehold.co/100x100.png?text=BT', bio: "Can we fix it? Yes, we can! Sharing my collection of construction toys, tools, and playsets. Always happy to help another budding builder." },
|
||||
{ id: 'user3', name: 'Carol Danvers', nickname: 'Captain Marvel', email: 'user3@example.com', role: 'User', avatarUrl: 'https://placehold.co/100x100.png?text=CD', bio: "Higher, further, faster. Sharing toys that inspire adventure, courage, and exploration. My collection includes superhero action figures and space-themed playsets." },
|
||||
{ id: 'user4', name: 'Charlie Brown', nickname: 'Chuck', email: 'user4@example.com', role: 'User' },
|
||||
{ id: 'user5', name: 'Diana Prince', nickname: 'Wonder Woman', email: 'user5@example.com', role: 'User' },
|
||||
{ id: 'user6', name: 'Edward Nigma', nickname: 'Riddler', email: 'user6@example.com', role: 'User' },
|
||||
{ id: 'admin-main', name: 'Main Admin', nickname: 'Head Honcho', email: 'admin@example.com', role: 'Admin' },
|
||||
];
|
||||
|
||||
export const rawToys: Omit<Toy, 'ownerName' | 'dataAiHint'>[] = [
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ export default {
|
|||
'login.invalid_credentials_toast_user': 'Invalid email or password. (Hint: user@example.com / password or admin@example.com / passwordadmin)',
|
||||
'register.create_account': 'Create Your Account',
|
||||
'register.description': 'Join ToyShare and start sharing the fun!',
|
||||
'register.name_label': 'Nickname',
|
||||
'register.full_name_label': 'Full Name',
|
||||
'register.nickname_label': 'Nickname (Optional)',
|
||||
'register.confirm_password_label': 'Confirm Password',
|
||||
'register.submit_button': 'Create Account',
|
||||
'register.loading_button': 'Registering...',
|
||||
|
|
@ -96,7 +97,8 @@ export default {
|
|||
'dashboard.profile.personal_info_title': 'Personal Information',
|
||||
'dashboard.profile.personal_info_description': 'Update your publicly visible profile information.',
|
||||
'dashboard.profile.avatar_url_label': 'Avatar URL',
|
||||
'dashboard.profile.full_name_label': 'Nickname',
|
||||
'dashboard.profile.full_name_label': 'Full Name',
|
||||
'dashboard.profile.nickname_label': 'Nickname',
|
||||
'dashboard.profile.email_label': 'Email Address (Read-only)',
|
||||
'dashboard.profile.bio_label': 'Bio',
|
||||
'dashboard.profile.phone_label': 'Phone Number',
|
||||
|
|
@ -230,7 +232,8 @@ export default {
|
|||
'admin.users.description': 'View and manage user accounts and permissions.',
|
||||
'admin.users.add_user_button': 'Add New User',
|
||||
'admin.users.back_to_users_button': 'Back to User List',
|
||||
'admin.users.table_header_name': 'Nickname',
|
||||
'admin.users.table_header_full_name': 'Full Name',
|
||||
'admin.users.table_header_nickname': 'Nickname',
|
||||
'admin.users.table_header_email': 'Email',
|
||||
'admin.users.table_header_role': 'Role',
|
||||
'admin.users.table_header_actions': 'Actions',
|
||||
|
|
@ -241,7 +244,8 @@ export default {
|
|||
'admin.users.add_user_description': 'Create a new user account and assign a role.',
|
||||
'admin.users.edit_user_title': 'Edit User',
|
||||
'admin.users.edit_user_description': "Update the user's details and role.",
|
||||
'admin.users.form_name_label': 'Nickname',
|
||||
'admin.users.form_full_name_label': 'Full Name',
|
||||
'admin.users.form_nickname_label': 'Nickname (Optional)',
|
||||
'admin.users.form_email_label': 'Email Address',
|
||||
'admin.users.form_role_label': 'Role',
|
||||
'admin.users.form_role_user': 'User',
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ export default {
|
|||
'login.invalid_credentials_toast_user': '無效的電子郵件或密碼。(提示: user@example.com / password 或 admin@example.com / passwordadmin)',
|
||||
'register.create_account': '建立您的帳戶',
|
||||
'register.description': '加入 ToyShare,開始分享樂趣!',
|
||||
'register.name_label': '暱稱',
|
||||
'register.full_name_label': '全名',
|
||||
'register.nickname_label': '暱稱 (選填)',
|
||||
'register.confirm_password_label': '確認密碼',
|
||||
'register.submit_button': '建立帳戶',
|
||||
'register.loading_button': '註冊中...',
|
||||
|
|
@ -96,7 +97,8 @@ export default {
|
|||
'dashboard.profile.personal_info_title': '個人資訊',
|
||||
'dashboard.profile.personal_info_description': '更新您公開顯示的個人資料資訊。',
|
||||
'dashboard.profile.avatar_url_label': '頭像 URL',
|
||||
'dashboard.profile.full_name_label': '暱稱',
|
||||
'dashboard.profile.full_name_label': '全名',
|
||||
'dashboard.profile.nickname_label': '暱稱',
|
||||
'dashboard.profile.email_label': '電子郵件地址 (唯讀)',
|
||||
'dashboard.profile.bio_label': '簡介',
|
||||
'dashboard.profile.phone_label': '電話號碼',
|
||||
|
|
@ -230,7 +232,8 @@ export default {
|
|||
'admin.users.description': '查看和管理使用者帳戶及權限。',
|
||||
'admin.users.add_user_button': '新增使用者',
|
||||
'admin.users.back_to_users_button': '返回使用者列表',
|
||||
'admin.users.table_header_name': '暱稱',
|
||||
'admin.users.table_header_full_name': '全名',
|
||||
'admin.users.table_header_nickname': '暱稱',
|
||||
'admin.users.table_header_email': '電子郵件',
|
||||
'admin.users.table_header_role': '角色',
|
||||
'admin.users.table_header_actions': '操作',
|
||||
|
|
@ -241,7 +244,8 @@ export default {
|
|||
'admin.users.add_user_description': '建立一個新的使用者帳戶並分配角色。',
|
||||
'admin.users.edit_user_title': '編輯使用者',
|
||||
'admin.users.edit_user_description': '更新使用者的詳細資訊和角色。',
|
||||
'admin.users.form_name_label': '暱稱',
|
||||
'admin.users.form_full_name_label': '全名',
|
||||
'admin.users.form_nickname_label': '暱稱 (選填)',
|
||||
'admin.users.form_email_label': '電子郵件地址',
|
||||
'admin.users.form_role_label': '角色',
|
||||
'admin.users.form_role_user': '使用者',
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ export interface Toy {
|
|||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
name: string; // This is now Full Name
|
||||
nickname?: string;
|
||||
email: string;
|
||||
role?: 'Admin' | 'User';
|
||||
avatarUrl?: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue