diff --git a/package-lock.json b/package-lock.json index 4b4a2493..e9f316c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7397,6 +7397,111 @@ "version": "0.1.5", "license": "MIT", "optional": true + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.2.tgz", + "integrity": "sha512-KUpBVxIbjzFiUZhiLIpJiBoelqzQtVZbdNNsehhUn36e2YzKHphnK8eTUW1s/4aPy5kH/UTid8IuVbaOpedhpw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.2.tgz", + "integrity": "sha512-9J7TPEcHNAZvwxXRzOtiUvwtTD+fmuY0l7RErf8Yyc7kMpE47MIQakl+3jecmkhOoIyi/Rp+ddq7j4wG6JDskQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.2.tgz", + "integrity": "sha512-BjH4ZSzJIoTTZRh6rG+a/Ry4SW0HlizcPorqNBixBWc3wtQtj4Sn9FnRZe22QqrPnzoaW0ctvSz4FaH4eGKMww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.2.tgz", + "integrity": "sha512-i3U2TcHgo26sIhcwX/Rshz6avM6nizrZPvrDVDY1bXcLH1ndjbO8zuC7RoHp0NSK7wjJMPYzm7NYL1ksSKFreA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.2.tgz", + "integrity": "sha512-AMfZfSVOIR8fa+TXlAooByEF4OB00wqnms1sJ1v+iu8ivwvtPvnkwdzzFMpsK5jA2S9oNeeQ04egIWVb4QWmtQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.2.tgz", + "integrity": "sha512-JkXysDT0/hEY47O+Hvs8PbZAeiCQVxKfGtr4GUpNAhlG2E0Mkjibuo8ryGD29Qb5a3IOnKYNoZlh/MyKd2Nbww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.2.tgz", + "integrity": "sha512-foaUL0NqJY/dX0Pi/UcZm5zsmSk5MtP/gxx3xOPyREkMFN+CTjctPfu3QaqrQHinaKdPnMWPJDKt4VjDfTBe/Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/src/app/auth/page.js b/src/app/auth/page.js index 8d286b37..5397547f 100644 --- a/src/app/auth/page.js +++ b/src/app/auth/page.js @@ -18,7 +18,7 @@ export default function AuthPage() { }); return ( -
+
(window.location.href = '/')} />
); diff --git a/src/app/politica-privacidad/page.tsx b/src/app/politica-privacidad/page.tsx new file mode 100644 index 00000000..b7cf0c76 --- /dev/null +++ b/src/app/politica-privacidad/page.tsx @@ -0,0 +1,119 @@ +export default function politicaPrivacidad() { + return ( +
+

Politica de privacidad

+
+

1. Datos Personales que Recopilamos

+

+ Recopilamos datos personales para facilitar el contacto entre personas que ofrecen ayuda sin ánimo de lucro y + aquellas que la necesitan en las zonas afectadas por catástrofes naturales. Los datos recopilados incluyen: +

+
    +
  • + Datos obligatorios: correo electrónico para el registro y ubicación aproximada (barrio o área general). +
  • +
  • Datos opcionales: número de teléfono y descripción de las necesidades de ayuda.
  • +
+

+ Nota: No proporciones ningún dato que no esté indicado en el formulario, como nombre completo, DNI o cuentas + bancarias. +

+
+
+

2. Finalidad y Base Legal del Tratamiento de Datos

+
    +
  • Finalidad: Facilitar la conexión entre personas que ofrecen y requieren ayuda en las áreas afectadas.
  • +
  • + Base legal: El tratamiento de los datos se basa en el consentimiento expreso del usuario, otorgado al + registrarse y rellenar el formulario de solicitud de ayuda. +
  • +
+
+
+

3. Consentimiento para la Recopilación y Publicación de Datos

+

+ Al registrarse y rellenar el formulario de solicitud de ayuda, el usuario otorga su consentimiento para la + recopilación y, cuando lo autorice expresamente, la publicación de su ubicación aproximada en el mapa, número + de teléfono y necesidades. Este consentimiento es revocable en cualquier momento. +

+

+ Para revocar el consentimiento de publicación, envía un correo a{' '} + + info@ajudadana.es + + , indicando ELIMINACIÓN DE SOLICITUD DE AYUDA EN EL MAPA, junto con el correo de registro y la ubicación + aproximada. Responderemos en un plazo máximo de 30 días. +

+
+
+

4. Duración de Conservación de los Datos

+

+ Los datos serán utilizados durante la emergencia y hasta un máximo de 6 meses después de la normalización de + la situación, momento en el cual serán eliminados y destruidos de forma segura. +

+
+
+

5. Derechos de los Usuarios

+

De acuerdo con el RGPD, los usuarios tienen derecho a:

+
    +
  • Acceso: Solicitar una copia de sus datos personales.
  • +
  • Rectificación: Modificar información incorrecta.
  • +
  • Supresión: Solicitar la eliminación de sus datos en cualquier momento.
  • +
  • Oposición y Limitación del Tratamiento: Oponerse al tratamiento o limitar su uso.
  • +
  • Portabilidad: Solicitar que sus datos sean transferidos a otra entidad.
  • +
+

+ Para ejercer estos derechos, envía una solicitud a{' '} + + info@ajudadana.es + + , incluyendo el derecho específico que deseas ejercer. La solicitud se procesará en un plazo de 30 días. +

+
+
+

6. Seguridad de los Datos

+

+ Implementamos medidas técnicas y organizativas para proteger los datos personales. En caso de una violación de + seguridad que pueda afectar los derechos y libertades de los usuarios, notificaremos a la AEPD en un plazo de + 72 horas y, si procede, a los usuarios afectados. +

+
+
+

7. Transferencia de Datos a Terceros

+

+ Actualmente, Ayuda Dana no realiza transferencias de datos personales fuera del Espacio Económico Europeo + (EEE). Si esto cambia, se informará y solicitará el consentimiento explícito de los usuarios. +

+
+
+

8. Privacidad de los Menores

+

+ El sitio no está dirigido a menores de 18 años. Si un padre o tutor detecta que un menor ha proporcionado + datos personales sin el debido consentimiento, contacta con nosotros en{' '} + + info@ajudadana.es + {' '} + para su eliminación. +

+
+
+

9. Modificaciones de la Política de Privacidad

+

+ Ayuda Dana se reserva el derecho de modificar esta Política de Privacidad. En caso de cambios sustanciales, + notificaremos a los usuarios registrados y solicitaremos nuevamente su consentimiento si los cambios implican + un uso ampliado de sus datos. +

+
+
+

10. Contacto

+

+ Para preguntas sobre nuestra Política de Privacidad o el uso de tus datos, contáctanos en{' '} + + info@ajudadana.es + +

+
+

Última actualización: 5 de noviembre de 2024

+
+ ); +} diff --git a/src/app/punto-recogida/page.js b/src/app/punto-recogida/page.js index b993a420..e61daec3 100644 --- a/src/app/punto-recogida/page.js +++ b/src/app/punto-recogida/page.js @@ -1,13 +1,14 @@ 'use client'; -import { useState, useCallback } from 'react'; -import { Package } from 'lucide-react'; +import { useState, useCallback, useEffect } from 'react'; import { supabase } from '@/lib/supabase/client'; +import { MapPin, Phone, Package, House, Contact, Megaphone } from 'lucide-react'; +import AddressAutocomplete from '@/components/AddressAutocomplete'; import { isValidPhone } from '@/helpers/utils'; import { PhoneInput } from '@/components/PhoneInput'; -export default function PuntoRecogida() { - const [formData, setFormData] = useState({ +export default function PuntosRecogida() { + const initialFormData = { name: '', type: 'permanente', location: '', @@ -17,13 +18,14 @@ export default function PuntoRecogida() { accepted_items: [], urgent_needs: '', status: 'active', - }); + }; - const [status, setStatus] = useState({ - isSubmitting: false, - error: null, - success: false, - }); + const [formData, setFormData] = useState(initialFormData); + const [showForm, setShowForm] = useState(false); + const [loading, setLoading] = useState(false); + const [collectionPoints, setCollectionPoints] = useState([]); + const [error, setError] = useState(null); + const [success, setSuccess] = useState(false); const tiposAyuda = ['Alimentos', 'Agua', 'Ropa', 'Mantas', 'Medicamentos', 'Productos de higiene']; @@ -31,18 +33,36 @@ export default function PuntoRecogida() { setFormData((formData) => ({ ...formData, contact_phone: phoneNumber })); }, []); - const handleSubmit = async (e) => { + useEffect(() => { + fetchCollectionPoints(); + }, []); + + async function fetchCollectionPoints() { + try { + let { data, error } = await supabase + .from('collection_points') + .select('*') + .order('created_at', { ascending: false }); + + if (error) throw error; + setCollectionPoints(data || []); + } catch (error) { + console.error('Error:', error); + setError('Error al cargar los puntos de recogida'); + } + } + + async function handleSubmit(e) { e.preventDefault(); - setStatus({ isSubmitting: true, error: null, success: false }); + setLoading(true); + setError(null); try { - // Validar campos requeridos - if (!formData.name || !formData.location || !formData.city || !formData.contact_name || !formData.contact_phone) { - throw new Error('Por favor, complete todos los campos obligatorios'); - } + const requiredFields = ['name', 'location', 'contact_phone']; + const missingFields = requiredFields.filter((field) => !formData[field]); - if (formData.accepted_items.length === 0) { - throw new Error('Seleccione al menos un tipo de ayuda'); + if (missingFields.length > 0) { + throw new Error('Por favor completa todos los campos obligatorios'); } if (!isValidPhone(formData.contact_phone)) { @@ -50,150 +70,261 @@ export default function PuntoRecogida() { return; } - // Insertar en Supabase directamente - const { error } = await supabase.from('collection_points').insert([formData]); - - if (error) throw error; - - // Limpiar formulario - setFormData({ - name: '', + const pointData = { + name: formData.name, type: 'permanente', - location: '', - city: '', - contact_name: '', - contact_phone: '', - accepted_items: [], - urgent_needs: '', + location: formData.location, + city: formData.city || null, + contact_name: formData.contact_name || null, + contact_phone: formData.contact_phone, + accepted_items: formData.accepted_items || [], + urgent_needs: formData.urgent_needs || null, status: 'active', - }); + }; + + const { error: insertError } = await supabase.from('collection_points').insert([pointData]); - setStatus({ isSubmitting: false, error: null, success: true }); - setTimeout(() => setStatus((prev) => ({ ...prev, success: false })), 5000); + if (insertError) throw insertError; + + await fetchCollectionPoints(); + setSuccess(true); + setShowForm(false); + setFormData(initialFormData); + + setTimeout(() => setSuccess(false), 3000); } catch (error) { - console.error('Error:', error); - setStatus({ - isSubmitting: false, - error: error.message || 'Error al registrar el punto de recogida', - success: false, - }); + console.error('Error al registrar punto de recogida:', error); + setError(error.message || 'Error al registrar el punto de recogida'); + } finally { + setLoading(false); } - }; + } return ( -
- {status.error && ( -
-

{status.error}

-
- )} - - {status.success && ( -
-

Punto de recogida registrado correctamente

-
- )} - -
-
+
+
+

-

Registrar Punto de Recogida

-

+ Puntos de recogida + + +
-
-
- - setFormData({ ...formData, name: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-blue-500" - /> -
+ {/* Lista de puntos de recogida */} +
+ {collectionPoints.length > 0 ? ( + collectionPoints.map((point) => ( +
+
+
+

{point.name}

+
+ + {point.location} +
+
+ + Referencia: {point.id} + + + {point.status === 'active' ? 'Activo' : 'Inactivo'} + +
-
- - setFormData({ ...formData, location: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-blue-500" - /> +
+ {point.city && ( +
+ + Ciudad: {point.city} +
+ )} + {point.contact_name && ( +
+ + Nombre de contacto: {point.contact_name} +
+ )} + {point.accepted_items && ( +
+ + + Necesita:{' '} + {Array.isArray(point.accepted_items) + ? point.accepted_items + .map((tipo) => { + return tipo; + }) + .join(', ') + : 'Ayuda general'} + +
+ )} + {point.contact_phone && ( +
+ + Teléfono: {point.contact_phone} +
+ )} + {point.urgent_needs && ( +
+ Necesidades urgentes: +

{point.urgent_needs}

+
+ )} +
+
+ )) + ) : ( +
+ +

No hay puntos de recogida registrados

+

+ Sé el primero en registrar un punto de recogida para ayudar con la logística de suministros. +

+
+ )} +
-
- - setFormData({ ...formData, city: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-blue-500" - /> -
+ {/* Modal2 de formulario */} + {showForm && ( +
+
+

Registrar Punto de Recogida

+ +
+ + setFormData({ ...formData, name: e.target.value })} + className="w-full p-2 border rounded" + required + /> +
+
+ + { + setFormData((prev) => ({ + ...prev, + location: address.fullAddress, + city: address.details.city, + coordinates: address.coordinates + ? { + lat: address.coordinates.lat, + lng: address.coordinates.lon, + } + : null, + })); + }} + placeholder="Buscar dirección..." + /> +
+
+ +
+ {tiposAyuda.map((tipo) => ( + + ))} +
+
+
+
+ + setFormData({ ...formData, contact_name: e.target.value })} + className="w-full p-2 border rounded" + /> +
+ +
-
- - setFormData({ ...formData, contact_name: e.target.value })} - className="w-full p-2 border rounded focus:ring-2 focus:ring-blue-500" - /> -
+
+ +