diff --git a/app/Http/Controllers/Dashboard/AtencionController.php b/app/Http/Controllers/Dashboard/AtencionController.php
index 090b263..2274323 100644
--- a/app/Http/Controllers/Dashboard/AtencionController.php
+++ b/app/Http/Controllers/Dashboard/AtencionController.php
@@ -1,4 +1,6 @@
-only(['start', 'end', 'type', 'action']);
- $input = array_merge(['action' => 'index', 'type' => 'api'], $query);
+ public function Atencion(Request $request)
+ {
+ $query = $request->only(['start', 'end', 'type', 'action']);
+ $input = array_merge(['action' => 'index', 'type' => 'api'], $query);
- $startDate = $input['start'] ?? date('Y-01-01');
- $endDate = $input['end'] ?? date('Y-12-31');
+ $startDate = $input['start'] ?? date('Y-01-01');
+ $endDate = $input['end'] ?? date('Y-12-31');
- $baseParams = [
- 'start_date' => $startDate,
- 'end_date' => $endDate,
- 'type' => $input['type'] ?? 'api',
- 'action' => $input['action'] ?? 'index',
- ];
+ $baseParams = [
+ 'start_date' => $startDate,
+ 'end_date' => $endDate,
+ 'type' => $input['type'] ?? 'api',
+ 'action' => $input['action'] ?? 'index',
+ ];
- $baseUrl = 'https://apoyos.comalcalco.gob.mx/beneficiaries/stats-by-date-range';
- $countsUrl = 'https://apoyos.comalcalco.gob.mx/beneficiaries/counts-by-date';
+ $baseUrl = 'https://apoyos.comalcalco.gob.mx/beneficiaries/stats-by-date-range';
+ $countsUrl = 'https://apoyos.comalcalco.gob.mx/beneficiaries/counts-by-date';
+ $dashboardUrl = 'https://apoyos.comalcalco.gob.mx/beneficiaries/dashboard/api';
+ $dashboardUrl2 = 'https://apoyos.comalcalco.gob.mx/beneficiaries/dashboard/api?type=servicio';
- try{
- $response = Http::get($baseUrl, $baseParams);
+ try {
+ $response = Http::get($baseUrl, $baseParams);
- if(!$response->successful()){
- return response()->json(['error' => 'Error del servicio'], $response->status());
- }
+ if (!$response->successful()) {
+ return response()->json(['error' => 'Error del servicio'], $response->status());
+ }
- $mainData = $response->json();
- $countsAc = [];
- try{
- $countsResp = Http::get($countsUrl, [
- 'start_date' => $startDate,
- 'end_date' => $endDate,
- ]);
+ $mainData = $response->json();
+ $countsAc = [];
+ try {
+ $countsResp = Http::get($countsUrl, [
+ 'start_date' => $startDate,
+ 'end_date' => $endDate,
+ ]);
- if($countsResp->successful()){
- $countsAc = $countsResp->json();
- } else {
- Log::error('Error al obtener los conteos de atención', ['status' => $countsResp->status()]);
- }
- }catch (\Exception $e) {
- Log::error('Error al obtener los conteos de atención', ['exception' => $e->getMessage()]);
- }
-
- $combinedData = array_merge(
- is_array($mainData) ? $mainData : [],
- [
- 'counts' => $countsAc,
- ]
- );
- return response()->json($combinedData, 200)
- ->header('Content-Type', 'application/json');
- }catch (\Exception $e) {
- Log::error('Error en la consulta de atención', ['exception' => $e->getMessage()]);
- return response()->json(['error' => 'Error en la consulta de atención'], 500);
+ if ($countsResp->successful()) {
+ $countsAc = $countsResp->json();
+ } else {
+ Log::error('Error al obtener los conteos de atención', ['status' => $countsResp->status()]);
}
+ } catch (\Exception $e) {
+ Log::error('Error al obtener los conteos de atención', ['exception' => $e->getMessage()]);
+ }
+
+ $dashboardData = [];
+ try {
+ $dashboardResp = Http::get($dashboardUrl);
+
+ if ($dashboardResp->successful()) {
+ $dashboardData = $dashboardResp->json();
+ } else {
+ Log::error('Error al obtener datos del dashboard', ['status' => $dashboardResp->status()]);
+ }
+ } catch (\Exception $e) {
+ Log::error('Error al obtener datos del dashboard', ['exception' => $e->getMessage()]);
+ }
+
+ $dashboardServicioData = [];
+ try {
+ $dashboardResp2 = Http::get($dashboardUrl2);
+
+ if ($dashboardResp2->successful()) {
+ $dashboardServicioData = $dashboardResp2->json();
+ } else {
+ Log::error('Error al obtener datos del dashboard servicio', ['status' => $dashboardResp2->status()]);
+ }
+ } catch (\Exception $e) {
+ Log::error('Error al obtener datos del dashboard servicio', ['exception' => $e->getMessage()]);
+ }
+
+ // Combina todos los resultados
+ $combinedData = array_merge(
+ is_array($mainData) ? $mainData : [],
+ [
+ 'counts' => $countsAc,
+ 'dashboard' => $dashboardData,
+ 'dashboard_servicio' => $dashboardServicioData,
+ ]
+ );
+ return response()->json($combinedData, 200)
+ ->header('Content-Type', 'application/json');
+ } catch (\Exception $e) {
+ Log::error('Error en la consulta de atención', ['exception' => $e->getMessage()]);
+ return response()->json(['error' => 'Error en la consulta de atención'], 500);
}
+ }
+
+ public function getSupportOptions(Request $request)
+ {
+ try {
+ $typeId = $request->query('type_id');
+
+ if (!$typeId) {
+ return response()->json(['error' => 'type_id es requerido'], 400);
+ }
+
+ $url = 'https://apoyos.comalcalco.gob.mx/beneficiaries/export/support-options';
+
+ $response = Http::timeout(30)->get($url, [
+ 'type_id' => $typeId
+ ]);
+
+ if (!$response->successful()) {
+ Log::error('Error al obtener opciones de apoyo', [
+ 'status' => $response->status(),
+ 'body' => $response->body(),
+ 'type_id' => $typeId
+ ]);
+
+ return response()->json([
+ 'error' => 'Error al obtener opciones de apoyo'
+ ], $response->status());
+ }
+
+ return response()->json($response->json());
+ } catch (\Exception $e) {
+ Log::error('Error en getSupportOptions', [
+ 'exception' => $e->getMessage(),
+ 'type_id' => $request->query('type_id')
+ ]);
+
+ return response()->json([
+ 'error' => 'Error interno del servidor'
+ ], 500);
+ }
+ }
+
+ public function exportExcel(Request $request)
+ {
+ try {
+ // CAMBIO: Usar los parámetros correctos que espera la API
+ $params = $request->only([
+ 'start_date',
+ 'end_date',
+ 'type_id',
+ 'support_id'
+ ]);
+
+ // Validaciones básicas
+ if (!$params['start_date'] || !$params['end_date']) {
+ return response()->json([
+ 'error' => 'Las fechas son requeridas'
+ ], 400);
+ }
+
+ if (!$params['type_id']) {
+ return response()->json([
+ 'error' => 'El type_id es requerido'
+ ], 400);
+ }
+
+ $url = 'https://apoyos.comalcalco.gob.mx/beneficiaries/export/excel';
+
+ // Log de parámetros para debug
+ Log::info('Exportando Excel con parámetros:', $params);
+
+ // IMPORTANTE: Hacer la petición sin timeout muy alto y con withoutVerifying para SSL
+ $response = Http::withoutVerifying()
+ ->timeout(60)
+ ->get($url, $params);
+
+ if (!$response->successful()) {
+ Log::error('Error al exportar Excel', [
+ 'status' => $response->status(),
+ 'body' => $response->body(),
+ 'params' => $params
+ ]);
+
+ return response()->json([
+ 'error' => 'Error al generar el archivo Excel: ' . $response->body()
+ ], $response->status());
+ }
+
+ // CORREGIR: Verificar que la respuesta sea realmente un Excel
+ $contentType = $response->header('Content-Type');
+
+ if (!str_contains($contentType, 'spreadsheet') && !str_contains($contentType, 'excel')) {
+ Log::error('Respuesta no es un archivo Excel', [
+ 'content_type' => $contentType,
+ 'body_preview' => substr($response->body(), 0, 200)
+ ]);
+
+ return response()->json([
+ 'error' => 'El servidor no devolvió un archivo Excel válido'
+ ], 400);
+ }
+
+ // Retornar el archivo Excel directamente con headers correctos
+ return response($response->body(), 200, [
+ 'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'Content-Disposition' => 'attachment; filename="beneficiarios_' .
+ $params['start_date'] . '_' . $params['end_date'] . '.xlsx"',
+ 'Content-Length' => strlen($response->body()),
+ 'Cache-Control' => 'no-cache, no-store, must-revalidate',
+ 'Pragma' => 'no-cache',
+ 'Expires' => '0'
+ ]);
+ } catch (\Exception $e) {
+ Log::error('Error en exportExcel', [
+ 'exception' => $e->getMessage(),
+ 'trace' => $e->getTraceAsString(),
+ 'params' => $request->all()
+ ]);
+
+ return response()->json([
+ 'error' => 'Error interno del servidor: ' . $e->getMessage()
+ ], 500);
+ }
+ }
}
diff --git a/colors.json.example b/colors.json.example
index fd28bbe..d36ba7d 100644
--- a/colors.json.example
+++ b/colors.json.example
@@ -23,4 +23,4 @@
"danger-dark":"#EF4444",
"info":"#3B82F6",
"info-dark":"#3B82F6"
-}
\ No newline at end of file
+}
diff --git a/resources/css/app.css b/resources/css/app.css
index e609f68..b0a29ba 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -18,12 +18,12 @@ @font-face {
src: url(./google-icons/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2');
}
-/* Scrollbar */
+/* Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
-
+
::-webkit-scrollbar-thumb {
background: #777777;
border-radius: 4px;
@@ -61,7 +61,7 @@ .btn-icon-secondary {
}
.header-icon {
- @apply hover:text-yellow-500 focus:text-yellow-600 hover:scale-105 hover:transition hover:duration-300;
+ @apply hover:text-primary focus:text-primary hover:scale-105 hover:transition hover:duration-300;
}
.input-primary {
diff --git a/resources/js/Components/Dashboard/Footer.vue b/resources/js/Components/Dashboard/Footer.vue
new file mode 100644
index 0000000..0219b96
--- /dev/null
+++ b/resources/js/Components/Dashboard/Footer.vue
@@ -0,0 +1,125 @@
+
+
+
diff --git a/resources/js/Components/Dashboard/Modal/ExportModal.vue b/resources/js/Components/Dashboard/Modal/ExportModal.vue
new file mode 100644
index 0000000..732991e
--- /dev/null
+++ b/resources/js/Components/Dashboard/Modal/ExportModal.vue
@@ -0,0 +1,387 @@
+
+
+
+
+
+ Configure los filtros para exportar los datos de beneficiarios
+
+ Seleccionados: {{ form.supportOptions.length }} de {{ supportOptionsData.length }}
+
+ Exportar a Excel
+
+
+
+ Selecciona un destino. +
+
+ + Sistema de seguimiento de apoyos +
+{{ totals.day ?? "0" }}
+{{ totals.week ?? "0" }}
++ CURP: + {{ item.citizen?.curp || "N/A" }} +
++ Dirección: + {{ item.citizen?.address || "N/A" }} +
++ Localidad: + {{ item.citizen.locality }} +
++ Apoyo: + {{ + item.warehouse?.name || + item.service?.name || + "N/A" + }} +
++ Cantidad: + {{ item.quantity }} +
++ Fallecido: + {{ item.deceased_name }} +
++ Solicitante: + {{ item.requester_name }} +
++ Observaciones: + {{ item.observations }} +
+No hay registros para mostrar
++ Ajusta los filtros para ver los beneficiarios +
++ Selecciona el rango de fechas para análisis gráfico +
++ Análisis detallado de los tipos de apoyos otorgados +
++ Período: {{ dateRange.start }} - {{ dateRange.end }} +
+Beneficiarios por género
++ Beneficiarios por rango etario +
+
+ + Sistema de seguimiento de obras +
++ Proyectos en seguimiento +
++ Estimaciones registradas +
++ Registro más reciente de progreso en obra +
++ No se encontraron registros de avances +
++ Registrado por +
++ {{ lastPlaneacion.name }} +
+Partida
++ {{ lastPlaneacion.desc_partida }} +
+Concepto
++ {{ lastPlaneacion.clave }} + {{ + lastPlaneacion.desc_concepto + }} +
++ {{ lastPlaneacion.desc_evidencia }} +
++ Estimación más reciente del proyecto +
++ No se encontraron registros de estimaciones +
++ Número de Estimación +
++ {{ lastEstimacion.num_estimacion }} +
+Proyecto
++ {{ + lastEstimacion.num_proyecto + ? `${lastEstimacion.num_proyecto} - ${lastEstimacion.proyecto}` + : lastEstimacion.proyecto + }} +
++ Monto Estimado +
++ {{ formatMoney(lastEstimacion.monto_estimacion) }} +
++ Monto Acumulado +
++ {{ formatMoney(lastEstimacion.monto_acumulado) }} +
++ Seguimiento detallado del progreso de cada proyecto +
++ {{ planeacionesErrorMessage }} +
+ ++ Comenzar agregando un nuevo proyecto. +
+| + Número + | ++ Proyecto + | ++ Progreso + | +
|---|---|---|
| + {{ p.num_proyecto || "--" }} + | +
+
+ {{ p.proyecto || "--" }}
+
+ |
+
+
+
+
+
+
+ {{
+ (Number(p.cumplimiento_total) || 0).toFixed(1)
+ }}%
+ |
+
+ Estimaciones detalladas por proyecto, concepto y partida +
++ {{ estimacionesErrorMessage }} +
+ ++ Comenzar agregando una nueva estimación. +
+| + | + Proyecto / Estimación + | ++ Estimación + | ++ Período + | ++ Monto + | +
|---|---|---|---|---|
| + + | +
+
+ {{
+ estimacionesGrouped[proyectoId].proyecto
+ .num_proyecto || "--"
+ }}
+
+
+ {{
+ estimacionesGrouped[proyectoId].proyecto.proyecto ||
+ "--"
+ }}
+
+ |
+
+
+ {{
+ estimacionesGrouped[proyectoId].estimaciones.length
+ }}
+ Estimación{{
+ estimacionesGrouped[proyectoId].estimaciones
+ .length > 1
+ ? "es"
+ : ""
+ }}
+
+ |
+ + | + |
| + |
+ {{ idx + 1 }}
+
+ {{ formatDate(est.created_at) }}
+
+ |
+
+ {{ idx + 1 }}
+ |
+
+
+ {{ (est.periodo_estimacion || "--").toUpperCase() }}
+
+ |
+
+
+ {{ formatMoney(est.monto_estimacion) }}
+
+ |
+
+ Total: + {{ + counters.sin_avances.count + }} +
++ Total: + {{ + counters.finalizadas.count + }} +
++ Total: + {{ + counters.abiertas.count + }} +
++ Registro de actividad de supervisores en proyectos +
+| + Supervisor + | ++ Tipo Acción + | ++ Detalle Acción + | ++ Fecha + | ++ Proyecto + | +
|---|---|---|---|---|
|
+
+
+
+
+
+
+ {{
+ supervisor.nombre
+ .split(" ")
+ .map((n) => n.charAt(0))
+ .join("")
+ .substring(0, 2)
+ .toUpperCase()
+ }}
+
+
+
+
+
+ {{ supervisor.nombre }}
+
+
+ {{ supervisor.correo }}
+
+ |
+
+
+ {{ supervisor.ultima_accion }}
+
+ |
+
+
+ {{ supervisor.detalle_accion }}
+
+
+ {{ supervisor.detalle_accion }}
+
+ |
+ + {{ + supervisor.fecha_accion + ? formatDateTime(supervisor.fecha_accion) + : "--" + }} + | +
+
+ {{ supervisor.proyecto_info }}
+
+ --
+ |
+
|
+
+ No hay supervisores registrados
+
+ |
+ ||||
+ + Sistema de seguimiento de trámites +
+Cargando datos...
+Resumen por unidad administrativa
++ Trámites Abiertos Hoy +
++ {{ + new Intl.NumberFormat().format( + data.procedures_opened_today + ) + }} +
++ Con Movimientos Hoy +
++ {{ + new Intl.NumberFormat().format( + data.procedures_with_movements_today + ) + }} +
+| + Unidad Administrativa + | ++ Abiertos + | ++ Movimientos Hoy + | ++ Cerrados + | ++ Total + | +
|---|---|---|---|---|
|
+
+ {{ administration.name }}
+
+ |
+ + + {{ + new Intl.NumberFormat().format( + administration.opened + ) + }} + + | ++ + {{ + new Intl.NumberFormat().format( + administration.movement_today + ) + }} + + | ++ + {{ + new Intl.NumberFormat().format( + administration.closed + ) + }} + + | +
+
+ {{
+ new Intl.NumberFormat().format(
+ administration.opened + administration.closed
+ )
+ }}
+
+ |
+
|
+
+ No hay datos disponibles
+
+ |
+ ||||
| + Procedimiento + | ++ Abiertos + | ++ Movimientos Hoy + | ++ Cerrados + | ++ Total + | +
|---|---|---|---|---|
|
+
+ {{ procedure.name }}
+
+ |
+ + + {{ new Intl.NumberFormat().format(procedure.opened) }} + + | ++ + {{ + new Intl.NumberFormat().format( + procedure.movement_today + ) + }} + + | ++ + {{ new Intl.NumberFormat().format(procedure.closed) }} + + | +
+
+ {{
+ new Intl.NumberFormat().format(
+ procedure.opened + procedure.closed
+ )
+ }}
+
+ |
+
|
+
+ No hay datos disponibles
+
+ |
+ ||||
Modo actual: {{ mode }}
++ Reporte generado el {{ new Date().toLocaleString("es-MX") }} +
+
- Sistema de seguimiento de apoyos
-Cargando datos...
-{{ totals.month ?? "--" }}
-Total mensual
-{{ totals.week ?? "--" }}
-Últimos 7 días
-{{ totals.day ?? "--" }}
-En el día actual
-Análisis detallado de los tipos de apoyos otorgados
-Beneficiarios por género
-Beneficiarios por rango etario
-- Selecciona un destino. -
-- Resumen de trámites por unidad administrativa -
-- Gráficas de apoyo a Beneficiarios y DIF -
-Proyectos en seguimiento
-
- - Sistema de seguimiento de obras -
-Cargando datos...
-Proyectos en seguimiento
-- Estimaciones registradas -
-- Registro más reciente de progreso en obra -
-- No se encontraron registros de avances -
-- Registrado por -
-- {{ lastPlaneacion.name }} -
-Partida
-- {{ lastPlaneacion.desc_partida }} -
-Concepto
-- {{ lastPlaneacion.clave }} - {{ - lastPlaneacion.desc_concepto - }} -
-- {{ lastPlaneacion.desc_evidencia }} -
-- Estimación más reciente del proyecto -
-- No se encontraron registros de estimaciones -
-- Número de Estimación -
-- {{ lastEstimacion.num_estimacion }} -
-Proyecto
-- {{ - lastEstimacion.num_proyecto - ? `${lastEstimacion.num_proyecto} - ${lastEstimacion.proyecto}` - : lastEstimacion.proyecto - }} -
-- Monto Estimado -
-- {{ formatMoney(lastEstimacion.monto_estimacion) }} -
-- Monto Acumulado -
-- {{ formatMoney(lastEstimacion.monto_acumulado) }} -
-- Seguimiento detallado del progreso de cada proyecto -
-- {{ planeacionesErrorMessage }} -
- -- Comenzar agregando un nuevo proyecto. -
-| - Número - | -- Proyecto - | -- Progreso - | -
|---|---|---|
| - {{ p.num_proyecto || "--" }} - | -
-
- {{ p.proyecto || "--" }}
-
- |
-
-
-
-
-
-
- {{
- (Number(p.cumplimiento_total) || 0).toFixed(1)
- }}%
- |
-
- Estimaciones detalladas por proyecto, concepto y partida -
-- {{ estimacionesErrorMessage }} -
- -- Comenzar agregando una nueva estimación. -
-| - | - Proyecto / Estimación - | -- Estimación - | -- Período - | -- Monto - | -
|---|---|---|---|---|
| - - | -
-
- {{
- estimacionesGrouped[proyectoId].proyecto
- .num_proyecto || "--"
- }}
-
-
- {{
- estimacionesGrouped[proyectoId].proyecto.proyecto ||
- "--"
- }}
-
- |
-
-
- {{
- estimacionesGrouped[proyectoId].estimaciones.length
- }}
- Estimación{{
- estimacionesGrouped[proyectoId].estimaciones.length >
- 1
- ? "es"
- : ""
- }}
-
- |
- - | - |
| - |
- {{ idx + 1 }}
-
- {{ formatDate(est.created_at) }}
-
- |
-
- {{ idx + 1 }}
- |
-
-
- {{ (est.periodo_estimacion || "--").toUpperCase() }}
-
- |
-
-
- {{ formatMoney(est.monto_estimacion) }}
-
- |
-
- Total: - {{ - counters.sin_avances.count - }} -
-- Total: - {{ - counters.finalizadas.count - }} -
-- Total: - {{ - counters.abiertas.count - }} -
-- Registro de actividad de supervisores en proyectos -
-| - Supervisor - | -- Tipo Acción - | -- Detalle Acción - | -- Fecha - | -- Proyecto - | -
|---|---|---|---|---|
|
-
-
-
-
-
-
- {{
- supervisor.nombre
- .split(" ")
- .map((n) => n.charAt(0))
- .join("")
- .substring(0, 2)
- .toUpperCase()
- }}
-
-
-
-
-
- {{ supervisor.nombre }}
-
-
- {{ supervisor.correo }}
-
- |
-
-
- {{ supervisor.ultima_accion }}
-
- |
-
-
- {{ supervisor.detalle_accion }}
-
-
- {{ supervisor.detalle_accion }}
-
- |
- - {{ - supervisor.fecha_accion - ? formatDateTime(supervisor.fecha_accion) - : "--" - }} - | -
-
- {{ supervisor.proyecto_info }}
-
- --
- |
-
|
-
- No hay supervisores registrados
-
- |
- ||||
- - Sistema de seguimiento de trámites -
-Cargando datos...
-Resumen por unidad administrativa
-- Trámites Abiertos Hoy -
-- {{ - new Intl.NumberFormat().format( - data.procedures_opened_today - ) - }} -
-- Con Movimientos Hoy -
-- {{ - new Intl.NumberFormat().format( - data.procedures_with_movements_today - ) - }} -
-| - Unidad Administrativa - | -- Abiertos - | -- Movimientos Hoy - | -- Cerrados - | -- Total - | -
|---|---|---|---|---|
|
-
- {{ administration.name }}
-
- |
- - - {{ - new Intl.NumberFormat().format(administration.opened) - }} - - | -- - {{ - new Intl.NumberFormat().format( - administration.movement_today - ) - }} - - | -- - {{ - new Intl.NumberFormat().format(administration.closed) - }} - - | -
-
- {{
- new Intl.NumberFormat().format(
- administration.opened + administration.closed
- )
- }}
-
- |
-
|
- No hay datos disponibles
- |
- ||||
| - Procedimiento - | -- Abiertos - | -- Movimientos Hoy - | -- Cerrados - | -- Total - | -
|---|---|---|---|---|
|
-
- {{ procedure.name }}
-
- |
- - - {{ new Intl.NumberFormat().format(procedure.opened) }} - - | -- - {{ - new Intl.NumberFormat().format( - procedure.movement_today - ) - }} - - | -- - {{ new Intl.NumberFormat().format(procedure.closed) }} - - | -
-
- {{
- new Intl.NumberFormat().format(
- procedure.opened + procedure.closed
- )
- }}
-
- |
-
|
- No hay datos disponibles
- |
- ||||
Modo actual: {{ mode }}
-- Reporte generado el {{ new Date().toLocaleString("es-MX") }} -
-