diff --git a/.env.qa b/.env.qa index fbba01d..3c41926 100644 --- a/.env.qa +++ b/.env.qa @@ -1,2 +1,2 @@ REACT_APP_ENVIRONMENT=qa -REACT_APP_API=https://www.gemcousa.solutions/GEMCOBackend/api \ No newline at end of file +REACT_APP_API=https://www.adminusa.gemcousa.solutions/GEMCOBackend/api \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 30b51ce..541de06 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -101,7 +101,7 @@ function App() { > - ? + adminusa diff --git a/src/Componest/Catalogos/CatRelacionBookPrecta/FileUploadExelWorkingHours.tsx b/src/Componest/Catalogos/CatRelacionBookPrecta/FileUploadExelWorkingHours.tsx deleted file mode 100644 index 886f28f..0000000 --- a/src/Componest/Catalogos/CatRelacionBookPrecta/FileUploadExelWorkingHours.tsx +++ /dev/null @@ -1,119 +0,0 @@ - -import * as React from 'react'; -import { useState } from 'react'; -import { Button, Card, Form } from 'react-bootstrap'; -import ExelServices from '../../../Utils/ExelFiles/Exel.services'; -import { FiSend } from "react-icons/fi"; -import { MsgInformativo } from '../../../Utils/Toast/msgInformativo'; -import * as XLSX from 'xlsx'; - -export default function FileUploadExel() { - const [WorkingHoursFile, setWorkingHoursFile] = useState(null); - const [showToast, setShowToast] = useState(false); - const [toastMsg, setToastMsg] = useState(''); - const [toastHeader, setToastHeader] = useState(''); - const [toastColor, setToastColor] = useState(''); - - const handleFileChange = async (event: React.ChangeEvent) => { - let file = event.target.files?.[0] || null; - - if (file && file.name.endsWith('.xls')) { - // Convertir XLS a XLSX usando la biblioteca xlsx - const data = await file.arrayBuffer(); - const workbook = XLSX.read(data, { type: 'array' }); - const convertedData = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); - file = new File([convertedData], file.name.replace('.xls', '.xlsx'), { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }); - } - - setWorkingHoursFile(file); - }; - - const handleSendFiles = async () => { - if (!WorkingHoursFile) { - setToastMsg('No hay archivos para enviar'); - setToastHeader('Error'); - setToastColor('danger'); - setShowToast(true); - return; - } - - const formDataBook = new FormData(); - formDataBook.append('file', WorkingHoursFile); - - try { - const responseBook = await ExelServices.uploadWorkingHours(formDataBook); - - if (!responseBook || responseBook.status !== 200) { - throw new Error('Error al subir el archivo de horas de trabajo'); - } - - setToastMsg('Archivo enviado exitosamente'); - setToastHeader('Informativo'); - setToastColor('success'); - setShowToast(true); - - setWorkingHoursFile(null); - - } catch (error) { - setToastMsg(`Error al enviar archivos: ${(error as Error).message || 'Error desconocido'}`); - setToastHeader('Error'); - setToastColor('danger'); - setShowToast(true); - } - }; - - return ( -
- - -
-
- - - - Arrastra o selecciona el archivo Excel - - - - - - - -
-
-
-
- - -
- ); -} diff --git a/src/Componest/Catalogos/CatWorkingHours/DTO/WorkingHours.ts b/src/Componest/Catalogos/CatWorkingHours/DTO/WorkingHours.ts new file mode 100644 index 0000000..66fe959 --- /dev/null +++ b/src/Componest/Catalogos/CatWorkingHours/DTO/WorkingHours.ts @@ -0,0 +1,19 @@ +export default interface WorkingHours { +empNo : string, +acNo : string, +name: string, +date : string, +clockIn1 : string, +clockOut1 : string, +clockIn2 : string, +clockOut2 : string, +clocIn3 : string, +clocOut3 : string, +clocIn4 : string, +clocOut4 : string, +clocIn5 : string, +clocOut5 : string, +totalInTime : string, +totalHoursWorked : string + +} \ No newline at end of file diff --git a/src/Componest/Catalogos/CatWorkingHours/FileUploadExelWorkingHours.tsx b/src/Componest/Catalogos/CatWorkingHours/FileUploadExelWorkingHours.tsx new file mode 100644 index 0000000..28aaf40 --- /dev/null +++ b/src/Componest/Catalogos/CatWorkingHours/FileUploadExelWorkingHours.tsx @@ -0,0 +1,474 @@ + +import * as React from 'react'; +import { useState } from 'react'; +import { Button, Card, Form, Col, Row, ToastHeader, } from 'react-bootstrap'; +import { BsSearch, BsFileEarmarkExcel } from 'react-icons/bs' +import ExelServices from '../../../Utils/ExelFiles/Exel.services'; +import { FiSend } from "react-icons/fi"; +import { MsgInformativo } from '../../../Utils/Toast/msgInformativo'; +import * as XLSX from 'xlsx'; +import DataTable from 'react-data-table-component'; +import { DTOWorkingHours } from '../../../DTO/DTOWorkingHours'; +import reportesServices from '../../../Services/Reportes/reportes.services'; + + +export default function FileUploadExel() { + const [WorkingHoursFile, setWorkingHoursFile] = useState(null); + const [showToast, setShowToast] = useState(false); + const [toastMsg, setToastMsg] = useState(''); + const [toastHeader, setToastHeader] = useState(''); + const [toastColor, setToastColor] = useState(''); + const [Inicio, setInicio] = useState(currentDate()) + const [Fin, setFin] = useState(currentDate()) + const [Data, setData] = useState>([]) + const [show, setShowMsg] = useState(false) + const [filtro, setFiltro] = useState('') + const [filteredData, setFilteredData] = useState>( + [] + ) + + + + + const handleFileChange = async (event: React.ChangeEvent) => { + let file = event.target.files?.[0] || null; + + if (file && file.name.endsWith('.xls')) { + // Convertir XLS a XLSX usando la biblioteca xlsx + const data = await file.arrayBuffer(); + const workbook = XLSX.read(data, { type: 'array' }); + const convertedData = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' }); + file = new File([convertedData], file.name.replace('.xls', '.xlsx'), { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + }); + } + + setWorkingHoursFile(file); + }; + + + + const columnsConcepts = [ + { + name: 'EmpNo', + width: '100px', + selector: (row : DTOWorkingHours ) => row.empNo, + sortable: true, + filter : true + }, + { + name: 'AcNo', + width: '80px', + selector :(row:DTOWorkingHours) => row.acNo, + sortable: true , + filter : true + }, + { + name: 'No', + width: '5px', + selector: (row : DTOWorkingHours) => row.no, + sortable: true, + filter : true + }, + { + name: 'Name', + width: '150px', + selector: (row : DTOWorkingHours) => row.name, + sortable : true , + filter : true + + }, + { + name: 'Date', + width: '150px', + selector : (row : DTOWorkingHours ) => row.date, + sortable: true, + filter : true + }, + { + name: 'ClockIn1', + width : '120px', + selector: (row : DTOWorkingHours) => row.clockIn1, + sortable: true , + filter : true + }, + { + name: 'ClockOut1', + width : '120px', + selector : (row : DTOWorkingHours) => row.clockOut1, + sortable : true , + filter : true + }, + { + name: 'ClockIn2', + width : '120px', + selector: (row : DTOWorkingHours) => row.clockIn2, + sortable: true , + filter : true + }, + { + name: 'ClockOut2', + width : '120px', + selector : (row : DTOWorkingHours) => row.clockOut2, + sortable : true, + filter : true + }, + { + name: 'ClockIn3', + width : '120px', + selector: (row : DTOWorkingHours) => row.clockIn3, + sortable: true , + filter : true + }, + { + name: 'ClockOut3', + width : '150px', + selector : (row : DTOWorkingHours) => row.clockOut3, + sortable : true, + filter : true + }, + { + name: 'ClockIn4', + width : '120px', + selector: (row : DTOWorkingHours) => row.clockIn4, + sortable: true , + filter : true + }, + { + name: 'ClockOut4', + width : '120px', + selector : (row : DTOWorkingHours) => row.clockOut4, + sortable : true, + filter : true + } , + { + name: 'ClockIn5', + width : '120px', + selector: (row : DTOWorkingHours) => row.clockIn5, + sortable: true , + filter : true + }, + { + name: 'ClockOut5', + width : '120px', + selector : (row : DTOWorkingHours) => row.clockOut5, + sortable : true, + filter : true + }, + { + name: 'TotalInTime', + width: '120px', + selector: (row : DTOWorkingHours) => row.totalInTime, + sortable : true , + filter : true + }, + + { + name: 'TotalHoursWorked', + width: '130px', + selector : (row : DTOWorkingHours) => row.totalHoursWorked, + sortable : true, + filter : true + + } + + + + + + ] + + + function currentDate (): string { + var today = new Date() + var dd = String(today.getDate()).padEnd(2,'0') + var mm = String(today.getMonth() + 1 ).padStart(2, '0') + var yyyy = today.getFullYear() + return yyyy+'-' + mm + '-' + dd + } + + const generarReporte = () => { + reportesServices.getRptWorkingHours(Inicio, Fin) + .then((response) => { + setData(response.data) + setFilteredData(response.data) + setToastMsg('Se econtro la siguiente informacion'); + setToastHeader('Informativo'); + setToastColor('success'); + setShowToast(true); + + }) + .catch((e:Error) => { + // alert('Ocurrio un Error'+e.message.toString()) + setToastMsg('No se ha introducido fechas validas') + setToastHeader('Error') + setToastColor('danger') + setShowToast(true) + return; + + + } ) + } + + + const donwloadExel = () => { + exportExcel(filteredData , 'Reportes de Horas Trabajadas') + } + + + + + + + + const filtraReporte = (e: any ) => { + const searchText = e.target.value.toLowerCase(); + setFiltro(searchText) + + const filtered = Data.filter((iteam) => { + return ( + (iteam.empNo && iteam.empNo.toString().toLocaleLowerCase().includes(searchText)) || + (iteam.name && iteam.name.toString().toLocaleLowerCase().includes(searchText)) || + (iteam.date && iteam.date.toString().toLocaleLowerCase().includes(searchText)) + ) + } ) + + + + console.log('filtered data ', filtered ) + setFilteredData(filtered) + } + + + + + + + const exportExcel = (jsonData: any[], fileName: string) => { + const Heading = [ + [ + 'EmpNo', + 'AcNo', + 'No', + 'Name', + 'Date', + 'ClockIn1', + 'ClockOut1', + 'ClockIn1', + 'ClockOut1', + 'ClockIn1', + 'ClockOut1', + 'ClockIn1', + 'ClockOut1', + 'ClockIn1', + 'ClockOut1', + 'TotalInTime', + 'TotalHoursWorked' + ] + + ] + + const wb = XLSX.utils.book_new() + const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]) + XLSX.utils.sheet_add_aoa(ws, Heading) + XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A2', skipHeader: true }) + XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') + XLSX.writeFile(wb, `${fileName}.xlsx`) + const range = XLSX.utils.decode_range(ws['!ref']!) + for (let C = range.s.c; C <= range.e.c; ++C) { + const address = XLSX.utils.encode_col(C) + '1' + if (!ws[address]) continue + ws[address].v = ws[address].v.toUpperCase() + } + } + + + + + + + + + + const handleSendFiles = async () => { + if (!WorkingHoursFile) { + setToastMsg('No hay archivos para enviar'); + setToastHeader('Error'); + setToastColor('danger'); + setShowToast(true); + return; + } + + const formDataBook = new FormData(); + formDataBook.append('file', WorkingHoursFile); + + try { + const responseBook = await ExelServices.uploadWorkingHours(formDataBook); + + if (!responseBook || responseBook.status !== 200) { + throw new Error('Error al subir el archivo de horas de trabajo'); + } + + setToastMsg('Archivo enviado exitosamente'); + setToastHeader('Informativo'); + setToastColor('success'); + setShowToast(true); + + setWorkingHoursFile(null); + + } catch (error) { + setToastMsg(`Error al enviar archivos: ${(error as Error).message || 'Error desconocido'}`); + setToastHeader('Error'); + setToastColor('danger'); + setShowToast(true); + } + }; + + + +return ( +
+ + +
+
+ + + + Arrastra o selecciona el archivo Excel + + + + + + + +
+
+
+
+ + + + + +
+ + + Desde + setInicio(e.target.value)} + size="sm" + /> + + + + Hasta + setFin(e.target.value)} + size="sm" + /> + + + + { + filtraReporte(e) + } } + + style={{ height: '20px', padding: '5px' }} + /> + + + + + + + + + + +
+
+
+ + + +
+ +
+
+
+
+); +} diff --git a/src/Componest/Reportes/RptTotalHours/RptTotalHours.tsx b/src/Componest/Reportes/RptTotalHours/RptTotalHours.tsx new file mode 100644 index 0000000..83f0c46 --- /dev/null +++ b/src/Componest/Reportes/RptTotalHours/RptTotalHours.tsx @@ -0,0 +1,448 @@ +import * as react from 'react' +import { useState } from 'react' +import reportesServices from '../../../Services/Reportes/reportes.services' +import DataTable from 'react-data-table-component' +import {DTOTotalHours} from '../../../DTO/Reportes/DTOTotalHours' +import * as XLSX from 'xlsx' +import { MsgInformativo } from '../../../Utils/Toast/msgInformativo' +import { Button, Card, Form, Col, Row, ToastHeader, CardBody, } from 'react-bootstrap'; +import { BsSearch, BsFileEarmarkExcel } from 'react-icons/bs' +import { DTOWorkingHours } from '../../../DTO/DTOWorkingHours' + + + +export default function RptTotalHours () +{ + const [Inicio, setInicio] = useState(currentDate()) + const [Fin , setFin] = useState(currentDate) + const [filtro, setFiltro] = useState('') + const [filteredData, setFilteredData] = useState> ( + [] + ) + const [filteredDataDet, setFilteredDataDet] = useState >( + [] + ) + + const [Data, setData] = useState> ([]) + const [DataDet , setDataDet ] = useState > ([]) + const [showToast, setShowToast] = useState(false); + const [toastMsg, setToastMsg] = useState(''); + const [toastHeader, setToastHeader] = useState(''); + const [toastColor, setToastColor] = useState(''); + + + function currentDate (): string { + var today = new Date() + var dd = String(today.getDate()).padEnd(2,'0') + var mm = String(today.getMonth() + 1 ).padStart(2, '0') + var yyyy = today.getFullYear() + return yyyy+'-' + mm + '-' + dd + } + + const generarRptRes = () => { + reportesServices.getRptTotalHours(Inicio, Fin) + .then((response) => { + setData(response.data) + setFilteredData(response.data) + setToastMsg('Se econtro la siguiente informacion'); + setToastHeader('Informativo'); + setToastColor('success'); + setShowToast(true); + + }) + .catch((e:Error) => { + // alert('Ocurrio un Error'+e.message.toString()) + setToastMsg('No se ha introducido fechas validas') + setToastHeader('Error') + setToastColor('danger') + setShowToast(true) + return; + } ) + } + + const generarRptDet = () => { + reportesServices.getRptWorkingHours(Inicio, Fin) + .then((response) => { + setDataDet(response.data); + }) + .catch((e: Error) => { + setToastMsg('Fechas No Validas'); + setToastHeader('Error'); + setToastColor('danger'); + setShowToast(true); + }); + }; + + + + + + + const columnsConcepts = [ + { + name: 'EmpNo', + width : '100px', + selector : (row : DTOTotalHours ) => row.empNo, + sortable: true, + filter : true + }, + + + + { + name: 'AcNo', + width : '100px', + selector : (row : DTOTotalHours) => row.acNo, + sortable : true, + filter : true + }, + { + name: 'Name', + width : '200px', + selector: (row: DTOTotalHours) => row.name, + sortable: true, + filter: true + + }, + + + + { + name: 'TotalHoursAccumulated', + width: '200px', + selector : (row: DTOTotalHours ) => row.totalHoursAccumulated, + sortable : true, + filter : true + }, + { + name: 'TotalHoursWithMilitaryMinutes', + with: '200px', + selector : (row: DTOTotalHours) => row.totalHoursWithMilitaryMinutes, + filter : true + } + + + + + + ] + + const columnsConceptsDet = [ + [ + { + name: 'Name' , + selector : (row: DTOWorkingHours ) => row.name, + sortable : true, + filter : true + }, + { + name: 'EmpNo', + + selector : (row : DTOWorkingHours ) => row.empNo, + sortable: true, + filter : true + } + ] + ] + + + + + // const donwloadExel = () => { + // exportExcel(filteredData, 'ReporteTotalHoras' ) + // } + + + // const exportExcel = (jsonData: any[], fileName: string) => { + // const Heading = [ + // [ + // 'EmpNo', + // 'AcNo', + // 'No', + // 'TotalHoursAccumuled', + // 'TotalHoursWithMilitaryMinutes' + + // ] + + + // ] + + + + // const Heading1 = [[ + // 'EmpNo', 'AcNo', 'Name', 'Date', 'ClockIn1', 'ClockOut1 ' ,'ClockIn1', 'ClockOut1 ' , + // 'ClockIn2', 'ClockOut2 ', 'ClockIn3', 'ClockOut3 ', 'ClockIn4', 'ClockOut4 ', + // 'ClockIn5', 'ClockOut5 ' + + + // ]] + + + // const wb = XLSX.utils.book_new() + // const ws: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]) + // XLSX.utils.sheet_add_aoa(ws, Heading) + // XLSX.utils.sheet_add_json(ws, jsonData, { origin: 'A2', skipHeader: true }) + // XLSX.utils.book_append_sheet(wb, ws, 'Sheet1') + // XLSX.writeFile(wb, `${fileName}.xlsx`) + // const range = XLSX.utils.decode_range(ws['!ref']!) + // for (let C = range.s.c; C <= range.e.c; ++C) { + // const address = XLSX.utils.encode_col(C) + '1' + // if (!ws[address]) continue + // ws[address].v = ws[address].v.toUpperCase() + // } + + + // } + + + + + + + const donwloadExel = () => { + exportExcel(filteredData, DataDet, 'ReporteTotal'); + + + }; + + + + + + + + + const exportExcel = (jsonData1: any[], jsonData2: any[], fileName: string) => { + const Heading1 = [ + [ + 'EmpNo', + 'AcNo', + 'No', + 'TotalHoursAccumuled', + 'TotalHoursWithMilitaryMinutes' + ] + ]; + + const Heading2 = [ + [ + 'EmpNo', 'AcNo', 'Name', 'Date', 'ClockIn1', 'ClockOut1', 'ClockIn1', 'ClockOut1', + 'ClockIn2', 'ClockOut2', 'ClockIn3', 'ClockOut3', 'ClockIn4', 'ClockOut4', + 'ClockIn5', 'ClockOut5' , 'TotalInTime' + ] + ]; + + // Crear libro de trabajo + const wb = XLSX.utils.book_new(); + + // Hoja 1 + const ws1: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]); + XLSX.utils.sheet_add_aoa(ws1, Heading1); + XLSX.utils.sheet_add_json(ws1, jsonData1, { origin: 'A2', skipHeader: true }); + XLSX.utils.book_append_sheet(wb, ws1, 'Resumen'); + + // Hoja 2 + const ws2: XLSX.WorkSheet = XLSX.utils.json_to_sheet([]); + XLSX.utils.sheet_add_aoa(ws2, Heading2); + XLSX.utils.sheet_add_json(ws2, jsonData2, { origin: 'A2', skipHeader: true }); + XLSX.utils.book_append_sheet(wb, ws2, 'Detalle'); + + // Convertir títulos a mayúsculas en ambas hojas + const capitalizeHeaders = (ws: XLSX.WorkSheet) => { + const range = XLSX.utils.decode_range(ws['!ref']!); + for (let C = range.s.c; C <= range.e.c; ++C) { + const address = XLSX.utils.encode_col(C) + '1'; + if (!ws[address]) continue; + ws[address].v = ws[address].v.toUpperCase(); + } + }; + + capitalizeHeaders(ws1); + capitalizeHeaders(ws2); + + // Escribir y descargar el archivo Excel + XLSX.writeFile(wb, `${fileName}.xlsx`); + }; + + + + + + + + const filtraReporte1 = (e: any) => { + const searchText = e.target.value.toLowerCase(); + setFiltro(searchText) + + const filtered = DataDet.filter((iteam) => { + return ( + (iteam.empNo && iteam.empNo.toString().toLocaleUpperCase().includes(searchText)) || + (iteam.name && iteam.name.toString().toLocaleLowerCase().includes(searchText) ) + + + ) + } ) + + setFilteredDataDet(filtered) + + } + + + + + + const filtraReporte = (e: any) => { + const searchText = e.target.value.toLowerCase(); + setFiltro(searchText) + + const filtered = Data.filter((iteam) => { + return ( + (iteam.empNo && iteam.empNo.toString().toLocaleUpperCase().includes(searchText)) || + (iteam.name && iteam.name.toString().toLocaleLowerCase().includes(searchText) ) + + + ) + } ) + + setFilteredData(filtered) + + } + + + + const generReportes = () => { + generarRptRes() + generarRptDet() + } + + + + // const filtros = (e: any) => { + // filtraReporte(e); + // filtraReporte1(e); + // } + + + + + + return( +
+ {/* */} + +
+ + + {/* Desde */} + + Desde + setInicio(e.target.value)} + size="sm" + /> + + + + {/* Hasta */} + Hasta + setFin(e.target.value)} + size="sm" + /> + + + + { + filtraReporte(e) + } } + // onChange={filtros} + style={{ height: '10px', padding: '5px' }} + /> + + + + + + + + + + +
+
+ {/*
*/} + + + + + + + +
+ + +
+
+
+ + + +
+ + ) + + + +} \ No newline at end of file diff --git a/src/DTO/DTOWorkingHours.ts b/src/DTO/DTOWorkingHours.ts index ac22d22..a826c5c 100644 --- a/src/DTO/DTOWorkingHours.ts +++ b/src/DTO/DTOWorkingHours.ts @@ -15,6 +15,7 @@ clockIn4: string, clockOut4: string, clockIn5: string, clockOut5: string, -totalInTime : string +totalInTime : string, +totalHoursWorked : string } \ No newline at end of file diff --git a/src/DTO/Reportes/DTOTotalHours.ts b/src/DTO/Reportes/DTOTotalHours.ts new file mode 100644 index 0000000..7a0ea66 --- /dev/null +++ b/src/DTO/Reportes/DTOTotalHours.ts @@ -0,0 +1,11 @@ +export interface DTOTotalHours { + + empNo : string , + acNo : string, + name : string, + totalHoursAccumulated : string + totalHoursWithMilitaryMinutes : string + + + +} \ No newline at end of file diff --git a/src/Services/Reportes/reportes.services.ts b/src/Services/Reportes/reportes.services.ts index ec8dda3..80e94ad 100644 --- a/src/Services/Reportes/reportes.services.ts +++ b/src/Services/Reportes/reportes.services.ts @@ -1,5 +1,7 @@ import DtoPrecuentaCheques from '../../Componest/Catalogos/CatRelacionBookPrecta/DTO/DTOPrecuentaCheques' import { DTORelPreChe } from '../../DTO/DTORelPreChe' +import { DTOWorkingHours } from '../../DTO/DTOWorkingHours' +import { DTOTotalHours } from '../../DTO/Reportes/DTOTotalHours' import http from '../common/http-common' @@ -30,7 +32,18 @@ class reportsDataService { - + getRptWorkingHours(Inicio : string , Fin: string ) + { + return http.get> ( + `/Reportes/GetAllWorkingHours?Inicio=${Inicio}&Fin=${Fin} ` + ) + } + + getRptTotalHours(Inicio : string , Fin : string) + { + return http.get> ( + `/Reportes/TotalHours?Inicio=${Inicio}&Fin=${Fin}`) + } diff --git a/src/index.tsx b/src/index.tsx index 6aa0e61..d92fc5b 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -31,7 +31,8 @@ import CatNotificaciones from './Componest/Catalogos/CatNotificaciones' // import { KPIAgenteAduanal } from './Components/Dashboard/KPIs/KPIAgenteAduanal' import CatRelacionBookPrecta from './Componest/Catalogos/CatRelacionBookPrecta/CatRelacionBookPrecta' import FileUploadExel from './Componest/Catalogos/FileUploadExel' -import FileUploadExelWorkingHours from './Componest/Catalogos/CatRelacionBookPrecta/FileUploadExelWorkingHours' +import FileUploadExelWorkingHours from './Componest/Catalogos/CatWorkingHours/FileUploadExelWorkingHours' +import RptTotalHours from './Componest/Reportes/RptTotalHours/RptTotalHours' const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) function PageNotFound() { @@ -56,6 +57,7 @@ root.render( } /> } /> } /> + } /> {/* } /> } />