diff --git a/src/app/casos-activos/mapa/page.tsx b/src/app/casos-activos/mapa/page.tsx
index 9e738f68..b59e5e55 100644
--- a/src/app/casos-activos/mapa/page.tsx
+++ b/src/app/casos-activos/mapa/page.tsx
@@ -7,10 +7,8 @@ import { useRouter, useSearchParams } from 'next/navigation';
import { tiposAyudaOptions } from '@/helpers/constants';
import Map, { PinMapa } from '@/components/map/map';
import PickupPoint from '@/components/PickupPoint';
-import { useTowns } from '@/context/TownProvider';
export default function Mapa() {
- const towns = useTowns();
const searchParams = useSearchParams();
const router = useRouter();
@@ -47,7 +45,7 @@ export default function Mapa() {
latitude: request.latitude ?? 0,
longitude: request.longitude ?? 0,
id: request.id,
- popup: ,
+ popup: ,
};
}
@@ -107,7 +105,7 @@ export default function Mapa() {
}
fetchData();
- }, [filtroData, towns]);
+ }, [filtroData]);
if (loading) {
return (
diff --git a/src/app/casos-activos/ofertas/page.js b/src/app/casos-activos/ofertas/page.js
index 4dc1df3b..c2a78d1b 100644
--- a/src/app/casos-activos/ofertas/page.js
+++ b/src/app/casos-activos/ofertas/page.js
@@ -6,11 +6,11 @@ import { supabase } from '@/lib/supabase/client';
import Pagination from '@/components/Pagination';
import { tiposAyudaOptions } from '@/helpers/constants';
import { useRouter, useSearchParams } from 'next/navigation';
-import { useTowns } from '../../../context/TownProvider';
-import OfferCard from '../../../components/OfferCard';
+import { useTowns } from '@/context/TownProvider';
+import OfferCard from '@/components/OfferCard';
export default function Ofertas() {
- const towns = useTowns();
+ const { towns } = useTowns();
const searchParams = useSearchParams();
const router = useRouter();
diff --git a/src/app/casos-activos/solicitudes/page.js b/src/app/casos-activos/solicitudes/page.js
index 5a86151e..99853cba 100644
--- a/src/app/casos-activos/solicitudes/page.js
+++ b/src/app/casos-activos/solicitudes/page.js
@@ -15,7 +15,7 @@ import { useTowns } from '@/context/TownProvider';
const MODAL_NAME = 'solicitudes';
export default function Solicitudes() {
- const towns = useTowns();
+ const { getTownById, towns } = useTowns();
const searchParams = useSearchParams();
const router = useRouter();
@@ -123,6 +123,8 @@ export default function Solicitudes() {
);
}
+ const puebloSeleccionado = getTownById(Number(filtroData.pueblo));
+
return (
<>
{/* FILTROS */}
@@ -179,14 +181,11 @@ export default function Solicitudes() {
className="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600 flex items-center gap-2 whitespace-nowrap"
>
- Ofrecer ayuda{' '}
- {filtroData.pueblo === 'todos'
- ? ''
- : ' a ' + towns.find((town) => town.id === Number(filtroData.pueblo))?.name}
+ Ofrecer ayuda {filtroData.pueblo === 'todos' ? '' : ' a ' + getTownById(Number(filtroData.pueblo))?.name}
) : (
- data.map((caso) => )
+ data.map((caso) => )
)}
@@ -194,11 +193,7 @@ export default function Solicitudes() {
- town.id === Number(filtroData.pueblo))?.name}
- onClose={closeModal}
- isModal={true}
- />
+
>
);
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index bac0251c..48aa29c9 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -2,10 +2,8 @@ import './globals.css';
import 'leaflet/dist/leaflet.css';
import SidebarLayout from '@/components/layout/SidebarLayout';
import { ModalProvider } from '@/context/ModalProvider';
-import { TownsProvider } from '@/context/TownProvider';
import { createClient } from '@/lib/supabase/server';
import { SessionProvider } from '@/context/SessionProvider';
-import { townsService } from '@/lib/service';
import { Toaster } from 'sonner';
import { PropsWithChildren } from 'react';
import { QueryClientProvider } from '@/context/QueryClientProvider';
@@ -23,18 +21,15 @@ const getSession = async () => {
export default async function RootLayout({ children }: PropsWithChildren) {
const session = await getSession();
- const towns = await townsService.getTowns();
return (
-
-
- {children}
-
-
+
+ {children}
+
diff --git a/src/app/oferta/[id]/page.js b/src/app/oferta/[id]/page.js
index ed95e8d0..80de85ca 100644
--- a/src/app/oferta/[id]/page.js
+++ b/src/app/oferta/[id]/page.js
@@ -3,15 +3,15 @@ import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import { supabase } from '@/lib/supabase/client';
import { ArrowLeft } from 'lucide-react';
-import OfferCard from '../../../components/OfferCard';
-import { useTowns } from '../../../context/TownProvider';
+import OfferCard from '@/components/OfferCard';
+import { useTowns } from '@/context/TownProvider';
export default function CasoDetalle() {
const params = useParams();
const { id } = params;
const [caso, setCaso] = useState(null);
const [loading, setLoading] = useState(true);
- const towns = useTowns();
+ const { towns } = useTowns();
useEffect(() => {
async function fetchCaso() {
const { data, error } = await supabase.from('help_requests').select('*').eq('id', id).single();
diff --git a/src/app/ofertas/page.js b/src/app/ofertas/page.js
index 3b8087ef..a3fac973 100644
--- a/src/app/ofertas/page.js
+++ b/src/app/ofertas/page.js
@@ -6,9 +6,9 @@ import { supabase } from '@/lib/supabase/client';
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 OfferCard from '../../components/OfferCard';
+import { useTowns } from '@/context/TownProvider';
+import { useSession } from '@/context/SessionProvider';
+import OfferCard from '@/components/OfferCard';
import Link from 'next/link';
export default function ListaSolicitudes() {
@@ -23,7 +23,7 @@ export default function ListaSolicitudes() {
const [data, setData] = useState([]);
const [currentPage, setCurrentPage] = useState(Number(searchParams.get('page')) || 1);
const [currentCount, setCurrentCount] = useState(0);
- const towns = useTowns();
+ const { towns } = useTowns();
const itemsPerPage = 10;
const numPages = (count) => {
diff --git a/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx b/src/app/solicitar-ayuda/_components/Form/FormContainer.tsx
index 620ac2e1..43971f3c 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, { FormEvent, useCallback, useEffect, useMemo, useState } from 'react';
+import React, { FormEvent, useCallback, useMemo, useState } from 'react';
import { FormRenderer } from './FormRenderer';
import { FormData, Status } from '../types';
@@ -49,14 +49,6 @@ export function FormContainer() {
email: session?.user?.user_metadata?.email || '',
});
- useEffect(() => {
- console.log('Component mounted');
- }, []);
-
- useEffect(() => {
- console.log('formData changed: ', formData);
- }, [formData]);
-
const [status, setStatus] = useState({
isSubmitting: false,
error: null,
@@ -180,7 +172,6 @@ export function FormContainer() {
}
: null,
}));
- console.log('address: ', address);
}, []);
const handlePhoneChange = useCallback((phoneNumber: string) => {
@@ -191,11 +182,7 @@ export function FormContainer() {
}, []);
const handleHelpTypeChange: React.ChangeEventHandler = useCallback((event) => {
- const { id, name, value, checked } = event.target;
- console.log('id: ', id);
- console.log('name: ', name);
- console.log('value: ', value);
- console.log('checked: ', checked);
+ const { id, checked } = event.target;
setFormData((formData) => {
const prevHelp = formData.tiposDeAyuda;
diff --git a/src/app/solicitud/page.js b/src/app/solicitud/page.js
deleted file mode 100644
index 861953ab..00000000
--- a/src/app/solicitud/page.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { ArrowLeft } from 'lucide-react';
-import Link from 'next/link';
-
-export default function Solicitud() {
- return (
-
-
-
-
No se encontró la solicitud.
-
-
- );
-}
diff --git a/src/app/solicitud/[id]/page.js b/src/app/solicitudes/[id]/page.tsx
similarity index 65%
rename from src/app/solicitud/[id]/page.js
rename to src/app/solicitudes/[id]/page.tsx
index 44548753..0b3d313d 100644
--- a/src/app/solicitud/[id]/page.js
+++ b/src/app/solicitudes/[id]/page.tsx
@@ -1,37 +1,31 @@
'use client';
-import { useEffect, useState } from 'react';
-import { useParams } from 'next/navigation';
-import { supabase } from '@/lib/supabase/client';
import { ArrowLeft } from 'lucide-react';
import SolicitudCard from '@/components/SolicitudCard';
-import { useTowns } from '../../../context/TownProvider';
+import { useQuery } from '@tanstack/react-query';
+import { HelpRequestData } from '@/types/Requests';
+import { helpRequestService } from '@/lib/service';
+import { useParams } from 'next/navigation';
export default function CasoDetalle() {
- const params = useParams();
- const { id } = params;
- const [caso, setCaso] = useState(null);
- const towns = useTowns();
- const [loading, setLoading] = useState(true);
- useEffect(() => {
- async function fetchCaso() {
- const { data, error } = await supabase.from('help_requests').select('*').eq('id', id).single();
- if (error) {
- console.error('Error fetching caso:', error);
- } else {
- setCaso(data);
- }
- setLoading(false);
- }
- fetchCaso();
- }, [id]);
- if (loading) {
+ const { id } = useParams<{ id: string }>();
+
+ const {
+ data: request,
+ isLoading,
+ error,
+ } = useQuery({
+ queryKey: ['help_requests', { id: id }],
+ queryFn: () => helpRequestService.getOne(Number(id)),
+ });
+
+ if (isLoading) {
return (
);
}
- if (!caso) {
+ if (error || request === undefined) {
return (
@@ -60,7 +54,7 @@ export default function CasoDetalle() {
Volver
-
+
);
}
diff --git a/src/app/solicitudes/editar/[id]/page.js b/src/app/solicitudes/editar/[id]/page.js
deleted file mode 100644
index 060cce30..00000000
--- a/src/app/solicitudes/editar/[id]/page.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { createClient } from '@/lib/supabase/server';
-import RequestHelp from '@/components/RequestHelp';
-import Unauthorized from '../../../../components/Unauthorized';
-
-const getRequest = async (id) => {
- const supabase = await createClient();
- const { data: session, sessionError } = await supabase.auth.getUser();
- if (sessionError || !session?.user) {
- return 'unauthorized';
- }
- const { data, error } = await supabase
- .from('help_requests')
- .select('*')
- .eq('id', id)
- .eq('type', 'necesita')
- .contains('additional_info', { email: session.user.email })
- .single();
- if (error) {
- throw new Error(error);
- }
- return data;
-};
-
-export default async function EditarSolicitud({ params }) {
- const { id } = await params;
- const request = await getRequest(id);
- if (request === 'unauthorized') {
- return ;
- }
- return (
-
- );
-}
diff --git a/src/app/solicitudes/editar/[id]/page.tsx b/src/app/solicitudes/editar/[id]/page.tsx
new file mode 100644
index 00000000..58c5d879
--- /dev/null
+++ b/src/app/solicitudes/editar/[id]/page.tsx
@@ -0,0 +1,26 @@
+import { PageProps } from '.next/types/app/page';
+import RequestHelp from '@/components/RequestHelp';
+import Unauthorized from '@/components/Unauthorized';
+import { helpRequestService } from '@/lib/service';
+import { createClient } from '@/lib/supabase/server';
+
+export default async function EditarSolicitud({ params }: PageProps) {
+ const { id } = await params;
+ const supabase = await createClient();
+ const { data: session } = await supabase.auth.getUser();
+ if (session.user === null) {
+ return ;
+ }
+ const request = await helpRequestService.getOne(Number(id));
+
+ return (
+
+ );
+}
diff --git a/src/app/solicitudes/page.tsx b/src/app/solicitudes/page.tsx
index 6f43df0a..72eb04e4 100644
--- a/src/app/solicitudes/page.tsx
+++ b/src/app/solicitudes/page.tsx
@@ -2,7 +2,6 @@
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';
@@ -11,7 +10,6 @@ import { helpRequestService } from '@/lib/service';
export default function ListaSolicitudes() {
const session = useSession();
- const towns = useTowns();
const userId = session.user?.id;
const {
@@ -58,16 +56,7 @@ export default function ListaSolicitudes() {
) : (
- requests.map((caso) => (
-
- ))
+ requests.map((caso) => )
)}
diff --git a/src/components/AsignarSolicitudButton.tsx b/src/components/AsignarSolicitudButton.tsx
index c0ae3f30..fabc1921 100644
--- a/src/components/AsignarSolicitudButton.tsx
+++ b/src/components/AsignarSolicitudButton.tsx
@@ -1,7 +1,7 @@
'use client';
import { useSession } from '@/context/SessionProvider';
-import { HelpRequestAssignmentData, HelpRequestData, HelpRequestAdditionalInfo } from '@/types/Requests';
+import { HelpRequestAssignmentData, HelpRequestData } from '@/types/Requests';
import { helpRequestService } from '@/lib/service';
import { MouseEvent } from 'react';
import { Spinner } from '@/components/Spinner';
@@ -18,7 +18,7 @@ type AsignarSolicitudButtonProps = {
export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitudButtonProps) {
const { toggleModal } = useModal();
const session = useSession();
-
+ const userId = session.user?.id;
const MODAL_NAME = `Solicitud-${helpRequest.id}`;
const {
@@ -43,6 +43,7 @@ export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitud
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['help_request_assignments'] });
+ queryClient.invalidateQueries({ queryKey: ['help_requests', { user_id: userId, type: 'necesita' }] });
},
onError: (e) => {
console.error('Error al asignarte a la petición de ayuda', e);
@@ -58,6 +59,7 @@ export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitud
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['help_request_assignments'] });
+ queryClient.invalidateQueries({ queryKey: ['help_requests', { user_id: userId, type: 'necesita' }] });
},
onError: (e) => {
console.error('Error al asignarte a la petición de ayuda', e);
@@ -96,7 +98,7 @@ export default function AsignarSolicitudButton({ helpRequest }: AsignarSolicitud
);
// Verifica el email dentro de additional_info utilizando un casting y encadenamiento opcional
- if ((helpRequest.additional_info as HelpRequestAdditionalInfo)?.email === session.user.email) return null;
+ if (helpRequest.user_id === session.user.id) return null;
return (
<>
diff --git a/src/components/OfferHelp.js b/src/components/OfferHelp.js
index aafaf0b9..ac321a58 100644
--- a/src/components/OfferHelp.js
+++ b/src/components/OfferHelp.js
@@ -24,7 +24,7 @@ export default function OfferHelp({
redirect = '/casos-activos/ofertas',
submitType = 'create',
}) {
- const towns = useTowns();
+ const { towns } = useTowns();
const session = useSession();
const router = useRouter();
diff --git a/src/components/RequestHelp.js b/src/components/RequestHelp.js
index 31e42ad1..bba68518 100644
--- a/src/components/RequestHelp.js
+++ b/src/components/RequestHelp.js
@@ -20,7 +20,7 @@ export default function RequestHelp({
id,
redirect = '/casos-activos/solicitudes',
}) {
- const towns = useTowns();
+ const { towns } = useTowns();
const router = useRouter();
const session = useSession();
const userId = session.user?.id;
diff --git a/src/components/SolicitudCard.tsx b/src/components/SolicitudCard.tsx
index 22851897..9d2db443 100644
--- a/src/components/SolicitudCard.tsx
+++ b/src/components/SolicitudCard.tsx
@@ -1,39 +1,27 @@
-import { AlertTriangle, Calendar, MapPin, MapPinned, Megaphone, Phone, Users } from 'lucide-react';
+import { AlertTriangle, MapPin, MapPinned, Megaphone, Phone, Users } from 'lucide-react';
import { tiposAyudaOptions } from '@/helpers/constants';
import Link from 'next/link';
import { useSession } from '@/context/SessionProvider';
-import { HelpRequestAdditionalInfo, HelpRequestData, HelpRequestAssignmentData } from '@/types/Requests';
-import { Town } from '@/types/Town';
+import { HelpRequestAdditionalInfo, HelpRequestData } from '@/types/Requests';
import AsignarSolicitudButton from '@/components/AsignarSolicitudButton';
import SolicitudHelpCount from '@/components/SolicitudHelpCount';
import PhoneInfo from '@/components/PhoneInfo.js';
+import { useTowns } from '@/context/TownProvider';
type SolicitudCardProps = {
caso: HelpRequestData;
- towns: Town[];
- isHref?: boolean;
- button?: SolicitudCardButton;
- isEdit?: boolean;
+ showLink?: boolean;
+ showEdit?: boolean;
};
-type SolicitudCardButton = {
- text: string;
- link: string;
-};
-
-export default function SolicitudCard({
- caso,
- towns,
- isHref = true,
- button = { text: 'Ver solicitud', link: '/solicitud/' },
- isEdit = false,
-}: SolicitudCardProps) {
+export default function SolicitudCard({ caso, showLink = true, showEdit = false }: SolicitudCardProps) {
const session = useSession();
-
+ const { getTownById } = useTowns();
const additionalInfo = caso.additional_info as HelpRequestAdditionalInfo;
-
const special_situations = 'special_situations' in additionalInfo ? additionalInfo.special_situations : undefined;
- const email = 'email' in additionalInfo ? additionalInfo.email : undefined;
+ const isMyRequest = session.user?.id && session.user.id === caso.user_id;
+ const canEdit = isMyRequest; //TODO: support admin editing
+
return (
@@ -92,8 +80,7 @@ export default function SolicitudCard({
- Pueblo:{' '}
- {towns.find((town) => town.id === caso.town_id)?.name || ''}
+ Pueblo: {getTownById(caso.town_id)?.name || ''}
)}
@@ -172,22 +159,20 @@ export default function SolicitudCard({
- {session && session.user && session.user.email && session.user.email === email && !isEdit && (
+ {canEdit && showEdit && (
Editar
)}
- {isHref && (
+ {showLink && (
- {button.text}
+ Ver solicitud
)}
diff --git a/src/context/TownProvider.tsx b/src/context/TownProvider.tsx
index 1e7ede0e..d7c5922b 100644
--- a/src/context/TownProvider.tsx
+++ b/src/context/TownProvider.tsx
@@ -1,16 +1,20 @@
'use client';
-import React, { createContext, ReactNode, useContext } from 'react';
+
+import { useQuery } from '@tanstack/react-query';
+import { townService } from '@/lib/service';
import { Town } from '@/types/Town';
-const TownsContext = createContext
([]);
+export const useTowns = () => {
+ const {
+ data: towns,
+ isLoading,
+ error,
+ } = useQuery({
+ queryKey: ['towns'],
+ queryFn: () => townService.getTowns(),
+ });
-type TownsProviderProps = {
- children: ReactNode;
- towns: Town[];
-};
+ const getTownById = (id: number) => towns?.find((t) => t.id === id);
-export const TownsProvider: React.FC = ({ children, towns }) => {
- return {children};
+ return { towns: towns ?? [], isLoading, error, getTownById };
};
-
-export const useTowns = () => useContext(TownsContext);
diff --git a/src/helpers/format.js b/src/helpers/format.js
index 2f96a9cc..d156714d 100644
--- a/src/helpers/format.js
+++ b/src/helpers/format.js
@@ -1,7 +1,7 @@
import SolicitudCard from '@/components/SolicitudCard';
import ReactDOMServer from 'react-dom/server';
-export const getMarkerBySolicitud = (solicitud, towns) => {
+export const getMarkerBySolicitud = (solicitud) => {
// TODO think if possible getLatLng from a given location
if (!solicitud.latitude || !solicitud.longitude) {
return null;
@@ -10,7 +10,7 @@ export const getMarkerBySolicitud = (solicitud, towns) => {
return {
id: solicitud.id,
coordinates: [solicitud.longitude, solicitud.latitude],
- descriptionHTML: getMarkerDescriptionBySolicitudAndTowns(solicitud, towns),
+ descriptionHTML: getMarkerDescriptionBySolicitudAndTowns(solicitud),
color: getMarkerColorBySolicitud(solicitud),
width: '400px',
};
@@ -28,8 +28,10 @@ export const getMarkerColorBySolicitud = (solicitud) => {
return '#000000';
}
};
-export const getMarkerDescriptionBySolicitudAndTowns = (solicitud, towns) => {
- return ReactDOMServer.renderToString();
+export const getMarkerDescriptionBySolicitudAndTowns = (solicitud) => {
+ return ReactDOMServer.renderToString(
+ ,
+ );
};
export const getMarkerByPuntoDeRecogida = (ptoDeRecogida) => {
diff --git a/src/lib/service.ts b/src/lib/service.ts
index 9d17ac96..f0aebddf 100644
--- a/src/lib/service.ts
+++ b/src/lib/service.ts
@@ -21,6 +21,17 @@ export const helpRequestService = {
if (error) throw error;
return data;
},
+ async getOne(id: number) {
+ const supabase = await getSupabaseClient();
+ const { data, error } = await supabase
+ .from('help_requests')
+ .select('*')
+ .eq('id', id)
+ .eq('type', 'necesita')
+ .single();
+ if (error) throw error;
+ return data;
+ },
async getRequestsByUser(user_id: string | undefined) {
if (user_id === undefined) return [];
@@ -88,6 +99,12 @@ export const townService = {
async create(townName: string) {
return await supabase.from('towns').insert({ name: townName }).select('id');
},
+ async getTowns() {
+ const supabase = await getSupabaseClient();
+ const { data, error } = await supabase.from('towns').select();
+ if (error) throw error;
+ return data;
+ },
async createIfNotExists(townName: string) {
const response = await this.getByName(townName);
if (response.error) return response;
@@ -217,15 +234,6 @@ export const mapService = {
},
};
-export const townsService = {
- async getTowns() {
- const supabase = await getSupabaseClient();
- const { data, error } = await supabase.from('towns').select();
- if (error) throw error;
- return data;
- },
-};
-
// Add this function to test the connection
export const testSupabaseConnection = async () => {
try {
diff --git a/src/lib/supabase/middleware.ts b/src/lib/supabase/middleware.ts
index 9814ec19..03a11751 100644
--- a/src/lib/supabase/middleware.ts
+++ b/src/lib/supabase/middleware.ts
@@ -29,21 +29,8 @@ export async function updateSession(request: NextRequest) {
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
// issues with users being randomly logged out.
- const {
- data: { user },
- } = await supabase.auth.getUser();
const url = request.nextUrl.clone();
- if (
- !user &&
- (request.nextUrl.pathname.startsWith('/ofertas') || request.nextUrl.pathname.startsWith('/solicitudes'))
- ) {
- // no user, no access to their offers or requests. Redirect to log in
-
- url.pathname = '/auth';
- return NextResponse.redirect(url);
- }
-
if (request.nextUrl.pathname === '/casos-activos') {
url.pathname = '/casos-activos/solicitudes';
return NextResponse.redirect(url);