Skip to content

Commit

Permalink
Merge branch 'main' into feat/mapa-solicitar-ayuda
Browse files Browse the repository at this point in the history
  • Loading branch information
Roberto Milla Martinez committed Nov 9, 2024
2 parents d38df35 + b8a9a9b commit 6905408
Show file tree
Hide file tree
Showing 38 changed files with 3,423 additions and 270 deletions.
3,218 changes: 3,082 additions & 136 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
"lint": "next lint",
"prettier:check": "prettier . --check",
"prettier:write": "prettier . --write",
"test:e2e": "npx playwright test"
"test:e2e": "npx playwright test",
"supabase:types": "npx supabase gen types --lang=typescript --local > src/types/database.ts",
"snaplet:sync": "npx @snaplet/seed sync",
"snaplet:seed": "npx tsx seed.ts > supabase/automated_seed.sql"
},
"dependencies": {
"@emailjs/browser": "^4.4.1",
Expand All @@ -30,12 +33,16 @@
},
"devDependencies": {
"@playwright/test": "^1.48.2",
"@snaplet/copycat": "^5.1.0",
"@snaplet/seed": "^0.98.0",
"@types/node": "^22.8.7",
"@types/pg": "^8.11.10",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"eslint": "^8",
"eslint-config-next": "15.0.2",
"eslint-config-prettier": "^9.1.0",
"pg": "^8.13.1",
"postcss": "^8",
"prettier": "3.3.3",
"supabase": "^1.215.0",
Expand Down
23 changes: 23 additions & 0 deletions seed.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { SeedPg } from '@snaplet/seed/adapter-pg';
import { defineConfig } from '@snaplet/seed/config';
import { Client } from 'pg';

export default defineConfig({
adapter: async () => {
const client = new Client({
connectionString: 'postgresql://postgres:postgres@localhost:54322/postgres',
});
await client.connect();
return new SeedPg(client);
},
select: [
// We don't alter any extensions tables that might be owned by extensions
'!*',
// We want to alter all the tables under public schema
'public*',
// We also want to alter some of the tables under the auth schema
'auth.users',
'auth.identities',
'auth.sessions',
],
});
2 changes: 1 addition & 1 deletion src/app/casos-activos/mapa/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function Mapa() {
latitude: request.latitude ?? 0,
longitude: request.longitude ?? 0,
id: request.id,
popup: <SolicitudCard showLink={true} showEdit={false} caso={request} />,
popup: <SolicitudCard format="small" showLink={true} showEdit={false} caso={request} />,
};
}

Expand Down
157 changes: 95 additions & 62 deletions src/app/casos-activos/solicitudes/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use client';

import { Suspense, useEffect, useState } from 'react';
import { Suspense, useEffect, useState, useCallback, useMemo, ChangeEventHandler } from '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 { HelpRequestData } from '@/types/Requests';
import { Toggle } from '@/components/Toggle';

export const dynamic = 'force-dynamic';

Expand All @@ -19,6 +20,12 @@ export default function SolicitudesPage() {
);
}

const itemsPerPage = 10;
const numPages = (count: number) => {
return Math.ceil(count / itemsPerPage) || 0;
};
const isStringTrue = (str: string): boolean => str === 'true';

function Solicitudes() {
const { towns } = useTowns();
const searchParams = useSearchParams();
Expand All @@ -30,36 +37,45 @@ function Solicitudes() {
const [data, setData] = useState<HelpRequestData[]>([]);
const [currentPage, setCurrentPage] = useState<number>(Number(searchParams.get('page')) || 1);
const [currentCount, setCurrentCount] = useState<number>(0);

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

const updateFilter = (filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page', value: string | number) => {
const params = new URLSearchParams(searchParams.toString());
params.set(filter, value.toString());
router.push(`?${params.toString()}`);
};

const [filtroData, setFiltroData] = useState({
urgencia: searchParams.get('urgencia') || 'todas',
tipoAyuda: searchParams.get('tipoAyuda') || 'todas',
pueblo: searchParams.get('pueblo') || 'todos',
soloSinAsignar: searchParams.get('soloSinAsignar') || 'true',
});

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);
}
const updateFilter = useCallback(
(filter: 'urgencia' | 'tipoAyuda' | 'pueblo' | 'page' | 'soloSinAsignar', value: string | number) => {
const params = new URLSearchParams(searchParams.toString());
params.set(filter, value.toString());
router.push(`?${params.toString()}`);
},
[searchParams, router],
);

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

const changePage = useCallback(
(newPage: number) => {
setCurrentPage(newPage);
updateFilter('page', newPage);
},
[updateFilter],
);

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

