From 66baa4c4aba455f083d6e87ca34b5861e9cb54b3 Mon Sep 17 00:00:00 2001 From: Jmond544 Date: Sun, 23 Jun 2024 06:25:36 -0500 Subject: [PATCH 1/2] chore: Update dependencies and add API base URL --- .env | 1 + package-lock.json | 100 +++++++++++++++++++++++ package.json | 5 +- src/Components/ContainerNotification.jsx | 20 +++-- src/api/peticiones.api.js | 19 +++++ src/api/useAxios.js | 8 ++ src/class.jsx | 21 ++++- 7 files changed, 163 insertions(+), 11 deletions(-) create mode 100644 .env create mode 100644 src/api/peticiones.api.js create mode 100644 src/api/useAxios.js diff --git a/.env b/.env new file mode 100644 index 0000000..483b6bc --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_API=http://127.0.0.1:8000 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b448757..f993a79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend-alerta-rimac", "version": "0.0.0", "dependencies": { + "axios": "^1.7.2", "leaflet": "^1.9.4", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -1671,6 +1672,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.4.19", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", @@ -1725,6 +1732,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1933,6 +1951,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2106,6 +2136,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2851,6 +2890,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2878,6 +2937,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -3902,6 +3975,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4519,6 +4613,12 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index 9973231..0b40f98 100644 --- a/package.json +++ b/package.json @@ -10,14 +10,15 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.7.2", "leaflet": "^1.9.4", "react": "^18.3.1", "react-dom": "^18.3.1", - "socket.io-client": "^4.7.5", "react-leaflet": "^4.2.1", "react-leaflet-cluster": "^2.1.0", "react-router": "^6.23.1", - "react-router-dom": "^6.23.1" + "react-router-dom": "^6.23.1", + "socket.io-client": "^4.7.5" }, "devDependencies": { "@types/react": "^18.3.3", diff --git a/src/Components/ContainerNotification.jsx b/src/Components/ContainerNotification.jsx index ed3b4d8..46be1e0 100644 --- a/src/Components/ContainerNotification.jsx +++ b/src/Components/ContainerNotification.jsx @@ -2,9 +2,10 @@ import { useEffect, useState } from "react"; import { io } from "socket.io-client"; import Notification from "./Notification"; -const ContainerNotification = () => { - const [notification, setNotification] = useState(""); - const [date, setDate] = useState(new Date()); +const ContainerNotification = ({flag, setFlag}) => { + const [title, setTitle] = useState("Alerta RIMAC"); + const [description, setDescription] = useState(""); + const [date, setDate] = useState(""); const [statusNotification, setStatusNotification] = useState(false); useEffect(() => { @@ -12,8 +13,13 @@ const ContainerNotification = () => { socket.on("notification", (data) => { setStatusNotification(true); - setNotification(data?.message?.gemini_output); - setDate(new Date(data.date)); + setFlag(!flag); + setTitle(data?.evento?.tipo); + setDescription(data?.evento?.gemini_output); + + const diferenciaMilisegundos = new Date() - new Date(data.fecha); + const diferenciaMinutos = diferenciaMilisegundos / (1000 * 60); + setDate(diferenciaMinutos.toString()); console.log(data); // Establecer un temporizador para ocultar la notificación después de 3 segundos @@ -34,9 +40,9 @@ const ContainerNotification = () => { statusNotification ? "translate-y-0 opacity-100" : "-translate-y-full opacity-0" - } transition-all duration-500 absolute`} + } transition-all duration-500 absolute z-50`} > - + ); }; diff --git a/src/api/peticiones.api.js b/src/api/peticiones.api.js new file mode 100644 index 0000000..a2fa0a0 --- /dev/null +++ b/src/api/peticiones.api.js @@ -0,0 +1,19 @@ +import { instanseAxios } from "./useAxios.js"; + +export const getByStatus = async () => { + try { + const { data } = await instanseAxios.get(`/eventos/get_eventos_by_state`); + return data; + } catch (error) { + console.error(error); + } +}; + +export const getById = async (id) => { + try { + const { data } = await instanseAxios.get(`/eventos/get_evento/${id}`); + return data; + } catch (error) { + console.error(error); + } +}; \ No newline at end of file diff --git a/src/api/useAxios.js b/src/api/useAxios.js new file mode 100644 index 0000000..e6ddc96 --- /dev/null +++ b/src/api/useAxios.js @@ -0,0 +1,8 @@ +import axios from "axios"; + +export const instanseAxios = axios.create({ + baseURL: "http://127.0.0.1:8000", + headers: { + "Content-Type": "application/json", + }, +}); \ No newline at end of file diff --git a/src/class.jsx b/src/class.jsx index 1df90d6..a7a252b 100644 --- a/src/class.jsx +++ b/src/class.jsx @@ -6,12 +6,13 @@ import { createBrowserRouter, useLoaderData, } from "react-router-dom"; -import Notification from "./Components/Notification"; +import { getById, getByStatus } from "./api/peticiones.api"; import { useEffect, useState } from "react"; import Detalles from "./Components/Detalles"; import MapEvents from "./Components/MapEvents"; import Loading from "./Components/Loading"; import { useNavigate } from "react-router-dom"; +import ContainerNotification from "./Components/ContainerNotification"; const router = createBrowserRouter([ { @@ -30,7 +31,23 @@ const router = createBrowserRouter([ ]); export default function App() { - return ; + const [flag, setFlag] = useState(false); + const [eventos, setEventos] = useState([]); + useEffect(() => { + console.log("flag", flag); + const fetchData = async () => { + const result = await getById(1); + setEventos(result); + console.log(result); + }; + fetchData(); + }, [flag]); + return ( +
+ + ; +
+ ); } function Root() { From 6ece5b61ea878bc73b370571cbb6b7c9d96776b3 Mon Sep 17 00:00:00 2001 From: Jmond544 Date: Sun, 23 Jun 2024 11:51:47 -0500 Subject: [PATCH 2/2] End --- package-lock.json | 46 +++++++++++++++++++++-- package.json | 3 +- src/Components/ContainerNotification.jsx | 6 +-- src/Components/Detalles.jsx | 31 +++++++++------ src/Components/Evento.jsx | 26 ++++++++----- src/Components/Map.jsx | 26 +++++++++---- src/Components/MapEvents.jsx | 17 +++++++-- src/assets/alerta.png | Bin 0 -> 3850 bytes src/assets/placeholder.png | Bin 0 -> 13490 bytes src/class.jsx | 18 +++++++-- src/main.jsx | 2 - src/store/eventsData.js | 10 +++++ src/utils/dateFormater.js | 39 +++++++++++++++++++ 13 files changed, 176 insertions(+), 48 deletions(-) create mode 100644 src/assets/alerta.png create mode 100644 src/assets/placeholder.png create mode 100644 src/store/eventsData.js create mode 100644 src/utils/dateFormater.js diff --git a/package-lock.json b/package-lock.json index f993a79..b168b7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,8 @@ "react-leaflet-cluster": "^2.1.0", "react-router": "^6.23.1", "react-router-dom": "^6.23.1", - "socket.io-client": "^4.7.5" + "socket.io-client": "^4.7.5", + "zustand": "^4.5.2" }, "devDependencies": { "@types/react": "^18.3.3", @@ -1373,14 +1374,14 @@ "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -2019,7 +2020,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/data-view-buffer": { @@ -5676,6 +5677,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -6052,6 +6062,34 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.2.tgz", + "integrity": "sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 0b40f98..c47e1cc 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "react-leaflet-cluster": "^2.1.0", "react-router": "^6.23.1", "react-router-dom": "^6.23.1", - "socket.io-client": "^4.7.5" + "socket.io-client": "^4.7.5", + "zustand": "^4.5.2" }, "devDependencies": { "@types/react": "^18.3.3", diff --git a/src/Components/ContainerNotification.jsx b/src/Components/ContainerNotification.jsx index 46be1e0..b29ab99 100644 --- a/src/Components/ContainerNotification.jsx +++ b/src/Components/ContainerNotification.jsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import { io } from "socket.io-client"; import Notification from "./Notification"; +import dateFormater from "../utils/dateFormater"; const ContainerNotification = ({flag, setFlag}) => { const [title, setTitle] = useState("Alerta RIMAC"); @@ -16,10 +17,7 @@ const ContainerNotification = ({flag, setFlag}) => { setFlag(!flag); setTitle(data?.evento?.tipo); setDescription(data?.evento?.gemini_output); - - const diferenciaMilisegundos = new Date() - new Date(data.fecha); - const diferenciaMinutos = diferenciaMilisegundos / (1000 * 60); - setDate(diferenciaMinutos.toString()); + setDate(dateFormater(data?.evento?.fecha)); console.log(data); // Establecer un temporizador para ocultar la notificación después de 3 segundos diff --git a/src/Components/Detalles.jsx b/src/Components/Detalles.jsx index 8b4301b..5acf3da 100644 --- a/src/Components/Detalles.jsx +++ b/src/Components/Detalles.jsx @@ -1,27 +1,32 @@ -import Logo from "../assets/logoxd.png"; -import Maps from "../assets/logoxd.png"; import { NavLink } from "react-router-dom"; import "leaflet/dist/leaflet.css"; +import { useEffect } from "react"; +import useEventsStore from "../store/eventsData"; -import { MapContainer, TileLayer, Marker, Popup, Circle } from "react-leaflet"; -const Detalles = ({ evento }) => { + +const Detalles = () => { + const {events} = useEventsStore(); + useEffect(() => { + console.log(events, "eventos desde dettales"); + } + ,[events]); return ( <>
-
+

Evento

-

{evento && evento.description}

+

{events[0].tipo}

Fecha y Hora

-

{evento && evento.date}

+

{events[0].fecha}

-
+ {/*

Recomendaciones

-

{evento && evento.recomendaciones}

-
+

{"por programar"}

+
*/} {/*

Lugar

@@ -38,9 +43,11 @@ const Detalles = ({ evento }) => {
*/} - +
+

Todo va a estar bien

+
- diff --git a/src/Components/Evento.jsx b/src/Components/Evento.jsx index fd0cdc2..1083164 100644 --- a/src/Components/Evento.jsx +++ b/src/Components/Evento.jsx @@ -1,20 +1,26 @@ import React from "react"; -import Ambulancia from "../assets//IconsImages/Ambulancia.png"; -import { MapContainer, TileLayer, Marker, Popup, Circle } from "react-leaflet"; +import alerta from "../assets/alerta.png"; +import dateFormater from "../utils/dateFormater"; +import { NavLink } from "react-router-dom"; + const Evento = ({ evento }) => { return (
- {evento.tipo} + {evento.tipo}
-
-

{evento.titulo}

-

{evento.tiempo}

+
+

+ {evento.tipo.split(" ").slice(0, 2).join(" ")} +

+

{dateFormater(evento.fecha)}

-

{evento.descripcion}

- +

{evento.tipo}

+ + +
diff --git a/src/Components/Map.jsx b/src/Components/Map.jsx index cd8f8c8..f9d9cf0 100644 --- a/src/Components/Map.jsx +++ b/src/Components/Map.jsx @@ -13,6 +13,14 @@ import EventosEspeciales from "../assets/IconsImages/EventosEspeciales.png"; import MaterialesPeligrosos from "../assets/IconsImages/MaterialesPeligrosos.png"; import Sismo from "../assets/IconsImages/Sismo.png"; import { NavLink, useNavigate } from "react-router-dom"; +import useEventsStore from "../store/eventsData"; + +const customIcon = new Icon({ + // iconUrl: "https://cdn-icons-png.flaticon.com/512/447/447031.png", + iconUrl: "https://cdn-icons-png.flaticon.com/512/447/447031.png", + iconSize: [38, 38], // size of the icon +}); +/* const customAbulanciaIcon = new Icon({ iconUrl: ambulanceIcon, @@ -42,7 +50,8 @@ const customSismoIcon = new Icon({ iconUrl: Sismo, iconSize: [38, 38], // size of the icon }); - +*/ +/* let markers = [ { geocode: [-12.092918, -77.025284], @@ -62,7 +71,7 @@ let markers = [ type: customSismoIcon, id: 3, }, -]; +];*/ const createClusterCustomIcon = function (cluster) { return new divIcon({ html: `${cluster.getChildCount()}`, @@ -73,8 +82,11 @@ const createClusterCustomIcon = function (cluster) { const Map = ({ latitud, longitud, eventosMapa }) => { const position = [latitud, longitud]; + const { events } = useEventsStore(); const navigate = useNavigate(); - + useEffect(() => { + console.log(events, "eventos desde map"); + }, [events]); return (
@@ -92,16 +104,16 @@ const Map = ({ latitud, longitud, eventosMapa }) => { iconCreateFunction={createClusterCustomIcon} > {/*{ lat: marker.latitud, lng: marker.longitud } */} - {eventosMapa && - markers.map((marker) => ( + {events && + events.map((marker) => ( - Ver más + Ver más diff --git a/src/Components/MapEvents.jsx b/src/Components/MapEvents.jsx index f702fa3..20672e6 100644 --- a/src/Components/MapEvents.jsx +++ b/src/Components/MapEvents.jsx @@ -1,13 +1,22 @@ -import React from "react"; +import React, { useEffect } from "react"; import "leaflet/dist/leaflet.css"; import Map from "./Map"; import Evento from "./Evento"; +import useEventsStore from "../store/eventsData"; + + const MapEvents = ({ latitud, longitud, eventos }) => { + const {events} = useEventsStore(); + useEffect(() => { + console.log(events, "eventos desde eventDetails"); + } + ,[events]); + return (
- - {eventos && - eventos.map((evento) => )} + + {events && + events.map((evento) => )}
); }; diff --git a/src/assets/alerta.png b/src/assets/alerta.png new file mode 100644 index 0000000000000000000000000000000000000000..7980e1a056808b59c01563de3828b947c2b20bf0 GIT binary patch literal 3850 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 literal 0 HcmV?d00001 diff --git a/src/class.jsx b/src/class.jsx index a7a252b..b818169 100644 --- a/src/class.jsx +++ b/src/class.jsx @@ -13,6 +13,7 @@ import MapEvents from "./Components/MapEvents"; import Loading from "./Components/Loading"; import { useNavigate } from "react-router-dom"; import ContainerNotification from "./Components/ContainerNotification"; +import useEventsStore from "./store/eventsData"; const router = createBrowserRouter([ { @@ -32,14 +33,23 @@ const router = createBrowserRouter([ export default function App() { const [flag, setFlag] = useState(false); - const [eventos, setEventos] = useState([]); + const { events, addEvent } = useEventsStore(); useEffect(() => { console.log("flag", flag); const fetchData = async () => { - const result = await getById(1); - setEventos(result); - console.log(result); + if (events[0]!=undefined) { + const result = await getById(events[events.lenght - 1].id+1); + console.log(result); + addEvent(result); + console.log(events, "eventos"); + } else { + const result = await getById(100); + console.log(result); + addEvent(result); + console.log(events, "eventos"); + } }; + fetchData(); }, [flag]); return ( diff --git a/src/main.jsx b/src/main.jsx index 6e83fd9..ffbdf84 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -4,7 +4,5 @@ import "./index.css"; import App from "./class"; ReactDOM.createRoot(document.getElementById("root")).render( - - ); diff --git a/src/store/eventsData.js b/src/store/eventsData.js new file mode 100644 index 0000000..4d2fa1c --- /dev/null +++ b/src/store/eventsData.js @@ -0,0 +1,10 @@ +import { create } from "zustand"; + +const useEventsStore = create((set) => ({ + events: [], + addEvent: (newEvent) => set((state) => ({ + events: [...state.events, newEvent] + })), + })); + + export default useEventsStore; \ No newline at end of file diff --git a/src/utils/dateFormater.js b/src/utils/dateFormater.js new file mode 100644 index 0000000..50fefc2 --- /dev/null +++ b/src/utils/dateFormater.js @@ -0,0 +1,39 @@ +export default function tiempoTranscurrido(fechaString) { + // Parsear el string de fecha en un objeto Date + const fecha = new Date(fechaString); + const ahora = new Date(); + + // Calcular la diferencia en milisegundos + const diferencia = ahora - fecha; + + // Definir los milisegundos en una unidad de tiempo + const unSegundo = 1000; + const unMinuto = unSegundo * 60; + const unaHora = unMinuto * 60; + const unDia = unaHora * 24; + const unaSemana = unDia * 7; + const unMes = unDia * 30; + const unAno = unDia * 365; + + if (diferencia < unMinuto) { + return "Hace un momento"; + } else if (diferencia < unaHora) { + const minutos = Math.floor(diferencia / unMinuto); + return `Hace ${minutos} ${minutos === 1 ? 'minuto' : 'minutos'}`; + } else if (diferencia < unDia) { + const horas = Math.floor(diferencia / unaHora); + return `Hace ${horas} ${horas === 1 ? 'hora' : 'horas'}`; + } else if (diferencia < unaSemana) { + const dias = Math.floor(diferencia / unDia); + return `Hace ${dias} ${dias === 1 ? 'día' : 'días'}`; + } else if (diferencia < unMes) { + const semanas = Math.floor(diferencia / unaSemana); + return `Hace ${semanas} ${semanas === 1 ? 'semana' : 'semanas'}`; + } else if (diferencia < unAno) { + const meses = Math.floor(diferencia / unMes); + return `Hace ${meses} ${meses === 1 ? 'mes' : 'meses'}`; + } else { + const anos = Math.floor(diferencia / unAno); + return `Hace ${anos} ${anos === 1 ? 'año' : 'años'}`; + } +} \ No newline at end of file