CoolFace
Apppublic

fmatituy/selectospromanager

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
dashboard_personal.py75 linesDownload Raw Back to personal
1from nicegui import ui
2from modules.personal.services_personal import get_dashboard_stats, get_novedades_activas
3from services.auth import require_auth, get_current_user
4from modules.layout import SelectosLayout
5
6@ui.page('/personal/dashboard')
7@require_auth
8def dashboard_personal_page():
9    user = get_current_user()
10    if user.get('rol') not in ["Administrador", "Gerente", "Supervisor", "SST"]:
11        return ui.navigate.to('/')
12
13    stats = get_dashboard_stats()
14    novedades = get_novedades_activas()
15
16    with SelectosLayout('Dashboard de Personal'):
17        ui.label('Monitor de Talento Humano').classes('text-3xl font-black text-slate-800 mb-6')
18        
19        # Tarjetas KPI
20        with ui.row().classes('w-full gap-4 mb-8 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4'):
21            with ui.card().classes('p-6 bg-blue-50 border border-blue-100 rounded-3xl shadow-sm'):
22                with ui.row().classes('items-center gap-3'):
23                    ui.icon('groups', color='blue-600', size='md').classes('p-3 bg-white rounded-2xl')
24                    with ui.column().classes('gap-0'):
25                        ui.label('Activos').classes('text-xs font-bold text-blue-600 uppercase')
26                        ui.label(str(stats['total_empleados'])).classes('text-2xl font-black text-slate-800')
27
28            with ui.card().classes('p-6 bg-emerald-50 border border-emerald-100 rounded-3xl shadow-sm'):
29                with ui.row().classes('items-center gap-3'):
30                    ui.icon('check_circle', color='emerald-600', size='md').classes('p-3 bg-white rounded-2xl')
31                    with ui.column().classes('gap-0'):
32                        ui.label('Presentes Hoy').classes('text-xs font-bold text-emerald-600 uppercase')
33                        ui.label(str(stats['presentes_hoy'])).classes('text-2xl font-black text-slate-800')
34
35            with ui.card().classes('p-6 bg-rose-50 border border-rose-100 rounded-3xl shadow-sm'):
36                with ui.row().classes('items-center gap-3'):
37                    ui.icon('event_busy', color='rose-600', size='md').classes('p-3 bg-white rounded-2xl')
38                    with ui.column().classes('gap-0'):
39                        ui.label('Novedades').classes('text-xs font-bold text-rose-600 uppercase')
40                        ui.label(str(stats['novedades_hoy'])).classes('text-2xl font-black text-slate-800')
41
42            with ui.card().classes('p-6 bg-amber-50 border border-amber-100 rounded-3xl shadow-sm'):
43                with ui.row().classes('items-center gap-3'):
44                    ui.icon('timer', color='amber-600', size='md').classes('p-3 bg-white rounded-2xl')
45                    with ui.column().classes('gap-0'):
46                        ui.label('Horas Mes').classes('text-xs font-bold text-amber-600 uppercase')
47                        ui.label(f"{stats['horas_mes']:.0f}").classes('text-2xl font-black text-slate-800')
48
49        with ui.row().classes('w-full gap-8 items-start'):
50            # Gráfica de Asistencia Semanal (Mock/Simulada)
51            with ui.card().classes('flex-[2] p-8 rounded-3xl border border-slate-200 shadow-sm'):
52                ui.label('Tendencia de Asistencia').classes('text-lg font-black text-slate-800 mb-4')
53                ui.echart({
54                    'xAxis': {'type': 'category', 'data': ['Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab']},
55                    'yAxis': {'type': 'value'},
56                    'series': [
57                        {'data': [12, 15, 14, 18, 16, 10], 'type': 'line', 'smooth': True, 'color': '#1e40af'},
58                        {'data': [1, 0, 2, 1, 0, 1], 'type': 'bar', 'color': '#ef4444'}
59                    ]
60                }).classes('h-64')
61
62            # Listado de Novedades Activas
63            with ui.card().classes('flex-1 p-8 rounded-3xl border border-slate-200 shadow-sm'):
64                ui.label('Novedades Activas').classes('text-lg font-black text-slate-800 mb-4')
65                if not novedades:
66                    ui.label('No hay novedades para hoy.').classes('text-slate-400 italic')
67                else:
68                    with ui.column().classes('w-full gap-3'):
69                        for n in novedades:
70                            with ui.row().classes('w-full items-center p-3 bg-slate-50 rounded-xl border border-slate-100'):
71                                ui.icon('warning', color='rose-500', size='xs')
72                                with ui.column().classes('gap-0'):
73                                    ui.label(n['empleado_nombre']).classes('text-xs font-bold text-slate-800')
74                                    ui.label(n['tipo']).classes('text-[10px] text-slate-500 uppercase')
75