diff --git a/backend/src/place/place.service.ts b/backend/src/place/place.service.ts index 6f258c3c9e281fab376587cf7811f10d0b2b1ba5..d13a40dce89040c710d4c542cb54ae964e04aee2 100644 --- a/backend/src/place/place.service.ts +++ b/backend/src/place/place.service.ts @@ -166,6 +166,7 @@ export class PlaceService { place.name = updatePlaceReqDto.name; place.openAt = updatePlaceReqDto.openAt; place.imageName = updatePlaceReqDto.image.filename; + place.address = updatePlaceReqDto.address; // Update categories const categories: Category[] = []; diff --git a/web/package-lock.json b/web/package-lock.json index 1a12efab09ca83526645989effdfdc6325f11ef9..cfe258b941830817d6518c6cd3beccbf6bf541dc 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -20,6 +20,7 @@ "@types/react-dom": "^18.2.21", "@vis.gl/react-google-maps": "^1.1.0", "axios": "^1.6.8", + "buffer": "^6.0.3", "react": "^18.2.0", "react-data-table-component": "^7.6.2", "react-dom": "^18.2.0", @@ -5844,6 +5845,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -6018,6 +6038,29 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -9590,6 +9633,25 @@ "node": ">=4" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", diff --git a/web/package.json b/web/package.json index 887ef2ba68ee5db93c477600ebef4a3df0c64698..d6ec7c7b90bca281a0926ca69ddfbf0e0cf31336 100644 --- a/web/package.json +++ b/web/package.json @@ -15,6 +15,7 @@ "@types/react-dom": "^18.2.21", "@vis.gl/react-google-maps": "^1.1.0", "axios": "^1.6.8", + "buffer": "^6.0.3", "react": "^18.2.0", "react-data-table-component": "^7.6.2", "react-dom": "^18.2.0", diff --git a/web/src/App.tsx b/web/src/App.tsx index 8dff12f1d12ddbbf9d2a12ea5179b98385885076..043cee412f94a3ecfe87c9388c834f89e1a0c1bc 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -3,6 +3,7 @@ import './App.css'; import { AuthContextProvider } from './context/auth_context'; import { MessageContextProvider } from './context/message_context'; import { router } from './router/router'; +import { ToastContainer } from 'react-toastify'; function App() { @@ -13,6 +14,14 @@ function App() { + ); } diff --git a/web/src/components/admin_panel_places/admin_panel_place_register/admin_panel_place_register.tsx b/web/src/components/admin_panel_places/admin_panel_place_register/admin_panel_place_register.tsx index 2b123a8585e93cac0c63a4bbe634c33020c9c0aa..9a2e93ccf5e6504b728bd85ffd5ced78cdf2b8ca 100644 --- a/web/src/components/admin_panel_places/admin_panel_place_register/admin_panel_place_register.tsx +++ b/web/src/components/admin_panel_places/admin_panel_place_register/admin_panel_place_register.tsx @@ -47,7 +47,7 @@ export const AdminPanelPlaceRegister = ({setWindowVisibility, idTown, categories } = usePlace(forceRenderList, setWindowVisibility); const [clickedCategories, setClickedCategories] = useState(new Array(categoriesList.length).fill(false)); const [isLoading, setIsLoading] = useState(false); - const [actualPlace, setActualPlace] = useState(EmptyPlace); + const [actualPlace, setActualPlace] = useState(null); const [openHourInput, setOpenHourInput] = useState(''); const [closeHourInput, setCloseHourInput] = useState(''); @@ -126,7 +126,7 @@ export const AdminPanelPlaceRegister = ({setWindowVisibility, idTown, categories onClick={() => setWindowVisibility(false)}/>
- {isLoading + {isLoading || (!isRegister && actualPlace===null) ? : @@ -223,7 +223,7 @@ export const AdminPanelPlaceRegister = ({setWindowVisibility, idTown, categories > {availableDaysList.map((option, index) => { return ( - + ); })} @@ -237,13 +237,13 @@ export const AdminPanelPlaceRegister = ({setWindowVisibility, idTown, categories Inicio Cierre
@@ -277,7 +277,7 @@ export const AdminPanelPlaceRegister = ({setWindowVisibility, idTown, categories

{errors.categoriesId?.message}

- +

{errors.imagesList?.message}

diff --git a/web/src/components/admin_panel_poi/admin_panel_poi_list/admin_panel_poi_list.tsx b/web/src/components/admin_panel_poi/admin_panel_poi_list/admin_panel_poi_list.tsx index 0ec33afc7ed80c9f1c7546d0a3c65fa47c1a758a..8250307c032a81fe7f3a7ed5c39a181415b5e8c3 100644 --- a/web/src/components/admin_panel_poi/admin_panel_poi_list/admin_panel_poi_list.tsx +++ b/web/src/components/admin_panel_poi/admin_panel_poi_list/admin_panel_poi_list.tsx @@ -2,22 +2,57 @@ import DataTable, { TableColumn } from 'react-data-table-component'; import { usePlace } from '../../../hooks/usePlace'; import './assets/css/styles.css'; import { LoadingSpinner } from '../../loading_spinner/loading_spinner'; -import { faEdit } from '@fortawesome/free-solid-svg-icons'; +import { faEye } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Dispatch, SetStateAction, useEffect, useState } from 'react'; import { usePointOfInterest } from '../../../hooks/usePointOfInterest'; import { PointOfInterest } from '../../../infraestructure/entities/poi'; +import { LoadingScreen } from '../../loading_screen/loading_screen'; interface props{ idTown: number; isWindowActive: boolean; - setWindowVisibility: (visibility: boolean) => void; setActualPoint: Dispatch>; - setIsRegisterPane: Dispatch>; + setWindowVisibilityViewer: (visibility: boolean) => void; + setBinaryData: Dispatch>; + setIsPDFViewerActive: Dispatch>; } -export const AdminPanelPoiList = ({idTown, isWindowActive}: props) => { +export const AdminPanelPoiList = ({idTown, isWindowActive, setActualPoint, setWindowVisibilityViewer, setBinaryData, + setIsPDFViewerActive +}: props) => { const [isLoading, setIsLoading] = useState(false); + const [isPDFLoading, setIsPDFLoading] = useState(false); + const [printButtonActive, setPrintButtonActive] = useState(false); + const [selectedRows, setSelectedRows] = useState([]); + const [actualPlaceId, setActualPlaceId] = useState(0); + const {getPdfById} = usePointOfInterest(); + + const handleRowSelected = (selected: { allSelected: boolean; selectedCount: number; selectedRows: PointOfInterest[];}) => { + setSelectedRows(selected.selectedRows.map((element)=>{return element.idPoint || -1})); + } + + useEffect(()=>{ + if(selectedRows.length>0){ + setPrintButtonActive(true); + }else{ + setPrintButtonActive(false); + } + },[selectedRows]); + + const handleClickPrintButton = () => { + const fetchPdf = async () => { + setIsPDFLoading(true); + const res = await getPdfById(actualPlaceId, selectedRows); + if(res!==null){ + setIsPDFViewerActive(true); + setBinaryData(res); + } + setIsPDFLoading(false); + } + fetchPdf(); + } + const { placeList, updatePlacesByTown @@ -29,6 +64,11 @@ export const AdminPanelPoiList = ({idTown, isWindowActive}: props) => { poiList } = usePointOfInterest(); + const handleViewSelectedPoint = (point: PointOfInterest) => { + setActualPoint(point); + setWindowVisibilityViewer(true); + } + const columns : TableColumn[] = [ { name: "Identificador", @@ -37,20 +77,19 @@ export const AdminPanelPoiList = ({idTown, isWindowActive}: props) => { }, { name: "Nombre", - selector: row => row.name, - sortable: true - }, - { - name: "Descripción", - selector: row => row.contentES, + selector: row => row.name.substring(0,40), sortable: true }, { name: "Acciones", cell: (row) => { return ( - { + if(!isWindowActive){ + handleViewSelectedPoint(row); + } + }} /> ); } @@ -73,39 +112,46 @@ export const AdminPanelPoiList = ({idTown, isWindowActive}: props) => { return (
- Lugar - { + const index = Number(event.target.value); + const place = placeList[index]; + setActualPlaceId(place.idPlace || 0); + refreshList(place.idPlace || 0); + }} + > + { + placeList === null || placeList.length===0 ? + + : + <> + + {placeList.map((place, index) => { + return ( + + ); + })} + } +
} + onSelectedRowsChange={handleRowSelected} columns={columns} data={poiList} selectableRows className="data_table" />
+ { + isPDFLoading && + }
); } \ No newline at end of file diff --git a/web/src/components/admin_panel_poi/admin_panel_poi_list/assets/css/styles.css b/web/src/components/admin_panel_poi/admin_panel_poi_list/assets/css/styles.css index a3154b01e61761a5e87179fa0764cb33593d7382..951c5a77215b1968b852b41a59867024e469611b 100644 --- a/web/src/components/admin_panel_poi/admin_panel_poi_list/assets/css/styles.css +++ b/web/src/components/admin_panel_poi/admin_panel_poi_list/assets/css/styles.css @@ -13,6 +13,11 @@ align-items: center; } +.print_btn{ + position: absolute; + right: 20px; +} + .poi_list_body{ display: flex; width: 100%; diff --git a/web/src/components/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx b/web/src/components/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx index d8f653e1dfa7ed5b1205a150713c13852063e512..25b25c85ed27df302a748c63b7bb2cc4ea164e00 100644 --- a/web/src/components/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx +++ b/web/src/components/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx @@ -35,7 +35,6 @@ export const AdminPanelPoiRegister = ({setWindowVisibility, idTown,forceRenderLi setLanguageDirectionsIndexSelected, } = usePointOfInterest(forceRenderList, setWindowVisibility); const [isLoading, setIsLoading] = useState(false); - const [actualPOI, setActualPOI] = useState(EmptyPointOfInterest); const [preview, setPreview] = useState(null); const [image, setImage] = useState(null); const { @@ -56,7 +55,6 @@ export const AdminPanelPoiRegister = ({setWindowVisibility, idTown,forceRenderLi if (!isRegister && form) { const pointGetted = await getPointById(form.idPoint || 0); if(pointGetted){ - setActualPOI(pointGetted); setValue('idPoint', pointGetted.idPlace); setValue('name', pointGetted.name); setValue('contentEN', pointGetted.contentEN); @@ -194,7 +192,7 @@ export const AdminPanelPoiRegister = ({setWindowVisibility, idTown,forceRenderLi
- Nombre del punto de interés + Imagén relacionada

{errors.image?.message}

diff --git a/web/src/components/admin_panel_poi/admin_panel_poi_screen/admin_panel_poi_screen.tsx b/web/src/components/admin_panel_poi/admin_panel_poi_screen/admin_panel_poi_screen.tsx index 57d32b8fc73526fd954c690ac4184e65fdbe544c..48c0763e4c4fc394be3db5a1c564817553f898bc 100644 --- a/web/src/components/admin_panel_poi/admin_panel_poi_screen/admin_panel_poi_screen.tsx +++ b/web/src/components/admin_panel_poi/admin_panel_poi_screen/admin_panel_poi_screen.tsx @@ -4,6 +4,9 @@ import "./assets/css/styles.css"; import { AdminPanelPoiList } from "../admin_panel_poi_list/admin_panel_poi_list"; import { Town } from "../../../infraestructure/entities/town"; import { PointOfInterest } from "../../../infraestructure/entities/poi"; +import { AdminPanelPoiViewer } from "../admin_panel_poi_viewer/admin_panel_poi_viewer"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; interface props { isWindowActive: boolean; @@ -15,15 +18,23 @@ export const AdminPanelPoiScreen = ({isWindowActive,setIsWindowActive, town}: pr const [renderCount, setRenderCount] = useState(0); const [isRegisterPane, setIsRegisterPane] = useState(true); const [actualPoint, setActualPoint] = useState(); - const [isPlaceRegisterWindowActive, setIsPlaceRegisterWindowActive] = useState(false); + const [isRegisterWindowActive, setIsRegisterWindowActive] = useState(false); + const [isViewerWindowActive, setIsViewerWindowActive] = useState(false); + const [isPDFViewerActive, setIsPDFViewerActive] = useState(false); + const [binaryData, setBinaryData] = useState(''); const forceRenderList = () =>{ setRenderCount(prevCount => prevCount + 1); setIsWindowActive(false); } - const setWindowVisibility = (visibility: boolean) => { - setIsPlaceRegisterWindowActive(visibility); + const setWindowVisibilityRegister = (visibility: boolean) => { + setIsRegisterWindowActive(visibility); + setIsWindowActive(visibility); + } + + const setWindowVisibilityViewer = (visibility: boolean) => { + setIsViewerWindowActive(visibility); setIsWindowActive(visibility); } @@ -35,7 +46,7 @@ export const AdminPanelPoiScreen = ({isWindowActive,setIsWindowActive, town}: pr disabled={isWindowActive || !town} onClick={() => { setIsRegisterPane(true); - setWindowVisibility(true); + setWindowVisibilityRegister(true); }} > Registrar punto @@ -43,17 +54,35 @@ export const AdminPanelPoiScreen = ({isWindowActive,setIsWindowActive, town}: pr
{ - isPlaceRegisterWindowActive && } + { + isViewerWindowActive && + } + setActualPoint={setActualPoint} setWindowVisibilityViewer={setWindowVisibilityViewer} + isWindowActive={isWindowActive} setBinaryData={setBinaryData} setIsPDFViewerActive={setIsPDFViewerActive}/> + { + isPDFViewerActive && +
+
+ { + setIsPDFViewerActive(false); + setBinaryData(''); + }}/> +
+
+