Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unificar formularios de edición y creación de ofertas/solicitudes #184

Merged
merged 18 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/app/casos-activos/ofertas/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function Ofertas() {
console.log('Error fetching solicitudes:', error);
setData([]);
} else {
setData(data || []);
setData((data as HelpRequestData[]) || []);
setCurrentCount(count ?? 0);
}
} catch (err) {
Expand Down Expand Up @@ -140,7 +140,7 @@ function Ofertas() {
</p>
</div>
) : (
data.map((caso) => <OfferCard caso={caso} showLink={true} key={caso.id} />)
data.map((caso) => <OfferCard caso={caso} showLink={true} showEdit={true} key={caso.id} />)
)}
</div>
<div className="flex items-center justify-center">
Expand Down
22 changes: 10 additions & 12 deletions src/app/casos-activos/solicitudes/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { Suspense, useEffect, useState, useCallback, useMemo, ChangeEventHandler } from 'react';
import { Suspense, useEffect, useState, useCallback, ChangeEventHandler } from 'react';
import { supabase } from '@/lib/supabase/client';
import SolicitudCard from '@/components/SolicitudCard';
import Pagination from '@/components/Pagination';
Expand Down Expand Up @@ -74,7 +74,7 @@ function Solicitudes() {

const handleToggleChange: ChangeEventHandler<HTMLInputElement> = useCallback(
(e) => changeDataFilter('soloSinAsignar', `${e.target.checked}`),
[],
[changeDataFilter],
);

useEffect(() => {
Expand Down Expand Up @@ -116,7 +116,7 @@ function Solicitudes() {
console.log('Error fetching solicitudes:', error);
setData([]);
} else {
setData(data || []);
setData((data as HelpRequestData[]) || []);
setCurrentCount(count ?? 0);
}
} catch (err) {
Expand Down Expand Up @@ -190,15 +190,13 @@ function Solicitudes() {
))}
</select>
</div>
{/*
<div className="flex flex-row flex-1 justify-end">
<Toggle
handleChange={handleToggleChange}
checked={isStringTrue(filtroData.soloSinAsignar)}
label="Sólo ofertas sin voluntarios"
/>
</div>
*/}
{/*<div className="flex flex-row flex-1 justify-end">
<Toggle
handleChange={handleToggleChange}
checked={isStringTrue(filtroData.soloSinAsignar)}
label="Sólo ofertas sin voluntarios"
/>
</div>*/}
</div>
</div>
<div className="grid gap-4">
Expand Down
2 changes: 1 addition & 1 deletion src/app/ofertas/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default function CasoDetalle() {
Volver
</button>
</div>
<OfferCard caso={request} showLink={false} />
<OfferCard caso={request} showLink={false} showEdit={true} />
</div>
);
}
13 changes: 2 additions & 11 deletions src/app/ofertas/editar/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import OfferHelp from '@/components/OfferHelp';
import Unauthorized from '@/components/Unauthorized';
import { createClient } from '@/lib/supabase/server';
import { helpRequestService } from '@/lib/service';
import EditHelpOffer from '@/components/HelpOffers/EditHelpOffer';

