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

[Melhoria] Mostrar filtros selecionados no popup de Filtros na tela principal #334

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Open
6 changes: 3 additions & 3 deletions src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,10 @@ const Home = () => {
setFilterData((prev) => ({ ...prev, search: v }));
setSearch(v);
}}
onCitiesChange={(v) => {
setFilterData((prev) => ({ ...prev, cities: v }));
onFilterBadgeClicked={(newFilterData) => {
setFilterData((prev) => ({ ...prev, ...newFilterData }));
const searchQuery = qs.stringify(
{ ...filterData, cities: v },
{ ...filterData, ...newFilterData },
{
skipNulls: true,
}
Expand Down
30 changes: 17 additions & 13 deletions src/pages/Home/components/Filter/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import CitiesFilter from './CitiesFilter';
import { IUseSuppliesData } from '@/hooks/useSupplies/types';
import { SupplyPriority } from '@/service/supply/types';

const ShelterAvailabilityStatusMapped: Record<
export const ShelterAvailabilityStatusMapped: Record<
ShelterAvailabilityStatus,
string
> = {
Expand All @@ -43,23 +43,27 @@ const priorityOpts = Object.entries(priorityOptions).reduce(
{} as Record<SupplyPriority, string>
);

const dataKeyToIdValueToObj =
(
prev: Record<string, IUseSuppliesData | ISupplyCategory>,
current: ISupplyCategory | IUseSuppliesData
) =>
({ ...prev, [current.id]: current });


export const mapSupplyCategories = (supplyCategories: ISupplyCategory[]) =>
supplyCategories.reduce(dataKeyToIdValueToObj, {} as Record<string, ISupplyCategory>);

export const mapSupplies = (supplies: IUseSuppliesData[]) =>
supplies.reduce(dataKeyToIdValueToObj, {} as Record<string, IUseSuppliesData>);

const Filter = (props: IFilterProps) => {
const { data, onClose, onSubmit, open } = props;
const { data: supplies, loading: loadingSupplies } = useSupplies();
const { data: supplyCategories, loading: loadingSupplyCategories } =
useSupplyCategories();
const mappedSupplyCategories = useMemo(() => {
return supplyCategories.reduce(
(prev, current) => ({ ...prev, [current.id]: current }),
{} as Record<string, ISupplyCategory>
);
}, [supplyCategories]);
const mappedSupplies = useMemo(() => {
return supplies.reduce(
(prev, current) => ({ ...prev, [current.id]: current }),
{} as Record<string, IUseSuppliesData>
);
}, [supplies]);
const mappedSupplyCategories = useMemo(() => mapSupplyCategories(supplyCategories), [supplyCategories]);
const mappedSupplies = useMemo(() => mapSupplies(supplies), [supplies]);

const { handleSubmit, values, setFieldValue } = useFormik<IFilterFormikProps>(
{
Expand Down
1 change: 1 addition & 0 deletions src/pages/Home/components/Filter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface IFilterFormProps {
supplyIds: string[];
shelterStatus: ShelterAvailabilityStatus[];
cities: string[];
[key: string]: string | string[];
}

export interface IFilterFormikProps {
Expand Down
88 changes: 88 additions & 0 deletions src/pages/Home/components/FilterBadges/FilterBadges.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useMemo } from 'react';
import { X } from 'lucide-react';

import { getSupplyPriorityProps } from '@/lib/utils';
import { useSupplyCategories } from '@/hooks/useSupplyCategories';
import { useSupplies } from '@/hooks/useSupplies';
import { ShelterAvailabilityStatusMapped, mapSupplies, mapSupplyCategories } from '../Filter/Filter';
import { IFilterBadgesProps } from './types';
import { IFilterFormProps, ShelterAvailabilityStatus } from '../Filter/types';

function removeFilter({ from: filterData, filter: item } : { from: IFilterFormProps, filter: string }): IFilterFormProps {
const filterFormPropsListNames = Object.keys(filterData);
const onlyArrayProps = filterFormPropsListNames.filter((prop) => Array.isArray(filterData[prop as keyof IFilterFormProps]));
const newFilterData: IFilterFormProps = {
search: "",
priority: [],
supplyCategoryIds: [],
supplyIds: [],
shelterStatus: [],
cities: []
}

onlyArrayProps.forEach((property: string) => {
const propertyValue = filterData[property as keyof IFilterFormProps];

if (Array.isArray(propertyValue)) {
const newValues = propertyValue.filter((it) => it !== item) as typeof propertyValue;
newFilterData[property] = [...newValues];
}
});

return newFilterData;
}

const ensureDataIsArray = (data: string[] | ShelterAvailabilityStatus[] | string): string[] | ShelterAvailabilityStatus[] => {

try {
if (Array.isArray(data)) {
return data;
}

throw new Error("Filter URI query is not an array.");
} catch (error) {
console.error(error);
}

return [];
};

const FilterBadges = React.forwardRef<
HTMLDivElement,
IFilterBadgesProps
>((props, ref) => {
const { filterData, onBadgeClicked } = props;

const { data: supplyCategories } = useSupplyCategories();
const mappedSupplyCategories = useMemo(() =>
mapSupplyCategories(supplyCategories), [supplyCategories]);
const { data: supplies } = useSupplies();
const mappedSupplies = useMemo(() => mapSupplies(supplies), [supplies]);

const renderFilterBadge = (filterKey: string, filterLabel: string) => {
return <div
className="flex items-center px-4 py-1 font-normal text-sm md:text-md rounded-3xl bg-gray-300 justify-center cursor-pointer hover:opacity-80 transition-all duration-200"
key={filterKey}
onClick={() =>
onBadgeClicked?.(removeFilter({ from: filterData, filter: filterKey }))}
>
<span className="pr-1">{filterLabel}</span> <X className="h-4 w-4" />
</div>;
};

return (
<div ref={ref} className="flex flex-wrap gap-1 items-center">
{ensureDataIsArray(filterData.cities)?.map((city) => renderFilterBadge(city, city))}
{ensureDataIsArray(filterData.priority)?.map((priorityLevel) =>
renderFilterBadge(priorityLevel, getSupplyPriorityProps(+priorityLevel).label))}
{ensureDataIsArray(filterData.supplyCategoryIds)?.map((supplyCategoryId) =>
renderFilterBadge(supplyCategoryId, mappedSupplyCategories[supplyCategoryId]?.name))}
{ensureDataIsArray(filterData.supplyIds)?.map((supplyId) =>
renderFilterBadge(supplyId, mappedSupplies[supplyId]?.name))}
{ensureDataIsArray(filterData.shelterStatus)?.map((statusLabel) =>
renderFilterBadge(statusLabel, ShelterAvailabilityStatusMapped[statusLabel as ShelterAvailabilityStatus]))}
</div>
);
});

export { FilterBadges };
3 changes: 3 additions & 0 deletions src/pages/Home/components/FilterBadges/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { FilterBadges } from './FilterBadges';

export { FilterBadges };
8 changes: 8 additions & 0 deletions src/pages/Home/components/FilterBadges/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IFilterFormProps } from "../Filter/types";


export interface IFilterBadgesProps
extends React.ComponentPropsWithoutRef<'div'> {
filterData: IFilterFormProps;
onBadgeClicked?: (v: IFilterFormProps) => void;
}
21 changes: 6 additions & 15 deletions src/pages/Home/components/ShelterListView/ShelterListView.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Fragment } from 'react';
import { CircleAlert, ListFilter, X } from 'lucide-react';
import { CircleAlert, ListFilter } from 'lucide-react';

import {
Alert,
Expand All @@ -12,6 +12,7 @@ import { cn } from '@/lib/utils';
import { IShelterListViewProps } from './types';
import { useSearchParams } from 'react-router-dom';
import { LoadingSkeleton } from '@/components/LoadingSkeleton';
import { FilterBadges } from '../FilterBadges';

const ShelterListView = React.forwardRef<HTMLDivElement, IShelterListViewProps>(
(props, ref) => {
Expand All @@ -22,7 +23,7 @@ const ShelterListView = React.forwardRef<HTMLDivElement, IShelterListViewProps>(
searchValue = '',
hasMoreItems = false,
onSearchValueChange,
onCitiesChange,
onFilterBadgeClicked,
onFetchMoreData,
className = '',
onOpenModal,
Expand Down Expand Up @@ -52,19 +53,9 @@ const ShelterListView = React.forwardRef<HTMLDivElement, IShelterListViewProps>(
: undefined
}
/>
<div className="flex flex-wrap gap-1 items-center">
{filterData.cities?.map((item) => (
<div
className="flex items-center px-4 py-1 font-normal text-sm md:text-md rounded-3xl bg-gray-300 justify-center cursor-pointer hover:opacity-80 transition-all duration-200"
key={item}
onClick={() =>
onCitiesChange?.(filterData.cities.filter((it) => it !== item))
}
>
<span className="pr-1">{item}</span> <X className="h-4 w-4" />
</div>
))}
</div>

<FilterBadges filterData={filterData} onBadgeClicked={onFilterBadgeClicked} />

<div className="flex flex-row">
<Button
variant="ghost"
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Home/components/ShelterListView/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface IShelterListViewProps
onOpenModal?: () => void;
onClearSearch?: () => void;
onSearchValueChange?: (v: string) => void;
onCitiesChange?: (v: string[]) => void;
onFilterBadgeClicked?: (v: IFilterFormProps) => void;
onFetchMoreData?: () => void;
onSelectShelter?: (shelter: IUseSheltersData) => void;
filterData: IFilterFormProps;
Expand Down