adding base project

This commit is contained in:
Azmat-7860
2026-10-07 09:07:57 +05:30
commit dc69f693f0
43 changed files with 5193 additions and 0 deletions
+330
View File
@@ -0,0 +1,330 @@
import React, { useState } from 'react';
import {
ShieldCheck,
Lock,
LayoutGrid,
Activity,
Key,
ShieldAlert,
CheckCircle,
MailCheck,
User,
Sliders,
FileText,
Copy,
ExternalLink,
Info,
} from 'lucide-react';
import { useAuth } from '../context/AuthContext';
import { DashboardLayout } from '../components/layout/DashboardLayout';
import { Badge } from '../components/common/Badge';
import { Button } from '../components/common/Button';
import { Card } from '../components/common/Card';
import { MOCK_STATS, MOCK_ACTIVITIES } from '../services/mockData';
import '../styles/dashboard.css';
export function Dashboard() {
const { user, token, isDemoMode, logout } = useAuth();
const [activeTab, setActiveTab] = useState('dashboard');
const [showTokenModal, setShowTokenModal] = useState(false);
const [copied, setCopied] = useState(false);
// Icon mapping for stats
const statIcons = {
ShieldCheck,
Lock,
LayoutGrid,
Activity,
};
// Icon mapping for activities
const activityIcons = {
Key,
ShieldAlert,
CheckCircle,
MailCheck,
};
const handleCopyToken = () => {
if (token) {
navigator.clipboard.writeText(token);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
return (
<DashboardLayout activeTab={activeTab} setActiveTab={setActiveTab}>
{/* Hero Welcome Banner */}
<section className="dashboard-hero animate-fade-in">
<div className="hero-left">
<div className="hero-tag">
<ShieldCheck size={16} />
<span>Identity & Access Controller</span>
</div>
<h1 className="hero-title">
Welcome back, <span className="gradient-text">{user?.firstName || 'Alex'}</span>
</h1>
<p className="hero-description">
AuthSec base project is operational. Your session is protected with Spring Boot JWT
authentication and granular role-based security boundaries.
</p>
</div>
<div className="hero-right">
<div className="hero-token-pill">
<Key size={14} />
<span>JWT: {token ? `${token.slice(0, 14)}...` : 'demo-token'}</span>
</div>
<div style={{ display: 'flex', gap: '8px' }}>
<Button
variant="secondary"
size="sm"
icon={Key}
onClick={() => setShowTokenModal(true)}
>
Inspect Token
</Button>
<Button
variant="outline"
size="sm"
onClick={logout}
>
Sign Out
</Button>
</div>
</div>
</section>
{/* Metric Stats Cards */}
<section className="stats-grid">
{MOCK_STATS.map((stat) => {
const Icon = statIcons[stat.icon] || Activity;
return (
<div key={stat.id} className="stat-card">
<div className="stat-card-header">
<span className="stat-card-title">{stat.title}</span>
<div className="stat-card-icon-box">
<Icon size={20} />
</div>
</div>
<div className="stat-card-value">{stat.value}</div>
<div className="stat-card-footer">
<span>{stat.subtitle}</span>
<span className={`stat-trend ${stat.status}`}>{stat.trend}</span>
</div>
</div>
);
})}
</section>
{/* Quick Action Buttons */}
<section>
<div className="section-header">
<h2 className="section-title">Quick Actions</h2>
</div>
<div className="quick-actions-grid">
<div className="quick-action-card" onClick={() => setShowTokenModal(true)}>
<div className="action-icon-circle">
<Key size={20} />
</div>
<div className="action-details">
<span className="action-name">Security Token</span>
<span className="action-desc">View JWT payload & auth headers</span>
</div>
</div>
<div
className="quick-action-card"
onClick={() => alert(`User Profile:\nName: ${user?.fullname || user?.firstName}\nEmail: ${user?.email}\nRoles: ${user?.roles?.join(', ')}`)}
>
<div className="action-icon-circle" style={{ background: 'linear-gradient(135deg, #06b6d4, #3b82f6)' }}>
<User size={20} />
</div>
<div className="action-details">
<span className="action-name">User Profile</span>
<span className="action-desc">Account ID #{user?.userId || '101'}</span>
</div>
</div>
<div
className="quick-action-card"
onClick={() => alert('System Parameters: Spring Boot Service Port 9292\nCORS: Enabled\nToken Lifetime: 24h')}
>
<div className="action-icon-circle" style={{ background: 'linear-gradient(135deg, #8b5cf6, #ec4899)' }}>
<Sliders size={20} />
</div>
<div className="action-details">
<span className="action-name">System Parameters</span>
<span className="action-desc">Endpoints & security policies</span>
</div>
</div>
<div
className="quick-action-card"
onClick={() => setActiveTab('security')}
>
<div className="action-icon-circle" style={{ background: 'linear-gradient(135deg, #10b981, #06b6d4)' }}>
<FileText size={20} />
</div>
<div className="action-details">
<span className="action-name">Audit Reports</span>
<span className="action-desc">Inspect security logs</span>
</div>
</div>
</div>
</section>
{/* Live Security Activity Stream */}
<section className="activity-card">
<div className="section-header">
<div>
<h2 className="section-title">Recent Security Events</h2>
<p style={{ fontSize: '0.85rem', color: 'var(--text-muted)' }}>
Audited session entries recorded for this workspace
</p>
</div>
<Badge variant="primary" size="md">
Live Stream
</Badge>
</div>
<div className="activity-list">
{MOCK_ACTIVITIES.map((act) => {
const Icon = activityIcons[act.icon] || Key;
return (
<div key={act.id} className="activity-item">
<div className="activity-left">
<div className="activity-icon">
<Icon size={18} />
</div>
<div className="activity-info">
<span className="activity-title">{act.title}</span>
<span className="activity-desc">
{act.description} &bull; <strong style={{ color: 'var(--text-secondary)' }}>IP: {act.ip}</strong>
</span>
</div>
</div>
<div className="activity-right">
<Badge
variant={
act.badge === 'SUCCESS' ? 'success' : act.badge === 'SECURITY' ? 'warning' : 'info'
}
>
{act.badge}
</Badge>
<span className="activity-time">{act.timestamp}</span>
</div>
</div>
);
})}
</div>
</section>
{/* Token Inspector Modal */}
{showTokenModal && (
<div
style={{
position: 'fixed',
inset: 0,
background: 'rgba(0, 0, 0, 0.7)',
backdropFilter: 'blur(6px)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 1000,
padding: '20px',
}}
onClick={() => setShowTokenModal(false)}
>
<div
className="custom-card animate-fade-in"
style={{ maxWidth: '580px', width: '100%', maxHeight: '90vh', overflowY: 'auto' }}
onClick={(e) => e.stopPropagation()}
>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<Key size={20} color="var(--color-primary-light)" />
<h3 style={{ fontSize: '1.25rem' }}>Session Token Inspector</h3>
</div>
<button
className="btn btn-ghost btn-sm"
onClick={() => setShowTokenModal(false)}
>
✕
</button>
</div>
<p style={{ fontSize: '0.85rem', color: 'var(--text-secondary)', marginBottom: '16px' }}>
This Bearer token is automatically attached to API requests in the <code>Authorization</code> header.
</p>
<div className="session-info-card">
<div className="session-info-row">
<span>Account Email:</span>
<strong>{user?.email || 'N/A'}</strong>
</div>
<div className="session-info-row">
<span>User ID:</span>
<strong>{user?.userId || '101'}</strong>
</div>
<div className="session-info-row">
<span>Assigned Roles:</span>
<strong>{Array.isArray(user?.roles) ? user.roles.join(', ') : 'ROLE_ADMIN'}</strong>
</div>
<div className="session-info-row">
<span>Mode:</span>
<strong>{isDemoMode ? 'Sandbox Demo Mode' : 'Live Spring Boot'}</strong>
</div>
</div>
<div style={{ marginTop: '16px' }}>
<label style={{ fontSize: '0.8rem', fontWeight: 600, color: 'var(--text-secondary)' }}>
Raw JWT Token:
</label>
<textarea
readOnly
value={token || ''}
style={{
width: '100%',
height: '80px',
background: 'var(--bg-input)',
color: 'var(--text-main)',
border: '1px solid var(--border-subtle)',
borderRadius: 'var(--radius-sm)',
padding: '10px',
fontSize: '0.75rem',
fontFamily: 'monospace',
resize: 'none',
marginTop: '6px',
}}
/>
</div>
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '10px', marginTop: '20px' }}>
<Button
variant="secondary"
size="sm"
icon={Copy}
onClick={handleCopyToken}
>
{copied ? 'Copied to Clipboard!' : 'Copy Token'}
</Button>
<Button
variant="primary"
size="sm"
onClick={() => setShowTokenModal(false)}
>
Done
</Button>
</div>
</div>
</div>
)}
</DashboardLayout>
);
}