Loading web/src/components/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx 0 → 100644 +207 −0 Original line number Diff line number Diff line import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useEffect, useState} from "react"; import "./assets/css/styles.css"; import { languaguesList } from "../../../constants/languages"; import { LoadingScreen } from "../../loading_screen/loading_screen"; import { usePointOfInterest } from "../../../hooks/usePointOfInterest"; import { EmptyPointOfInterest, PointOfInterest } from "../../../infraestructure/entities/poi"; import { ImageDropzone } from "../../image_dropzone/image_dropzone"; import { usePlace } from "../../../hooks/usePlace"; interface props { setWindowVisibility: (visibility: boolean) => void; idTown: number; forceRenderList: () => void; isRegister: boolean; form?: PointOfInterest; } export const AdminPanelPoiRegister = ({setWindowVisibility, idTown,forceRenderList, isRegister, form}: props) => { const { register, errors, setDescriptions, setDirections, descriptions, directions, setLanguageDescriptionIndexSelected, handleSubmit, onSubmitRegister, getPointById, setValue, languageDescriptionIndexSelected, languageDirectionsIndexSelected, setLanguageDirectionsIndexSelected, } = usePointOfInterest(forceRenderList, setWindowVisibility); const [isLoading, setIsLoading] = useState(false); const [actualPOI, setActualPOI] = useState<PointOfInterest>(EmptyPointOfInterest); const [preview, setPreview] = useState<string | ArrayBuffer | null>(null); const [image, setImage] = useState<File | null>(null); const { placeList, updatePlacesByTown } = usePlace(); useEffect(() => { if(image){ setValue('image', image, {shouldValidate: true}); } },[image]); useEffect(() => { setIsLoading(true); const fetchData = async () => { await updatePlacesByTown(idTown); 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); setValue('contentES', pointGetted.contentES); setValue('directionsEN', pointGetted.directionsEN); setValue('directionsES', pointGetted.directionsES); } } }; fetchData(); setIsLoading(false); },[]); return ( <div className="poi_register_wrap"> <div className="poi_register_header"> Registra el punto de interés <FontAwesomeIcon icon={faWindowClose} className="close_btn" onClick={() => setWindowVisibility(false)}/> </div> <div className="poi_register_body"> {isLoading ? <LoadingScreen/> : <form onSubmit={handleSubmit(onSubmitRegister)}> <div className="inputs_container"> <div className="input"> <div className="input_header"> Nombre del punto de interés </div> <input type="text" {...register('name')} autoComplete="off" /> <p className="error">{errors.name?.message}</p> </div> <div className="input"> <div className="input_header"> Descripción del punto de interés <select name="language_description_select" onChange={(e) => setLanguageDescriptionIndexSelected(Number(e.target.value))}> {languaguesList.map((language, index) => { return ( <option key={index} value={index}>{language}</option> ); })} </select> </div> { languaguesList.map((language, index) => { if(index===languageDescriptionIndexSelected){ return ( <textarea id={index.toString()} className="poi_description" value={descriptions[index]} key={language} onChange={(e) => { const updatedDescriptionsList = [...descriptions]; updatedDescriptionsList[index] = e.target.value; setDescriptions(updatedDescriptionsList); if(index===0){ setValue('contentES', updatedDescriptionsList[index], {shouldValidate: true}); }else{ setValue('contentEN', updatedDescriptionsList[index], {shouldValidate: true}); } }} /> ); } }) } <p className="error">{errors.contentEN?.message || errors.contentES?.message}</p> </div> <div className="input"> <div className="input_header"> Direcciones hacia el siguiente punto de interés <select name="language_description_select" onChange={(e) => setLanguageDirectionsIndexSelected(Number(e.target.value))}> {languaguesList.map((language, index) => { return ( <option key={index} value={index}>{language}</option> ); })} </select> </div> { languaguesList.map((language, index) => { if(index===languageDirectionsIndexSelected){ return ( <textarea id={index.toString()} className="poi_description" value={directions[index]} key={language} onChange={(e) => { const updatedDirectionsList = [...directions]; updatedDirectionsList[index] = e.target.value; setDirections(updatedDirectionsList); if(index===0){ setValue('directionsES', updatedDirectionsList[index], {shouldValidate: true}); }else{ setValue('directionsEN', updatedDirectionsList[index], {shouldValidate: true}); } }} /> ); } }) } <p className="error">{errors.directionsEN?.message || errors.directionsES?.message}</p> </div> <div className="place_select"> <label>Lugar al que pertenece el punto de interés</label> {placeList === null || placeList.length===0 ? <option disabled defaultValue="" value="">No hay lugares</option> : <select {...register('idPlace')}> <> <option disabled selected={isRegister} value="">Selecciona el lugar</option> {placeList.map((place) => { return ( <option key={place.idPlace} selected={place.idPlace===form?.idPlace} value={place.idPlace}>{place.name}</option> ); })} </> </select> } <p className="error">{errors.idPlace?.message}</p> </div> <input type="submit"/> </div> <div className="image_cnt"> <div className="input_header"> Nombre del punto de interés </div> <ImageDropzone setImage={setImage} preview={preview} setPreview={setPreview}/> <p className="error">{errors.image?.message}</p> </div> </form> } </div> </div> ); } No newline at end of file web/src/components/admin_panel_poi/admin_panel_poi_register/assets/css/styles.css 0 → 100644 +137 −0 Original line number Diff line number Diff line *{ user-select: none; } .poi_register_wrap{ position: absolute; z-index: 99; left: 0; right: 0; top: 0; bottom: 0; margin: auto; width: 75vw; height: 90vh; display: flex; flex-direction: column; background: white; border: solid 2px black; } .poi_register_header{ display: flex; width: 100%; align-items: center; justify-content: center; padding: 5px; background: #ccc; height: 7%; } .close_btn{ display: inline-block; cursor: pointer; height: 3%; position: absolute; right: 5px; } .poi_register_body{ height: 93%; width: 100%; } .poi_register_body form{ height: 100%; display: flex; } .inputs_container{ height: 100%; width: 60%; } .image_cnt{ height: 100%; width: 40%; display: flex; align-items: center; flex-direction: column; } .input{ width: 100%; display: flex; flex-direction: column; } .input_header{ display: flex; align-items: center; justify-content: center; position: relative; } .input .input_header select{ position: absolute; right: 5px; } .error{ color: red; font-size: 12px; padding: 0; margin: 0; } .poi_description{ height: 100px; padding: 5px; overflow-y: auto; resize: none; } .town_select_cnt{ display: flex; width: 100%; } .town_select_cnt div{ width: 50%; height: 100%; display: flex; flex-direction: row; justify-content: center; align-items: center; } .town_select_cnt div select{ width: 50%; } .input_body{ display: flex; width: 100%; flex-direction: row; } .input_body div{ height: 100%; width: 50%; display: flex; flex-direction: row; justify-content: center; align-items: center; } .place_select{ display: flex; flex-direction: column; width: 50%; justify-content: center; align-items: center; } .place_select select{ width: 60%; } No newline at end of file Loading
web/src/components/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx 0 → 100644 +207 −0 Original line number Diff line number Diff line import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useEffect, useState} from "react"; import "./assets/css/styles.css"; import { languaguesList } from "../../../constants/languages"; import { LoadingScreen } from "../../loading_screen/loading_screen"; import { usePointOfInterest } from "../../../hooks/usePointOfInterest"; import { EmptyPointOfInterest, PointOfInterest } from "../../../infraestructure/entities/poi"; import { ImageDropzone } from "../../image_dropzone/image_dropzone"; import { usePlace } from "../../../hooks/usePlace"; interface props { setWindowVisibility: (visibility: boolean) => void; idTown: number; forceRenderList: () => void; isRegister: boolean; form?: PointOfInterest; } export const AdminPanelPoiRegister = ({setWindowVisibility, idTown,forceRenderList, isRegister, form}: props) => { const { register, errors, setDescriptions, setDirections, descriptions, directions, setLanguageDescriptionIndexSelected, handleSubmit, onSubmitRegister, getPointById, setValue, languageDescriptionIndexSelected, languageDirectionsIndexSelected, setLanguageDirectionsIndexSelected, } = usePointOfInterest(forceRenderList, setWindowVisibility); const [isLoading, setIsLoading] = useState(false); const [actualPOI, setActualPOI] = useState<PointOfInterest>(EmptyPointOfInterest); const [preview, setPreview] = useState<string | ArrayBuffer | null>(null); const [image, setImage] = useState<File | null>(null); const { placeList, updatePlacesByTown } = usePlace(); useEffect(() => { if(image){ setValue('image', image, {shouldValidate: true}); } },[image]); useEffect(() => { setIsLoading(true); const fetchData = async () => { await updatePlacesByTown(idTown); 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); setValue('contentES', pointGetted.contentES); setValue('directionsEN', pointGetted.directionsEN); setValue('directionsES', pointGetted.directionsES); } } }; fetchData(); setIsLoading(false); },[]); return ( <div className="poi_register_wrap"> <div className="poi_register_header"> Registra el punto de interés <FontAwesomeIcon icon={faWindowClose} className="close_btn" onClick={() => setWindowVisibility(false)}/> </div> <div className="poi_register_body"> {isLoading ? <LoadingScreen/> : <form onSubmit={handleSubmit(onSubmitRegister)}> <div className="inputs_container"> <div className="input"> <div className="input_header"> Nombre del punto de interés </div> <input type="text" {...register('name')} autoComplete="off" /> <p className="error">{errors.name?.message}</p> </div> <div className="input"> <div className="input_header"> Descripción del punto de interés <select name="language_description_select" onChange={(e) => setLanguageDescriptionIndexSelected(Number(e.target.value))}> {languaguesList.map((language, index) => { return ( <option key={index} value={index}>{language}</option> ); })} </select> </div> { languaguesList.map((language, index) => { if(index===languageDescriptionIndexSelected){ return ( <textarea id={index.toString()} className="poi_description" value={descriptions[index]} key={language} onChange={(e) => { const updatedDescriptionsList = [...descriptions]; updatedDescriptionsList[index] = e.target.value; setDescriptions(updatedDescriptionsList); if(index===0){ setValue('contentES', updatedDescriptionsList[index], {shouldValidate: true}); }else{ setValue('contentEN', updatedDescriptionsList[index], {shouldValidate: true}); } }} /> ); } }) } <p className="error">{errors.contentEN?.message || errors.contentES?.message}</p> </div> <div className="input"> <div className="input_header"> Direcciones hacia el siguiente punto de interés <select name="language_description_select" onChange={(e) => setLanguageDirectionsIndexSelected(Number(e.target.value))}> {languaguesList.map((language, index) => { return ( <option key={index} value={index}>{language}</option> ); })} </select> </div> { languaguesList.map((language, index) => { if(index===languageDirectionsIndexSelected){ return ( <textarea id={index.toString()} className="poi_description" value={directions[index]} key={language} onChange={(e) => { const updatedDirectionsList = [...directions]; updatedDirectionsList[index] = e.target.value; setDirections(updatedDirectionsList); if(index===0){ setValue('directionsES', updatedDirectionsList[index], {shouldValidate: true}); }else{ setValue('directionsEN', updatedDirectionsList[index], {shouldValidate: true}); } }} /> ); } }) } <p className="error">{errors.directionsEN?.message || errors.directionsES?.message}</p> </div> <div className="place_select"> <label>Lugar al que pertenece el punto de interés</label> {placeList === null || placeList.length===0 ? <option disabled defaultValue="" value="">No hay lugares</option> : <select {...register('idPlace')}> <> <option disabled selected={isRegister} value="">Selecciona el lugar</option> {placeList.map((place) => { return ( <option key={place.idPlace} selected={place.idPlace===form?.idPlace} value={place.idPlace}>{place.name}</option> ); })} </> </select> } <p className="error">{errors.idPlace?.message}</p> </div> <input type="submit"/> </div> <div className="image_cnt"> <div className="input_header"> Nombre del punto de interés </div> <ImageDropzone setImage={setImage} preview={preview} setPreview={setPreview}/> <p className="error">{errors.image?.message}</p> </div> </form> } </div> </div> ); } No newline at end of file
web/src/components/admin_panel_poi/admin_panel_poi_register/assets/css/styles.css 0 → 100644 +137 −0 Original line number Diff line number Diff line *{ user-select: none; } .poi_register_wrap{ position: absolute; z-index: 99; left: 0; right: 0; top: 0; bottom: 0; margin: auto; width: 75vw; height: 90vh; display: flex; flex-direction: column; background: white; border: solid 2px black; } .poi_register_header{ display: flex; width: 100%; align-items: center; justify-content: center; padding: 5px; background: #ccc; height: 7%; } .close_btn{ display: inline-block; cursor: pointer; height: 3%; position: absolute; right: 5px; } .poi_register_body{ height: 93%; width: 100%; } .poi_register_body form{ height: 100%; display: flex; } .inputs_container{ height: 100%; width: 60%; } .image_cnt{ height: 100%; width: 40%; display: flex; align-items: center; flex-direction: column; } .input{ width: 100%; display: flex; flex-direction: column; } .input_header{ display: flex; align-items: center; justify-content: center; position: relative; } .input .input_header select{ position: absolute; right: 5px; } .error{ color: red; font-size: 12px; padding: 0; margin: 0; } .poi_description{ height: 100px; padding: 5px; overflow-y: auto; resize: none; } .town_select_cnt{ display: flex; width: 100%; } .town_select_cnt div{ width: 50%; height: 100%; display: flex; flex-direction: row; justify-content: center; align-items: center; } .town_select_cnt div select{ width: 50%; } .input_body{ display: flex; width: 100%; flex-direction: row; } .input_body div{ height: 100%; width: 50%; display: flex; flex-direction: row; justify-content: center; align-items: center; } .place_select{ display: flex; flex-direction: column; width: 50%; justify-content: center; align-items: center; } .place_select select{ width: 60%; } No newline at end of file