fmatituy/selectospromanager
0
1from nicegui import ui2from services.auth import require_auth, get_current_user3from modules.layout import SelectosLayout4from datetime import datetime5 6@ui.page('/personal/solicitud-permiso')7@require_auth8def solicitud_permiso_asistente_page():9 user = get_current_user()10 11 TIPO_PERMISOS = [12 "Permiso por Cita Médica",13 "Calamidad Doméstica",14 "Trámite Administrativo",15 "Licencia por Luto",16 "Licencia de Paternidad/Maternidad",17 "Vacaciones",18 "Otro"19 ]20 21 with SelectosLayout('Solicitud de Permisos'):22 # CONTENEDOR PRINCIPAL MOBILE-FIRST (Estilo Formulario de Avances)23 with ui.column().classes('w-full max-w-xl mx-auto p-4 gap-6 pb-32'):24 25 # Cabecera de la Herramienta26 with ui.row().classes('w-full items-center gap-4 mb-4'):27 with ui.element('div').classes('w-12 h-12 bg-indigo-700 rounded-[1.5rem] flex items-center justify-center shadow-lg shadow-indigo-200'):28 ui.icon('assignment_ind', color='white', size='24px')29 with ui.column().classes('gap-0'):30 ui.label('Permisos y Citas').classes('text-2xl font-black text-slate-800 tracking-tight')31 ui.label('Gestiona tus ausencias y solicitudes legales.').classes('text-xs text-slate-400 font-bold')32 33 # --- FORMULARIO ---34 35 # 1. Motivo del Permiso36 with ui.column().classes('w-full gap-2'):37 ui.label('¿CUÁL ES EL MOTIVO DE TU AUSENCIA?').classes('text-[10px] font-black text-slate-400 tracking-[0.2em] ml-2')38 tipo = ui.select(TIPO_PERMISOS, label='Seleccionar Motivo *').props('outlined rounded-[2rem] h-14 behavior=menu').classes('w-full bg-white shadow-sm')39 40 # 2. Fechas41 with ui.column().classes('w-full bg-slate-50 p-6 rounded-[2.5rem] border border-slate-100 gap-4'):42 ui.label('FECHAS PROGRAMADAS').classes('text-[10px] font-black text-slate-500 tracking-[0.2em] ml-2')43 with ui.row().classes('w-full grid grid-cols-1 sm:grid-cols-2 gap-4'):44 f_ini = ui.input('Desde (Fecha)', value=datetime.now().strftime('%Y-%m-%d')).props('type=date outlined rounded-2xl bg-white').classes('w-full')45 f_fin = ui.input('Hasta (Fecha)', value=datetime.now().strftime('%Y-%m-%d')).props('type=date outlined rounded-2xl bg-white').classes('w-full')46 47 # 3. Justificación48 with ui.column().classes('w-full gap-2'):49 ui.label('DETALLES / JUSTIFICACIÓN').classes('text-[10px] font-black text-slate-400 tracking-[0.2em] ml-2')50 detalles = ui.textarea('Describe brevemente la razón de tu solicitud...').props('outlined rounded-[2rem]').classes('w-full bg-white h-32 shadow-sm')51 52 # 4. Soporte53 with ui.column().classes('w-full gap-2'):54 ui.label('SOPORTE O CERTIFICADO (OPCIONAL)').classes('text-[10px] font-black text-slate-400 tracking-[0.2em] ml-2')55 with ui.column().classes('w-full p-6 border-2 border-dashed border-slate-200 rounded-[2rem] items-center gap-2 bg-slate-50/50'):56 ui.icon('cloud_upload', color='slate-400', size='md')57 ui.label('Adjuntar archivo o foto del certificado').classes('text-[10px] font-bold text-slate-400 uppercase tracking-widest')58 ui.button('SUBIR SOPORTE', icon='attach_file').props('flat rounded-xl color=indigo-700').classes('font-black text-xs')59 60 # BOTÓN FIJO EN LA PARTE INFERIOR (Action Bar Mobile Style)61 with ui.row().classes('fixed bottom-0 left-0 right-0 p-6 bg-white/80 backdrop-blur-xl border-t border-slate-100 z-50'):62 def enviar_solicitud():63 if not tipo.value:64 return ui.notify('Seleccione el motivo del permiso', type='warning', icon='warning')65 66 try:67 from modules.sst.services_sst_ext import reportar_ausentismo68 data = {69 'trabajador_id': user.get('id'),70 'tipo_permiso': tipo.value,71 'fecha_inicio': f_ini.value,72 'fecha_fin': f_fin.value,73 'detalles': detalles.value,74 'soporte_path': None, # Por implementar subida real si se requiere75 'estado': 'Pendiente'76 }77 reportar_ausentismo(data)78 ui.notify('SOLICITUD RADICADA EXITOSAMENTE Y EVALUADA POR SST', type='positive', icon='check_circle')79 ui.timer(1.2, lambda: ui.navigate.to('/'), once=True)80 except Exception as e:81 print(f"Error reportando ausentismo: {e}")82 ui.notify('Error al radicar solicitud. Contacte a soporte.', type='negative')83 84 ui.button('CANCELAR', on_click=lambda: ui.navigate.to('/')).props('flat rounded-full color=slate-400').classes('flex-1 font-black text-xs h-14')85 ui.button('RADICAR SOLICITUD', icon='send', on_click=enviar_solicitud).props('unelevated color=indigo-900 rounded-[2rem]').classes('flex-[2] font-black h-14 shadow-2xl shadow-indigo-400/20')86 