useEffect(() => {
async function fetchData() {
Expand All @@ -84,6 +100,12 @@ function Solicitudes() {
if (filtroData.urgencia !== 'todas') {
query.eq('urgency', filtroData.urgencia);
}

// Solo agregar filtro si es true
if (isStringTrue(filtroData.soloSinAsignar)) {
query.eq('asignees_count', 0);
}

query.neq('status', 'finished');
// Ejecutar la consulta con paginación
const { data, count, error } = await query
Expand Down Expand Up @@ -128,42 +150,53 @@ function Solicitudes() {
<>
{/* 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 className="flex flex-col space-y-3 w-full">
<div className="flex flex-col sm:flex-row gap-2 w-full justify-end">
<div className="flex flex-col justify-center">
<p className="font-bold text-md">Filtros</p>
</div>
<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 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 All @@ -174,7 +207,7 @@ function Solicitudes() {
</p>
</div>
) : (
data.map((caso) => <SolicitudCard showLink={true} showEdit={true} key={caso.id} caso={caso} />)
data.map((caso) => <SolicitudCard format="small" showLink={true} showEdit={true} key={caso.id} caso={caso} />)
)}
</div>
<div className="flex items-center justify-center">
Expand Down
2 changes: 1 addition & 1 deletion src/app/punto-recogida/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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';
import { PhoneInput } from '@/components/input/PhoneInput';
import { CollectionPointData, CollectionPointInsert } from '@/types/DataPoints';

export const dynamic = 'force-dynamic';
Expand Down
4 changes: 2 additions & 2 deletions src/app/solicitar-ayuda/_components/Form/FormContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import React, { FormEvent, useCallback, useMemo, useState } from 'react';

import { FormRenderer } from './FormRenderer';
import { FormData, Status } from '../types';
import { formatPhoneNumber, isValidPhone } from '@/helpers/utils';
import { helpRequestService, townService } from '@/lib/service';
import { formatPhoneNumber, isValidPhone, removeUrls } from '@/helpers/utils';
import { Database } from '@/types/database';
import { Enums } from '@/types/common';
import { useRouter } from 'next/navigation';
Expand Down Expand Up @@ -96,7 +96,7 @@ export function FormContainer({ session }: any) {
latitude: formData.coordinates ? parseFloat(latitude) : null,
longitude: formData.coordinates ? parseFloat(longitude) : null,
help_type: mapHelpToEnum(formData.tiposDeAyuda),
description: formData.descripcion,
description: removeUrls(formData.descripcion),
urgency: formData.urgencia,
number_of_people: formData.numeroDePersonas || 1,
contact_info: formatPhoneNumber(formData.contacto),
Expand Down
24 changes: 6 additions & 18 deletions src/app/solicitar-ayuda/_components/Form/FormRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'use client';
import React from 'react';
import { Check } from 'lucide-react';

import { PhoneInput } from '@/components/PhoneInput';
import AddressMap, { AddressDescriptor } from '../../../../components/AddressMap';
import { PhoneInput } from '@/components/input/PhoneInput';
import AddressAutocomplete from '@/components/AddressAutocomplete.js';
import { TIPOS_DE_AYUDA } from '../constants';
import { TipoDeAyudaInputRenderer } from '../TipoDeAyudaInputRenderer';
import { FormData, HelpCategory, Status } from '../types';
import AddressMap, { AddressDescriptor } from '../../../../components/AddressMap';
import { LngLat } from '@/components/map/GeolocationMap';
import { LimitedTextarea } from '@/components/input/LimitedTextarea';

type FormRendererProps = {
status: Status;
Expand Down Expand Up @@ -93,19 +93,6 @@ export function FormRenderer({
</p>
</div>
)}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Ubicación exacta <span className="text-red-500">*</span>
</label>
<AddressAutocomplete
onSelect={handleAddressSelection}
placeholder="Calle, número, piso, ciudad..."
required
/>
<p className="mt-1 text-sm text-gray-500">
Incluya todos los detalles posibles para poder localizarle (campo obligatorio)
</p>
</div>

<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Tipo de ayuda necesaria</label>
Expand Down Expand Up @@ -136,13 +123,14 @@ export function FormRenderer({

<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Descripción de la situación</label>
<textarea
<LimitedTextarea
name="descripcion"
value={formData.descripcion}
onChange={handleDescriptionChange}
className="w-full p-2 border rounded focus:ring-2 focus:ring-red-500"
rows={3}
placeholder="Describa su situación actual y el tipo de ayuda que necesita"
maxLength={350}
/>
</div>

Expand Down
2 changes: 1 addition & 1 deletion src/components/OfferHelp.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import AddressAutocomplete from '@/components/AddressAutocomplete';
import { mapToIdAndLabel, tiposAyudaOptions as _tiposAyudaOptions } from '@/helpers/constants';
import { isValidPhone } from '@/helpers/utils';

import { PhoneInput } from '@/components/PhoneInput';
import { PhoneInput } from '@/components/input/PhoneInput';
import { formatPhoneNumber } from '@/helpers/utils';
import { useTowns } from '@/context/TownProvider';
import { useRouter } from 'next/navigation';
Expand Down
2 changes: 1 addition & 1 deletion src/components/RequestHelp.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { mapToIdAndLabel, tiposAyudaOptions } from '@/helpers/constants';
import { formatPhoneNumber, isValidPhone } from '@/helpers/utils';
import { helpRequestService, locationService, townService } from '@/lib/service';

import { PhoneInput } from '@/components/PhoneInput';
import { PhoneInput } from '@/components/input/PhoneInput';
import { useRouter } from 'next/navigation';
import { CallCenterLink } from '@/components/CallCenterLink';
import AddressMap from './AddressMap';
Expand Down
Loading

0 comments on commit 6905408

Please sign in to comment.