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

Map filters #216

Merged
merged 24 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
daf6661
feat: map filters wip
j8seangel Nov 11, 2024
d99fb06
basic styles for Solicitudes page
satellitestudiodesign Nov 12, 2024
d335678
add missing filters
satellitestudiodesign Nov 12, 2024
646313f
style tweaks
satellitestudiodesign Nov 12, 2024
5243f2d
tweak filters UI and add result count when filtering
satellitestudiodesign Nov 12, 2024
b55a430
change map viz and use a GeoJSONLayer
satellitestudiodesign Nov 12, 2024
75e196c
tweaks
satellitestudiodesign Nov 12, 2024
286d597
mobile layout
satellitestudiodesign Nov 12, 2024
f314c34
virtualize list
satellitestudiodesign Nov 12, 2024
5280fa2
fix sticky map
satellitestudiodesign Nov 12, 2024
dd4b932
Merge branch 'main' into map-filters
j8seangel Nov 13, 2024
594c1e0
move Map and List to components folder
satellitestudiodesign Nov 13, 2024
22c7e02
Merge branch 'main' into map-filters
j8seangel Nov 14, 2024
9defe94
update package-lock
j8seangel Nov 15, 2024
46827ac
fix: keep used properties in HelpRequestData
j8seangel Nov 15, 2024
57c2b10
Merge branch 'main' into solicitudes-asigness-count
j8seangel Nov 15, 2024
86e622e
query solicitudes sort by created_at
j8seangel Nov 15, 2024
d1f377b
fix lint
j8seangel Nov 15, 2024
d7ec10e
filter soloSinAsignar in server
j8seangel Nov 15, 2024
51608d1
more strict filter search
j8seangel Nov 15, 2024
cb8fb88
highlight matched search text
j8seangel Nov 15, 2024
40cc1cb
not render points without coordinates
j8seangel Nov 15, 2024
6846b55
fix query
j8seangel Nov 15, 2024
547960a
remove log
j8seangel Nov 15, 2024
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
28 changes: 28 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
"leaflet": "^1.9.4",
"lucide-react": "^0.454.0",
"maplibre-gl": "^4.7.1",
"match-sorter": "^8.0.0",
"next": "15.0.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-google-places-autocomplete": "^4.1.0",
"react-map-gl": "^7.1.7",
"react-virtuoso": "^4.12.0",
"sonner": "^1.7.0"
},
"devDependencies": {
Expand Down
32 changes: 0 additions & 32 deletions src/app/casos-activos/mapa/actions.tsx

This file was deleted.

157 changes: 0 additions & 157 deletions src/app/casos-activos/mapa/page.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import TabNavigation from '@/components/TabNavigation';
import { PropsWithChildren } from 'react';
import { SupabaseClient } from '@supabase/supabase-js';
import { Database } from '@/types/database';

const getCount = async (supabase: SupabaseClient<Database>) => {
const { count: solicitaCount, error: solicitaError } = await supabase
.from('help_requests')
Expand Down
114 changes: 114 additions & 0 deletions src/app/casos-activos/solicitudes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
'use client';

import { useEffect, useState, useCallback } from 'react';
import { matchSorter } from 'match-sorter';
import { useRouter, useSearchParams } from 'next/navigation';
import { FilterType } from './types';
import { useTowns } from '@/context/TownProvider';
import { TabNavigationCount } from '@/components/TabNavigation';
import Modal from '@/components/Modal';
import { MAP_MODAL_NAME } from '@/components/map/map';
import { HelpRequestData } from '@/types/Requests';
import SolicitudCard from '@/components/solicitudes/SolicitudCard';
import SolicitudList, { isStringTrue } from '@/components/solicitudes/SolicitudList';
import SolicitudMap from '@/components/solicitudes/SolicitudMap';

type DataFilter = { keys: (keyof HelpRequestData)[]; value: string };
function getDataFiltered(data: HelpRequestData[], filters: DataFilter[]) {
if (!filters || !filters.length) {
return data;
}

return filters.reduceRight(
(results, { value, keys }) =>
matchSorter(results, value, { keys, threshold: matchSorter.rankings.WORD_STARTS_WITH }),
data,
);
}

type SolicitudesProps = {
count: TabNavigationCount;
data: HelpRequestData[];
};

export function Solicitudes({ data, count }: SolicitudesProps) {
const { towns } = useTowns();
const searchParams = useSearchParams();
const router = useRouter();
const [selectedMarker, setSelectedMarker] = useState<HelpRequestData | null>(null);

const [dataFiltered, setDataFiltered] = useState<HelpRequestData[]>(data);

const [filtersData, setFiltersData] = useState({
search: searchParams.get('search') || '',
urgencia: searchParams.get('urgencia') || 'todas',
tipoAyuda: searchParams.get('tipoAyuda') || 'todas',
pueblo: searchParams.get('pueblo') || 'todos',
soloSinAsignar: searchParams.get('soloSinAsignar') || 'false',
});

const updateFilter = useCallback(
(filter: FilterType, value: string | number) => {
const params = new URLSearchParams(searchParams.toString());
params.set(filter, value.toString());
if (filter === 'soloSinAsignar') {
router.push(`?${params.toString()}`);
}
},
[searchParams, router],
);

const changeDataFilter = useCallback(
(type: FilterType, newFilter: string) => {
setFiltersData((prev) => ({
...prev,
[type]: newFilter,
}));
updateFilter(type, newFilter);
},
[updateFilter],
);

useEffect(() => {
const filters: DataFilter[] = [];
if (filtersData.search) {
filters.push({
keys: ['description'],
value: filtersData.search,
});
}
if (filtersData.pueblo && filtersData.pueblo !== 'todos') {
const town = towns.find((t) => t.id === parseInt(filtersData.pueblo));
filters.push({ keys: ['location'], value: town?.name || '' });
}
if (filtersData.urgencia && filtersData.urgencia !== 'todas') {
filters.push({ keys: ['urgency'], value: filtersData.urgencia });
}
if (filtersData.tipoAyuda && filtersData.tipoAyuda !== 'todas') {
filters.push({ keys: ['help_type'], value: filtersData.tipoAyuda });
}
const preFilteredData = isStringTrue(filtersData.soloSinAsignar)
? data.filter((d) => d.asignees_count === 0)
: data;
setDataFiltered(getDataFiltered(preFilteredData, filters));
}, [data, filtersData, towns]);

return (
<>
<div className="lg:flex lg:flex-row-reverse">
<SolicitudMap data={dataFiltered} setSelectedMarker={setSelectedMarker} />
<SolicitudList
data={dataFiltered}
count={count}
filtersData={filtersData}
onDataFilterChange={changeDataFilter}
/>
</div>
{selectedMarker && (
<Modal id={MAP_MODAL_NAME}>
<SolicitudCard format="small" showLink={true} showEdit={false} caso={selectedMarker} />
</Modal>
)}
</>
);
}
Loading