Skip to content

Commit

Permalink
Merge pull request #115 from MartinGerritsen/feature/cookie-consent
Browse files Browse the repository at this point in the history
Feature/cookie consent
  • Loading branch information
patrickwebsdev authored Nov 7, 2024
2 parents 194cca8 + a9ba936 commit aed9285
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 42 deletions.
27 changes: 14 additions & 13 deletions src/app/casos-activos/solicitudes/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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) => {
Expand Down Expand Up @@ -172,7 +174,7 @@ export default function Solicitudes() {

<button
onClick={() => {
toggleModal(true);
toggleModal(MODAL_NAME, true);
}}
className="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600 flex items-center gap-2 whitespace-nowrap"
>
Expand All @@ -190,15 +192,14 @@ export default function Solicitudes() {
<div className="flex items-center justify-center">
<Pagination currentPage={currentPage} totalPages={numPages(currentCount)} onPageChange={changePage} />
</div>
{showModal && (
<Modal>
<OfferHelp
town={towns.find((town) => town.id === Number(filtroData.pueblo))?.name}
onClose={closeModal}
isModal={true}
/>
</Modal>
)}

<Modal id={MODAL_NAME}>
<OfferHelp
town={towns.find((town) => town.id === Number(filtroData.pueblo))?.name}
onClose={closeModal}
isModal={true}
/>
</Modal>
</>
);
}
6 changes: 2 additions & 4 deletions src/app/voluntometro/page.js
Original file line number Diff line number Diff line change
@@ -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 () => {
Expand Down Expand Up @@ -39,7 +37,6 @@ const getCount = async () => {
ofertas: ofreceCount || 0,
};
};

const getVolunteers = async () => {
const today = new Date().toISOString().split('T')[0];

Expand Down Expand Up @@ -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', {
Expand All @@ -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;
Expand Down
77 changes: 77 additions & 0 deletions src/components/CookieBanner/CookieBanner.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Modal id={MODAL_NAME} allowClose={false}>
<div className="bg-yellow-50 p-4 rounded">
<h2 className="text-yellow-800 font-semibold mb-4">Política de Cookies</h2>
<p className="text-yellow-800">
Usamos cookies para mejorar su experiencia. Al aceptar, usted está de acuerdo con nuestra{' '}
<Link href={POLICY_URL} className="text-yellow-900 font-semibold underline">
política de cookies
</Link>
.
</p>
<div className="mt-4 flex justify-end space-x-4">
<button
onClick={handleRejectCookies}
className="flex-1 bg-red-500 text-white py-3 px-4 rounded-lg font-semibold"
>
Rechazar
</button>
<button
onClick={handleAcceptCookies}
className="flex-1 bg-green-500 text-white py-3 px-4 rounded-lg font-semibold"
>
Aceptar
</button>
</div>
</div>
</Modal>
);
};

export default CookieBanner;
38 changes: 32 additions & 6 deletions src/components/Modal.js → src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -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<ModalProps> = ({ id, children, maxWidth = 'max-w-2xl', allowClose = true }) => {
const { isModalOpen, toggleModal } = useModal();
if (!isModalOpen[id]) return null;

const handleBackdropClick = (e) => {
const handleBackdropClick = (e: MouseEvent<HTMLDivElement>) => {
if (allowClose && e.target === e.currentTarget) {
toggleModal();
toggleModal(id);
}
};

Expand All @@ -19,7 +45,7 @@ export const Modal = ({ children, maxWidth = 'max-w-2xl', allowClose = true }) =
<div className={`relative bg-white rounded-lg shadow-xl ${maxWidth} w-full m-4`}>
{allowClose && (
<button
onClick={() => toggleModal()}
onClick={() => toggleModal(id)}
className="absolute top-1 right-1 text-gray-400 hover:text-gray-500 z-10 focus:outline-none"
>
<span className="sr-only">Close</span>
Expand Down
8 changes: 5 additions & 3 deletions src/components/auth/PhoneNumberDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { PhoneInput } from '@/components/PhoneInput';
import { formatPhoneNumber } from '@/helpers/utils';
import { isValidPhone } from '@/helpers/utils';

const MODAL_NAME = 'phone-number';

const PhoneForm = ({ onSubmit }) => {
const [phoneNumber, setPhoneNumber] = useState('');

Expand Down Expand Up @@ -79,7 +81,7 @@ const PhoneNumberDialog = () => {
if (metadata.telefono) {
return;
}
toggleModal();
toggleModal(MODAL_NAME);
};

fetchNumber();
Expand All @@ -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 (
<Modal maxWidth={'max-w-md'} allowClose={false}>
<Modal id={MODAL_NAME} maxWidth={'max-w-md'} allowClose={false}>
<PhoneForm onSubmit={handleSubmit} />
</Modal>
);
Expand Down
2 changes: 2 additions & 0 deletions src/components/layout/EmergencyLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -33,6 +34,7 @@ export default function EmergencyLayout({ children }: PropsWithChildren) {
<div className="max-w-7xl w-full">{children}</div>
</main>
<Footer />
<CookieBanner />
</div>
</div>
);
Expand Down
11 changes: 6 additions & 5 deletions src/components/map/map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -34,7 +35,7 @@ const DEFAULT_ZOOM = 12;
const Map: FC<MapProps> = ({ markers = [] }) => {
const [selectedMarker, setSelectedMarker] = useState<PinMapa | null>(null);

const { showModal, toggleModal } = useModal();
const { toggleModal } = useModal();

console.log(selectedMarker);
return (
Expand All @@ -50,11 +51,11 @@ const Map: FC<MapProps> = ({ markers = [] }) => {
{markers.map((m) => {
return (
<Marker
key={m.id}
key={`marker-${m.id}-${m.latitude}-${m.longitude}-${m.urgency}`}
longitude={m.longitude}
latitude={m.latitude}
onClick={() => {
toggleModal(true);
toggleModal(MODAL_NAME, true);
setSelectedMarker(m);
}}
anchor="bottom"
Expand All @@ -63,7 +64,7 @@ const Map: FC<MapProps> = ({ markers = [] }) => {
</Marker>
);
})}
{selectedMarker && showModal && <Modal>{selectedMarker.popup}</Modal>}
{selectedMarker && <Modal id={MODAL_NAME}>{selectedMarker.popup}</Modal>}
</ReactMap>
);
};
Expand Down
30 changes: 19 additions & 11 deletions src/context/EmergencyProvider.tsx
Original file line number Diff line number Diff line change
@@ -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<EmergencyCtx>({ 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<EmergencyContextType>({
isModalOpen: {},
toggleModal: () => {},
});

type EmergencyProviderProps = {
children: ReactNode;
};

export const EmergencyProvider: React.FC<SessionProviderProps> = ({ children }) => {
const [showModal, setShowModal] = useState(false);
export const EmergencyProvider: FC<EmergencyProviderProps> = ({ 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 <EmergencyContext.Provider value={{ showModal, toggleModal }}>{children}</EmergencyContext.Provider>;
return <EmergencyContext.Provider value={{ isModalOpen, toggleModal }}>{children}</EmergencyContext.Provider>;
};

export const useModal = () => {
Expand Down

0 comments on commit aed9285

Please sign in to comment.