I see this error with the app, reported by NextJS, please fix it. The er

This commit is contained in:
Indigo Tang 2025-07-06 12:25:32 +00:00
parent 38fccc09b7
commit 861ec9280e
2 changed files with 43 additions and 17 deletions

View File

@ -1,14 +1,13 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { getAllUsers } from "@/data/operations";
import { useI18n, useCurrentLocale } from "@/locales/client"; import { useI18n, useCurrentLocale } from "@/locales/client";
import { UserCog, Trash2, PlusCircle } from "lucide-react"; import { UserCog, Trash2, PlusCircle, Loader2 } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { import {
AlertDialog, AlertDialog,
@ -23,24 +22,44 @@ import {
} from "@/components/ui/alert-dialog"; } from "@/components/ui/alert-dialog";
import type { User } from '@/types'; import type { User } from '@/types';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
import { deleteUser } from '@/app/actions/user'; import { deleteUser, getUsers } from '@/app/actions/user';
export default function AdminUserManagementPage({ users }: { users: User[] }) { export default function AdminUserManagementPage() {
const t = useI18n(); const t = useI18n();
const locale = useCurrentLocale(); const locale = useCurrentLocale();
const router = useRouter(); const router = useRouter();
const { toast } = useToast(); const { toast } = useToast();
const [users, setUsers] = useState<User[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isDeleting, setIsDeleting] = useState(false); const [isDeleting, setIsDeleting] = useState(false);
// We receive users as a prop after fetching them in a wrapper component. useEffect(() => {
const allUsers = users.sort((a, b) => a.name.localeCompare(b.name)); const fetchUsers = async () => {
try {
const fetchedUsers = await getUsers();
setUsers(fetchedUsers.sort((a, b) => a.name.localeCompare(b.name)));
} catch (error) {
toast({
title: t('admin.users.toast_error_title'),
description: "Failed to load user data.",
variant: "destructive",
});
} finally {
setIsLoading(false);
}
};
fetchUsers();
}, [t, toast]);
const handleDeleteUser = async (userId: string) => { const handleDeleteUser = async (userId: string) => {
setIsDeleting(true); setIsDeleting(true);
const result = await deleteUser(userId); const result = await deleteUser(userId);
if (result.success) { if (result.success) {
toast({ title: t('admin.users.user_deleted_toast') }); toast({ title: t('admin.users.user_deleted_toast') });
// The page will re-render due to revalidation, no need for router.refresh() const updatedUsers = await getUsers();
setUsers(updatedUsers.sort((a, b) => a.name.localeCompare(b.name)));
} else { } else {
toast({ toast({
title: t('admin.users.toast_error_title'), title: t('admin.users.toast_error_title'),
@ -51,6 +70,14 @@ export default function AdminUserManagementPage({ users }: { users: User[] }) {
setIsDeleting(false); setIsDeleting(false);
}; };
if (isLoading) {
return (
<div className="flex justify-center items-center h-64">
<Loader2 className="h-12 w-12 animate-spin text-primary" />
</div>
);
}
return ( return (
<div className="space-y-8"> <div className="space-y-8">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -71,7 +98,7 @@ export default function AdminUserManagementPage({ users }: { users: User[] }) {
<CardTitle className="text-xl font-headline">{t('admin.users.title')}</CardTitle> <CardTitle className="text-xl font-headline">{t('admin.users.title')}</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
{allUsers.length > 0 ? ( {users.length > 0 ? (
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow> <TableRow>
@ -82,7 +109,7 @@ export default function AdminUserManagementPage({ users }: { users: User[] }) {
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{allUsers.map((user) => ( {users.map((user) => (
<TableRow key={user.id}> <TableRow key={user.id}>
<TableCell className="font-medium">{user.name}</TableCell> <TableCell className="font-medium">{user.name}</TableCell>
<TableCell>{user.email}</TableCell> <TableCell>{user.email}</TableCell>
@ -133,9 +160,3 @@ export default function AdminUserManagementPage({ users }: { users: User[] }) {
</div> </div>
); );
} }
// Wrapper component to fetch data on the server and pass to the client component
export default function AdminUserManagementPageWrapper() {
const users = getAllUsers();
return <AdminUserManagementPage users={users} />;
}

View File

@ -5,6 +5,7 @@ import db from '@/lib/db';
import type { User } from '@/types'; import type { User } from '@/types';
import { randomUUID } from 'crypto'; import { randomUUID } from 'crypto';
import { revalidatePath } from 'next/cache'; import { revalidatePath } from 'next/cache';
import { getAllUsers as dbGetAllUsers, getUserById } from '@/data/operations';
interface RegisterUserResult { interface RegisterUserResult {
success: boolean; success: boolean;
@ -114,9 +115,13 @@ export async function deleteUser(id: string): Promise<DeleteUserResult> {
return { success: true, message: 'User deleted successfully.' }; return { success: true, message: 'User deleted successfully.' };
} catch (error) { } catch (error) {
console.error('Delete user error:', error); console.error('Delete user error:', error);
if (error.code === 'SQLITE_CONSTRAINT_FOREIGNKEY') { if ((error as any).code === 'SQLITE_CONSTRAINT_FOREIGNKEY') {
return { success: false, message: 'Cannot delete user. They still have toys listed in the system.' }; return { success: false, message: 'Cannot delete user. They still have toys listed in the system.' };
} }
return { success: false, message: 'An unexpected error occurred during deletion.' }; return { success: false, message: 'An unexpected error occurred during deletion.' };
} }
} }
export async function getUsers(): Promise<User[]> {
return dbGetAllUsers();
}