File: /var/www/igsms.viitorcloud.co/igsmsportal/views/ProfileView.tsx
import React, { useState } from 'react';
import { User, UserRole, Grievance, GrievanceStatus } from '../types';
interface ProfileViewProps {
user: User;
grievances: Grievance[];
onUpdateUser: (updatedFields: Partial<User>) => void;
}
const ProfileView: React.FC<ProfileViewProps> = ({ user, grievances, onUpdateUser }) => {
const [isEditing, setIsEditing] = useState(false);
const [editData, setEditData] = useState({
name: user.name,
department: user.department || ''
});
const [isSaving, setIsSaving] = useState(false);
const getStats = () => {
const total = grievances.length;
const resolved = grievances.filter(g => g.status === GrievanceStatus.RESOLVED).length;
const inProgress = grievances.filter(g => g.status === GrievanceStatus.IN_PROGRESS).length;
if (user.role === UserRole.CITIZEN) {
return [
{ label: 'Applications Filed', value: total, icon: 'fa-file-signature', color: 'blue' },
{ label: 'Successfully Resolved', value: resolved, icon: 'fa-check-double', color: 'emerald' },
{ label: 'Pending Action', value: total - resolved, icon: 'fa-clock', color: 'amber' }
];
}
if (user.role === UserRole.OFFICER) {
return [
{ label: 'Cases Managed', value: total, icon: 'fa-briefcase', color: 'indigo' },
{ label: 'Redressal Rate', value: total > 0 ? `${Math.round((resolved / total) * 100)}%` : '0%', icon: 'fa-chart-pie', color: 'emerald' },
{ label: 'Current Load', value: inProgress, icon: 'fa-layer-group', color: 'orange' }
];
}
return [
{ label: 'State Oversight', value: 'Full', icon: 'fa-shield-halved', color: 'slate' },
{ label: 'System Uptime', value: '99.9%', icon: 'fa-microchip', color: 'blue' },
{ label: 'Dept Count', value: '12', icon: 'fa-building', color: 'indigo' }
];
};
const stats = getStats();
const handleSave = () => {
setIsSaving(true);
// Simulate API delay
setTimeout(() => {
onUpdateUser({
name: editData.name,
department: user.role === UserRole.OFFICER ? editData.department : user.department
});
setIsSaving(false);
setIsEditing(false);
}, 800);
};
return (
<div className="animate-fade-in space-y-8 py-4">
<header className="mb-10">
<h2 className="text-3xl font-black text-slate-900 tracking-tight">Profile Intelligence</h2>
<p className="text-slate-500 font-medium">Managing identity and performance across the IGSMS ecosystem.</p>
</header>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Profile Card */}
<div className="lg:col-span-1 space-y-8">
<div className="bg-white rounded-[2.5rem] border border-slate-200 overflow-hidden shadow-sm">
<div className="h-32 bg-slate-900 flex items-center justify-center">
<div className="w-24 h-24 rounded-[2rem] bg-white border-4 border-slate-900 translate-y-12 flex items-center justify-center text-3xl font-black text-blue-600 shadow-xl">
{user.name.charAt(0)}
</div>
</div>
<div className="pt-16 pb-10 px-8 text-center">
{!isEditing ? (
<>
<h3 className="text-xl font-black text-slate-900">{user.name}</h3>
<p className="text-[10px] font-black text-blue-600 uppercase tracking-[0.2em] mt-1">{user.role}</p>
<div className="mt-8 pt-8 border-t border-slate-50 space-y-4">
<div className="flex justify-between items-center px-4">
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Employee ID</span>
<span className="text-xs font-bold text-slate-700">GUJ-{user.id.padStart(4, '0')}</span>
</div>
{user.department && (
<div className="flex justify-between items-center px-4">
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Department</span>
<span className="text-xs font-bold text-slate-700">{user.department}</span>
</div>
)}
<div className="flex justify-between items-center px-4">
<span className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Account Status</span>
<span className="text-[10px] px-3 py-1 bg-emerald-50 text-emerald-600 rounded-full font-black uppercase tracking-wider">Verified</span>
</div>
</div>
<button
onClick={() => setIsEditing(true)}
className="w-full mt-10 py-4 bg-slate-900 text-white rounded-2xl font-black text-xs uppercase tracking-widest hover:bg-slate-800 transition-all shadow-lg shadow-slate-200"
>
Update Identity
</button>
</>
) : (
<div className="space-y-6 text-left">
<div className="space-y-2">
<label className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Full Name</label>
<input
type="text"
value={editData.name}
onChange={e => setEditData({...editData, name: e.target.value})}
className="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-sm font-bold focus:ring-2 focus:ring-blue-500 outline-none"
/>
</div>
{user.role === UserRole.OFFICER && (
<div className="space-y-2">
<label className="text-[10px] font-black text-slate-400 uppercase tracking-widest">Department</label>
<input
type="text"
value={editData.department}
onChange={e => setEditData({...editData, department: e.target.value})}
className="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-sm font-bold focus:ring-2 focus:ring-blue-500 outline-none"
/>
</div>
)}
<div className="flex gap-3 pt-4">
<button
onClick={handleSave}
disabled={isSaving}
className="flex-1 py-3 bg-blue-600 text-white rounded-xl font-black text-[10px] uppercase tracking-widest shadow-lg shadow-blue-500/20 hover:bg-blue-700 transition-all"
>
{isSaving ? <i className="fa-solid fa-spinner animate-spin"></i> : 'Save Changes'}
</button>
<button
onClick={() => { setIsEditing(false); setEditData({ name: user.name, department: user.department || '' }); }}
className="px-6 py-3 bg-slate-100 text-slate-600 rounded-xl font-black text-[10px] uppercase tracking-widest hover:bg-slate-200 transition-all"
>
Cancel
</button>
</div>
</div>
)}
</div>
</div>
<div className="bg-blue-50 p-8 rounded-[2rem] border border-blue-100">
<h4 className="text-xs font-black text-blue-800 uppercase tracking-widest mb-4">Security Notice</h4>
<p className="text-xs font-bold text-blue-900/70 leading-relaxed italic">
"This session is monitored for integrity. Please ensure your digital signature is updated every 90 days for uninterrupted access to IGSMS services."
</p>
</div>
</div>
{/* Stats and Activity */}
<div className="lg:col-span-2 space-y-8">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{stats.map((s, idx) => (
<div key={idx} className="bg-white p-8 rounded-[2rem] border border-slate-100 shadow-sm flex flex-col items-center text-center group hover:border-blue-200 transition-colors">
<div className={`w-12 h-12 rounded-2xl flex items-center justify-center mb-6 text-xl transition-all ${
s.color === 'emerald' ? 'bg-emerald-50 text-emerald-600' :
s.color === 'blue' ? 'bg-blue-50 text-blue-600' :
s.color === 'amber' ? 'bg-amber-50 text-amber-600' :
s.color === 'orange' ? 'bg-orange-50 text-orange-600' : 'bg-slate-50 text-slate-600'
}`}>
<i className={`fa-solid ${s.icon}`}></i>
</div>
<p className="text-3xl font-black text-slate-900">{s.value}</p>
<p className="text-[10px] font-black text-slate-400 uppercase tracking-widest mt-2">{s.label}</p>
</div>
))}
</div>
<div className="bg-white p-10 rounded-[2.5rem] border border-slate-100 shadow-sm">
<div className="flex items-center justify-between mb-8">
<h4 className="text-lg font-black text-slate-900">Recent System Engagement</h4>
<button className="text-[10px] font-black text-blue-600 uppercase tracking-widest hover:underline">Download Log</button>
</div>
<div className="space-y-6">
{grievances.slice(0, 4).map((g, idx) => (
<div key={idx} className="flex items-center justify-between p-5 bg-slate-50 rounded-2xl border border-slate-100 group hover:bg-white hover:shadow-md transition-all">
<div className="flex items-center gap-4">
<div className="w-10 h-10 bg-white rounded-xl border border-slate-200 flex items-center justify-center text-slate-400 group-hover:text-blue-600 group-hover:border-blue-200 transition-all">
<i className="fa-solid fa-clock-rotate-left text-xs"></i>
</div>
<div>
<p className="text-xs font-black text-slate-800">{g.title}</p>
<p className="text-[10px] font-bold text-slate-400 mt-1 uppercase tracking-tight">{g.ticketNumber} • {new Date(g.updatedAt).toLocaleDateString()}</p>
</div>
</div>
<div className="text-right">
<span className="text-[9px] font-black uppercase text-slate-400 tracking-widest">{g.status}</span>
</div>
</div>
))}
{grievances.length === 0 && (
<div className="py-20 text-center">
<i className="fa-solid fa-ghost text-4xl text-slate-100 mb-4"></i>
<p className="text-xs font-bold text-slate-400">No activity logged in the current cycle.</p>
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
};
export default ProfileView;