From 1ca03273c126a6065c7c19be8f47590b26118804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20Luna=20Hern=C3=A1ndez?= <42101656@uaz.edu.mx> Date: Wed, 6 Nov 2024 12:14:39 -0600 Subject: [PATCH 1/7] Se crea un componente de un interruptor y sus estilos --- .../components/switch/assets/css/styles.css | 62 +++++++++++++++++++ .../presentation/components/switch/switch.tsx | 14 +++++ 2 files changed, 76 insertions(+) create mode 100644 web/src/presentation/components/switch/assets/css/styles.css create mode 100644 web/src/presentation/components/switch/switch.tsx diff --git a/web/src/presentation/components/switch/assets/css/styles.css b/web/src/presentation/components/switch/assets/css/styles.css new file mode 100644 index 00000000..86369a45 --- /dev/null +++ b/web/src/presentation/components/switch/assets/css/styles.css @@ -0,0 +1,62 @@ +/* The switch - the box around the slider */ +.switch { + position: relative; + display: inline-block; + width: 40px; /* 60px * 2/3 */ + height: 22.67px; /* 34px * 2/3 */ +} + +/* Hide default HTML checkbox */ +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* The slider */ +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + -webkit-transition: 0.4s; + transition: 0.4s; +} + +.slider:before { + position: absolute; + content: ""; + height: 17.33px; /* 26px * 2/3 */ + width: 17.33px; /* 26px * 2/3 */ + left: 2.67px; /* 4px * 2/3 */ + bottom: 2.67px; /* 4px * 2/3 */ + background-color: white; + -webkit-transition: 0.4s; + transition: 0.4s; +} + +input:checked + .slider { + background-color: #2196f3; +} + +input:focus + .slider { + box-shadow: 0 0 1px #2196f3; +} + +input:checked + .slider:before { + -webkit-transform: translateX(17.33px); /* 26px * 2/3 */ + -ms-transform: translateX(17.33px); /* 26px * 2/3 */ + transform: translateX(17.33px); /* 26px * 2/3 */ +} + +/* Rounded sliders */ +.slider.round { + border-radius: 22.67px; /* 34px * 2/3 */ +} + +.slider.round:before { + border-radius: 50%; +} diff --git a/web/src/presentation/components/switch/switch.tsx b/web/src/presentation/components/switch/switch.tsx new file mode 100644 index 00000000..457ce591 --- /dev/null +++ b/web/src/presentation/components/switch/switch.tsx @@ -0,0 +1,14 @@ +import "./assets/css/styles.css"; + +interface Props { + onClick?: () => void; +} + +export const Swicth = ({ onClick }: Props) => { + return ( + + ); +}; -- GitLab From 3ef6f5db0a34c6082723858f0ab3a40c961a13cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Omar=20Luna=20Hern=C3=A1ndez?= <42101656@uaz.edu.mx> Date: Wed, 6 Nov 2024 13:04:45 -0600 Subject: [PATCH 2/7] Se modifica para que las direcciones hacia el siguiente punto puedan ser null --- .../dto/create-pointAndTraduction.dto.ts | 4 +- .../dto/create-pointTrad.dto.ts | 2 +- .../src/pointOfInterest/dto/getPoint.dto.ts | 2 +- .../pointOfInterest/dto/printPointInfo.dto.ts | 2 +- web/src/data/datasource/api/entities/poi.ts | 4 +- web/src/data/datasource/api/poi_datasource.ts | 6 +- web/src/domain/model/POIModel.ts | 2 +- web/src/domain/useCase/usePointOfInterest.ts | 186 +++++++++--------- .../admin_panel_poi_register.tsx | 117 ++++++----- .../admin_panel_poi_viewer.tsx | 91 ++++----- 10 files changed, 223 insertions(+), 193 deletions(-) diff --git a/backend/src/pointOfInterest/dto/create-pointAndTraduction.dto.ts b/backend/src/pointOfInterest/dto/create-pointAndTraduction.dto.ts index 1c77b9e5..dc58fa5b 100644 --- a/backend/src/pointOfInterest/dto/create-pointAndTraduction.dto.ts +++ b/backend/src/pointOfInterest/dto/create-pointAndTraduction.dto.ts @@ -12,7 +12,7 @@ export class CreatePointAndTradDto { @ApiProperty() contentES: string; @ApiProperty() - directionsEN: string; + directionsEN?: string; @ApiProperty() - directionsES: string; + directionsES?: string; } diff --git a/backend/src/pointOfInterest/dto/create-pointTrad.dto.ts b/backend/src/pointOfInterest/dto/create-pointTrad.dto.ts index 6c4a0dcd..9998e907 100644 --- a/backend/src/pointOfInterest/dto/create-pointTrad.dto.ts +++ b/backend/src/pointOfInterest/dto/create-pointTrad.dto.ts @@ -4,6 +4,6 @@ export class CreatePointTradDto { language: LANGUAGES; idPoint: number; content: string; - directions: string; + directions?: string; audioName: string; } diff --git a/backend/src/pointOfInterest/dto/getPoint.dto.ts b/backend/src/pointOfInterest/dto/getPoint.dto.ts index 2a826ef0..352b3e56 100644 --- a/backend/src/pointOfInterest/dto/getPoint.dto.ts +++ b/backend/src/pointOfInterest/dto/getPoint.dto.ts @@ -4,5 +4,5 @@ export class getPointDto { name: string; imageName: string; content: string; - directions: string; + directions?: string; } diff --git a/backend/src/pointOfInterest/dto/printPointInfo.dto.ts b/backend/src/pointOfInterest/dto/printPointInfo.dto.ts index 20696a29..19d91673 100644 --- a/backend/src/pointOfInterest/dto/printPointInfo.dto.ts +++ b/backend/src/pointOfInterest/dto/printPointInfo.dto.ts @@ -2,4 +2,4 @@ export class printPointInfo { idPoint: number; namePlace: string; name: string; -} \ No newline at end of file +} diff --git a/web/src/data/datasource/api/entities/poi.ts b/web/src/data/datasource/api/entities/poi.ts index ad5936a3..8227265a 100644 --- a/web/src/data/datasource/api/entities/poi.ts +++ b/web/src/data/datasource/api/entities/poi.ts @@ -8,8 +8,8 @@ export interface PointOfInterest { image: File | string; contentEN: string; contentES: string; - directionsEN: string; - directionsES: string; + directionsEN?: string; + directionsES?: string; } /** diff --git a/web/src/data/datasource/api/poi_datasource.ts b/web/src/data/datasource/api/poi_datasource.ts index 206f5c92..4e26660e 100644 --- a/web/src/data/datasource/api/poi_datasource.ts +++ b/web/src/data/datasource/api/poi_datasource.ts @@ -22,8 +22,10 @@ export class POIDatasourceProd implements PoiDatasourceInf { formToSend.append("image", form.image); formToSend.append("contentEN", form.contentEN); formToSend.append("contentES", form.contentES); - formToSend.append("directionsEN", form.directionsEN); - formToSend.append("directionsES", form.directionsES); + if (form.directionsEN && form.directionsES) { + formToSend.append("directionsEN", form.directionsEN); + formToSend.append("directionsES", form.directionsES); + } const headers = { "Content-Type": "multipart/form-data", diff --git a/web/src/domain/model/POIModel.ts b/web/src/domain/model/POIModel.ts index 72d14080..c8bf2ac2 100644 --- a/web/src/domain/model/POIModel.ts +++ b/web/src/domain/model/POIModel.ts @@ -15,7 +15,7 @@ export interface POIModel { /** Content description of the point of interest */ content: string; /** Directions to the point of interest */ - directions: string; + directions?: string; } /** diff --git a/web/src/domain/useCase/usePointOfInterest.ts b/web/src/domain/useCase/usePointOfInterest.ts index 656e827a..2104b533 100644 --- a/web/src/domain/useCase/usePointOfInterest.ts +++ b/web/src/domain/useCase/usePointOfInterest.ts @@ -13,102 +13,110 @@ import { showErrorAxios } from "../../core/utils/Messages"; const POIDatasouce = new POIDatasourceProd(); const POIRepository = new POIRepositoryProd(POIDatasouce); -// Define resolver for form validation -const resolver: Resolver = async (data) => { - const errors: FieldErrors = {}; - - // Validate idPlace - if (!data.idPlace) { - errors.idPlace = { - type: "required", - message: "Debe seleccionar el lugar al que pertenece el punto de interés", - }; - } +// Custom hook for point of interest functionality +export const usePointOfInterest = ( + forceRenderList?: () => void, + setIsWindowActive?: (visibility: boolean) => void +) => { + const [isLastPoint, setIsLastPoint] = useState(false); - // Validate name - if (!data.name) { - errors.name = { - type: "required", - message: "El nombre del punto de interés es requerido", - }; - } else if (data.name.length > 255) { - errors.name = { - type: "maxLength", - message: "El tamaño no debe sobrepasar los 255 caracteres", - }; - } + // Define resolver for form validation + const resolver: Resolver = async (data) => { + const errors: FieldErrors = {}; - // Validate content in English - if (!data.contentEN) { - errors.contentEN = { - type: "required", - message: "La descripción del punto de interés en inglés es requerida", - }; - } else if (data.contentEN.length > 1024) { - errors.contentEN = { - type: "maxLength", - message: "El tamaño no debe sobrepasar los 1024 caracteres", - }; - } + // Validate idPlace + if (!data.idPlace) { + errors.idPlace = { + type: "required", + message: + "Debe seleccionar el lugar al que pertenece el punto de interés", + }; + } - // Validate content in Spanish - if (!data.contentES) { - errors.contentES = { - type: "required", - message: "La descripción del punto de interés en español es requerida", - }; - } else if (data.contentES.length > 1024) { - errors.contentES = { - type: "maxLength", - message: "El tamaño no debe sobrepasar los 1024 caracteres", - }; - } + // Validate name + if (!data.name) { + errors.name = { + type: "required", + message: "El nombre del punto de interés es requerido", + }; + } else if (data.name.length > 255) { + errors.name = { + type: "maxLength", + message: "El tamaño no debe sobrepasar los 255 caracteres", + }; + } - // Validate directions in English - if (!data.directionsEN) { - errors.directionsEN = { - type: "required", - message: "Las direcciones del punto de interés en inglés son requeridas", - }; - } else if (data.directionsEN.length > 1024) { - errors.directionsEN = { - type: "maxLength", - message: "El tamaño no debe sobrepasar los 1024 caracteres", - }; - } + // Validate content in English + if (!data.contentEN) { + errors.contentEN = { + type: "required", + message: "La descripción del punto de interés en inglés es requerida", + }; + } else if (data.contentEN.length > 1024) { + errors.contentEN = { + type: "maxLength", + message: "El tamaño no debe sobrepasar los 1024 caracteres", + }; + } - // Validate directions in Spanish - if (!data.directionsES) { - errors.directionsES = { - type: "required", - message: "Las direcciones del punto de interés en español son requeridas", - }; - } else if (data.directionsES.length > 1024) { - errors.directionsES = { - type: "maxLength", - message: "El tamaño no debe sobrepasar los 1024 caracteres", - }; - } + // Validate content in Spanish + if (!data.contentES) { + errors.contentES = { + type: "required", + message: "La descripción del punto de interés en español es requerida", + }; + } else if (data.contentES.length > 1024) { + errors.contentES = { + type: "maxLength", + message: "El tamaño no debe sobrepasar los 1024 caracteres", + }; + } - // Validate image - if (!data.image) { - errors.image = { - type: "required", - message: "Debe de haber al menos 1 imagen representativa del lugar", - }; - } + // Validate directions in English + if (!isLastPoint) { + if (!data.directionsEN) { + errors.directionsEN = { + type: "required", + message: + "Las direcciones del punto de interés en inglés son requeridas", + }; + } else if (data.directionsEN.length > 1024) { + errors.directionsEN = { + type: "maxLength", + message: "El tamaño no debe sobrepasar los 1024 caracteres", + }; + } + } - return { - values: Object.keys(errors).length > 0 ? {} : data, - errors: errors, - }; -}; + // Validate directions in Spanish + if (!isLastPoint) { + if (!data.directionsES) { + errors.directionsES = { + type: "required", + message: + "Las direcciones del punto de interés en español son requeridas", + }; + } else if (data.directionsES.length > 1024) { + errors.directionsES = { + type: "maxLength", + message: "El tamaño no debe sobrepasar los 1024 caracteres", + }; + } + } -// Custom hook for point of interest functionality -export const usePointOfInterest = ( - forceRenderList?: () => void, - setIsWindowActive?: (visibility: boolean) => void -) => { + // Validate image + if (!data.image) { + errors.image = { + type: "required", + message: "Debe de haber al menos 1 imagen representativa del lugar", + }; + } + + return { + values: Object.keys(errors).length > 0 ? {} : data, + errors: errors, + }; + }; const { register, handleSubmit, @@ -242,5 +250,7 @@ export const usePointOfInterest = ( getPointById, updatePOIByPlace, getPdfById, + isLastPoint, + setIsLastPoint, }; }; diff --git a/web/src/presentation/admin/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx b/web/src/presentation/admin/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx index 5c490a4b..9672eb53 100644 --- a/web/src/presentation/admin/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx +++ b/web/src/presentation/admin/admin_panel_poi/admin_panel_poi_register/admin_panel_poi_register.tsx @@ -9,6 +9,7 @@ import { PointOfInterest } from "../../../../data/datasource/api/entities/poi"; import { usePlace } from "../../../../domain/useCase/usePlace"; import { usePointOfInterest } from "../../../../domain/useCase/usePointOfInterest"; import { LoadingScreen } from "../../../components/loading_screen/loading_screen"; +import { Swicth } from "../../../components/switch/switch"; // Define the props interface for the component interface props { @@ -43,6 +44,8 @@ export const AdminPanelPoiRegister = ({ languageDescriptionIndexSelected, languageDirectionsIndexSelected, setLanguageDirectionsIndexSelected, + isLastPoint, + setIsLastPoint, } = usePointOfInterest(forceRenderList, setWindowVisibility); // State variables for loading, image preview, and image file @@ -169,58 +172,70 @@ export const AdminPanelPoiRegister = ({
- Direcciones hacia el siguiente punto de interés - + setLanguageDirectionsIndexSelected( + Number(e.target.value) + ) + } + > + {languaguesList.map((language, index) => { + return ( + + ); + })} + +
+ {languaguesList.map((language, index) => { + if (index === languageDirectionsIndexSelected) { return ( - +