169 lines
No EOL
5 KiB
TypeScript
169 lines
No EOL
5 KiB
TypeScript
/**
|
|
* This file is part of Sharenet.
|
|
*
|
|
* Sharenet is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
|
|
*
|
|
* You may obtain a copy of the license at:
|
|
* https://creativecommons.org/licenses/by-nc-sa/4.0/
|
|
*
|
|
* Copyright (c) 2024 Continuist <continuist02@gmail.com>
|
|
*/
|
|
|
|
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { userApi, User } from '@/lib/api';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@/components/ui/table';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from '@/components/ui/dialog';
|
|
import { Input } from '@/components/ui/input';
|
|
import { Label } from '@/components/ui/label';
|
|
|
|
export default function UsersPage() {
|
|
const [users, setUsers] = useState<User[]>([]);
|
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
const [editingUser, setEditingUser] = useState<User | null>(null);
|
|
const [formData, setFormData] = useState({
|
|
username: '',
|
|
email: '',
|
|
});
|
|
|
|
useEffect(() => {
|
|
loadUsers();
|
|
}, []);
|
|
|
|
const loadUsers = async () => {
|
|
try {
|
|
const response = await userApi.getAll();
|
|
setUsers(response.data);
|
|
} catch (error) {
|
|
console.error('Error loading users:', error);
|
|
}
|
|
};
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
try {
|
|
if (editingUser) {
|
|
await userApi.update(editingUser.id, formData);
|
|
} else {
|
|
await userApi.create(formData);
|
|
}
|
|
setIsDialogOpen(false);
|
|
setEditingUser(null);
|
|
setFormData({ username: '', email: '' });
|
|
loadUsers();
|
|
} catch (error) {
|
|
console.error('Error saving user:', error);
|
|
}
|
|
};
|
|
|
|
const handleEdit = (user: User) => {
|
|
setEditingUser(user);
|
|
setFormData({ username: user.username, email: user.email });
|
|
setIsDialogOpen(true);
|
|
};
|
|
|
|
const handleDelete = async (id: string) => {
|
|
if (confirm('Are you sure you want to delete this user?')) {
|
|
try {
|
|
await userApi.delete(id);
|
|
loadUsers();
|
|
} catch (error) {
|
|
console.error('Error deleting user:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex justify-between items-center">
|
|
<h1 className="text-2xl font-bold">Users</h1>
|
|
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
|
<DialogTrigger asChild>
|
|
<Button onClick={() => {
|
|
setEditingUser(null);
|
|
setFormData({ username: '', email: '' });
|
|
}}>
|
|
Add User
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>{editingUser ? 'Edit User' : 'Add User'}</DialogTitle>
|
|
</DialogHeader>
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="username">Username</Label>
|
|
<Input
|
|
id="username"
|
|
value={formData.username}
|
|
onChange={(e) => setFormData({ ...formData, username: e.target.value })}
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="email">Email</Label>
|
|
<Input
|
|
id="email"
|
|
type="email"
|
|
value={formData.email}
|
|
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
required
|
|
/>
|
|
</div>
|
|
<Button type="submit">{editingUser ? 'Update' : 'Create'}</Button>
|
|
</form>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>ID</TableHead>
|
|
<TableHead>Username</TableHead>
|
|
<TableHead>Email</TableHead>
|
|
<TableHead>Created At</TableHead>
|
|
<TableHead>Updated At</TableHead>
|
|
<TableHead>Actions</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{users.map((user) => (
|
|
<TableRow key={user.id}>
|
|
<TableCell>{user.id}</TableCell>
|
|
<TableCell>{user.username}</TableCell>
|
|
<TableCell>{user.email}</TableCell>
|
|
<TableCell>{new Date(user.created_at).toLocaleString()}</TableCell>
|
|
<TableCell>{new Date(user.updated_at).toLocaleString()}</TableCell>
|
|
<TableCell>
|
|
<div className="space-x-2">
|
|
<Button variant="outline" size="sm" onClick={() => handleEdit(user)}>
|
|
Edit
|
|
</Button>
|
|
<Button variant="destructive" size="sm" onClick={() => handleDelete(user.id)}>
|
|
Delete
|
|
</Button>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
);
|
|
}
|