From 2233c422b76b437bdc25964dca2d5222586917b8 Mon Sep 17 00:00:00 2001
From: Troleomotor10
Date: Thu, 7 Nov 2024 18:48:49 +0100
Subject: [PATCH 01/17] docs: add google SSO supabase + update supabase docs
---
.env.example | 5 ++--
CONTRIBUTING.md | 66 ++++++++++++++++++++++++++++++++++----------
supabase/config.toml | 8 +++---
3 files changed, 58 insertions(+), 21 deletions(-)
diff --git a/.env.example b/.env.example
index 8b8552c1..2c15a743 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,5 @@
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
-
-API_KEY=
+SUPABASE_GOOGLE_AUTH_ID=
+SUPABASE_GOOGLE_AUTH_SECRET=
+API_KEY=
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4ec724c1..67f17ebd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -46,33 +46,69 @@ Este mensaje indica que se han añadido instrucciones de instalación local en e
¡Gracias por contribuir! Tu ayuda hace una gran diferencia para el proyecto.
-
-
## Desarrollo local - levantar db de desarrollo local
### Pre requisitos
-- [docker](https://docs.docker.com/engine/install/) y [docker compose](https://docs.docker.com/compose/install/)
-- [cli de supabase](https://supabase.com/docs/guides/local-development/cli/getting-started)
+- [Docker](https://docs.docker.com/engine/install/) y [Docker Compose](https://docs.docker.com/compose/install/)
+- [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started)
-### Instalar self hosted supabase
+Si ya tienes cualquiera de los dos, **actualizalos para evitar errores**.
-```
+Si usas docker desktop en Windows, esta es la configuración que deberías tener.
+
+
+### Iniciar supabase en local
+
+Entramos en la carpeta del repositorio
+
+```bash
cd ${DIRECTORIO_DE_EMERGENCY_CV}
-supabase login
-supabase init
-supabase link --project-ref nmvcsenkfqbdlfdtiqdo
+```
+
+Iniciamos la base de datos (**tener docker encendido**)
+
+```bash
supabase start
```
-### Para hacer cambios en el schema
+Si no vemos las tablas ni los datos de ejemplo cargados podemos refrescar la base de datos con:
+
+```bash
+supabase db reset
+```
+
+### Hacer cambios en el schema
-- Editar como queremos que sea en local (studio de supabase)
-- Ejecutar el comando:
+#### Crear migracion automatica
+Nos interesa usar esta opción, cuando queremos **editar la base de datos desde el studio web**
+
+Cuando acabemos de realizar los cambios en el studio web, ejecutaremos el siguiente comando para generar la migration.
+
+```bash
+supabase db diff -f nombre_migracion
```
-// nombre de la migracion es indicativo, no tiene nigun efecto
-supabase db diff -f ${NOMBRE_DE_LA_MIGRACION}
+
+#### Crear migración manual
+
+Nos interesa usar esta opción, cuando queremos **editar la base de datos con codigo SQL manual**.
+
+Primero, creamos la el archivo migration con
+
+```bash
+supabase migration new nombre_migracion
+```
+
+Se creara un **nuevo fichero** con el nombre que hemos usado **en supabase/migrations**
+
+En ese archivo añadiremos todo el código SQL que necesitemos
+
+Si queremos visualizar nuestros cambios en local, podemos usar
+
+```bash
+supabase db reset
```
-- Esto generara una migracion en el local, hay que añadir esto al PR y github actions lo pondra en produccion.
+
+La migration que generemos, la añadiremos en el PR.
diff --git a/supabase/config.toml b/supabase/config.toml
index 0172bd1c..a79ce9fc 100644
--- a/supabase/config.toml
+++ b/supabase/config.toml
@@ -190,11 +190,11 @@ verify_enabled = true
# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`,
# `twitter`, `slack`, `spotify`, `workos`, `zoom`.
-[auth.external.apple]
-enabled = false
-client_id = ""
+[auth.external.google]
+enabled = true
+client_id = "env(SUPABASE_GOOGLE_AUTH_ID)"
# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead:
-secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)"
+secret = "env(SUPABASE_GOOGLE_AUTH_SECRET)"
# Overrides the default auth redirectUrl.
redirect_uri = ""
# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
From 9e8dab506566d8c4cc69724ead04cc23591d1192 Mon Sep 17 00:00:00 2001
From: Troleomotor10
Date: Thu, 7 Nov 2024 18:49:16 +0100
Subject: [PATCH 02/17] feat: add privacy policy google auth
---
src/components/auth/PhoneNumberDialog.js | 60 +++++++++++++++++++-----
1 file changed, 48 insertions(+), 12 deletions(-)
diff --git a/src/components/auth/PhoneNumberDialog.js b/src/components/auth/PhoneNumberDialog.js
index 94da5dee..53404a42 100644
--- a/src/components/auth/PhoneNumberDialog.js
+++ b/src/components/auth/PhoneNumberDialog.js
@@ -12,27 +12,41 @@ import { isValidPhone } from '@/helpers/utils';
const MODAL_NAME = 'phone-number';
const PhoneForm = ({ onSubmit }) => {
- const [phoneNumber, setPhoneNumber] = useState('');
+ const [formData, setFormData] = useState({
+ phoneNumber: '',
+ privacyPolicy: '',
+ });
const handleSubmit = useCallback(
(e) => {
e.preventDefault();
- /* Form validation */
- if (!isValidPhone(phoneNumber)) {
+ /* PHONE VALIDATION */
+ if (!isValidPhone(formData.phoneNumber)) {
alert('El teléfono de contacto no es válido.');
return;
}
- const formatedPhoneNumber = formatPhoneNumber(phoneNumber);
- onSubmit(formatedPhoneNumber);
- setPhoneNumber('');
+ /* POLICY PRIVACY VALIDATION */
+ if (!formData.privacyPolicy) {
+ alert('Para continuar, debes aceptar la Política de Privacidad.');
+ return;
+ }
+
+ const formatedPhoneNumber = formatPhoneNumber(formData.phoneNumber);
+
+ onSubmit(formData.phoneNumber, formData.privacyPolicy);
+
+ setFormData({
+ phoneNumber: '',
+ privacyPolicy: '',
+ });
},
- [onSubmit, phoneNumber],
+ [onSubmit, formData],
);
const handleChange = useCallback((phoneNumber) => {
- setPhoneNumber(phoneNumber);
+ setFormData((formData) => ({ ...formData, phoneNumber }))
}, []);
return (
@@ -51,9 +65,31 @@ const PhoneForm = ({ onSubmit }) => {
Tu número de teléfono no será usado con ningún otro propósito ni compartido con terceras personas.
-
+
+ {/* PHONE NUMBER */}
+
+
+ {/* PRIVACY POLICY */}
+
+
setFormData({ ...formData, privacyPolicy: e.target.checked })}
+ className="min-w-4 min-h-4 cursor-pointer"
+ id="privacyPolicy"
+ required
+ />
+
+ He leído y aceptado la{' '}
+
+ política de privacidad
+ {' '}
+ y acepto que «ajudadana.es» recoja y guarde los datos enviados a través de este formulario.
+
+
-
+ {/* ACCEPT AND SAVE */}
+
{
fetchNumber();
}, []);
- const handleSubmit = useCallback(async (phoneNumber) => {
+ const handleSubmit = useCallback(async (phoneNumber, privacyPolicy) => {
const { data: session, error: errorGettingUser } = await authService.getSessionUser();
if (!session.user || errorGettingUser) {
@@ -95,7 +131,7 @@ const PhoneNumberDialog = () => {
}
const metadata = session.user.user_metadata;
- const metadataWithPhone = { ...metadata, telefono: phoneNumber };
+ const metadataWithPhone = { ...metadata, telefono: phoneNumber, privacyPolicy };
const { error: updateUserError } = await authService.updateUser({
data: metadataWithPhone,
From df3813183573c2e44ecc8501071c5687b6bdaeeb Mon Sep 17 00:00:00 2001
From: Troleomotor10
Date: Thu, 7 Nov 2024 18:49:58 +0100
Subject: [PATCH 03/17] fix: login google auth
---
src/components/UserInfo.js | 4 +---
src/components/layout/Sidebar.js | 21 +++++++++++++++++----
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/components/UserInfo.js b/src/components/UserInfo.js
index 67601052..c14db152 100644
--- a/src/components/UserInfo.js
+++ b/src/components/UserInfo.js
@@ -1,10 +1,8 @@
import Link from 'next/link';
import { LogIn } from 'lucide-react';
import { authService } from '@/lib/service';
-import { useSession } from '../context/SessionProvider';
-export default function UserProfile() {
- const { user } = useSession();
+export default function UserProfile({ user }) {
const handleLogout = async () => {
const response = await authService.signOut();
if (!response.error) {
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 34887bfb..48ae9535 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -24,7 +24,8 @@ import {
CarTaxiFront,
} from 'lucide-react';
import UserInfo from '../UserInfo';
-import { useSession } from '../../context/SessionProvider';
+import { useState, useEffect } from 'react';
+import { supabase } from '@/lib/supabase/client';
const menuItems = [
{
@@ -146,7 +147,19 @@ const menuItems = [
export default function Sidebar({ isOpen, toggle }) {
const router = useRouter();
const pathname = usePathname();
- const session = useSession();
+
+ const [user, setUser] = useState(null);
+
+ useEffect(() => {
+ const fetchUser = async () => {
+ const {
+ data: { user },
+ } = await supabase.auth.getUser();
+ setUser(user);
+ };
+ fetchUser();
+ }, []);
+
return (
<>
{/* Quitamos el overlay con fondo negro */}
@@ -179,7 +192,7 @@ export default function Sidebar({ isOpen, toggle }) {
{menuItems.map((item) =>
- (session && session.user && session.user.email && item.isAuth) || !item.isAuth ? (
+ (user && user.email && item.isAuth) || !item.isAuth ? (
item.isHref ? (
-
+
{/* Toggle button for desktop */}
From 63f14809eb2c5de7e8a16ca90b79a17aef6c125e Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:42:58 +0100
Subject: [PATCH 04/17] feat: save user_id when creating a help_request
---
.../_components/Form/FormContainer.tsx | 13 ++++++++-----
src/components/OfferHelp.js | 16 +++++++++-------
src/components/RequestHelp.js | 6 +++++-
src/types/database.ts | 3 +++
...241107182626_Add user_id in help_requests.sql | 6 ++++++
5 files changed, 31 insertions(+), 13 deletions(-)
create mode 100644 supabase/migrations/20241107182626_Add user_id in help_requests.sql
diff --git a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx b/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx
index ce94b157..fb796ca9 100644
--- a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx
+++ b/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx
@@ -1,6 +1,6 @@
'use client';
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
+import React, { FormEvent, useCallback, useEffect, useMemo, useState } from 'react';
import { FormRenderer } from './FormRenderer';
import { FormData, Status } from '../types';
@@ -32,8 +32,10 @@ export function FormContainer() {
const router = useRouter();
const session = useSession();
+ const userId = session.user?.id;
+
const [formData, setFormData] = useState({
- nombre: session?.user?.user_metadata?.full_name.split(" ")[0]|| '',
+ nombre: session?.user?.user_metadata?.full_name.split(' ')[0] || '',
ubicacion: '',
coordinates: null,
tiposDeAyuda: new Map(TIPOS_DE_AYUDA.map(({ id }) => [id, false])),
@@ -62,7 +64,7 @@ export function FormContainer() {
});
const handleSubmit = useCallback(
- async (e: any) => {
+ async (e: FormEvent) => {
e.preventDefault();
/* Form validation */
@@ -91,7 +93,7 @@ export function FormContainer() {
try {
const helpRequestData: Database['public']['Tables']['help_requests']['Insert'] = {
type: 'necesita',
- name: formData.nombre.split(" ")[0],
+ name: formData.nombre.split(' ')[0],
location: formData.ubicacion,
latitude: formData.coordinates ? parseFloat(formData.coordinates.lat) : null,
longitude: formData.coordinates ? parseFloat(formData.coordinates.lng) : null,
@@ -107,6 +109,7 @@ export function FormContainer() {
},
town_id: parseInt(formData.pueblo),
status: 'active',
+ user_id: userId,
};
await helpRequestService.createRequest(helpRequestData);
@@ -139,7 +142,7 @@ export function FormContainer() {
});
}
},
- [formData, router],
+ [userId, formData, router],
);
const handleInputElementChange: React.ChangeEventHandler = useCallback((e) => {
diff --git a/src/components/OfferHelp.js b/src/components/OfferHelp.js
index 54b00a76..aafaf0b9 100644
--- a/src/components/OfferHelp.js
+++ b/src/components/OfferHelp.js
@@ -1,7 +1,7 @@
'use client';
-import { useState, useEffect, useCallback } from 'react';
-import { HeartHandshake, Check, Mail } from 'lucide-react';
+import { useState, useCallback } from 'react';
+import { HeartHandshake, Check } from 'lucide-react';
import { helpRequestService } from '@/lib/service';
import AddressAutocomplete from '@/components/AddressAutocomplete';
import { mapToIdAndLabel, tiposAyudaOptions as _tiposAyudaOptions } from '@/helpers/constants';
@@ -9,9 +9,9 @@ import { isValidPhone } from '@/helpers/utils';
import { PhoneInput } from '@/components/PhoneInput';
import { formatPhoneNumber } from '@/helpers/utils';
-import { useTowns } from '../context/TownProvider';
+import { useTowns } from '@/context/TownProvider';
import { useRouter } from 'next/navigation';
-import { useSession } from '../context/SessionProvider';
+import { useSession } from '@/context/SessionProvider';
export default function OfferHelp({
town,
@@ -29,6 +29,8 @@ export default function OfferHelp({
const router = useRouter();
+ const userId = session.user?.id;
+
const [formData, setFormData] = useState({
nombre: data.name || session?.user?.user_metadata?.full_name || '',
telefono: data.contact_info || session?.user?.user_metadata?.telefono || '',
@@ -41,7 +43,7 @@ export default function OfferHelp({
radio: data.resources?.radius || 1,
experiencia: data.additional_info?.experience || '',
comentarios: data.description || '',
- aceptaProtocolo: submitType ? true : false,
+ aceptaProtocolo: !!submitType,
pueblo: submitType === 'edit' ? data?.town_id : town ? town.id : '',
status: data?.status || '',
});
@@ -110,7 +112,6 @@ export default function OfferHelp({
email: formData.email,
experience: formData.experiencia,
},
- status: 'active',
resources: {
vehicle: formData.vehiculo,
availability: formData.disponibilidad,
@@ -121,7 +122,8 @@ export default function OfferHelp({
help_type: formData.tiposAyuda,
other_help: formData.otraAyuda,
town_id: formData.pueblo,
- status: formData.status,
+ status: formData.status || 'active',
+ user_id: userId,
};
if (submitType === 'create') {
diff --git a/src/components/RequestHelp.js b/src/components/RequestHelp.js
index 0e861d76..76559c27 100644
--- a/src/components/RequestHelp.js
+++ b/src/components/RequestHelp.js
@@ -10,8 +10,9 @@ import { helpRequestService } from '@/lib/service';
import { PhoneInput } from '@/components/PhoneInput';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
-import { useTowns } from '../context/TownProvider';
+import { useTowns } from '@/context/TownProvider';
import { CallCenterLink } from '@/components/CallCenterLink';
+import { useSession } from '@/context/SessionProvider';
export default function RequestHelp({
data = {},
@@ -23,6 +24,8 @@ export default function RequestHelp({
}) {
const towns = useTowns();
const router = useRouter();
+ const session = useSession();
+ const userId = session.user?.id;
const [formData, setFormData] = useState({
nombre: data.name || '',
ubicacion: data.location || '',
@@ -93,6 +96,7 @@ export default function RequestHelp({
},
town_id: formData.pueblo,
status: formData.status,
+ user_id: userId,
};
if (submitType === 'create') {
const { error } = await helpRequestService.createRequest(helpRequestData);
diff --git a/src/types/database.ts b/src/types/database.ts
index c831508a..2a181cf2 100644
--- a/src/types/database.ts
+++ b/src/types/database.ts
@@ -188,6 +188,7 @@ export type Database = {
town_id: number | null;
type: string | null;
urgency: string | null;
+ user_id: string | null;
};
Insert: {
additional_info?: Json | null;
@@ -208,6 +209,7 @@ export type Database = {
town_id?: number | null;
type?: string | null;
urgency?: string | null;
+ user_id?: string | null;
};
Update: {
additional_info?: Json | null;
@@ -228,6 +230,7 @@ export type Database = {
town_id?: number | null;
type?: string | null;
urgency?: string | null;
+ user_id?: string | null;
};
Relationships: [
{
diff --git a/supabase/migrations/20241107182626_Add user_id in help_requests.sql b/supabase/migrations/20241107182626_Add user_id in help_requests.sql
new file mode 100644
index 00000000..43f14c5a
--- /dev/null
+++ b/supabase/migrations/20241107182626_Add user_id in help_requests.sql
@@ -0,0 +1,6 @@
+alter table "public"."help_requests" add column "user_id" uuid;
+
+UPDATE help_requests hr
+SET user_id = i.user_id
+FROM auth.identities i
+WHERE hr.additional_info->>'email' = i.email;
\ No newline at end of file
From 6028f79e4bc5972cd16b0658428d71956f848ca1 Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:43:30 +0100
Subject: [PATCH 05/17] feat: add search help_requests by user_id
---
src/lib/service.ts | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/src/lib/service.ts b/src/lib/service.ts
index 613dd318..9d17ac96 100644
--- a/src/lib/service.ts
+++ b/src/lib/service.ts
@@ -22,6 +22,34 @@ export const helpRequestService = {
return data;
},
+ async getRequestsByUser(user_id: string | undefined) {
+ if (user_id === undefined) return [];
+ const { data: assignments, error: assignmentsError } = await supabase
+ .from('help_request_assignments')
+ .select('help_request_id')
+ .eq('user_id', user_id);
+ if (assignmentsError) throw assignmentsError;
+ const helpRequestIds = assignments.map((assignment) => assignment.help_request_id);
+ const { data: requests, error: requestsError } = await supabase
+ .from('help_requests')
+ .select('*')
+ .eq('type', 'necesita')
+ .or(`user_id.eq.${user_id},id.in.(${helpRequestIds.join(',')})`);
+ if (requestsError) throw requestsError;
+ return requests;
+ },
+
+ async getOffersByUser(user_id: string | undefined) {
+ if (user_id === undefined) return [];
+ const { data: requests, error: requestsError } = await supabase
+ .from('help_requests')
+ .select('*')
+ .eq('type', 'ofrece')
+ .eq('user_id', user_id);
+ if (requestsError) throw requestsError;
+ return requests;
+ },
+
async getAssignments(id: number) {
const { data, error } = await supabase.from('help_request_assignments').select('*').eq('help_request_id', id);
From 6a9c0fd2294a641d9944b34721e46f87be611895 Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:46:55 +0100
Subject: [PATCH 06/17] refactor: change emergencyprovider to modalprovider to
suit its real purpose
---
src/app/casos-activos/solicitudes/page.js | 2 +-
src/app/layout.tsx | 6 +++---
src/components/AsignarSolicitudButton.tsx | 2 +-
src/components/CookieBanner/CookieBanner.tsx | 2 +-
src/components/Modal.tsx | 2 +-
src/components/auth/PhoneNumberDialog.js | 2 +-
src/components/map/map.tsx | 2 +-
src/context/{EmergencyProvider.tsx => ModalProvider.tsx} | 4 ++--
8 files changed, 11 insertions(+), 11 deletions(-)
rename src/context/{EmergencyProvider.tsx => ModalProvider.tsx} (89%)
diff --git a/src/app/casos-activos/solicitudes/page.js b/src/app/casos-activos/solicitudes/page.js
index c1f78bdf..5a86151e 100644
--- a/src/app/casos-activos/solicitudes/page.js
+++ b/src/app/casos-activos/solicitudes/page.js
@@ -9,7 +9,7 @@ import OfferHelp from '@/components/OfferHelp';
import { useRouter, useSearchParams } from 'next/navigation';
import { tiposAyudaOptions } from '@/helpers/constants';
import Modal from '@/components/Modal';
-import { useModal } from '@/context/EmergencyProvider';
+import { useModal } from '@/context/ModalProvider';
import { useTowns } from '@/context/TownProvider';
const MODAL_NAME = 'solicitudes';
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 3513c0bf..8dc4b0ea 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,7 +1,7 @@
import './globals.css';
import 'leaflet/dist/leaflet.css';
import EmergencyLayout from '@/components/layout/EmergencyLayout';
-import { EmergencyProvider } from '@/context/EmergencyProvider';
+import { ModalProvider } from '@/context/ModalProvider';
import { TownsProvider } from '@/context/TownProvider';
import { createClient } from '@/lib/supabase/server';
import { SessionProvider } from '@/context/SessionProvider';
@@ -31,9 +31,9 @@ export default async function RootLayout({ children }: PropsWithChildren) {
-
+
{children}
-
+
diff --git a/src/components/AsignarSolicitudButton.tsx b/src/components/AsignarSolicitudButton.tsx
index 38da6778..c0ae3f30 100644
--- a/src/components/AsignarSolicitudButton.tsx
+++ b/src/components/AsignarSolicitudButton.tsx
@@ -9,7 +9,7 @@ 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';
+import { useModal } from '@/context/ModalProvider';
type AsignarSolicitudButtonProps = {
helpRequest: HelpRequestData;
diff --git a/src/components/CookieBanner/CookieBanner.tsx b/src/components/CookieBanner/CookieBanner.tsx
index d99de933..88180564 100644
--- a/src/components/CookieBanner/CookieBanner.tsx
+++ b/src/components/CookieBanner/CookieBanner.tsx
@@ -2,7 +2,7 @@
import { FC, useEffect, useState } from 'react';
import Modal from '@/components/Modal';
-import { useModal } from '@/context/EmergencyProvider';
+import { useModal } from '@/context/ModalProvider';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx
index e7b8950e..7f9b036d 100644
--- a/src/components/Modal.tsx
+++ b/src/components/Modal.tsx
@@ -1,4 +1,4 @@
-import { useModal } from '@/context/EmergencyProvider';
+import { useModal } from '@/context/ModalProvider';
import { MouseEvent, FC, ReactNode } from 'react';
type TailwindMaxWidth =
diff --git a/src/components/auth/PhoneNumberDialog.js b/src/components/auth/PhoneNumberDialog.js
index 94da5dee..8de2da5e 100644
--- a/src/components/auth/PhoneNumberDialog.js
+++ b/src/components/auth/PhoneNumberDialog.js
@@ -4,7 +4,7 @@ import React, { useCallback, useEffect, useState } from 'react';
import Modal from '@/components/Modal';
import { authService } from '@/lib/service';
-import { useModal } from '@/context/EmergencyProvider';
+import { useModal } from '@/context/ModalProvider';
import { PhoneInput } from '@/components/PhoneInput';
import { formatPhoneNumber } from '@/helpers/utils';
import { isValidPhone } from '@/helpers/utils';
diff --git a/src/components/map/map.tsx b/src/components/map/map.tsx
index 956a2ba3..dd115b84 100644
--- a/src/components/map/map.tsx
+++ b/src/components/map/map.tsx
@@ -4,7 +4,7 @@ import { FC, ReactNode, useState } from 'react';
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';
+import { useModal } from '@/context/ModalProvider';
import Modal from '@/components/Modal';
import { MapPinFilled } from '@/components/icons/MapPinFilled';
diff --git a/src/context/EmergencyProvider.tsx b/src/context/ModalProvider.tsx
similarity index 89%
rename from src/context/EmergencyProvider.tsx
rename to src/context/ModalProvider.tsx
index 76a109fe..21614782 100644
--- a/src/context/EmergencyProvider.tsx
+++ b/src/context/ModalProvider.tsx
@@ -12,11 +12,11 @@ const EmergencyContext = createContext({
toggleModal: () => {},
});
-type EmergencyProviderProps = {
+type ModalProviderProps = {
children: ReactNode;
};
-export const EmergencyProvider: FC = ({ children }) => {
+export const ModalProvider: FC = ({ children }) => {
const [isModalOpen, setIsModalOpen] = useState<{ [key: string]: boolean }>({});
const toggleModal = (id: string, force?: boolean) => {
From fa6de2a965800b020bc0430583a36d79ed398b5e Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:48:27 +0100
Subject: [PATCH 07/17] refactor: change emergencyLayout to SidebarLayout to
suit its real purpose
---
src/app/layout.tsx | 4 +-
.../layout/{Sidebar.js => Sidebar.tsx} | 263 ++++++++++--------
...{EmergencyLayout.tsx => SidebarLayout.tsx} | 2 +-
3 files changed, 144 insertions(+), 125 deletions(-)
rename src/components/layout/{Sidebar.js => Sidebar.tsx} (54%)
rename src/components/layout/{EmergencyLayout.tsx => SidebarLayout.tsx} (94%)
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 8dc4b0ea..bac0251c 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,6 +1,6 @@
import './globals.css';
import 'leaflet/dist/leaflet.css';
-import EmergencyLayout from '@/components/layout/EmergencyLayout';
+import SidebarLayout from '@/components/layout/SidebarLayout';
import { ModalProvider } from '@/context/ModalProvider';
import { TownsProvider } from '@/context/TownProvider';
import { createClient } from '@/lib/supabase/server';
@@ -32,7 +32,7 @@ export default async function RootLayout({ children }: PropsWithChildren) {
- {children}
+ {children}
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.tsx
similarity index 54%
rename from src/components/layout/Sidebar.js
rename to src/components/layout/Sidebar.tsx
index 34887bfb..883ff459 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.tsx
@@ -1,5 +1,3 @@
-// components/Sidebar.js
-
'use client';
import React from 'react';
@@ -24,129 +22,150 @@ import {
CarTaxiFront,
} from 'lucide-react';
import UserInfo from '../UserInfo';
-import { useSession } from '../../context/SessionProvider';
-
-const menuItems = [
- {
- icon: Home,
- title: 'Inicio',
- path: '/',
- color: 'text-gray-600',
- isHome: true,
- },
- {
- icon: AlertCircle,
- title: 'Casos Activos',
- description: 'Ver todos los casos activos',
- path: '/casos-activos',
- color: 'text-orange-600',
- highlight: true,
- },
- {
- icon: Inbox,
- title: 'Mis solicitudes',
- description: 'Edita o elimina tus solicitudes',
- path: '/solicitudes',
- color: 'text-red-500',
- isAuth: true,
- },
- {
- icon: Inbox,
- title: 'Mis ofertas',
- description: 'Edita o elimina tus ofertas',
- path: '/ofertas',
- color: 'text-green-500',
- isAuth: true,
- },
- {
- icon: Thermometer,
- title: 'Voluntómetro',
- description: 'Medidor de voluntarios por localidad',
- path: '/voluntometro',
- color: 'text-yellow-500',
- },
- {
- icon: Search,
- title: 'Solicitar Ayuda',
- description: 'Si necesitas asistencia',
- path: '/solicitar-ayuda',
- color: 'text-red-600',
- },
- {
- icon: HeartHandshake,
- title: 'Ofrecer Ayuda',
- description: 'Si puedes ayudar a otros',
- path: '/ofrecer-ayuda',
- color: 'text-green-600',
- },
- {
- icon: UserSearch,
- title: 'Desaparecidos',
- description: 'Reportar personas',
- path: 'https://desaparecidosdana.pythonanywhere.com/',
- color: 'text-purple-600',
- isHref: true,
- },
- {
- icon: Package,
- title: 'Punto de Recogida',
- description: 'Gestionar donaciones',
- path: '/punto-recogida',
- color: 'text-blue-600',
- },
- {
- icon: Truck,
- title: 'Puntos de Entrega',
- description: 'Para transportistas y logística',
- path: '/puntos-entrega',
- color: 'text-gray-800',
- },
- {
- icon: Scale,
- title: 'Servicio Notarial',
- description: 'Servicio notarial gratuito',
- path: 'https://valencia.notariado.org/portal/-/20241031-servicio-notarial-de-ayuda-gratuito-para-los-afectados-por-la-dana-noticia-p%C3%BAblica-',
- color: 'text-indigo-600',
- isHref: true,
- },
- {
- icon: Landmark,
- title: 'Reclamar a Consorcio',
- description: 'Seguro de riesgos extraordinarios',
- path: 'https://www.consorseguros.es/ambitos-de-actividad/seguros-de-riesgos-extraordinarios/solicitud-de-indemnizacion',
- color: 'text-pink-600',
- isHref: true,
- },
- {
- icon: MessageCircleQuestion,
- title: 'Ayuda Psicológica',
- description: 'Conecta con psicólogos voluntarios',
- path: 'https://ayudana.org/',
- color: 'text-teal-600',
- isHref: true,
- },
- {
- icon: CarTaxiFront,
- title: 'Compartir Coche',
- description: 'Viaja u ofrece viajes con otros',
- path: 'https://anem.guruwalk.com/',
- color: 'text-amber-600',
- isHref: true,
- },
- {
- icon: Car,
- title: 'Encontrar tu Coche',
- description: 'Sistema de registro y consulta de vehículos perdidos',
- path: 'https://tucochedana.es/index.php/',
- color: 'text-blue-600',
- isHref: true,
- },
-];
+import { useSession } from '@/context/SessionProvider';
+import { useQuery } from '@tanstack/react-query';
+import { HelpRequestData } from '@/types/Requests';
+import { helpRequestService } from '@/lib/service';
-export default function Sidebar({ isOpen, toggle }) {
+type SidebarProps = {
+ isOpen: boolean;
+ toggle: () => void;
+};
+export default function Sidebar({ isOpen, toggle }: SidebarProps) {
const router = useRouter();
const pathname = usePathname();
const session = useSession();
+
+ const userId = session.user?.id;
+
+ const { data: requests } = useQuery({
+ queryKey: ['help_requests', { user_id: userId }],
+ queryFn: () => helpRequestService.getRequestsByUser(userId),
+ });
+ const { data: offers } = useQuery({
+ queryKey: ['help_requests', { user_id: userId }],
+ queryFn: () => helpRequestService.getOffersByUser(userId),
+ });
+ const hasRequests = (requests?.length ?? 0) > 0;
+ const hasOffers = (offers?.length ?? 0) > 0;
+
+ const menuItems = [
+ {
+ icon: Home,
+ title: 'Inicio',
+ path: '/',
+ color: 'text-gray-600',
+ isHome: true,
+ },
+ {
+ icon: AlertCircle,
+ title: 'Casos Activos',
+ description: 'Ver todos los casos activos',
+ path: '/casos-activos',
+ color: 'text-orange-600',
+ highlight: true,
+ },
+ {
+ icon: Inbox,
+ title: 'Mis solicitudes',
+ description: 'Edita o elimina tus solicitudes',
+ path: '/solicitudes',
+ color: 'text-red-500',
+ hide: !hasRequests,
+ },
+ {
+ icon: Inbox,
+ title: 'Mis ofertas',
+ description: 'Edita o elimina tus ofertas',
+ path: '/ofertas',
+ color: 'text-green-500',
+ hide: !hasOffers,
+ },
+ {
+ icon: Thermometer,
+ title: 'Voluntómetro',
+ description: 'Medidor de voluntarios por localidad',
+ path: '/voluntometro',
+ color: 'text-yellow-500',
+ },
+ {
+ icon: Search,
+ title: 'Solicitar Ayuda',
+ description: 'Si necesitas asistencia',
+ path: '/solicitar-ayuda',
+ color: 'text-red-600',
+ },
+ {
+ icon: HeartHandshake,
+ title: 'Ofrecer Ayuda',
+ description: 'Si puedes ayudar a otros',
+ path: '/ofrecer-ayuda',
+ color: 'text-green-600',
+ },
+ {
+ icon: UserSearch,
+ title: 'Desaparecidos',
+ description: 'Reportar personas',
+ path: 'https://desaparecidosdana.pythonanywhere.com/',
+ color: 'text-purple-600',
+ isHref: true,
+ },
+ {
+ icon: Package,
+ title: 'Punto de Recogida',
+ description: 'Gestionar donaciones',
+ path: '/punto-recogida',
+ color: 'text-blue-600',
+ },
+ {
+ icon: Truck,
+ title: 'Puntos de Entrega',
+ description: 'Para transportistas y logística',
+ path: '/puntos-entrega',
+ color: 'text-gray-800',
+ },
+ {
+ icon: Scale,
+ title: 'Servicio Notarial',
+ description: 'Servicio notarial gratuito',
+ path: 'https://valencia.notariado.org/portal/-/20241031-servicio-notarial-de-ayuda-gratuito-para-los-afectados-por-la-dana-noticia-p%C3%BAblica-',
+ color: 'text-indigo-600',
+ isHref: true,
+ },
+ {
+ icon: Landmark,
+ title: 'Reclamar a Consorcio',
+ description: 'Seguro de riesgos extraordinarios',
+ path: 'https://www.consorseguros.es/ambitos-de-actividad/seguros-de-riesgos-extraordinarios/solicitud-de-indemnizacion',
+ color: 'text-pink-600',
+ isHref: true,
+ },
+ {
+ icon: MessageCircleQuestion,
+ title: 'Ayuda Psicológica',
+ description: 'Conecta con psicólogos voluntarios',
+ path: 'https://ayudana.org/',
+ color: 'text-teal-600',
+ isHref: true,
+ },
+ {
+ icon: CarTaxiFront,
+ title: 'Compartir Coche',
+ description: 'Viaja u ofrece viajes con otros',
+ path: 'https://anem.guruwalk.com/',
+ color: 'text-amber-600',
+ isHref: true,
+ },
+ {
+ icon: Car,
+ title: 'Encontrar tu Coche',
+ description: 'Sistema de registro y consulta de vehículos perdidos',
+ path: 'https://tucochedana.es/index.php/',
+ color: 'text-blue-600',
+ isHref: true,
+ },
+ ];
+
return (
<>
{/* Quitamos el overlay con fondo negro */}
@@ -179,7 +198,7 @@ export default function Sidebar({ isOpen, toggle }) {
{menuItems.map((item) =>
- (session && session.user && session.user.email && item.isAuth) || !item.isAuth ? (
+ !item.hide ? (
item.isHref ? (
{
From 434e840e699b6ced4989fb0c64bbde7061f77adc Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:53:25 +0100
Subject: [PATCH 08/17] refactor: change name to follow nextjs rules
---
src/components/layout/Sidebar.tsx | 12 ++++++------
src/components/layout/SidebarLayout.tsx | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
index 883ff459..287c698f 100644
--- a/src/components/layout/Sidebar.tsx
+++ b/src/components/layout/Sidebar.tsx
@@ -29,9 +29,9 @@ import { helpRequestService } from '@/lib/service';
type SidebarProps = {
isOpen: boolean;
- toggle: () => void;
+ toggleAction: () => void;
};
-export default function Sidebar({ isOpen, toggle }: SidebarProps) {
+export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
const router = useRouter();
const pathname = usePathname();
const session = useSession();
@@ -169,11 +169,11 @@ export default function Sidebar({ isOpen, toggle }: SidebarProps) {
return (
<>
{/* Quitamos el overlay con fondo negro */}
- {isOpen &&
}
+ {isOpen &&
}
{/* Toggle button for mobile */}
@@ -226,7 +226,7 @@ export default function Sidebar({ isOpen, toggle }: SidebarProps) {
key={item.path}
onClick={() => {
router.push(item.path);
- if (window.innerWidth < 768) toggle();
+ if (window.innerWidth < 768) toggleAction();
}}
className={`w-full text-left transition-colors ${
item.isHome
@@ -259,7 +259,7 @@ export default function Sidebar({ isOpen, toggle }: SidebarProps) {
{/* Toggle button for desktop */}
- setIsSidebarOpen(!isSidebarOpen)} />
+ setIsSidebarOpen(!isSidebarOpen)} />
From 1d7e7ae7fa10b341c62d969c8e3b5d46127f57de Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:55:40 +0100
Subject: [PATCH 09/17] fix: correct query keys to avoid cache bug
---
src/components/layout/Sidebar.tsx | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
index 287c698f..1e5f58c5 100644
--- a/src/components/layout/Sidebar.tsx
+++ b/src/components/layout/Sidebar.tsx
@@ -39,16 +39,18 @@ export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
const userId = session.user?.id;
const { data: requests } = useQuery({
- queryKey: ['help_requests', { user_id: userId }],
+ queryKey: ['help_requests', { user_id: userId, type: 'necesita' }],
queryFn: () => helpRequestService.getRequestsByUser(userId),
});
const { data: offers } = useQuery({
- queryKey: ['help_requests', { user_id: userId }],
+ queryKey: ['help_requests', { user_id: userId, type: 'ofrece' }],
queryFn: () => helpRequestService.getOffersByUser(userId),
});
const hasRequests = (requests?.length ?? 0) > 0;
const hasOffers = (offers?.length ?? 0) > 0;
+ console.log(offers);
+
const menuItems = [
{
icon: Home,
From 6abc2147c01ce839c1fdbee2ddda47aada1f4484 Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 19:56:17 +0100
Subject: [PATCH 10/17] refactor: remove console log
---
src/components/layout/Sidebar.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
index 1e5f58c5..5f9d4ed6 100644
--- a/src/components/layout/Sidebar.tsx
+++ b/src/components/layout/Sidebar.tsx
@@ -49,8 +49,6 @@ export default function Sidebar({ isOpen, toggleAction }: SidebarProps) {
const hasRequests = (requests?.length ?? 0) > 0;
const hasOffers = (offers?.length ?? 0) > 0;
- console.log(offers);
-
const menuItems = [
{
icon: Home,
From fa734cf242908fbaef447b3745a652099e261c33 Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 20:00:50 +0100
Subject: [PATCH 11/17] style: run prettier
---
src/app/auth/page.js | 4 ++--
.../_components/Form/FormRenderer.tsx | 3 ++-
src/components/SolicitudCard.tsx | 2 +-
src/components/auth/Login.js | 6 +-----
tests/navigation/encuentra-coche.spec.ts | 12 ++++++------
5 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/src/app/auth/page.js b/src/app/auth/page.js
index 8179d575..5397547f 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/solicitar-ayuda/_components/Form/FormRenderer.tsx b/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx
index e0196b30..b0968a8e 100644
--- a/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx
+++ b/src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx
@@ -84,7 +84,8 @@ export function FormRenderer({
className="w-full p-2 border rounded focus:ring-2 focus:ring-green-500 focus:border-green-500"
/>
- {isUserLoggedIn ? 'Se utilizará para que puedas eliminar o editar la información de tu solicitud'
+ {isUserLoggedIn
+ ? 'Se utilizará para que puedas eliminar o editar la información de tu solicitud'
: 'Se utilizará para que puedas actualizar tu solicitud y marcarla como completada. Para realizar cambios, deberás registrarte con el mismo email'}
diff --git a/src/components/SolicitudCard.tsx b/src/components/SolicitudCard.tsx
index cc901992..22851897 100644
--- a/src/components/SolicitudCard.tsx
+++ b/src/components/SolicitudCard.tsx
@@ -160,7 +160,7 @@ export default function SolicitudCard({
-
{caso?.name?.split(" ")[0] || 'Necesita Ayuda'}
+
{caso?.name?.split(' ')[0] || 'Necesita Ayuda'}
{new Date(caso.created_at!).toLocaleDateString() +
' ' +
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 4f16c40a..5ae228fe 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -48,13 +48,11 @@ export default function Login({ onSuccessCallback }) {
throw new Error('Error a la hora de obtener el usuario');
}
return session.user.user_metadata.privacyPolicy;
-
};
const handleSubmit = async (e) => {
e.preventDefault();
-
setStatus({ isSubmitting: true, error: null, success: false });
if (!isPrivacyAccepted) {
@@ -69,14 +67,12 @@ export default function Login({ onSuccessCallback }) {
return;
}
- const response = await authService.signIn(formData.email, formData.password);
-
+ const response = await authService.signIn(formData.email, formData.password);
if (response.error) {
setStatus({ isSubmitting: false, error: 'El email o contraseña son inválidos', success: false });
return;
}
-
if (formData.privacyPolicy && !isPrivacyAccepted) {
await updatePrivacyPolicy(true);
diff --git a/tests/navigation/encuentra-coche.spec.ts b/tests/navigation/encuentra-coche.spec.ts
index eb9bd65e..c5906881 100644
--- a/tests/navigation/encuentra-coche.spec.ts
+++ b/tests/navigation/encuentra-coche.spec.ts
@@ -1,10 +1,10 @@
import { test, expect } from '@playwright/test';
test('should navigate to the "Encontrar tu Coche" page ', async ({ page }) => {
- await page.goto('/');
- await page.click('text=Encontrar tu Coche');
- await expect(page).toHaveURL('https://tucochedana.es/index.php/');
- await expect(page.locator('p:has-text("Sistema")')).toHaveText(
- 'Sistema de registro y consulta de vehículos perdidos.',
- );
+ await page.goto('/');
+ await page.click('text=Encontrar tu Coche');
+ await expect(page).toHaveURL('https://tucochedana.es/index.php/');
+ await expect(page.locator('p:has-text("Sistema")')).toHaveText(
+ 'Sistema de registro y consulta de vehículos perdidos.',
+ );
});
From b1ddbec14022eb12c1ebd19425d2f4a8a90b4481 Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 20:16:44 +0100
Subject: [PATCH 12/17] fix: remove banners from edit request form
---
src/components/RequestHelp.js | 54 +----------------------------------
1 file changed, 1 insertion(+), 53 deletions(-)
diff --git a/src/components/RequestHelp.js b/src/components/RequestHelp.js
index 76559c27..31e42ad1 100644
--- a/src/components/RequestHelp.js
+++ b/src/components/RequestHelp.js
@@ -1,17 +1,15 @@
'use client';
import { useCallback, useState } from 'react';
-import { AlertTriangle, Check, Mail } from 'lucide-react';
+import { Check, Mail } from 'lucide-react';
import AddressAutocomplete from '@/components/AddressAutocomplete';
import { mapToIdAndLabel, tiposAyudaOptions } from '@/helpers/constants';
import { formatPhoneNumber, isValidPhone } from '@/helpers/utils';
import { helpRequestService } from '@/lib/service';
import { PhoneInput } from '@/components/PhoneInput';
-import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { useTowns } from '@/context/TownProvider';
-import { CallCenterLink } from '@/components/CallCenterLink';
import { useSession } from '@/context/SessionProvider';
export default function RequestHelp({
@@ -155,56 +153,6 @@ export default function RequestHelp({
return (
- {/* Banner de emergencia */}
-
-
-
-
-
EMERGENCIA ACTIVA - Inundaciones CV
-
- Para emergencias médicas inmediatas, llame al 112. Este formulario es para coordinar ayuda y asistencia.
-
-
-
-
-
-
-
-
-
PARA PERSONAS CON DIFICULTADES TECNICAS
-
-
- AVISO IMPORTANTE: Esta información es sólo para personas que tengan dificultades técnicas a la hora de
- pedir ayuda.
-
-
- Hemos habilitado el número para facilitar la petición de ayuda a aquellas personas
- que encuentren complicado usar la página web.{' '}
-
-
- ¡Importante! No saturéis el teléfono si podéis usar la página web, por favor. Si tenéis alguna duda
- sobre la página web o deseas aportar nuevas ideas, por favor escríbenos a{' '}
-
- info@ajudadana.es
-
-
-
También puedes contactar con nosotros a través de:
-
-
- WhatsApp
-
-
-
-
-
-
{status.error && (
{status.error}
From adb2b6cfc7d8df95e8c367a9d878a9957cbd76ad Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 20:16:58 +0100
Subject: [PATCH 13/17] feat: use proper query to get my requests
---
src/app/solicitudes/page.js | 196 -----------------------------------
src/app/solicitudes/page.tsx | 76 ++++++++++++++
2 files changed, 76 insertions(+), 196 deletions(-)
delete mode 100644 src/app/solicitudes/page.js
create mode 100644 src/app/solicitudes/page.tsx
diff --git a/src/app/solicitudes/page.js b/src/app/solicitudes/page.js
deleted file mode 100644
index 53bf9d5f..00000000
--- a/src/app/solicitudes/page.js
+++ /dev/null
@@ -1,196 +0,0 @@
-'use client';
-
-import { useState, useEffect } from 'react';
-import { Search } from 'lucide-react';
-import { supabase } from '@/lib/supabase/client';
-import SolicitudCard from '@/components/SolicitudCard';
-import Pagination from '@/components/Pagination';
-import { useRouter, useSearchParams } from 'next/navigation';
-import { tiposAyudaOptions } from '@/helpers/constants';
-import { useTowns } from '../../context/TownProvider';
-import { useSession } from '../../context/SessionProvider';
-import Link from 'next/link';
-
-export default function ListaSolicitudes() {
- const session = useSession();
-
- const searchParams = useSearchParams();
- const router = useRouter();
-
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(null);
-
- const [data, setData] = useState([]);
- const [currentPage, setCurrentPage] = useState(Number(searchParams.get('page')) || 1);
- const [currentCount, setCurrentCount] = useState(0);
- const towns = useTowns();
-
- const itemsPerPage = 10;
- const numPages = (count) => {
- return Math.ceil(count / itemsPerPage) || 0;
- };
-
- const updateFilter = (filter, value) => {
- const params = new URLSearchParams(searchParams.toString());
- params.set(filter, value);
- router.push(`?${params.toString()}`);
- };
- const [filtroData, setFiltroData] = useState({
- urgencia: searchParams.get('urgencia') || 'todas',
- tipoAyuda: searchParams.get('tipoAyuda') || 'todas',
- pueblo: searchParams.get('pueblo') || 'todos',
- });
-
- const changeDataFilter = (type, newFilter) => {
- setFiltroData((prev) => ({
- ...prev,
- [type]: newFilter,
- }));
- updateFilter(type, newFilter);
- };
-
- function changePage(newPage) {
- setCurrentPage(newPage);
- updateFilter('page', newPage);
- }
- useEffect(() => {
- async function fetchData() {
- try {
- setLoading(true);
- setError(null);
-
- // Comenzamos la consulta
- const query = supabase
- .from('help_requests')
- .select('*', { count: 'exact' })
- .eq('type', 'necesita')
- .contains('additional_info', { email: session.user.email });
- // Solo agregar filtro si no es "todos"
- if (filtroData.pueblo !== 'todos') {
- query.eq('town_id', filtroData.pueblo);
- }
-
- // Solo agregar filtro si no es "todas"
- if (filtroData.urgencia !== 'todas') {
- query.eq('urgency', filtroData.urgencia);
- }
-
- // Ejecutar la consulta con paginación
- const { data, count, error } = await query
- .range((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage - 1)
- .order('created_at', { ascending: false });
-
- if (error) {
- console.log('Error fetching solicitudes:', error);
- setData([]);
- } else {
- setData(data || []);
- setCurrentCount(count);
- }
- } catch (err) {
- console.log('Error general:', err);
- setError('Error de conexión.');
- } finally {
- setLoading(false);
- }
- }
-
- fetchData();
- }, [filtroData, currentPage]);
-
- if (loading) {
- return (
-
- );
- }
-
- if (error) {
- return (
-
- );
- }
-
- return (
- <>
-
- {/* FILTROS */}
-
-
Filtros
-
- changeDataFilter('tipoAyuda', e.target.value)}
- className="px-4 py-2 rounded-lg w-full border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white text-gray-900 shadow-sm"
- >
- Todas las necesidades
- {Object.entries(tiposAyudaOptions).map(([key, label]) => (
-
- {label}
-
- ))}
-
- changeDataFilter('urgencia', e.target.value)}
- className="px-4 py-2 rounded-lg w-full border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white text-gray-900 shadow-sm"
- >
- Todas las prioridades
- Alta prioridad
- Media prioridad
- Baja prioridad
-
- changeDataFilter('pueblo', e.target.value)}
- className="px-4 py-2 rounded-lg w-full border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white text-gray-900 shadow-sm"
- >
- Todos los pueblos
- {towns.map((item) => (
-
- {item.name}
-
- ))}
-
-
-
-
- {data.length === 0 ? (
-
-
- {filtroData.urgencia === 'todas' && filtroData.tipoAyuda === 'todas' && filtroData.pueblo === 'todos'
- ? 'No se encontraron solicitudes de ayuda correspondientes a tu cuenta.'
- : 'No se encontraron solicitudes que coincidan con los filtros.'}
-
-
-
-
- Solicitar ayuda
-
-
- ) : (
- data.map((caso) => (
-
- ))
- )}
-
-
-
- >
- );
-}
diff --git a/src/app/solicitudes/page.tsx b/src/app/solicitudes/page.tsx
new file mode 100644
index 00000000..6f43df0a
--- /dev/null
+++ b/src/app/solicitudes/page.tsx
@@ -0,0 +1,76 @@
+'use client';
+
+import { Search } from 'lucide-react';
+import SolicitudCard from '@/components/SolicitudCard';
+import { useTowns } from '@/context/TownProvider';
+import { useSession } from '@/context/SessionProvider';
+import Link from 'next/link';
+import { useQuery } from '@tanstack/react-query';
+import { HelpRequestData } from '@/types/Requests';
+import { helpRequestService } from '@/lib/service';
+
+export default function ListaSolicitudes() {
+ const session = useSession();
+ const towns = useTowns();
+ const userId = session.user?.id;
+
+ const {
+ data: requests,
+ isLoading,
+ error,
+ } = useQuery({
+ queryKey: ['help_requests', { user_id: userId, type: 'necesita' }],
+ queryFn: () => helpRequestService.getRequestsByUser(userId),
+ });
+
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ if (error || requests === undefined) {
+ return (
+
+ );
+ }
+
+ return (
+ <>
+
+
+ {requests.length === 0 ? (
+
+
+ No se encontraron solicitudes de ayuda correspondientes a tu cuenta.
+
+
+
+
+ Solicitar ayuda
+
+
+ ) : (
+ requests.map((caso) => (
+
+ ))
+ )}
+
+
+ >
+ );
+}
From f6357be94b0e42a71e0e1ad27256f97e9277a4f4 Mon Sep 17 00:00:00 2001
From: GuillePrograma94
Date: Thu, 7 Nov 2024 19:26:27 +0000
Subject: [PATCH 14/17] Guarda cambios antes de actualizar con main
---
src/app/page.tsx | 6 +-
.../personas-animales-desaparecidos/page.js | 61 +++++++++++++++++++
src/components/layout/Sidebar.js | 13 +---
3 files changed, 66 insertions(+), 14 deletions(-)
create mode 100644 src/app/personas-animales-desaparecidos/page.js
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 47801201..2a01896c 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -159,10 +159,10 @@ export default function Home() {
priority: 'high',
},
{
- title: 'Personas Desaparecidas',
- description: 'Reportar o buscar personas',
+ title: 'Desaparecidos y Extraviados',
+ description: 'Reportar o buscar Personas, animales y vehículos',
icon: Users,
- path: 'https://desaparecidosdana.pythonanywhere.com/',
+ path: '/personas-animales-desaparecidos',
color: 'purple',
priority: 'high',
},
diff --git a/src/app/personas-animales-desaparecidos/page.js b/src/app/personas-animales-desaparecidos/page.js
new file mode 100644
index 00000000..9bcb8242
--- /dev/null
+++ b/src/app/personas-animales-desaparecidos/page.js
@@ -0,0 +1,61 @@
+// personas-animales-desaparecidos/page.js
+
+import { Users, PawPrint, Car, UserSearch } from 'lucide-react';
+
+export default function PersonasAnimalesDesaparecidos() {
+ return (
+
+ {/* Encabezado con fondo de color e icono */}
+
+
+
+ Personas, Animales y Vehículos Desaparecidos
+
+
+
+ {/* Tarjeta grande para información */}
+
+
+ En esta página puedes acceder a diferentes herramientas externas para encontrar personas, animales y vehículos desaparecidos.
+ Selecciona la opción que necesitas para más información y para reportar un caso o buscar ayuda.
+
+
+
+ {/* Tres columnas de botones */}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
index 34887bfb..4c2e06e0 100644
--- a/src/components/layout/Sidebar.js
+++ b/src/components/layout/Sidebar.js
@@ -82,10 +82,9 @@ const menuItems = [
{
icon: UserSearch,
title: 'Desaparecidos',
- description: 'Reportar personas',
- path: 'https://desaparecidosdana.pythonanywhere.com/',
+ description: 'Personas, animales ...',
+ path: '/personas-animales-desaparecidos',
color: 'text-purple-600',
- isHref: true,
},
{
icon: Package,
@@ -133,14 +132,6 @@ const menuItems = [
color: 'text-amber-600',
isHref: true,
},
- {
- icon: Car,
- title: 'Encontrar tu Coche',
- description: 'Sistema de registro y consulta de vehículos perdidos',
- path: 'https://tucochedana.es/index.php/',
- color: 'text-blue-600',
- isHref: true,
- },
];
export default function Sidebar({ isOpen, toggle }) {
From 90d3ff0e5e0cb3d3256e8fca0b33c6f4865f2f2b Mon Sep 17 00:00:00 2001
From: Pinx0
Date: Thu, 7 Nov 2024 21:18:31 +0100
Subject: [PATCH 15/17] refactor: use useSession and next Image
---
src/components/{UserInfo.js => UserInfo.tsx} | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
rename src/components/{UserInfo.js => UserInfo.tsx} (81%)
diff --git a/src/components/UserInfo.js b/src/components/UserInfo.tsx
similarity index 81%
rename from src/components/UserInfo.js
rename to src/components/UserInfo.tsx
index c14db152..767a91be 100644
--- a/src/components/UserInfo.js
+++ b/src/components/UserInfo.tsx
@@ -1,8 +1,15 @@
+'use client';
+
import Link from 'next/link';
import { LogIn } from 'lucide-react';
import { authService } from '@/lib/service';
+import { useSession } from '@/context/SessionProvider';
+import Image from 'next/image';
+
+export default function UserProfile() {
+ const session = useSession();
+ const user = session.user;
-export default function UserProfile({ user }) {
const handleLogout = async () => {
const response = await authService.signOut();
if (!response.error) {
@@ -25,7 +32,7 @@ export default function UserProfile({ user }) {
return (
{user.user_metadata.avatar_url ? (
-
+
) : (
Date: Thu, 7 Nov 2024 21:20:14 +0100
Subject: [PATCH 16/17] style: run prettier
---
src/app/personas-animales-desaparecidos/page.js | 6 +++---
src/components/auth/PhoneNumberDialog.js | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/app/personas-animales-desaparecidos/page.js b/src/app/personas-animales-desaparecidos/page.js
index 9bcb8242..d309ee4e 100644
--- a/src/app/personas-animales-desaparecidos/page.js
+++ b/src/app/personas-animales-desaparecidos/page.js
@@ -16,8 +16,8 @@ export default function PersonasAnimalesDesaparecidos() {
{/* Tarjeta grande para información */}
- En esta página puedes acceder a diferentes herramientas externas para encontrar personas, animales y vehículos desaparecidos.
- Selecciona la opción que necesitas para más información y para reportar un caso o buscar ayuda.
+ En esta página puedes acceder a diferentes herramientas externas para encontrar personas, animales y vehículos
+ desaparecidos. Selecciona la opción que necesitas para más información y para reportar un caso o buscar ayuda.
@@ -58,4 +58,4 @@ export default function PersonasAnimalesDesaparecidos() {
);
-}
\ No newline at end of file
+}
diff --git a/src/components/auth/PhoneNumberDialog.js b/src/components/auth/PhoneNumberDialog.js
index b11ca453..c061659b 100644
--- a/src/components/auth/PhoneNumberDialog.js
+++ b/src/components/auth/PhoneNumberDialog.js
@@ -46,7 +46,7 @@ const PhoneForm = ({ onSubmit }) => {
);
const handleChange = useCallback((phoneNumber) => {
- setFormData((formData) => ({ ...formData, phoneNumber }))
+ setFormData((formData) => ({ ...formData, phoneNumber }));
}, []);
return (
@@ -65,10 +65,10 @@ const PhoneForm = ({ onSubmit }) => {
Tu número de teléfono no será usado con ningún otro propósito ni compartido con terceras personas.
-
+
{/* PHONE NUMBER */}
-
+
{/* PRIVACY POLICY */}
Date: Thu, 7 Nov 2024 23:02:09 +0100
Subject: [PATCH 17/17] fix: google profile image
---
next.config.mjs | 8 ++++++++
src/components/UserInfo.tsx | 8 +++++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/next.config.mjs b/next.config.mjs
index d7d3e1dc..dee75a64 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -5,6 +5,14 @@ const nextConfig = {
experimental: {
serverActions: true,
},
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'lh3.googleusercontent.com',
+ },
+ ],
+ },
};
export default nextConfig;
diff --git a/src/components/UserInfo.tsx b/src/components/UserInfo.tsx
index 767a91be..6c60f787 100644
--- a/src/components/UserInfo.tsx
+++ b/src/components/UserInfo.tsx
@@ -32,7 +32,13 @@ export default function UserProfile() {
return (
{user.user_metadata.avatar_url ? (
-
+
) : (