deconstructing admin panel :)
This commit is contained in:
parent
ab17c2bb92
commit
275a7873d2
@ -7,6 +7,7 @@ import {
|
|||||||
resetUserPassword,
|
resetUserPassword,
|
||||||
} from "../../services/api";
|
} from "../../services/api";
|
||||||
import DocumentUpload from "../documentUpload/DocumentUpload";
|
import DocumentUpload from "../documentUpload/DocumentUpload";
|
||||||
|
import Documents from "../documentUpload/Documents";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
@ -241,228 +242,157 @@ function AdminPanel() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="grid gap-6">
|
{/* <div className="grid gap-6"> */}
|
||||||
|
<>
|
||||||
{activeTab === "documents" && (
|
{activeTab === "documents" && (
|
||||||
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl overflow-hidden shadow-xl">
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 shadow-xl">
|
||||||
<motion.div
|
<Documents />
|
||||||
initial={{ opacity: 0, y: 20 }}
|
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{ duration: 0.5 }}
|
|
||||||
>
|
|
||||||
<div className="overflow-x-auto">
|
|
||||||
<table className="w-full">
|
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-primary-700">
|
|
||||||
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
|
||||||
Име
|
|
||||||
</th>
|
|
||||||
{/* <th className="px-6 py-4 text-left text-md text-neutral-400">
|
|
||||||
Статус
|
|
||||||
</th> */}
|
|
||||||
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
|
||||||
Прикачено од
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
|
||||||
Споделено со
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
|
||||||
Креирано на
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{documents.map((doc) => (
|
|
||||||
<tr
|
|
||||||
key={doc.id}
|
|
||||||
className="border-b border-primary-700/50 hover:bg-primary-700/30"
|
|
||||||
>
|
|
||||||
<td className="px-6 py-4 text-white">{doc.title}</td>
|
|
||||||
{/* <td className="px-6 py-4">
|
|
||||||
<span
|
|
||||||
className={`px-3 py-1 rounded-full text-xs font-medium ${
|
|
||||||
doc.status === "completed"
|
|
||||||
? "bg-green-500/20 text-green-300"
|
|
||||||
: doc.status === "pending"
|
|
||||||
? "bg-yellow-500/20 text-yellow-300"
|
|
||||||
: doc.status === "uploading"
|
|
||||||
? "bg-primary-500/20 text-primary-300"
|
|
||||||
: "bg-neutral-500/20 text-neutral-300"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{doc.status}
|
|
||||||
</span>
|
|
||||||
</td> */}
|
|
||||||
<td className="px-6 py-4 text-neutral-300">
|
|
||||||
{doc.uploadedBy?.name} ({doc.uploadedBy?.email})
|
|
||||||
</td>
|
|
||||||
<td className="px-6 py-4 text-neutral-300">
|
|
||||||
{doc.sharedWith && doc.sharedWith.length > 0
|
|
||||||
? doc.sharedWith.map((user) => (
|
|
||||||
<div
|
|
||||||
key={user.id}
|
|
||||||
className="whitespace-nowrap"
|
|
||||||
>
|
|
||||||
{user.name} ({user.email})
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
: "None"}
|
|
||||||
</td>
|
|
||||||
<td className="px-6 py-4 text-neutral-300">
|
|
||||||
{new Date(doc.createdAt).toLocaleString()}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</motion.div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</>
|
||||||
{activeTab === "users" && (
|
{activeTab === "users" && (
|
||||||
<>
|
<>
|
||||||
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 mb-6 shadow-xl">
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 mb-6 shadow-xl">
|
||||||
<h2 className="text-xl font-bold text-white mb-4">
|
<h2 className="text-xl font-bold text-white mb-4">
|
||||||
Креирај корисник
|
Креирај корисник
|
||||||
</h2>
|
</h2>
|
||||||
<form
|
<form
|
||||||
ref={createUserFormRef}
|
ref={createUserFormRef}
|
||||||
onSubmit={handleCreateUser}
|
onSubmit={handleCreateUser}
|
||||||
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Име"
|
placeholder="Име"
|
||||||
value={newUser.name}
|
value={newUser.name}
|
||||||
id="name"
|
id="name"
|
||||||
name="name"
|
name="name"
|
||||||
required
|
required
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewUser({ ...newUser, name: e.target.value })
|
setNewUser({ ...newUser, name: e.target.value })
|
||||||
}
|
}
|
||||||
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
||||||
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
||||||
focus:ring-1 focus:ring-primary-500"
|
focus:ring-1 focus:ring-primary-500"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
id="email"
|
id="email"
|
||||||
name="email"
|
name="email"
|
||||||
placeholder="Мејл"
|
placeholder="Мејл"
|
||||||
value={newUser.email}
|
value={newUser.email}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewUser({ ...newUser, email: e.target.value })
|
setNewUser({ ...newUser, email: e.target.value })
|
||||||
}
|
}
|
||||||
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
||||||
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
||||||
focus:ring-1 focus:ring-primary-500"
|
focus:ring-1 focus:ring-primary-500"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
// type="password"
|
// type="password"
|
||||||
id="password"
|
id="password"
|
||||||
name="password"
|
name="password"
|
||||||
placeholder="Лозинка"
|
placeholder="Лозинка"
|
||||||
value={newUser.password}
|
value={newUser.password}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewUser({ ...newUser, password: e.target.value })
|
setNewUser({ ...newUser, password: e.target.value })
|
||||||
}
|
}
|
||||||
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
||||||
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
||||||
focus:ring-1 focus:ring-primary-500"
|
focus:ring-1 focus:ring-primary-500"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="isAdmin"
|
id="isAdmin"
|
||||||
checked={newUser.isAdmin}
|
checked={newUser.isAdmin}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setNewUser({ ...newUser, isAdmin: e.target.checked })
|
setNewUser({ ...newUser, isAdmin: e.target.checked })
|
||||||
}
|
}
|
||||||
className="rounded border-primary-600 bg-primary-700/30 text-primary-500
|
className="rounded border-primary-600 bg-primary-700/30 text-primary-500
|
||||||
focus:ring-primary-500"
|
focus:ring-primary-500"
|
||||||
/>
|
/>
|
||||||
<label htmlFor="isAdmin" className="text-white">
|
<label htmlFor="isAdmin" className="text-white">
|
||||||
Дали е Администратор
|
Дали е Администратор
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="flex items-center justify-center space-x-2 px-4 py-2
|
className="flex items-center justify-center space-x-2 px-4 py-2
|
||||||
bg-primary-600 hover:bg-primary-700 text-white rounded-lg
|
bg-primary-600 hover:bg-primary-700 text-white rounded-lg
|
||||||
transition-colors shadow-lg"
|
transition-colors shadow-lg"
|
||||||
>
|
>
|
||||||
<FiUserPlus className="w-4 h-4" />
|
<FiUserPlus className="w-4 h-4" />
|
||||||
<span>Креирај корисник</span>
|
<span>Креирај корисник</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl overflow-hidden shadow-xl">
|
|
||||||
<table className="w-full">
|
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-primary-700">
|
|
||||||
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
|
||||||
Име
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
|
||||||
Мејл
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
|
||||||
Улога
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
|
||||||
Ресетирај
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{users.map((user) => (
|
|
||||||
<tr
|
|
||||||
key={user.id}
|
|
||||||
className="border-b border-primary-700/50 hover:bg-primary-700/30"
|
|
||||||
>
|
|
||||||
<td className="px-6 py-4 text-white">{user.name}</td>
|
|
||||||
<td className="px-6 py-4 text-white">{user.email}</td>
|
|
||||||
<td className="px-6 py-4">
|
|
||||||
<span
|
|
||||||
className={`px-3 py-1 rounded-full text-xs font-medium
|
|
||||||
${user.isAdmin ? "bg-primary-500/20 text-primary-300" : "bg-neutral-500/20 text-neutral-300"}`}
|
|
||||||
>
|
|
||||||
{user.isAdmin ? "Admin" : "User"}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td className="px-6 py-4">
|
|
||||||
<button
|
|
||||||
onClick={() =>
|
|
||||||
setResetPasswordModal({
|
|
||||||
isOpen: true,
|
|
||||||
userId: user.id,
|
|
||||||
userName: user.name,
|
|
||||||
newPassword: "",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
className="flex items-center space-x-1 text-neutral-400 hover:text-white transition-colors"
|
|
||||||
>
|
|
||||||
<FiKey className="w-4 h-4" />
|
|
||||||
<span>Ресетирај лозинка</span>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{activeTab === "upload" && (
|
|
||||||
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 shadow-xl">
|
|
||||||
<DocumentUpload />
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl overflow-hidden shadow-xl">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-primary-700">
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Име
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Мејл
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Улога
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Ресетирај
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{users.map((user) => (
|
||||||
|
<tr
|
||||||
|
key={user.id}
|
||||||
|
className="border-b border-primary-700/50 hover:bg-primary-700/30"
|
||||||
|
>
|
||||||
|
<td className="px-6 py-4 text-white">{user.name}</td>
|
||||||
|
<td className="px-6 py-4 text-white">{user.email}</td>
|
||||||
|
<td className="px-6 py-4">
|
||||||
|
<span
|
||||||
|
className={`px-3 py-1 rounded-full text-xs font-medium
|
||||||
|
${user.isAdmin ? "bg-primary-500/20 text-primary-300" : "bg-neutral-500/20 text-neutral-300"}`}
|
||||||
|
>
|
||||||
|
{user.isAdmin ? "Admin" : "User"}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setResetPasswordModal({
|
||||||
|
isOpen: true,
|
||||||
|
userId: user.id,
|
||||||
|
userName: user.name,
|
||||||
|
newPassword: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
className="flex items-center space-x-1 text-neutral-400 hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<FiKey className="w-4 h-4" />
|
||||||
|
<span>Ресетирај лозинка</span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{activeTab === "upload" && (
|
||||||
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 shadow-xl">
|
||||||
|
<DocumentUpload />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
135
frontend/src/components/documentUpload/Documents.jsx
Normal file
135
frontend/src/components/documentUpload/Documents.jsx
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import { getAllDocuments } from "../../services/api";
|
||||||
|
import { getAllUsers } from "../../services/api";
|
||||||
|
import {
|
||||||
|
FiUsers,
|
||||||
|
FiFile,
|
||||||
|
FiUpload,
|
||||||
|
FiKey,
|
||||||
|
FiLoader,
|
||||||
|
FiUserPlus,
|
||||||
|
} from "react-icons/fi";
|
||||||
|
|
||||||
|
function Documents() {
|
||||||
|
const [documents, setDocuments] = useState([]);
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const [documentsResponse, usersResponse] = await Promise.all([
|
||||||
|
getAllDocuments(),
|
||||||
|
getAllUsers(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Make sure we're getting the data property from the response
|
||||||
|
setDocuments(
|
||||||
|
Array.isArray(documentsResponse.data) ? documentsResponse.data : [],
|
||||||
|
);
|
||||||
|
setUsers(Array.isArray(usersResponse.data) ? usersResponse.data : []);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
setError("Failed to load data");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center justify-center p-8">
|
||||||
|
<FiLoader className="w-8 h-8 animate-spin text-primary-500" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<div className="p-4 bg-red-500/10 border border-red-500/20 rounded-lg text-red-200">
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl overflow-hidden shadow-xl">
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-primary-700">
|
||||||
|
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
||||||
|
Име
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
||||||
|
Прикачено од
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
||||||
|
Споделено со
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-md text-neutral-400">
|
||||||
|
Креирано на
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{documents.length > 0 ? (
|
||||||
|
documents.map((doc) => (
|
||||||
|
<tr
|
||||||
|
key={doc.id}
|
||||||
|
className="border-b border-primary-700/50 hover:bg-primary-700/30"
|
||||||
|
>
|
||||||
|
<td className="px-6 py-4 text-white">{doc.title || "N/A"}</td>
|
||||||
|
<td className="px-6 py-4 text-neutral-300">
|
||||||
|
{doc.uploadedBy ? (
|
||||||
|
<>
|
||||||
|
{doc.uploadedBy.name} ({doc.uploadedBy.email})
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"N/A"
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-neutral-300">
|
||||||
|
{doc.sharedWith && doc.sharedWith.length > 0 ? (
|
||||||
|
<div className="whitespace-nowrap">
|
||||||
|
{doc.sharedWith.map((user) => (
|
||||||
|
<div key={user.id}>
|
||||||
|
{user.name} ({user.email})
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
"None"
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-neutral-300">
|
||||||
|
{doc.createdAt
|
||||||
|
? new Date(doc.createdAt).toLocaleString()
|
||||||
|
: "N/A"}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan="4"
|
||||||
|
className="px-6 py-4 text-center text-neutral-400"
|
||||||
|
>
|
||||||
|
No documents available
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Documents;
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
function Users() {
|
||||||
|
const [newUser, setNewUser] = useState({});
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl p-6 mb-6 shadow-xl">
|
||||||
|
<h2 className="text-xl font-bold text-white mb-4">Креирај корисник</h2>
|
||||||
|
<form
|
||||||
|
ref={createUserFormRef}
|
||||||
|
onSubmit={handleCreateUser}
|
||||||
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Име"
|
||||||
|
value={newUser.name}
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
required
|
||||||
|
onChange={(e) => setNewUser({ ...newUser, name: e.target.value })}
|
||||||
|
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
||||||
|
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
||||||
|
focus:ring-1 focus:ring-primary-500"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="Мејл"
|
||||||
|
value={newUser.email}
|
||||||
|
onChange={(e) => setNewUser({ ...newUser, email: e.target.value })}
|
||||||
|
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
||||||
|
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
||||||
|
focus:ring-1 focus:ring-primary-500"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
// type="password"
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
placeholder="Лозинка"
|
||||||
|
value={newUser.password}
|
||||||
|
onChange={(e) =>
|
||||||
|
setNewUser({ ...newUser, password: e.target.value })
|
||||||
|
}
|
||||||
|
className="bg-primary-700/30 border border-primary-600 rounded-lg px-4 py-2
|
||||||
|
text-white placeholder-neutral-400 focus:outline-none focus:border-primary-500
|
||||||
|
focus:ring-1 focus:ring-primary-500"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="isAdmin"
|
||||||
|
checked={newUser.isAdmin}
|
||||||
|
onChange={(e) =>
|
||||||
|
setNewUser({ ...newUser, isAdmin: e.target.checked })
|
||||||
|
}
|
||||||
|
className="rounded border-primary-600 bg-primary-700/30 text-primary-500
|
||||||
|
focus:ring-primary-500"
|
||||||
|
/>
|
||||||
|
<label htmlFor="isAdmin" className="text-white">
|
||||||
|
Дали е Администратор
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="flex items-center justify-center space-x-2 px-4 py-2
|
||||||
|
bg-primary-600 hover:bg-primary-700 text-white rounded-lg
|
||||||
|
transition-colors shadow-lg"
|
||||||
|
>
|
||||||
|
<FiUserPlus className="w-4 h-4" />
|
||||||
|
<span>Креирај корисник</span>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-primary-800/50 backdrop-blur-lg rounded-xl overflow-hidden shadow-xl">
|
||||||
|
<table className="w-full">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-primary-700">
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Име
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Мејл
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Улога
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm text-neutral-400">
|
||||||
|
Ресетирај
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{users.map((user) => (
|
||||||
|
<tr
|
||||||
|
key={user.id}
|
||||||
|
className="border-b border-primary-700/50 hover:bg-primary-700/30"
|
||||||
|
>
|
||||||
|
<td className="px-6 py-4 text-white">{user.name}</td>
|
||||||
|
<td className="px-6 py-4 text-white">{user.email}</td>
|
||||||
|
<td className="px-6 py-4">
|
||||||
|
<span
|
||||||
|
className={`px-3 py-1 rounded-full text-xs font-medium
|
||||||
|
${user.isAdmin ? "bg-primary-500/20 text-primary-300" : "bg-neutral-500/20 text-neutral-300"}`}
|
||||||
|
>
|
||||||
|
{user.isAdmin ? "Admin" : "User"}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
setResetPasswordModal({
|
||||||
|
isOpen: true,
|
||||||
|
userId: user.id,
|
||||||
|
userName: user.name,
|
||||||
|
newPassword: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
className="flex items-center space-x-1 text-neutral-400 hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<FiKey className="w-4 h-4" />
|
||||||
|
<span>Ресетирај лозинка</span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user