diff --git a/src/app/auth/page.js b/src/app/auth/page.js
index 5397547f..8179d575 100644
--- a/src/app/auth/page.js
+++ b/src/app/auth/page.js
@@ -6,11 +6,11 @@ import { authService } from '@/lib/service';
export default function AuthPage() {
const router = useRouter();
-
+
useEffect(() => {
async function fetchSession() {
const { data: session } = await authService.getSessionUser();
- if (session.user) {
+ if (session.user) {
router.push('/');
}
}
diff --git a/src/app/casos-activos/solicitudes/page.js b/src/app/casos-activos/solicitudes/page.js
index 23379005..c1f78bdf 100644
--- a/src/app/casos-activos/solicitudes/page.js
+++ b/src/app/casos-activos/solicitudes/page.js
@@ -10,7 +10,9 @@ import { useRouter, useSearchParams } from 'next/navigation';
import { tiposAyudaOptions } from '@/helpers/constants';
import Modal from '@/components/Modal';
import { useModal } from '@/context/EmergencyProvider';
-import { useTowns } from '../../../context/TownProvider';
+import { useTowns } from '@/context/TownProvider';
+
+const MODAL_NAME = 'solicitudes';
export default function Solicitudes() {
const towns = useTowns();
@@ -23,10 +25,10 @@ export default function Solicitudes() {
const [data, setData] = useState([]);
const [currentPage, setCurrentPage] = useState(Number(searchParams.get('page')) || 1);
const [currentCount, setCurrentCount] = useState(0);
- const { showModal, toggleModal } = useModal();
+ const { toggleModal } = useModal();
const closeModal = () => {
- toggleModal(false);
+ toggleModal(MODAL_NAME, false);
};
const itemsPerPage = 10;
const numPages = (count) => {
@@ -172,12 +174,15 @@ export default function Solicitudes() {
) : (
@@ -187,11 +192,14 @@ export default function Solicitudes() {
- {showModal && (
-
-
-
- )}
+
+
+ town.id === Number(filtroData.pueblo))?.name}
+ onClose={closeModal}
+ isModal={true}
+ />
+
>
);
}
diff --git a/src/app/voluntometro/page.js b/src/app/voluntometro/page.js
index 1568a427..b9b228fd 100644
--- a/src/app/voluntometro/page.js
+++ b/src/app/voluntometro/page.js
@@ -1,7 +1,5 @@
import { supabase } from '@/lib/supabase/client';
import { HeartHandshake, Search, Thermometer } from 'lucide-react';
-import OfferHelp from '@/components/OfferHelp';
-import Modal from '@/components/Modal';
import TownCardInfo from '@/components/TownCardInfo';
const getCount = async () => {
@@ -39,7 +37,6 @@ const getCount = async () => {
ofertas: ofreceCount || 0,
};
};
-
const getVolunteers = async () => {
const today = new Date().toISOString().split('T')[0];
@@ -87,7 +84,7 @@ const getVolunteers = async () => {
export default async function Voluntometro() {
const pueblos = await getVolunteers();
const count = await getCount();
- console.log(pueblos.ofertasButton);
+
const getFechaHoy = () => {
const fecha = new Date();
return fecha.toLocaleDateString('es-ES', {
@@ -96,6 +93,7 @@ export default async function Voluntometro() {
year: 'numeric',
});
};
+
const getTopAndBottomPueblos = () => {
const sortedPueblos = [...pueblos].sort((a, b) => {
const volunteersDiffA = a.count - a.needHelp;
diff --git a/src/components/AsignarSolicitudButton.tsx b/src/components/AsignarSolicitudButton.tsx
index c12b4935..38da6778 100644
--- a/src/components/AsignarSolicitudButton.tsx
+++ b/src/components/AsignarSolicitudButton.tsx
@@ -8,14 +8,19 @@ import { Spinner } from '@/components/Spinner';
import Link from 'next/link';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
+import Modal from '@/components/Modal';
+import { useModal } from '@/context/EmergencyProvider';
type AsignarSolicitudButtonProps = {
helpRequest: HelpRequestData;
};
export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitudButtonProps) {
+ const { toggleModal } = useModal();
const session = useSession();
+ const MODAL_NAME = `Solicitud-${helpRequest.id}`;
+
const {
data: assignments,
isLoading,
@@ -60,10 +65,15 @@ export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitud
},
});
- async function handleSubmit(e: MouseEvent) {
+ async function handleAcceptanceSubmit(e: MouseEvent) {
e.preventDefault();
+ toggleModal(MODAL_NAME, false);
assignMutation.mutate();
}
+ async function handleSubmit(e: MouseEvent) {
+ e.preventDefault();
+ toggleModal(MODAL_NAME, true);
+ }
async function handleCancel(e: MouseEvent) {
e.preventDefault();
unassignMutation.mutate();
@@ -105,6 +115,26 @@ export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitud
Quiero ayudar
)}
+
+
+
Quiero ayudar
+
¿Te comprometes a atender esta solicitud?
+
+
+
+
+
+
>
);
}
diff --git a/src/components/CookieBanner/CookieBanner.tsx b/src/components/CookieBanner/CookieBanner.tsx
new file mode 100644
index 00000000..d99de933
--- /dev/null
+++ b/src/components/CookieBanner/CookieBanner.tsx
@@ -0,0 +1,77 @@
+'use client';
+
+import { FC, useEffect, useState } from 'react';
+import Modal from '@/components/Modal';
+import { useModal } from '@/context/EmergencyProvider';
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+
+const MODAL_NAME = 'cookie-banner';
+const POLICY_URL = '/politica-privacidad';
+const COOKIE_CONSENT_KEY = 'ajudaDanaCookieConsentAccepted';
+
+const CookieBanner: FC = () => {
+ const { toggleModal } = useModal();
+ const pathname = usePathname();
+ const [hasConsent, setHasConsent] = useState(false);
+
+ useEffect(() => {
+ // Check for consent in localStorage when the component mounts
+ const consent = localStorage.getItem(COOKIE_CONSENT_KEY);
+ setHasConsent(Boolean(consent));
+ }, []);
+
+ const handleAcceptCookies = () => {
+ // Set consent in localStorage and close the modal
+ localStorage.setItem(COOKIE_CONSENT_KEY, 'true');
+ setHasConsent(true);
+ toggleModal(MODAL_NAME, false);
+ };
+
+ const handleRejectCookies = () => {
+ // Redirect to Google if cookies are rejected
+ window.location.href = 'https://www.google.com';
+ };
+
+ useEffect(() => {
+ // Show the modal only if consent is not given and we're not on the policy page
+ if (!hasConsent && pathname !== POLICY_URL) {
+ toggleModal(MODAL_NAME, true);
+ } else {
+ toggleModal(MODAL_NAME, false);
+ }
+ }, [hasConsent, pathname]);
+
+ if (hasConsent) return null; // Do not render the modal if consent is already given
+
+ return (
+
+
+
Política de Cookies
+
+ Usamos cookies para mejorar su experiencia. Al aceptar, usted está de acuerdo con nuestra{' '}
+
+ política de cookies
+
+ .
+
+
+
+
+
+
+
+ );
+};
+
+export default CookieBanner;
diff --git a/src/components/Modal.js b/src/components/Modal.tsx
similarity index 53%
rename from src/components/Modal.js
rename to src/components/Modal.tsx
index 10b6ae89..e7b8950e 100644
--- a/src/components/Modal.js
+++ b/src/components/Modal.tsx
@@ -1,13 +1,39 @@
import { useModal } from '@/context/EmergencyProvider';
+import { MouseEvent, FC, ReactNode } from 'react';
-export const Modal = ({ children, maxWidth = 'max-w-2xl', allowClose = true }) => {
- const { showModal, toggleModal } = useModal();
+type TailwindMaxWidth =
+ | 'max-w-xs'
+ | 'max-w-sm'
+ | 'max-w-md'
+ | 'max-w-lg'
+ | 'max-w-xl'
+ | 'max-w-2xl'
+ | 'max-w-3xl'
+ | 'max-w-4xl'
+ | 'max-w-5xl'
+ | 'max-w-6xl'
+ | 'max-w-7xl'
+ | 'max-w-full'
+ | 'max-w-screen-sm'
+ | 'max-w-screen-md'
+ | 'max-w-screen-lg'
+ | 'max-w-screen-xl'
+ | 'max-w-screen-2xl';
- if (!showModal) return null;
+type ModalProps = {
+ id: string;
+ children: ReactNode;
+ maxWidth?: TailwindMaxWidth;
+ allowClose?: boolean;
+};
+
+const Modal: FC = ({ id, children, maxWidth = 'max-w-2xl', allowClose = true }) => {
+ const { isModalOpen, toggleModal } = useModal();
+ if (!isModalOpen[id]) return null;
- const handleBackdropClick = (e) => {
+ const handleBackdropClick = (e: MouseEvent) => {
if (allowClose && e.target === e.currentTarget) {
- toggleModal();
+ toggleModal(id);
}
};
@@ -19,7 +45,7 @@ export const Modal = ({ children, maxWidth = 'max-w-2xl', allowClose = true }) =
{allowClose && (
+ {/* Política de privacidad */}
+ {!isPrivacyAccepted && (
+
+
+
setFormData({ ...formData, privacyPolicy: e.target.checked })}
+ className="min-w-4 min-h-4 cursor-pointer"
+ id="privacyPolicy"
+ required
+ />
+
+
+
+ )}
{
const [phoneNumber, setPhoneNumber] = useState('');
@@ -79,7 +81,7 @@ const PhoneNumberDialog = () => {
if (metadata.telefono) {
return;
}
- toggleModal();
+ toggleModal(MODAL_NAME);
};
fetchNumber();
@@ -103,11 +105,11 @@ const PhoneNumberDialog = () => {
throw new Error('Error a la hora de actualizar el usuario con un numero de telefono');
}
- toggleModal();
+ toggleModal(MODAL_NAME);
}, []);
return (
-
+
);
diff --git a/src/components/layout/EmergencyLayout.tsx b/src/components/layout/EmergencyLayout.tsx
index 2d883b06..e835ee10 100644
--- a/src/components/layout/EmergencyLayout.tsx
+++ b/src/components/layout/EmergencyLayout.tsx
@@ -4,6 +4,7 @@ import { useState, useEffect, PropsWithChildren } from 'react';
// @ts-ignore
import Sidebar from './Sidebar';
import Footer from './Footer';
+import CookieBanner from '@/components/CookieBanner/CookieBanner';
export default function EmergencyLayout({ children }: PropsWithChildren) {
const [isSidebarOpen, setIsSidebarOpen] = useState(true); // Por defecto abierto
@@ -33,6 +34,7 @@ export default function EmergencyLayout({ children }: PropsWithChildren) {
{children}
+
);
diff --git a/src/components/map/map.tsx b/src/components/map/map.tsx
index c121fa78..956a2ba3 100644
--- a/src/components/map/map.tsx
+++ b/src/components/map/map.tsx
@@ -5,10 +5,11 @@ import ReactMap from 'react-map-gl/maplibre';
import 'maplibre-gl/dist/maplibre-gl.css';
import { Marker } from 'react-map-gl/maplibre';
import { useModal } from '@/context/EmergencyProvider';
-// @ts-ignore
import Modal from '@/components/Modal';
import { MapPinFilled } from '@/components/icons/MapPinFilled';
+const MODAL_NAME = `map-marker`;
+
const urgencyToColor = {
alta: 'text-red-500',
media: 'text-amber-500',
@@ -34,7 +35,7 @@ const DEFAULT_ZOOM = 12;
const Map: FC = ({ markers = [] }) => {
const [selectedMarker, setSelectedMarker] = useState(null);
- const { showModal, toggleModal } = useModal();
+ const { toggleModal } = useModal();
console.log(selectedMarker);
return (
@@ -50,11 +51,11 @@ const Map: FC = ({ markers = [] }) => {
{markers.map((m) => {
return (
{
- toggleModal(true);
+ toggleModal(MODAL_NAME, true);
setSelectedMarker(m);
}}
anchor="bottom"
@@ -63,7 +64,7 @@ const Map: FC = ({ markers = [] }) => {
);
})}
- {selectedMarker && showModal && {selectedMarker.popup}}
+ {selectedMarker && {selectedMarker.popup}}
);
};
diff --git a/src/context/EmergencyProvider.tsx b/src/context/EmergencyProvider.tsx
index fcd02baa..76a109fe 100644
--- a/src/context/EmergencyProvider.tsx
+++ b/src/context/EmergencyProvider.tsx
@@ -1,24 +1,32 @@
'use client';
-import React, { createContext, ReactNode, useContext, useState } from 'react';
+import React, { createContext, FC, ReactNode, useContext, useState } from 'react';
-const EmergencyContext = createContext({ showModal: false, toggleModal: () => {} });
-
-type EmergencyCtx = {
- showModal: boolean;
- toggleModal: (force: boolean) => void;
+type EmergencyContextType = {
+ isModalOpen: { [key: string]: boolean };
+ toggleModal: (id: string, force?: boolean) => void;
};
-type SessionProviderProps = {
+const EmergencyContext = createContext({
+ isModalOpen: {},
+ toggleModal: () => {},
+});
+
+type EmergencyProviderProps = {
children: ReactNode;
};
-export const EmergencyProvider: React.FC = ({ children }) => {
- const [showModal, setShowModal] = useState(false);
+export const EmergencyProvider: FC = ({ children }) => {
+ const [isModalOpen, setIsModalOpen] = useState<{ [key: string]: boolean }>({});
- const toggleModal = (force: boolean) => setShowModal((prev) => (force !== undefined ? force : !prev));
+ const toggleModal = (id: string, force?: boolean) => {
+ setIsModalOpen((prev) => ({
+ ...prev,
+ [id]: force !== undefined ? force : !prev[id],
+ }));
+ };
- return {children};
+ return {children};
};
export const useModal = () => {