38956-vm/src/pages/AdminOverview.tsx
2026-03-03 20:42:48 +00:00

162 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import { useAuth } from '../context/AuthContext';
import { Store, LayoutDashboard, Calendar as CalendarIcon, Users, Clock, UserCircle } from 'lucide-react';
import Dashboard from './Dashboard';
import Calendar from './Calendar';
import PersonnelList from './PersonnelList';
import { startOfWeek, endOfWeek } from 'date-fns';
export default function AdminOverview() {
const { token } = useAuth();
const [branches, setBranches] = useState<any[]>([]);
const [selectedBranchId, setSelectedBranchId] = useState<number | null>(null);
const [activeTab, setActiveTab] = useState<'dashboard' | 'calendar' | 'personnel'>('dashboard');
const [summary, setSummary] = useState<{ totalBranches: number, totalActiveEmployees: number, totalPlannedShifts: number } | null>(null);
useEffect(() => {
const fetchBranches = async () => {
try {
const res = await fetch('/api/admin/branches', { headers: { Authorization: `Bearer ${token}` } });
if (res.ok) {
const data = await res.json();
setBranches(data);
if (data.length > 0) setSelectedBranchId(data[0].id);
}
} catch (err) {
console.error(err);
}
};
const fetchSummary = async () => {
try {
const currentWeekStart = startOfWeek(new Date(), { weekStartsOn: 1 }).getTime();
const currentWeekEnd = endOfWeek(new Date(), { weekStartsOn: 1 }).getTime();
const res = await fetch(`/api/admin/summary?start=${currentWeekStart}&end=${currentWeekEnd}`, { headers: { Authorization: `Bearer ${token}` } });
if (res.ok) {
const data = await res.json();
setSummary(data);
}
} catch (err) {
console.error(err);
}
};
if (token) {
fetchBranches();
fetchSummary();
}
}, [token]);
return (
<div className="space-y-6 pb-20 md:pb-6">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
<h1 className="text-2xl font-bold text-mua-text">Şube Raporları & Vardiyalar</h1>
{/* Branch Selector */}
<div className="flex items-center bg-mua-surface border border-mua-border rounded-xl px-3 py-2 shadow-sm">
<Store className="h-5 w-5 text-mua-text-muted mr-2" />
<select
value={selectedBranchId || ''}
onChange={(e) => setSelectedBranchId(Number(e.target.value))}
className="bg-transparent border-none focus:ring-0 text-sm font-medium text-mua-text w-full md:w-48 cursor-pointer outline-none"
>
{branches.map(b => (
<option key={b.id} value={b.id}>{b.name}</option>
))}
</select>
</div>
</div>
{selectedBranchId ? (
<div className="bg-mua-surface rounded-2xl shadow-sm border border-mua-border overflow-hidden">
<div className="flex border-b border-mua-border">
<button
onClick={() => setActiveTab('dashboard')}
className={`flex-1 py-4 text-sm font-medium flex items-center justify-center transition-colors ${
activeTab === 'dashboard'
? 'text-mua-primary border-b-2 border-mua-primary bg-mua-primary-light/50'
: 'text-mua-text-muted hover:text-mua-text hover:bg-mua-bg'
}`}
>
<LayoutDashboard className="h-4 w-4 mr-2" />
Özet Dashboard
</button>
<button
onClick={() => setActiveTab('calendar')}
className={`flex-1 py-4 text-sm font-medium flex items-center justify-center transition-colors ${
activeTab === 'calendar'
? 'text-mua-primary border-b-2 border-mua-primary bg-mua-primary-light/50'
: 'text-mua-text-muted hover:text-mua-text hover:bg-mua-bg'
}`}
>
<CalendarIcon className="h-4 w-4 mr-2" />
Vardiya Takvimi
</button>
<button
onClick={() => setActiveTab('personnel')}
className={`flex-1 py-4 text-sm font-medium flex items-center justify-center transition-colors ${
activeTab === 'personnel'
? 'text-mua-primary border-b-2 border-mua-primary bg-mua-primary-light/50'
: 'text-mua-text-muted hover:text-mua-text hover:bg-mua-bg'
}`}
>
<UserCircle className="h-4 w-4 mr-2" />
Personel & Yöneticiler
</button>
</div>
{/* Global Summary Section (Below Tabs) */}
{summary && (
<div className="bg-mua-bg border-b border-mua-border p-4 md:px-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="bg-mua-surface rounded-xl shadow-sm border border-mua-border p-4 flex items-center">
<div className="bg-mua-primary-light p-3 rounded-xl mr-4">
<Store className="h-5 w-5 text-mua-primary" />
</div>
<div>
<p className="text-xs font-medium text-mua-text-muted mb-1">Toplam Şube</p>
<p className="text-xl font-bold text-mua-text">{summary.totalBranches}</p>
</div>
</div>
<div className="bg-mua-surface rounded-xl shadow-sm border border-mua-border p-4 flex items-center">
<div className="bg-blue-50 p-3 rounded-xl mr-4">
<Users className="h-5 w-5 text-blue-500" />
</div>
<div>
<p className="text-xs font-medium text-mua-text-muted mb-1">Tüm Şubeler - Aktif Personel</p>
<p className="text-xl font-bold text-mua-text">{summary.totalActiveEmployees}</p>
</div>
</div>
<div className="bg-mua-surface rounded-xl shadow-sm border border-mua-border p-4 flex items-center">
<div className="bg-mua-pistachio-light p-3 rounded-xl mr-4">
<Clock className="h-5 w-5 text-mua-pistachio" />
</div>
<div>
<p className="text-xs font-medium text-mua-text-muted mb-1">Tüm Şubeler - Haftalık Vardiya</p>
<p className="text-xl font-bold text-mua-text">{summary.totalPlannedShifts}</p>
</div>
</div>
</div>
</div>
)}
<div className="p-4 md:p-6 bg-mua-bg">
{activeTab === 'dashboard' ? (
<Dashboard branchId={selectedBranchId} />
) : activeTab === 'calendar' ? (
<Calendar branchId={selectedBranchId} />
) : (
<PersonnelList />
)}
</div>
</div>
) : (
<div className="bg-mua-surface rounded-2xl shadow-sm border border-mua-border p-12 flex flex-col items-center justify-center text-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-mua-primary mb-4"></div>
<p className="text-mua-text-muted">Şubeler yükleniyor...</p>
</div>
)}
</div>
);
}