Add admin role with user management (create/delete users)
First registered user becomes admin automatically. Admins see a "Manage Users" button in the dashboard header that opens a new /admin page for listing, creating, and deleting users. Backend enforces admin-only access on /admin/* routes. Startup migration adds the is_admin column to existing SQLite databases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useNavigate, Link } from 'react-router-dom';
|
||||
import AddPurchase from '../components/AddPurchase';
|
||||
import PurchaseList from '../components/PurchaseList';
|
||||
import PortfolioChart from '../components/PortfolioChart';
|
||||
@@ -12,6 +12,8 @@ const styles = {
|
||||
header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1.5rem' },
|
||||
logo: { fontSize: '1.4rem', fontWeight: 700, color: '#f7931a' },
|
||||
logoutBtn: { background: 'none', border: '1px solid #555', color: '#aaa', borderRadius: '8px', padding: '0.4rem 1rem', cursor: 'pointer' },
|
||||
adminBtn: { background: 'none', border: '1px solid #f7931a', color: '#f7931a', borderRadius: '8px', padding: '0.4rem 1rem', cursor: 'pointer', textDecoration: 'none', fontSize: '1rem' },
|
||||
headerBtns: { display: 'flex', gap: '0.5rem', alignItems: 'center' },
|
||||
statsGrid: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '1rem', marginBottom: '1.5rem' },
|
||||
statCard: { background: '#1a1a1a', padding: '1rem', borderRadius: '12px', border: '1px solid #333' },
|
||||
statLabel: { color: '#888', fontSize: '0.8rem', marginBottom: '0.3rem' },
|
||||
@@ -68,8 +70,11 @@ export default function Dashboard() {
|
||||
fetchData();
|
||||
}, [fetchData]);
|
||||
|
||||
const isAdmin = localStorage.getItem('is_admin') === 'true';
|
||||
|
||||
const handleLogout = () => {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('is_admin');
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
@@ -81,7 +86,10 @@ export default function Dashboard() {
|
||||
<div style={styles.app}>
|
||||
<div style={styles.header}>
|
||||
<div style={styles.logo}>₿ BTC Portfolio</div>
|
||||
<button style={styles.logoutBtn} onClick={handleLogout}>Logout</button>
|
||||
<div style={styles.headerBtns}>
|
||||
{isAdmin && <Link to="/admin" style={styles.adminBtn}>Manage Users</Link>}
|
||||
<button style={styles.logoutBtn} onClick={handleLogout}>Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{stats && (
|
||||
|
||||
Reference in New Issue
Block a user