export default async function EditarSolicitud({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
Expand All @@ -12,14 +12,5 @@ export default async function EditarSolicitud({ params }: { params: Promise<{ id
}
const numberId = Number(id);
const request = await helpRequestService.getOne(numberId);
return (
<OfferHelp
title="Editar solicitud de ayuda"
submitType="edit"
data={request}
id={numberId}
button={['Editar oferta', 'Editando oferta...']}
redirect="/ofertas"
/>
);
return <EditHelpOffer request={request} />;
}
150 changes: 12 additions & 138 deletions src/app/ofertas/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
'use client';

import { useState, useEffect, Suspense } from 'react';
import { Suspense } from 'react';
import { HeartHandshake } from 'lucide-react';
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 Link from 'next/link';
import { HelpRequestData } from '@/types/Requests';
import { useQuery } from '@tanstack/react-query';
import { helpRequestService } from '@/lib/service';

export default function ListaSolicitudesPage() {
return (
Expand All @@ -22,157 +19,37 @@ export default function ListaSolicitudesPage() {

function ListaSolicitudes() {
const session = useSession();
const userId = session.user?.id;

const searchParams = useSearchParams();
const router = useRouter();

const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);

const [data, setData] = useState<HelpRequestData[]>([]);
const [currentPage, setCurrentPage] = useState<number>(Number(searchParams.get('page')) || 1);
const [currentCount, setCurrentCount] = useState<number>(0);
const { towns } = useTowns();

const itemsPerPage = 10;
const numPages = (count: number) => {
return Math.ceil(count / itemsPerPage) || 0;
};

const updateFilter = (filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page', value: string) => {
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 { data, isLoading, error } = useQuery<HelpRequestData[]>({
queryKey: ['help_requests', { user_id: userId, type: 'ofrece' }],
queryFn: () => helpRequestService.getOffersByUser(userId),
});

const changeDataFilter = (type: 'urgencia' | 'tipoAyuda' | 'pueblo', newFilter: string) => {
setFiltroData((prev) => ({
...prev,
[type]: newFilter,
}));
updateFilter(type, newFilter);
};

function changePage(newPage: number) {
setCurrentPage(newPage);
updateFilter('page', newPage.toString());
}
useEffect(() => {
async function fetchData() {
try {
setLoading(true);
setError(null);

// Comenzamos la consulta
const query = supabase
.from('help_requests')
.select('*', { count: 'exact' })
.eq('type', 'ofrece')
.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 || count === null) {
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) {
if (isLoading) {
return (
<div className="flex justify-center items-center min-h-screen">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
</div>
);
}

if (error) {
if (error || !data) {
return (
<div className="bg-red-100 border-l-4 border-red-500 p-4 rounded">
<p className="text-red-700">{error}</p>
<p className="text-red-700">{error?.message}</p>
</div>
);
}

return (
<>
<div className="space-y-6 mx-auto max-w-7xl px-4 sm:px-6 mt-10">
{/* FILTROS */}
<div className="flex flex-col sm:flex-row gap-2 items-center justify-between">
<p className="font-bold text-md">Filtros</p>
<div className="flex flex-col sm:flex-row gap-2 w-full justify-end">
<select
value={filtroData.tipoAyuda}
onChange={(e) => 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"
>
<option value="todas">Todas las necesidades</option>
{Object.entries(tiposAyudaOptions).map(([key, label]) => (
<option key={key} value={key}>
{label}
</option>
))}
</select>
<select
value={filtroData.urgencia}
onChange={(e) => 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"
>
<option value="todas">Todas las prioridades</option>
<option value="alta">Alta prioridad</option>
<option value="media">Media prioridad</option>
<option value="baja">Baja prioridad</option>
</select>
<select
value={filtroData.pueblo}
onChange={(e) => 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"
>
<option value="todos">Todos los pueblos</option>
{towns.map((item) => (
<option key={item.id} value={item.id}>
{item.name}
</option>
))}
</select>
</div>
</div>
<div className="grid gap-4">
{data.length === 0 ? (
<div className="bg-white rounded-lg shadow-lg border border-gray-300 text-center flex justify-center items-center p-10 flex-col gap-5">
<p className="text-gray-700 text-lg font-medium">
{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.'}
No se encontraron solicitudes de ayuda correspondientes a tu cuenta.
</p>
<Link
href="/ofrecer-ayuda"
Expand All @@ -183,12 +60,9 @@ function ListaSolicitudes() {
</Link>
</div>
) : (
data.map((caso) => <OfferCard showLink={true} key={caso.id} caso={caso} />)
data.map((caso) => <OfferCard showLink={true} showEdit={true} key={caso.id} caso={caso} />)
)}
</div>
<div className="flex items-center justify-center">
<Pagination currentPage={currentPage} totalPages={numPages(currentCount)} onPageChange={changePage} />
</div>
</div>
</>
);
Expand Down
21 changes: 2 additions & 19 deletions src/app/ofrecer-ayuda/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
'use client';
import OfferHelp from '@/components/OfferHelp';
import { supabase } from '@/lib/supabase/client';
import { useEffect, useState } from 'react';
import CreateHelpOffer from '@/components/HelpOffers/CreateHelpOffer';

export default function OfrecerAyuda() {
const [session, setSession] = useState(null);

useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }: any) => {
setSession(session);
});
}, []);

return session ? (
<OfferHelp sessionProp={session} />
) : (
<div className="flex justify-center items-center min-h-screen">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
</div>
);
return <CreateHelpOffer />;
}
4 changes: 2 additions & 2 deletions src/app/punto-recogida/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState, useCallback, useEffect, FormEvent } from 'react';
import { supabase } from '@/lib/supabase/client';
import { MapPin, Phone, Package, House, Contact, Megaphone } from 'lucide-react';
import AddressAutocomplete from '@/components/AddressAutocomplete';
import AddressAutocomplete, { AddressDetails } from '@/components/AddressAutocomplete';
import { isValidPhone } from '@/helpers/utils';
import { PhoneInput } from '@/components/input/PhoneInput';
import { CollectionPointData, CollectionPointInsert } from '@/types/DataPoints';
Expand Down Expand Up @@ -220,7 +220,7 @@ export default function PuntosRecogida() {
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Dirección completa *</label>
<AddressAutocomplete
onSelect={(address: any) => {
onSelect={(address: AddressDetails) => {
setFormData((prev) => ({
...prev,
location: address.fullAddress,
Expand Down
4 changes: 2 additions & 2 deletions src/app/puntos-entrega/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useState, useEffect, FormEvent } from 'react';
import { supabase } from '@/lib/supabase/client';
import { Truck, MapPin, Phone, Mail, Calendar, Package } from 'lucide-react';
import AddressAutocomplete from '@/components/AddressAutocomplete';
import AddressAutocomplete, { AddressDetails } from '@/components/AddressAutocomplete';
import { DeliveryPointData, DeliveryPointInsert, isCoordinates } from '@/types/DataPoints';

export default function PuntosEntrega() {
Expand Down Expand Up @@ -226,7 +226,7 @@ export default function PuntosEntrega() {
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Dirección exacta *</label>
<AddressAutocomplete
onSelect={(address: any) => {
onSelect={(address: AddressDetails) => {
setFormData((prev) => ({
...prev,
location: address.fullAddress,
Expand Down
Loading
Loading