← back to Mauricio-Alvarez-T__Boveda-LOLS

Function bodies 67 total

All specs Real LLM only Function bodies
useAttendanceActions function · typescript · L16-L116 (101 LOC)
frontend/src/hooks/attendance/useAttendanceActions.ts
export function useAttendanceActions({
    date,
    workers,
    attendance,
    feriadoActual,
    fetchAttendanceInfo
}: UseAttendanceActionsProps) {
    const { selectedObra } = useObra();
    const { hasPermission } = useAuth();
    const [saving, setSaving] = useState(false);

    // Track the latest data for action callbacks via ref to avoid dependency cycles
    const latestData = useRef({ selectedObra, date, workers, attendance, feriadoActual });
    useEffect(() => {
        latestData.current = { selectedObra, date, workers, attendance, feriadoActual };
    }, [selectedObra, date, workers, attendance, feriadoActual]);

    const handleSave = useCallback(async () => {
        const { selectedObra: currentObra, date: currentDate, workers: currentWorkers, attendance: currentAttendance } = latestData.current;
        const isGlobal = !currentObra;
        if (isGlobal && !hasPermission('asistencia.tomar.global')) return;

        setSaving(true);
        try {
            const 
useAttendanceData function · typescript · L11-L274 (264 LOC)
frontend/src/hooks/attendance/useAttendanceData.ts
export function useAttendanceData() {
    const { selectedObra } = useObra();
    const { hasPermission } = useAuth();

    const [date, setDate] = useState(new Date().toISOString().split('T')[0]);
    const [loading, setLoading] = useState(false);
    const [workers, setWorkers] = useState<Trabajador[]>([]);
    const [attendance, setAttendance] = useState<Record<number, Partial<Asistencia>>>({});
    const [horariosObra, setHorariosObra] = useState<ConfiguracionHorario[]>([]);
    const [estados, setEstados] = useState<EstadoAsistencia[]>([]);
    const [feriadoActual, setFeriadoActual] = useState<Feriado | null>(null);
    const [searchQuery, setSearchQuery] = useState('');
    const [selectedEmpresaId, setSelectedEmpresaId] = useState<number | null>(null);
    const [statusFilter, setStatusFilter] = useState<number | null>(null);
    const [alertasFaltas, setAlertasFaltas] = useState<AlertaFalta[]>([]);
    const [reportMonth, setReportMonth] = useState((new Date().getMonth() + 1).
useAttendanceExport function · typescript · L17-L281 (265 LOC)
frontend/src/hooks/attendance/useAttendanceExport.ts
export function useAttendanceExport({
    date,
    workers,
    attendance,
    estados,
    reportMonth,
    reportYear
}: UseAttendanceExportProps) {
    const { selectedObra } = useObra();
    const { hasPermission } = useAuth();
    
    const latestData = useRef({ selectedObra, date, workers, attendance, estados, reportMonth, reportYear });
    useEffect(() => {
        latestData.current = { selectedObra, date, workers, attendance, estados, reportMonth, reportYear };
    }, [selectedObra, date, workers, attendance, estados, reportMonth, reportYear]);

    const handleExportExcel = useCallback(async (returnFile = false) => {
        if (!hasPermission('asistencia.exportar_excel')) {
            toast.error('No tienes permiso para exportar a Excel');
            return null;
        }
        
        const {
            selectedObra: currentObra,
            date: currentDate,
            reportMonth: currentMonth,
            reportYear: currentYear
        } = latestData.curren
useInlineEdit function · typescript · L9-L45 (37 LOC)
frontend/src/hooks/inventario/useInlineEdit.ts
export function useInlineEdit({ canEdit, onUpdateStock, onRefresh }: InlineEditOptions) {
    const [editingCell, setEditingCell] = useState<string | null>(null);
    const [editValue, setEditValue] = useState('');

    const startEdit = useCallback((key: string, currentValue: number) => {
        if (!canEdit) return;
        setEditingCell(key);
        setEditValue(String(currentValue || ''));
    }, [canEdit]);

    const cancelEdit = useCallback(() => {
        setEditingCell(null);
        setEditValue('');
    }, []);

    const saveEdit = useCallback(async (itemId: number, obraId: number | null, bodegaId: number | null) => {
        const num = parseInt(editValue, 10);
        if (isNaN(num) || num < 0) {
            cancelEdit();
            return;
        }
        
        const ok = await onUpdateStock(itemId, obraId, bodegaId, { cantidad: num });
        if (ok) onRefresh();
        
        cancelEdit();
    }, [editValue, onUpdateStock, onRefresh, cancelEdit]);

    ret
useInventarioActions function · typescript · L5-L39 (35 LOC)
frontend/src/hooks/inventario/useInventarioActions.ts
export function useInventarioActions() {
    const updateStock = useCallback(async (
        itemId: number,
        obraId: number | null,
        bodegaId: number | null,
        data: { cantidad?: number; valor_arriendo_override?: number | null }
    ) => {
        try {
            await api.put('/inventario/stock', {
                item_id: itemId,
                obra_id: obraId,
                bodega_id: bodegaId,
                ...data
            });
            toast.success('Stock actualizado');
            return true;
        } catch (err: any) {
            toast.error(err.response?.data?.error || 'Error al actualizar stock');
            return false;
        }
    }, []);

    const updateDescuento = useCallback(async (obraId: number, porcentaje: number) => {
        try {
            await api.put(`/inventario/descuento/obra/${obraId}`, { porcentaje });
            toast.success('Descuento actualizado');
            return true;
        } catch (err: any) {
        
useInventarioData function · typescript · L78-L124 (47 LOC)
frontend/src/hooks/inventario/useInventarioData.ts
export function useInventarioData() {
    const [resumen, setResumen] = useState<ResumenData | null>(null);
    const [stockObra, setStockObra] = useState<StockObraData | null>(null);
    const [stockBodega, setStockBodega] = useState<StockBodegaData | null>(null);
    const [loading, setLoading] = useState(false);

    const fetchResumen = useCallback(async () => {
        setLoading(true);
        try {
            const res = await api.get<ApiResponse<ResumenData>>('/inventario/resumen');
            setResumen(res.data.data);
        } catch {
            setResumen(null);
        } finally {
            setLoading(false);
        }
    }, []);

    const fetchStockObra = useCallback(async (obraId: number) => {
        setLoading(true);
        try {
            const res = await api.get<ApiResponse<StockObraData>>(`/inventario/stock/obra/${obraId}`);
            setStockObra(res.data.data);
        } catch {
            setStockObra(null);
        } finally {
            setLoadin
useItemDetail function · typescript · L29-L128 (100 LOC)
frontend/src/hooks/inventario/useItemDetail.ts
export function useItemDetail(): UseItemDetailReturn {
    const [selectedItemId, setSelectedItemId] = useState<number | null>(null);
    const [itemData, setItemData] = useState<ItemInventario | null>(null);
    const [stockLocations, setStockLocations] = useState<StockLocation[]>([]);
    const [loading, setLoading] = useState(false);
    const [stockLoading, setStockLoading] = useState(false);

    // Cache de items ya vistos (no de stock)
    const cache = useRef<Map<number, ItemInventario>>(new Map());

    const fetchStock = useCallback(async (itemId: number) => {
        try {
            const res = await api.post<{ data: Record<number, StockLocation[]> }>(
                '/inventario/stock-por-items',
                { item_ids: [itemId] }
            );
            return res.data.data[itemId] || [];
        } catch {
            return [];
        }
    }, []);

    const fetchItem = useCallback(async (itemId: number): Promise<ItemInventario | null> => {
        // Cache hi
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
loadHiddenCols function · typescript · L6-L11 (6 LOC)
frontend/src/hooks/inventario/useResumenMensualFilters.ts
function loadHiddenCols(): Set<string> {
    try {
        const raw = localStorage.getItem(STORAGE_KEY);
        return raw ? new Set(JSON.parse(raw)) : new Set();
    } catch { return new Set(); }
}
saveHiddenCols function · typescript · L13-L15 (3 LOC)
frontend/src/hooks/inventario/useResumenMensualFilters.ts
function saveHiddenCols(set: Set<string>) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify([...set]));
}
useResumenMensualFilters function · typescript · L17-L114 (98 LOC)
frontend/src/hooks/inventario/useResumenMensualFilters.ts
export function useResumenMensualFilters(data: ResumenData) {
    const { obras, bodegas, categorias } = data;

    const [collapsedCats, setCollapsedCats] = useState<Set<number>>(new Set());
    const [hiddenCols, setHiddenCols] = useState<Set<string>>(loadHiddenCols);
    const [hideEmpty, setHideEmpty] = useState(false);
    const [search, setSearch] = useState('');
    const [selectedCategoryId, setSelectedCategoryId] = useState<number | null>(null);
    const [showImages, setShowImages] = useState(false);

    useEffect(() => { saveHiddenCols(hiddenCols); }, [hiddenCols]);

    const colsWithStock = useMemo(() => {
        const set = new Set<string>();
        for (const cat of categorias) {
            for (const item of cat.items) {
                for (const [key, ub] of Object.entries(item.ubicaciones)) {
                    if (ub && ub.cantidad > 0) set.add(key);
                }
            }
        }
        return set;
    }, [categorias]);

    const visibleObras = us
useTransferencias function · typescript · L29-L181 (153 LOC)
frontend/src/hooks/inventario/useTransferencias.ts
export function useTransferencias() {
    const [transferencias, setTransferencias] = useState<Transferencia[]>([]);
    const [selected, setSelected] = useState<Transferencia | null>(null);
    const [loading, setLoading] = useState(false);
    const [total, setTotal] = useState(0);
    const [discrepancias, setDiscrepancias] = useState<TransferenciaConDiscrepancias[]>([]);
    const [selectedDiscrepancia, setSelectedDiscrepancia] = useState<TransferenciaConDiscrepancias | null>(null);

    const fetchAll = useCallback(async (query: Record<string, any> = {}) => {
        setLoading(true);
        try {
            const params = new URLSearchParams();
            Object.entries(query).forEach(([k, v]) => { if (v != null) params.set(k, String(v)); });
            const res = await api.get<TransferenciaListResponse>(`/transferencias?${params}`);
            setTransferencias(res.data.data);
            setTotal(res.data.total);
        } catch {
            setTransferencias([]);
      
useDashboardLayout function · typescript · L11-L96 (86 LOC)
frontend/src/hooks/useDashboardLayout.ts
export function useDashboardLayout(userId: number, permisos: Permission[]) {
    // Filter widgets the user can see
    const allowedWidgets = useMemo(() => {
        return WIDGET_REGISTRY.filter(w => {
            if (!w.requiredPermission) return true;
            const { modulo, accion } = w.requiredPermission!;
            const accionMap: Record<string, string> = {
                puede_ver: 'ver',
                puede_crear: 'crear',
                puede_editar: 'editar',
                puede_eliminar: 'eliminar'
            };
            return permisos.includes(`${modulo}.${accionMap[accion] || accion}`);
        });
    }, [permisos]);

    // Load saved order from localStorage, or use default
    const getSavedOrder = useCallback((): string[] => {
        try {
            const saved = localStorage.getItem(`${STORAGE_KEY_PREFIX}${userId}`);
            if (saved) {
                const parsed: string[] = JSON.parse(saved);
                // Only keep IDs that are stil
useFormDirtyProtection function · typescript · L10-L34 (25 LOC)
frontend/src/hooks/useFormDirtyProtection.ts
export function useFormDirtyProtection(isDirty: boolean) {
    useEffect(() => {
        // Evitar que recargue la página o vaya atrás en el navegador
        const handleBeforeUnload = (e: BeforeUnloadEvent) => {
            if (isDirty) {
                e.preventDefault();
                e.returnValue = ''; // Requerido por Chrome
            }
        };

        if (isDirty) {
            window.addEventListener('beforeunload', handleBeforeUnload);
            // Avisar al ecosistema Modal que estamos sucios
            document.body.setAttribute('data-modal-dirty', 'true');
        } else {
            window.removeEventListener('beforeunload', handleBeforeUnload);
            document.body.removeAttribute('data-modal-dirty');
        }

        return () => {
            window.removeEventListener('beforeunload', handleBeforeUnload);
            document.body.removeAttribute('data-modal-dirty');
        };
    }, [isDirty]);
}
cn function · typescript · L7-L9 (3 LOC)
frontend/src/utils/cn.ts
export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs));
}
exportStockObra function · typescript · L48-L280 (233 LOC)
frontend/src/utils/exportExcel.ts
export async function exportStockObra(data: StockObraData) {
    const wb = new ExcelJS.Workbook();
    wb.creator = 'Bóveda LOLS';
    wb.created = new Date();

    const sheetName = data.obra.nombre.substring(0, 31);
    const ws = wb.addWorksheet(sheetName, {
        views: [{ showGridLines: false }],
    });

    // ── Anchos de columna ──
    ws.columns = [
        { key: 'nro',     width: 7 },
        { key: 'desc',    width: 45 },
        { key: 'm2',      width: 10 },
        { key: 'arriendo', width: 16 },
        { key: 'unidad',  width: 8 },
        { key: 'cantidad', width: 12 },
        { key: 'total',   width: 18 },
    ];

    let row: ExcelJS.Row;

    // ══════════════════════════════════════════════
    //  TÍTULO — branding header
    // ══════════════════════════════════════════════
    ws.mergeCells('A1:G1');
    row = ws.getRow(1);
    row.height = 36;
    row.getCell(1).value = `📦  INVENTARIO — ${data.obra.nombre.toUpperCase()}`;
    row.getCell(1).font = boldFon
Same scanner, your repo: https://repobility.com — Repobility
exportResumen function · typescript · L285-L523 (239 LOC)
frontend/src/utils/exportExcel.ts
export async function exportResumen(data: import('../hooks/inventario/useInventarioData').ResumenData) {
    const wb = new ExcelJS.Workbook();
    wb.creator = 'Bóveda LOLS';
    wb.created = new Date();

    const ws = wb.addWorksheet('Resumen General', {
        views: [{ showGridLines: false }],
    });

    // Construir columnas base
    const cols: Partial<ExcelJS.Column>[] = [
        { key: 'nro',     width: 7 },
        { key: 'desc',    width: 45 },
        { key: 'm2',      width: 10 },
        { key: 'arriendo', width: 14 },
        { key: 'unidad',  width: 8 },
        { key: 'total_qty', width: 12 },
    ];

    // Columnas por obra y bodega
    data.obras.forEach(o => cols.push({ key: `obra_${o.id}`, width: 10 }));
    data.bodegas.forEach(b => cols.push({ key: `bodega_${b.id}`, width: 10 }));

    ws.columns = cols;

    let row: ExcelJS.Row;

    // ══════════════════════════════════════════════
    //  TÍTULO
    // ══════════════════════════════════════════════
    c
run function · javascript · L18-L42 (25 LOC)
tmp/update_db_states.js
async function run() {
    try {
        console.log('--- Current States ---');
        const [states] = await db.query('SELECT * FROM estados_asistencia');
        console.log(JSON.stringify(states, null, 2));

        console.log('\n--- Updating 1/2 to JI ---');
        const [updateJI] = await db.query("UPDATE estados_asistencia SET nombre = 'Jornada Incompleta (JI)', codigo = 'JI' WHERE codigo = '1/2'");
        console.log('Update JI:', updateJI.affectedRows, 'rows');

        console.log('\n--- Refining Absence States ---');
        // Rename 'Falta' to 'Falta Injustificada' if it exists or consolidate
        // We want only 'Falta Justificada' and 'Falta Injustificada'
        // Let's see what we have first.
        
        const [updatedStates] = await db.query('SELECT * FROM estados_asistencia');
        console.log('\n--- Updated States ---');
        console.log(JSON.stringify(updatedStates, null, 2));

        process.exit(0);
    } catch (e) {
        console.error(e);
‹ prevpage 2 / 2