Loading web/src/components/admin_panel_places/admin_panel_place_list/admin_panel_place_list.tsx +36 −4 Original line number Diff line number Diff line Loading @@ -3,16 +3,34 @@ import { usePlace } from '../../../hooks/usePlace'; import './assets/css/styles.css'; import { Place } from '../../../infraestructure/entities/place'; import { LoadingSpinner } from '../../loading_spinner/loading_spinner'; import { faEdit } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Dispatch, SetStateAction, useEffect } from 'react'; interface props{ idTown: number; isWindowActive: boolean; setIsWindowActive: Dispatch<SetStateAction<boolean>>; setActualPlace: Dispatch<SetStateAction<Place | undefined>>; setIsRegisterPane: Dispatch<SetStateAction<boolean>>; } export const AdminPanelPlaceList = ({idTown}: props) => { export const AdminPanelPlaceList = ({idTown, isWindowActive, setIsWindowActive, setActualPlace, setIsRegisterPane}: props) => { const { placeList, pending } = usePlace(idTown); pending, updatePlacesByTown } = usePlace(); const handleEditSelectedCategory = (place: Place) => { setIsRegisterPane(false); setActualPlace(place); setIsWindowActive(true); } useEffect(() => { updatePlacesByTown(idTown); },[]); const columns : TableColumn<Place>[] = [ { Loading @@ -27,6 +45,20 @@ export const AdminPanelPlaceList = ({idTown}: props) => { { name: "Estado", selector: row => row.available }, { name: "Acciones", cell: (row) => { return ( <FontAwesomeIcon style={isWindowActive ? {color: 'gray'}: {cursor: 'pointer'}} icon={faEdit} onClick={() => { if(!isWindowActive){ handleEditSelectedCategory(row); } }} /> ); } } ]; Loading @@ -36,7 +68,7 @@ export const AdminPanelPlaceList = ({idTown}: props) => { progressComponent={ <LoadingSpinner style={{display: 'flex'}}/> } columns={columns} data={placeList} selectableRows className="data_table"/> columns={columns} data={placeList} className="data_table"/> </div> ); } No newline at end of file web/src/components/admin_panel_places/admin_panel_place_register/admin_panel_place_register.tsx +196 −142 Original line number Diff line number Diff line import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Dispatch, SetStateAction, useState} from "react"; import { Dispatch, SetStateAction, useEffect, useState} from "react"; import "./assets/css/styles.css"; import { MapComponent } from "../../map/map"; import { usePlace } from "../../../hooks/usePlace"; import { languaguesList } from "../../../constants/languages"; import { LoadingScreen } from "../../loading_screen/loading_screen"; import { MultipleImagesDropzone } from "../../multiple_images_dropzone/multiple_images_dropzone"; import { AvailableDays, availableDaysList } from "../../../infraestructure/entities/place"; import { AvailableDays, availableDaysList, EmptyPlace, Place } from "../../../infraestructure/entities/place"; import { Category } from "../../../infraestructure/entities/category"; interface props { Loading @@ -15,31 +15,40 @@ interface props { categoriesList: Category[]; idTown: number; forceRenderList: () => void; isRegister: boolean; form?: Place; } export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesList, forceRenderList}: props) => { export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesList, forceRenderList, isRegister, form}: props) => { const { register, handleSubmit, errors, onSubmit, setValue, languageDescriptionIndexSelected, descriptions, setDescriptions, setLanguageDescriptionIndexSelected, isLoading, updateTimeForm, availableDays, setAvailableDays, resetField, categoriesId, setCategoriesId, } = usePlace(idTown, forceRenderList, setIsWindowActive); getPlaceById, onSubmitRegister, onSubmitUpdate, clearErrors } = usePlace(forceRenderList, setIsWindowActive); const [clickedCategories, setClickedCategories] = useState<boolean[]>(new Array(categoriesList.length).fill(false)); const [isLoading, setIsLoading] = useState(false); const [actualPlace, setActualPlace] = useState<Place>(EmptyPlace); const [openHourInput, setOpenHourInput] = useState(''); const [closeHourInput, setCloseHourInput] = useState(''); const onClickCategory = (idCategory: number, indexList: number) => { const onClickCategory = (idCategory: number) => { const index = categoriesId.indexOf(idCategory); const indexList = categoriesList.findIndex(category => category.idCategory === idCategory); const clickedCategoriesBackup = clickedCategories.map((clickedCategory, index)=> { if(index === indexList){ return !clickedCategory; Loading @@ -61,6 +70,43 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi setClickedCategories(clickedCategoriesBackup); } useEffect(() => { setIsLoading(true); const fetchData = async () => { setValue('idTown', idTown); if (!isRegister && form) { const placeGetted = await getPlaceById(form.idPlace || 0); if(placeGetted){ setActualPlace(placeGetted); setValue('idPlace', placeGetted.idPlace); setValue('name', placeGetted.name); setValue('descriptions', placeGetted.descriptions); setDescriptions(placeGetted.descriptions || ['', '']); setValue('openAt', placeGetted.openAt); setOpenHourInput(placeGetted.openAt < 10 ? `0${placeGetted.openAt}:00` : `${placeGetted.openAt}:00`); setCloseHourInput(placeGetted.closeAt < 10 ? `0${placeGetted.closeAt}:00` : `${placeGetted.closeAt}:00`); setValue('closeAt', placeGetted.closeAt); setValue('available', placeGetted.available); setAvailableDays(placeGetted.available); const clickedCategoriesBackup : boolean[] = []; categoriesList.forEach((category) => { if(placeGetted.categoriesId.indexOf(category.idCategory) > -1){ clickedCategoriesBackup.push(true); }else{ clickedCategoriesBackup.push(false); } }); setClickedCategories(clickedCategoriesBackup); setCategoriesId(placeGetted.categoriesId); } } else { setValue('available', availableDays, { shouldValidate: true }); } }; fetchData(); setIsLoading(false); },[]); return ( <div className="place_register_wrap"> <div className="place_register_header"> Loading @@ -69,12 +115,11 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi onClick={() => setIsWindowActive(false)}/> </div> <div className="place_register_body"> <form onSubmit={handleSubmit(onSubmit)}> { isLoading {isLoading ? <LoadingScreen/> : <form onSubmit={handleSubmit(isRegister ? onSubmitRegister : onSubmitUpdate)}> <div className="inputs_container"> <div className="input"> <div className="input_header"> Loading Loading @@ -131,7 +176,9 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi <input type="time" autoComplete="off" value={openHourInput} onChange={(event) => { setOpenHourInput(event.target.value); updateTimeForm(event.target.value, true); }} /> Loading @@ -142,7 +189,9 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi <input type="time" autoComplete="off" value={closeHourInput} onChange={(event) => { setCloseHourInput(event.target.value); updateTimeForm(event.target.value, false); }} /> Loading @@ -163,7 +212,7 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi > {availableDaysList.map((option, index) => { return ( <option key={index} value={index}>{option.name}</option> <option key={index} selected={option.option===actualPlace.available} value={index}>{option.name}</option> ); })} </select> Loading @@ -177,11 +226,13 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi Inicio <input type="date" defaultValue={actualPlace.startDate?.toString().substring(0,10)} {...register('startDate')} /> Cierre <input type="date" defaultValue={actualPlace.endDate?.toString().substring(0,10)} {...register('endDate')} /> </div> Loading @@ -202,10 +253,10 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi categoriesList.map((category, index) => { return ( <div className="category_item" onClick={() => onClickCategory(category.idCategory, index)} onClick={() => onClickCategory(category.idCategory)} style={clickedCategories[index] ? {border: '2px solid blue'} : {border: '1px solid black'}} > {category.nameES} {category.nameES + " " + category.idCategory} </div> ); }) Loading @@ -215,21 +266,24 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi <p className="error">{errors.categoriesId?.message}</p> </div> <MultipleImagesDropzone setValue={setValue}/> <MultipleImagesDropzone setValue={setValue} imagesList={actualPlace.imagesList}/> <p className="error">{errors.imagesList?.message}</p> <input type="submit"/> </div> } <div className="map_container"> <div className="map"> <MapComponent setValue={setValue}/> <MapComponent setValue={setValue} setIsLoading={setIsLoading} latitude={actualPlace.latitude} longitude={actualPlace.longitude} clearErrors={clearErrors}/> </div> <div className="map_error_cnt"> <p className="error">{errors.latitude?.message}</p> </div> </div> </form> } </div> </div> ); Loading web/src/components/admin_panel_places/admin_panel_place_screen/admin_panel_place_screen.tsx +13 −5 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import "./assets/css/styles.css"; import { AdminPanelPlaceList } from "../admin_panel_place_list/admin_panel_place_list"; import { Town } from "../../../infraestructure/entities/town"; import { useCategory } from "../../../hooks/useCategory"; import { LoadingScreen } from "../../loading_screen/loading_screen"; import { Place } from "../../../infraestructure/entities/place"; interface props { isWindowActive: boolean; Loading @@ -14,21 +14,22 @@ interface props { export const AdminPanelPlaceScreen = ({isWindowActive,setIsWindowActive, town}: props) => { const [renderCount, setRenderCount] = useState(0); const [isRegisterPane, setIsRegisterPane] = useState(true); const [actualPlace, setActualPlace] = useState<Place | undefined>(); const { categoriesList, updateCategoriesList, pending } = useCategory(); const forceRenderList = () =>{ setRenderCount(prevCount => prevCount + 1); setIsWindowActive(false); } useEffect(()=>{ updateCategoriesList(); },[]); if(pending) return <LoadingScreen/> return ( <div className="admin_panel_place_content"> Loading @@ -36,7 +37,10 @@ export const AdminPanelPlaceScreen = ({isWindowActive,setIsWindowActive, town}: Administrar lugares dentro de Pueblo Mágico <button className="place_add_btn" disabled={isWindowActive || !town} onClick={() => setIsWindowActive(true)} onClick={() => { setIsRegisterPane(true); setIsWindowActive(true); }} > Registrar lugar </button> Loading @@ -48,9 +52,13 @@ export const AdminPanelPlaceScreen = ({isWindowActive,setIsWindowActive, town}: idTown={town?.idTown || -1} categoriesList={categoriesList} forceRenderList={forceRenderList} isRegister={isRegisterPane} form={actualPlace} /> } <AdminPanelPlaceList idTown={town?.idTown || -1} key={renderCount}/> <AdminPanelPlaceList idTown={town?.idTown || -1} key={renderCount} isWindowActive={isWindowActive} setIsWindowActive={setIsWindowActive} setActualPlace={setActualPlace} setIsRegisterPane={setIsRegisterPane}/> </div> </div> ); Loading web/src/components/map/map.tsx +39 −38 Original line number Diff line number Diff line import { GoogleMap, Marker, useLoadScript } from "@react-google-maps/api"; import { useState, useMemo } from "react"; import { useState, Dispatch, SetStateAction, useEffect } from "react"; import { REACT_APP_GOOGLE_API_KEY } from "../../constants/api_keys"; import { LoadingScreen } from "../loading_screen/loading_screen"; import { UseFormSetValue } from "react-hook-form"; import { UseFormClearErrors, UseFormSetValue } from "react-hook-form"; import { Place } from "../../infraestructure/entities/place"; import { APIProvider, Map, Marker } from "@vis.gl/react-google-maps"; interface props{ setValue: UseFormSetValue<Place>; setIsLoading: Dispatch<SetStateAction<boolean>>; clearErrors: UseFormClearErrors<Place>; latitude?: number; longitude?: number; } export const MapComponent = ({setValue}: props) => { const {isLoaded} = useLoadScript({ googleMapsApiKey: REACT_APP_GOOGLE_API_KEY }); const [marker, setMarker] = useState(false); const [latitude, setLatitude] = useState(0.0); const [longitude, setLongitude] = useState(0.0); const updateMarker = (event: google.maps.MapMouseEvent) => { if (event.latLng) { setMarker(true); setLatitude(event.latLng.lat()); setLongitude(event.latLng.lng()); setValue("latitude", event.latLng.lat(), {shouldValidate: true}); setValue("longitude", event.latLng.lng(), {shouldValidate: true}); export interface Position{ latitude: number; longitude: number; } export const MapComponent = ({setValue, setIsLoading, latitude, longitude, clearErrors}: props) => { const [position, setPosition] = useState<Position>({latitude: 0.0, longitude: 0.0}); const center = {lat: 23.687, lng: -102.74}; useEffect(() => { if(latitude && longitude){ setPosition({latitude, longitude}); } }, [latitude]); const center = useMemo(() => ( {lat: 23.687, lng: -102.74} ),[]) useEffect(() => { setValue('latitude',position.latitude); setValue('longitude',position.longitude); clearErrors('latitude'); clearErrors('longitude'); },[position]); return ( <APIProvider apiKey={REACT_APP_GOOGLE_API_KEY} onLoad={() => setIsLoading(false)}> <div style={{width: '100%', height: '100%'}}> {!isLoaded ? <LoadingScreen/> : <GoogleMap center={center} zoom={8} mapContainerStyle={{height: '100%'}} onClick={updateMarker} > {marker && <Marker position={{lat: latitude, lng: longitude}}/>} </GoogleMap> } <Map defaultCenter={center} defaultZoom={8} gestureHandling={'greedy'} disableDefaultUI={true} onClick={(event)=> { const lat = event.detail.latLng?.lat || 0.0; const lng = event.detail.latLng?.lng || 0.0; setPosition({latitude: lat, longitude: lng}); }}> <Marker position={{lat: position.latitude, lng: position.longitude}}/> </Map> </div> </APIProvider> ); } No newline at end of file web/src/components/multiple_images_dropzone/multiple_images_dropzone.tsx +3 −6 Original line number Diff line number Diff line Loading @@ -7,15 +7,16 @@ import { faTimesCircle } from "@fortawesome/free-solid-svg-icons"; interface props{ setValue: UseFormSetValue<Place>; imagesList?: File[] | string[]; } export const MultipleImagesDropzone = ({setValue}:props) => { export const MultipleImagesDropzone = ({setValue, imagesList}:props) => { const { getRootProps, getInputProps, imagesFiles, removeImage, } = useDropzoneMultiplesImages(setValue); } = useDropzoneMultiplesImages(setValue, imagesList); return ( <div className="multiple_images_dropzone_root"> Loading @@ -25,14 +26,10 @@ export const MultipleImagesDropzone = ({setValue}:props) => { </div> <div className="previews_list_cnt"> { imagesFiles && imagesFiles.map((image, index) => { return ( <div className="preview" key={index} onClick={() => { }} > <div className="preview_inner"> <img Loading Loading
web/src/components/admin_panel_places/admin_panel_place_list/admin_panel_place_list.tsx +36 −4 Original line number Diff line number Diff line Loading @@ -3,16 +3,34 @@ import { usePlace } from '../../../hooks/usePlace'; import './assets/css/styles.css'; import { Place } from '../../../infraestructure/entities/place'; import { LoadingSpinner } from '../../loading_spinner/loading_spinner'; import { faEdit } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Dispatch, SetStateAction, useEffect } from 'react'; interface props{ idTown: number; isWindowActive: boolean; setIsWindowActive: Dispatch<SetStateAction<boolean>>; setActualPlace: Dispatch<SetStateAction<Place | undefined>>; setIsRegisterPane: Dispatch<SetStateAction<boolean>>; } export const AdminPanelPlaceList = ({idTown}: props) => { export const AdminPanelPlaceList = ({idTown, isWindowActive, setIsWindowActive, setActualPlace, setIsRegisterPane}: props) => { const { placeList, pending } = usePlace(idTown); pending, updatePlacesByTown } = usePlace(); const handleEditSelectedCategory = (place: Place) => { setIsRegisterPane(false); setActualPlace(place); setIsWindowActive(true); } useEffect(() => { updatePlacesByTown(idTown); },[]); const columns : TableColumn<Place>[] = [ { Loading @@ -27,6 +45,20 @@ export const AdminPanelPlaceList = ({idTown}: props) => { { name: "Estado", selector: row => row.available }, { name: "Acciones", cell: (row) => { return ( <FontAwesomeIcon style={isWindowActive ? {color: 'gray'}: {cursor: 'pointer'}} icon={faEdit} onClick={() => { if(!isWindowActive){ handleEditSelectedCategory(row); } }} /> ); } } ]; Loading @@ -36,7 +68,7 @@ export const AdminPanelPlaceList = ({idTown}: props) => { progressComponent={ <LoadingSpinner style={{display: 'flex'}}/> } columns={columns} data={placeList} selectableRows className="data_table"/> columns={columns} data={placeList} className="data_table"/> </div> ); } No newline at end of file
web/src/components/admin_panel_places/admin_panel_place_register/admin_panel_place_register.tsx +196 −142 Original line number Diff line number Diff line import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Dispatch, SetStateAction, useState} from "react"; import { Dispatch, SetStateAction, useEffect, useState} from "react"; import "./assets/css/styles.css"; import { MapComponent } from "../../map/map"; import { usePlace } from "../../../hooks/usePlace"; import { languaguesList } from "../../../constants/languages"; import { LoadingScreen } from "../../loading_screen/loading_screen"; import { MultipleImagesDropzone } from "../../multiple_images_dropzone/multiple_images_dropzone"; import { AvailableDays, availableDaysList } from "../../../infraestructure/entities/place"; import { AvailableDays, availableDaysList, EmptyPlace, Place } from "../../../infraestructure/entities/place"; import { Category } from "../../../infraestructure/entities/category"; interface props { Loading @@ -15,31 +15,40 @@ interface props { categoriesList: Category[]; idTown: number; forceRenderList: () => void; isRegister: boolean; form?: Place; } export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesList, forceRenderList}: props) => { export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesList, forceRenderList, isRegister, form}: props) => { const { register, handleSubmit, errors, onSubmit, setValue, languageDescriptionIndexSelected, descriptions, setDescriptions, setLanguageDescriptionIndexSelected, isLoading, updateTimeForm, availableDays, setAvailableDays, resetField, categoriesId, setCategoriesId, } = usePlace(idTown, forceRenderList, setIsWindowActive); getPlaceById, onSubmitRegister, onSubmitUpdate, clearErrors } = usePlace(forceRenderList, setIsWindowActive); const [clickedCategories, setClickedCategories] = useState<boolean[]>(new Array(categoriesList.length).fill(false)); const [isLoading, setIsLoading] = useState(false); const [actualPlace, setActualPlace] = useState<Place>(EmptyPlace); const [openHourInput, setOpenHourInput] = useState(''); const [closeHourInput, setCloseHourInput] = useState(''); const onClickCategory = (idCategory: number, indexList: number) => { const onClickCategory = (idCategory: number) => { const index = categoriesId.indexOf(idCategory); const indexList = categoriesList.findIndex(category => category.idCategory === idCategory); const clickedCategoriesBackup = clickedCategories.map((clickedCategory, index)=> { if(index === indexList){ return !clickedCategory; Loading @@ -61,6 +70,43 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi setClickedCategories(clickedCategoriesBackup); } useEffect(() => { setIsLoading(true); const fetchData = async () => { setValue('idTown', idTown); if (!isRegister && form) { const placeGetted = await getPlaceById(form.idPlace || 0); if(placeGetted){ setActualPlace(placeGetted); setValue('idPlace', placeGetted.idPlace); setValue('name', placeGetted.name); setValue('descriptions', placeGetted.descriptions); setDescriptions(placeGetted.descriptions || ['', '']); setValue('openAt', placeGetted.openAt); setOpenHourInput(placeGetted.openAt < 10 ? `0${placeGetted.openAt}:00` : `${placeGetted.openAt}:00`); setCloseHourInput(placeGetted.closeAt < 10 ? `0${placeGetted.closeAt}:00` : `${placeGetted.closeAt}:00`); setValue('closeAt', placeGetted.closeAt); setValue('available', placeGetted.available); setAvailableDays(placeGetted.available); const clickedCategoriesBackup : boolean[] = []; categoriesList.forEach((category) => { if(placeGetted.categoriesId.indexOf(category.idCategory) > -1){ clickedCategoriesBackup.push(true); }else{ clickedCategoriesBackup.push(false); } }); setClickedCategories(clickedCategoriesBackup); setCategoriesId(placeGetted.categoriesId); } } else { setValue('available', availableDays, { shouldValidate: true }); } }; fetchData(); setIsLoading(false); },[]); return ( <div className="place_register_wrap"> <div className="place_register_header"> Loading @@ -69,12 +115,11 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi onClick={() => setIsWindowActive(false)}/> </div> <div className="place_register_body"> <form onSubmit={handleSubmit(onSubmit)}> { isLoading {isLoading ? <LoadingScreen/> : <form onSubmit={handleSubmit(isRegister ? onSubmitRegister : onSubmitUpdate)}> <div className="inputs_container"> <div className="input"> <div className="input_header"> Loading Loading @@ -131,7 +176,9 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi <input type="time" autoComplete="off" value={openHourInput} onChange={(event) => { setOpenHourInput(event.target.value); updateTimeForm(event.target.value, true); }} /> Loading @@ -142,7 +189,9 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi <input type="time" autoComplete="off" value={closeHourInput} onChange={(event) => { setCloseHourInput(event.target.value); updateTimeForm(event.target.value, false); }} /> Loading @@ -163,7 +212,7 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi > {availableDaysList.map((option, index) => { return ( <option key={index} value={index}>{option.name}</option> <option key={index} selected={option.option===actualPlace.available} value={index}>{option.name}</option> ); })} </select> Loading @@ -177,11 +226,13 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi Inicio <input type="date" defaultValue={actualPlace.startDate?.toString().substring(0,10)} {...register('startDate')} /> Cierre <input type="date" defaultValue={actualPlace.endDate?.toString().substring(0,10)} {...register('endDate')} /> </div> Loading @@ -202,10 +253,10 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi categoriesList.map((category, index) => { return ( <div className="category_item" onClick={() => onClickCategory(category.idCategory, index)} onClick={() => onClickCategory(category.idCategory)} style={clickedCategories[index] ? {border: '2px solid blue'} : {border: '1px solid black'}} > {category.nameES} {category.nameES + " " + category.idCategory} </div> ); }) Loading @@ -215,21 +266,24 @@ export const AdminPanelPlaceRegister = ({setIsWindowActive, idTown, categoriesLi <p className="error">{errors.categoriesId?.message}</p> </div> <MultipleImagesDropzone setValue={setValue}/> <MultipleImagesDropzone setValue={setValue} imagesList={actualPlace.imagesList}/> <p className="error">{errors.imagesList?.message}</p> <input type="submit"/> </div> } <div className="map_container"> <div className="map"> <MapComponent setValue={setValue}/> <MapComponent setValue={setValue} setIsLoading={setIsLoading} latitude={actualPlace.latitude} longitude={actualPlace.longitude} clearErrors={clearErrors}/> </div> <div className="map_error_cnt"> <p className="error">{errors.latitude?.message}</p> </div> </div> </form> } </div> </div> ); Loading
web/src/components/admin_panel_places/admin_panel_place_screen/admin_panel_place_screen.tsx +13 −5 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import "./assets/css/styles.css"; import { AdminPanelPlaceList } from "../admin_panel_place_list/admin_panel_place_list"; import { Town } from "../../../infraestructure/entities/town"; import { useCategory } from "../../../hooks/useCategory"; import { LoadingScreen } from "../../loading_screen/loading_screen"; import { Place } from "../../../infraestructure/entities/place"; interface props { isWindowActive: boolean; Loading @@ -14,21 +14,22 @@ interface props { export const AdminPanelPlaceScreen = ({isWindowActive,setIsWindowActive, town}: props) => { const [renderCount, setRenderCount] = useState(0); const [isRegisterPane, setIsRegisterPane] = useState(true); const [actualPlace, setActualPlace] = useState<Place | undefined>(); const { categoriesList, updateCategoriesList, pending } = useCategory(); const forceRenderList = () =>{ setRenderCount(prevCount => prevCount + 1); setIsWindowActive(false); } useEffect(()=>{ updateCategoriesList(); },[]); if(pending) return <LoadingScreen/> return ( <div className="admin_panel_place_content"> Loading @@ -36,7 +37,10 @@ export const AdminPanelPlaceScreen = ({isWindowActive,setIsWindowActive, town}: Administrar lugares dentro de Pueblo Mágico <button className="place_add_btn" disabled={isWindowActive || !town} onClick={() => setIsWindowActive(true)} onClick={() => { setIsRegisterPane(true); setIsWindowActive(true); }} > Registrar lugar </button> Loading @@ -48,9 +52,13 @@ export const AdminPanelPlaceScreen = ({isWindowActive,setIsWindowActive, town}: idTown={town?.idTown || -1} categoriesList={categoriesList} forceRenderList={forceRenderList} isRegister={isRegisterPane} form={actualPlace} /> } <AdminPanelPlaceList idTown={town?.idTown || -1} key={renderCount}/> <AdminPanelPlaceList idTown={town?.idTown || -1} key={renderCount} isWindowActive={isWindowActive} setIsWindowActive={setIsWindowActive} setActualPlace={setActualPlace} setIsRegisterPane={setIsRegisterPane}/> </div> </div> ); Loading
web/src/components/map/map.tsx +39 −38 Original line number Diff line number Diff line import { GoogleMap, Marker, useLoadScript } from "@react-google-maps/api"; import { useState, useMemo } from "react"; import { useState, Dispatch, SetStateAction, useEffect } from "react"; import { REACT_APP_GOOGLE_API_KEY } from "../../constants/api_keys"; import { LoadingScreen } from "../loading_screen/loading_screen"; import { UseFormSetValue } from "react-hook-form"; import { UseFormClearErrors, UseFormSetValue } from "react-hook-form"; import { Place } from "../../infraestructure/entities/place"; import { APIProvider, Map, Marker } from "@vis.gl/react-google-maps"; interface props{ setValue: UseFormSetValue<Place>; setIsLoading: Dispatch<SetStateAction<boolean>>; clearErrors: UseFormClearErrors<Place>; latitude?: number; longitude?: number; } export const MapComponent = ({setValue}: props) => { const {isLoaded} = useLoadScript({ googleMapsApiKey: REACT_APP_GOOGLE_API_KEY }); const [marker, setMarker] = useState(false); const [latitude, setLatitude] = useState(0.0); const [longitude, setLongitude] = useState(0.0); const updateMarker = (event: google.maps.MapMouseEvent) => { if (event.latLng) { setMarker(true); setLatitude(event.latLng.lat()); setLongitude(event.latLng.lng()); setValue("latitude", event.latLng.lat(), {shouldValidate: true}); setValue("longitude", event.latLng.lng(), {shouldValidate: true}); export interface Position{ latitude: number; longitude: number; } export const MapComponent = ({setValue, setIsLoading, latitude, longitude, clearErrors}: props) => { const [position, setPosition] = useState<Position>({latitude: 0.0, longitude: 0.0}); const center = {lat: 23.687, lng: -102.74}; useEffect(() => { if(latitude && longitude){ setPosition({latitude, longitude}); } }, [latitude]); const center = useMemo(() => ( {lat: 23.687, lng: -102.74} ),[]) useEffect(() => { setValue('latitude',position.latitude); setValue('longitude',position.longitude); clearErrors('latitude'); clearErrors('longitude'); },[position]); return ( <APIProvider apiKey={REACT_APP_GOOGLE_API_KEY} onLoad={() => setIsLoading(false)}> <div style={{width: '100%', height: '100%'}}> {!isLoaded ? <LoadingScreen/> : <GoogleMap center={center} zoom={8} mapContainerStyle={{height: '100%'}} onClick={updateMarker} > {marker && <Marker position={{lat: latitude, lng: longitude}}/>} </GoogleMap> } <Map defaultCenter={center} defaultZoom={8} gestureHandling={'greedy'} disableDefaultUI={true} onClick={(event)=> { const lat = event.detail.latLng?.lat || 0.0; const lng = event.detail.latLng?.lng || 0.0; setPosition({latitude: lat, longitude: lng}); }}> <Marker position={{lat: position.latitude, lng: position.longitude}}/> </Map> </div> </APIProvider> ); } No newline at end of file
web/src/components/multiple_images_dropzone/multiple_images_dropzone.tsx +3 −6 Original line number Diff line number Diff line Loading @@ -7,15 +7,16 @@ import { faTimesCircle } from "@fortawesome/free-solid-svg-icons"; interface props{ setValue: UseFormSetValue<Place>; imagesList?: File[] | string[]; } export const MultipleImagesDropzone = ({setValue}:props) => { export const MultipleImagesDropzone = ({setValue, imagesList}:props) => { const { getRootProps, getInputProps, imagesFiles, removeImage, } = useDropzoneMultiplesImages(setValue); } = useDropzoneMultiplesImages(setValue, imagesList); return ( <div className="multiple_images_dropzone_root"> Loading @@ -25,14 +26,10 @@ export const MultipleImagesDropzone = ({setValue}:props) => { </div> <div className="previews_list_cnt"> { imagesFiles && imagesFiles.map((image, index) => { return ( <div className="preview" key={index} onClick={() => { }} > <div className="preview_inner"> <img Loading