const express = require('express'); const router = express.Router(); const { requireAuth } = require('../middlewares/authMiddleware'); const { createFormMock } = require('../utils/formHelper'); router.use(requireAuth); // Fallback data si la API estuviera inaccesible (con capacidad física real) const defaultBuildings = [ { id: 1, code: 'CENTRAL', name: 'Edificio Central', is_active: true, is_virtual: false, address: 'Tte. Gral. Juan Domingo Perón 802, CABA', description: 'Sede central institucional de UniCABA. Aulas de grado, auditorio y laboratorios.', floors: 4, classrooms_count: 29, physical_capacity: 1250, total_capacity: 1250, capacity_display: '1250' }, { id: 2, code: 'VIRTUAL', name: 'Campus Virtual', is_active: true, is_virtual: true, address: 'campus.unicaba.edu.ar / MS Teams & Moodle', description: 'Entorno de aprendizaje digital, aulas sincrónicas y videoconferencias.', floors: 0, classrooms_count: 2, physical_capacity: 0, total_capacity: 0, capacity_display: 'Ilimitada (Virtual)' } ]; // 1. List Buildings const handleListBuildings = async (req, res) => { try { const { search = '', status = '' } = req.query; let buildings = []; let stats = { total_buildings: 2, total_classrooms: 31, physical_classrooms_count: 29, total_physical_capacity: 1250, total_floors: 4 }; try { const apiRes = await req.apiClient.get('/buildings', { params: { search, status } }); if (apiRes.data && apiRes.data.buildings) { buildings = apiRes.data.buildings; if (apiRes.data.stats) { stats = apiRes.data.stats; } } } catch (apiErr) { console.warn('API /buildings notice, using fallback:', apiErr.message); buildings = [...defaultBuildings]; } // Si por alguna razón la lista vino vacía de la API y no había filtros de búsqueda, usar default if (buildings.length === 0 && !search && !status) { buildings = [...defaultBuildings]; } // Asegurar campos calculados consistentes para cada edificio buildings = buildings.map(b => { const is_virtual = Boolean(b.is_virtual || (b.code && b.code.toUpperCase() === 'VIRTUAL') || (b.name && b.name.toUpperCase().includes('VIRTUAL'))); return { ...b, is_virtual, capacity_display: is_virtual ? 'Ilimitada (Virtual)' : String(b.physical_capacity !== undefined ? b.physical_capacity : (b.total_capacity || 0)), total_capacity: is_virtual ? 0 : (b.physical_capacity !== undefined ? b.physical_capacity : (b.total_capacity || 0)), floors_display: is_virtual ? 'Digital' : String(b.floors ?? 1) }; }); // Capacidad física total: suma exclusiva de sedes presenciales (nunca suma 9999) const total_physical_capacity = stats.total_physical_capacity || buildings .filter(b => !b.is_virtual) .reduce((acc, b) => acc + (b.physical_capacity || b.total_capacity || 0), 0); res.render('buildings/list', { title: 'Gestión de Edificios - Edu-Space Admin', buildings, total_classrooms: stats.total_classrooms || buildings.reduce((a, b) => a + (b.classrooms_count || 0), 0), total_capacity: total_physical_capacity, total_physical_capacity, search, status_filter: status }); } catch (error) { console.error('Error rendering buildings list:', error.message); res.render('buildings/list', { title: 'Gestión de Edificios - Edu-Space Admin', buildings: defaultBuildings, total_classrooms: 31, total_capacity: 1250, total_physical_capacity: 1250, search: '', status_filter: '' }); } }; router.get(['/', '/list', '/list_buildings'], handleListBuildings); // 2. Add Building (GET & POST) router.get(['/add', '/add_building'], (req, res) => { const form = createFormMock({ name: '', code: '', address: '', floors: 1, description: '', is_active: true }); res.render('buildings/form', { title: 'Nuevo Edificio - Edu-Space Admin', building: null, form }); }); router.post(['/add', '/add_building'], async (req, res) => { try { const { name, code, address, floors, description, is_active } = req.body; const payload = { name: (name || '').trim(), code: (code || '').trim().toUpperCase() || null, address: (address || '').trim() || null, floors: parseInt(floors, 10) || 1, description: (description || '').trim() || null, is_active: is_active === 'true' || is_active === 'on' || is_active === true || is_active === '1' }; await req.apiClient.post('/buildings', payload); res.redirect('/buildings/list_buildings?created=1'); } catch (err) { console.warn('Error creating building:', err.response?.data || err.message); res.redirect('/buildings/list_buildings?error=create'); } }); // 3. View Building router.get(['/view/:id', '/view_building', '/:id'], async (req, res) => { const id = parseInt(req.params.id || req.query.id, 10) || 1; let building = null; let classrooms = []; try { const apiRes = await req.apiClient.get(`/buildings/${id}`); if (apiRes.data && apiRes.data.building) { building = apiRes.data.building; classrooms = apiRes.data.classrooms || []; } } catch (e) { building = defaultBuildings.find(b => b.id === id) || defaultBuildings[0]; } if (!building) { return res.redirect('/buildings/list_buildings'); } const is_virtual = Boolean(building.is_virtual || (building.code && building.code.toUpperCase() === 'VIRTUAL') || (building.name && building.name.toUpperCase().includes('VIRTUAL'))); building = { ...building, is_virtual, capacity_display: is_virtual ? 'Ilimitada (Virtual)' : String(building.physical_capacity || building.total_capacity || 0), floors_display: is_virtual ? 'Digital' : String(building.floors ?? 1) }; res.render('buildings/view', { title: `Edificio ${building.name} - Edu-Space Admin`, building, classrooms }); }); // 4. Edit Building (GET) const handleEditBuildingGet = async (req, res) => { const id = parseInt(req.params.id || req.query.id, 10) || 1; let building = null; try { const apiRes = await req.apiClient.get(`/buildings/${id}`); if (apiRes.data && apiRes.data.building) { building = apiRes.data.building; } } catch (e) { building = defaultBuildings.find(b => b.id === id) || defaultBuildings[0]; } if (!building) { return res.redirect('/buildings/list_buildings'); } const form = createFormMock({ name: building.name, code: building.code, address: building.address, floors: building.floors, description: building.description, is_active: building.is_active }); res.render('buildings/form', { title: `Editar Edificio - ${building.name}`, building, form }); }; router.get(['/edit/:id', '/:id/edit', '/edit_building'], handleEditBuildingGet); // 5. Edit Building (POST) const handleEditBuildingPost = async (req, res) => { const id = parseInt(req.params.id || req.query.id || req.body.id, 10) || 1; const { name, code, address, floors, description, is_active } = req.body; try { const payload = { name: (name || '').trim(), code: (code || '').trim().toUpperCase() || null, address: (address || '').trim() || null, floors: parseInt(floors, 10) || 0, description: (description || '').trim() || null, is_active: is_active === 'true' || is_active === 'on' || is_active === true || is_active === '1' }; await req.apiClient.put(`/buildings/${id}`, payload); res.redirect('/buildings/list_buildings?updated=1'); } catch (err) { console.warn('Error updating building:', err.response?.data || err.message); res.redirect('/buildings/list_buildings?error=update'); } }; router.post(['/edit/:id', '/:id/edit', '/edit_building'], handleEditBuildingPost); // 6. Toggle Building router.post(['/toggle/:id', '/:id/toggle', '/toggle_building'], async (req, res) => { const id = parseInt(req.params.id || req.query.id || req.body.id, 10) || 1; try { await req.apiClient.post(`/buildings/${id}/toggle`); } catch (e) { console.warn('Error toggling building:', e.message); } res.redirect('/buildings/list_buildings'); }); // 7. Delete Building router.post(['/delete/:id', '/:id/delete', '/delete_building'], async (req, res) => { const id = parseInt(req.params.id || req.query.id || req.body.id, 10); try { await req.apiClient.delete(`/buildings/${id}`); } catch (e) { console.warn('Error deleting building:', e.message); } res.redirect('/buildings/list_buildings'); }); module.exports = router;