Zuma32

Admin portal

Aug 7th, 2025
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 13.51 KB | Source Code | 0 0
  1. import React, { useEffect, useState } from "react";
  2. import { useAuth } from "./authContext"
  3. import axios from "axios";
  4. import { Plus, Edit, Trash2, Users, Ambulance } from "lucide-react";
  5. import WebSocketDemo from "./websocket";
  6.  
  7. function AdminPortal() {
  8.     const { role } = useAuth();
  9.     const [users, setUsers] = useState([]);
  10.     const [loading, setLoading] = useState(false);
  11.     const [showAddForm, setShowAddForm] = useState(false);
  12.     const [firstName, setFirstName] = useState("");
  13.     const [lastName, setLastName] = useState("");
  14.     const [age, setAge] = useState("");
  15.     const [password, setPassword] = useState("");
  16.     const [phone, setPhone] = useState("");
  17.     const [email, setEmail] = useState("");
  18.     const [usePhone, setUsePhone] = useState(true);
  19.  
  20.     const [user, setUser] = useState("");
  21.    
  22.  
  23.     const getMembers = async () => {
  24.         const token = localStorage.getItem("token");
  25.         setLoading(true);
  26.        
  27.         try {
  28.             const response = await axios.get(
  29.                 "http://127.0.0.1:8000/users/organization/",
  30.                 {
  31.                     headers: {
  32.                         'Authorization': `Bearer ${token}`,
  33.                         'Content-Type': 'application/json'
  34.                     }
  35.                 }
  36.             );
  37.             setUsers(response.data);
  38.         } catch (error) {
  39.             console.error("Error fetching users:", error);
  40.         } finally {
  41.             setLoading(false);
  42.         }
  43.     };
  44.  
  45.     const addUser = async (e) => {
  46.         e.preventDefault();
  47.         const token = localStorage.getItem("token");
  48.  
  49.         const payload = {
  50.             first_name: firstName,
  51.             last_name: lastName,
  52.             age: Number(age),
  53.             role : (role == "HealthAdmin" ? "Doctor": "Driver"),
  54.             password,
  55.             ...(usePhone ? { phone_number: phone.replace(/^0/, "+233") } : { email }),
  56.         };
  57.  
  58.         console.log(payload)
  59.                
  60.         try {
  61.             const response = await axios.post(
  62.                 "http://127.0.0.1:8000/users/organization/",
  63.                 payload,
  64.                 {
  65.                     headers: {
  66.                         'Authorization': `Bearer ${token}`,
  67.                         'Content-Type': 'application/json'
  68.                     }
  69.                 }
  70.             );
  71.  
  72.             getMembers();
  73.             setShowAddForm(false);
  74.         } catch (error) {
  75.             console.error("Error adding user:", error);
  76.         }
  77.     };
  78.  
  79.     const deleteUser = async (username) => {
  80.         const token = localStorage.getItem("token");
  81.         console.log(users);
  82.         try {
  83.             await axios.delete(
  84.                 `http://127.0.0.1:8000/users/organization/${username}/`,
  85.                 {
  86.                     headers: {
  87.                         'Authorization': `Bearer ${token}`,
  88.                         'Content-Type': 'application/json'
  89.                     }
  90.                 }
  91.             );
  92.            
  93.             setUsers(users.filter(user => user.email !== username || user.phone_number !== username));
  94.  
  95.             getMembers();
  96.         } catch (error) {
  97.             console.error("Error deleting user:", error);
  98.         }
  99.     };
  100.  
  101.     useEffect(() => {
  102.         getMembers();
  103.         if(localStorage.getItem('user')) {
  104.             const u = JSON.parse(localStorage.getItem('user'));
  105.             setUser(u);
  106.             console.log(u.email);
  107.         }
  108.     }, []);
  109.  
  110.     return (
  111.         <div className="min-h-screen bg-gradient-to-br from-gray-900 via-gray-800 to-gray-700 p-6">
  112.             <WebSocketDemo/>
  113.             <div className="max-w-6xl mx-auto">
  114.                 {/* Header */}
  115.                 <div className="bg-gray-900 rounded-lg shadow-lg p-6 mb-6 border-b-4 border-red-500 flex items-center justify-between">
  116.                     <div className="flex items-center gap-3">
  117.                         <Ambulance className="w-8 h-8 text-red-500" />
  118.                         <div>
  119.                             <h1 className="text-2xl font-bold text-white">{(user) ? user.first_name + " " + user.last_name:""} </h1>
  120.                             <p className="text-gray-400">{role}</p>
  121.                         </div>
  122.                     </div>
  123.                     <button
  124.                         onClick={() => setShowAddForm(!showAddForm)}
  125.                         className="flex items-center gap-2 bg-red-500 text-white px-4 py-2 rounded-lg hover:bg-red-600 transition-colors shadow-md font-semibold"
  126.                     >
  127.                         <Plus className="w-4 h-4" />
  128.                         Add User
  129.                     </button>
  130.                 </div>
  131.                 {/* Add User Form */}
  132.                 {showAddForm && (
  133.                     <div className="bg-gray-800 rounded-lg shadow-lg p-6 mb-6 border border-gray-700">
  134.                         <h2 className="text-lg font-semibold mb-4 text-white">Add New User</h2>
  135.                         <button onClick={() => setUsePhone(!usePhone)} className="text-blue-400 mb-2">
  136.                             Create user {usePhone ? "using email":"using phone"}
  137.                         </button>
  138.                         <form onSubmit={addUser} className="grid grid-cols-1 md:grid-cols-2 gap-4">
  139.                            {usePhone ?
  140.                             <input
  141.                                 type="phone"
  142.                                 placeholder="phone"
  143.                                 value={phone}
  144.                                 onChange={(e) => setPhone(e.target.value)}
  145.                                 className="px-3 py-2 bg-gray-700 text-white border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
  146.                                 required
  147.                             /> :
  148.                             <input
  149.                                 type="email"
  150.                                 placeholder="Email"
  151.                                 value={email}
  152.                                 onChange={(e) => setEmail(e.target.value)}
  153.                                 className="px-3 py-2 bg-gray-700 text-white border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
  154.                                 required
  155.                             />  
  156.                         }
  157.                             <input
  158.                                 type="password"
  159.                                 placeholder="Password"
  160.                                 value={password}
  161.                                 onChange={(e) => setPassword(e.target.value)}
  162.                                 className="px-3 py-2 bg-gray-700 text-white border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-400"
  163.                                 required
  164.                             />
  165.                             <input
  166.                                 type="text"
  167.                                 placeholder="First Name"
  168.                                 value={firstName}
  169.                                 onChange={ (e) => setFirstName(e.target.value)}
  170.                                 className="px-3 py-2 bg-gray-700 text-white border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
  171.                             />
  172.                             <input
  173.                                 type="text"
  174.                                 placeholder="Last Name"
  175.                                 value={lastName}
  176.                                 onChange={(e) => setLastName(e.target.value)}
  177.                                 className="px-3 py-2 bg-gray-700 text-white border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
  178.                             />
  179.                              <input
  180.                                 type="number"
  181.                                 placeholder="Age"
  182.                                 value={age}
  183.                                 onChange={(e) => setAge(e.target.value)}
  184.                                 className="px-3 py-2 bg-gray-700 text-white border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
  185.                             />
  186.                             <div className="md:col-span-2 flex gap-2">
  187.                                 <button
  188.                                     type="submit"
  189.                                     className="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition-colors font-semibold shadow-md"
  190.                                 >
  191.                                     Add User
  192.                                 </button>
  193.                                 <button
  194.                                     type="button"
  195.                                     onClick={() => setShowAddForm(false)}
  196.                                     className="bg-gray-500 text-white px-4 py-2 rounded-lg hover:bg-gray-600 transition-colors font-semibold shadow-md"
  197.                                 >
  198.                                     Cancel
  199.                                 </button>
  200.                             </div>
  201.                         </form>
  202.                     </div>
  203.                 )}
  204.                 {/* Users Table */}
  205.                 <div className="bg-gray-800 rounded-lg shadow-lg overflow-hidden border border-gray-700">
  206.                     <div className="px-6 py-4 border-b border-gray-700">
  207.                         <h2 className="text-lg font-semibold text-white">Organization Users ({users.length})</h2>
  208.                     </div>
  209.                     {loading ? (
  210.                         <div className="p-6 text-center">
  211.                             <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-red-500 mx-auto"></div>
  212.                             <p className="mt-2 text-gray-400">Loading users...</p>
  213.                         </div>
  214.                     ) : (
  215.                         <div className="overflow-x-auto">
  216.                             <table className="w-full">
  217.                                 <thead className="bg-gray-900">
  218.                                     <tr>
  219.                                         <th className="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">User</th>
  220.                                         <th className="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Email/Number</th>
  221.                                         <th className="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Role</th>
  222.                                         <th className="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Actions</th>
  223.                                     </tr>
  224.                                 </thead>
  225.                                 <tbody className="bg-gray-800 divide-y divide-gray-700">
  226.                                     {users.map((user) => (
  227.                                         <tr key={user.id} className="hover:bg-gray-700">
  228.                                             <td className="px-6 py-4 whitespace-nowrap">
  229.                                                 <div>
  230.                                                     <div className="text-sm font-medium text-white">
  231.                                                         {user.first_name} {user.last_name}
  232.                                                     </div>
  233.                                                     <div className="text-sm text-gray-400">@{user.username}</div>
  234.                                                 </div>
  235.                                             </td>
  236.                                             <td className="px-6 py-4 whitespace-nowrap text-sm text-white">
  237.                                                 {(user.email) ? user.email : user.phone_number}
  238.                                             </td>
  239.                                             <td className="px-6 py-4 whitespace-nowrap">
  240.                                                 <span className="px-2 py-1 text-xs rounded-full bg-blue-900 text-blue-300">
  241.                                                     {user.role || 'User'}
  242.                                                 </span>
  243.                                             </td>
  244.                                             <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
  245.                                                 <div className="flex gap-2">
  246.                                                     <button className="text-blue-400 hover:text-blue-200 p-1">
  247.                                                         <Edit className="w-4 h-4" />
  248.                                                     </button>
  249.                                                     <button
  250.                                                         onClick={() => deleteUser(user.email ? user.email : user.phone_number)}
  251.                                                         className="text-red-400 hover:text-red-200 p-1"
  252.                                                     >
  253.                                                         <Trash2 className="w-4 h-4" />
  254.                                                     </button>
  255.                                                 </div>
  256.                                             </td>
  257.                                         </tr>
  258.                                     ))}
  259.                                 </tbody>
  260.                             </table>
  261.                         </div>
  262.                     )}
  263.                 </div>
  264.             </div>
  265.         </div>
  266.     );
  267. }
  268.  
  269. export default AdminPortal;
Advertisement
Add Comment
Please, Sign In to add comment