I see this error with the app, reported by NextJS, please fix it. The er
This commit is contained in:
parent
38fccc09b7
commit
861ec9280e
|
|
@ -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'),
|
||||||
|
|
@ -50,6 +69,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">
|
||||||
|
|
@ -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} />;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue