geocrop-platform./apps/web/src/Admin.tsx

124 lines
4.7 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import axios from 'axios';
const API_ENDPOINT = 'https://api.portfolio.techarvest.co.zw';
interface User {
email: string;
is_active: boolean;
is_admin: boolean;
login_count: number;
login_limit: number;
}
const Admin: React.FC = () => {
const [users, setUsers] = useState<User[]>([]);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [limit, setLimit] = useState(3);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const fetchUsers = async () => {
try {
const response = await axios.get(`${API_ENDPOINT}/admin/users`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});
setUsers(response.data);
} catch (err) {
console.error('Failed to fetch users:', err);
}
};
useEffect(() => {
fetchUsers();
}, []);
const handleCreateUser = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError('');
try {
await axios.post(`${API_ENDPOINT}/admin/users`, {
email,
password,
login_limit: limit
}, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});
setEmail('');
setPassword('');
fetchUsers();
alert('User created successfully');
} catch (err: any) {
setError(err.response?.data?.detail || 'Failed to create user');
} finally {
setLoading(false);
}
};
return (
<div style={{ maxWidth: '900px', margin: '40px auto', padding: '20px', fontFamily: 'system-ui, sans-serif' }}>
<h1 style={{ color: '#333' }}>Admin Dashboard - User Management</h1>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: '30px' }}>
{/* Create User Form */}
<section style={{ background: 'white', padding: '20px', borderRadius: '8px', boxShadow: '0 2px 10px rgba(0,0,0,0.1)' }}>
<h2 style={{ fontSize: '18px', marginBottom: '15px' }}>Create New Access</h2>
<form onSubmit={handleCreateUser} style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
{error && <div style={{ color: 'red', fontSize: '12px' }}>{error}</div>}
<input
type="email" placeholder="Email" value={email} onChange={e => setEmail(e.target.value)} required
style={{ padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }}
/>
<input
type="password" placeholder="Password" value={password} onChange={e => setPassword(e.target.value)} required
style={{ padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }}
/>
<div>
<label style={{ fontSize: '12px', display: 'block', marginBottom: '4px' }}>Login Limit</label>
<input
type="number" value={limit} onChange={e => setLimit(parseInt(e.target.value))}
style={{ padding: '8px', border: '1px solid #ddd', borderRadius: '4px', width: '100%' }}
/>
</div>
<button
type="submit" disabled={loading}
style={{ padding: '10px', background: '#1a73e8', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer', fontWeight: 'bold' }}
>
{loading ? 'Creating...' : 'Create Account'}
</button>
</form>
</section>
{/* User List */}
<section style={{ background: 'white', padding: '20px', borderRadius: '8px', boxShadow: '0 2px 10px rgba(0,0,0,0.1)' }}>
<h2 style={{ fontSize: '18px', marginBottom: '15px' }}>Active Access Keys</h2>
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '14px' }}>
<thead>
<tr style={{ borderBottom: '2px solid #eee', textAlign: 'left' }}>
<th style={{ padding: '10px' }}>Email</th>
<th style={{ padding: '10px' }}>Logins</th>
<th style={{ padding: '10px' }}>Limit</th>
<th style={{ padding: '10px' }}>Role</th>
</tr>
</thead>
<tbody>
{users.map(u => (
<tr key={u.email} style={{ borderBottom: '1px solid #f0f0f0' }}>
<td style={{ padding: '10px' }}>{u.email}</td>
<td style={{ padding: '10px' }}>{u.login_count}</td>
<td style={{ padding: '10px' }}>{u.login_limit}</td>
<td style={{ padding: '10px' }}>{u.is_admin ? 'Admin' : 'Guest'}</td>
</tr>
))}
</tbody>
</table>
</section>
</div>
</div>
);
};
export default Admin;