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] Adicionar filtro de pix e contato - Issue #325 #341

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from
137 changes: 121 additions & 16 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const initialFilterData: IFilterFormProps = {
supplyIds: [],
shelterStatus: [],
cities: [],
pix: '',
contact: '',
};

const Home = () => {
Expand Down Expand Up @@ -62,6 +64,8 @@ const Home = () => {
supplyIds: values.supplyIds,
shelterStatus: values.shelterStatus,
cities: values.cities,
pix: values.pix,
contact: values.contact,
};
return searchQueryArgs;
}, []);
Expand Down
29 changes: 29 additions & 0 deletions src/pages/Home/components/Filter/CheckBoxFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';

interface CheckBoxFilterProps {
onChangeCheck: (ev: React.ChangeEvent<HTMLInputElement>) => void;
defaultChecked?: boolean;
label: string;
}

const CheckBoxFilter: React.FC<CheckBoxFilterProps> = ({
onChangeCheck,
defaultChecked,
label,
}) => {
return (
<div>
<label className="flex items-center mb-4">
<input
type="checkbox"
className="mr-2 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onChange={onChangeCheck}
defaultChecked={defaultChecked}
/>
{label}
</label>
</div>
);
};

export default CheckBoxFilter;
134 changes: 77 additions & 57 deletions src/pages/Home/components/Filter/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ import { priorityOptions } from '@/lib/utils';
import CitiesFilter from './CitiesFilter';
import { IUseSuppliesData } from '@/hooks/useSupplies/types';
import { SupplyPriority } from '@/service/supply/types';
import TitleSection from './TitleSection';
import Section from './Section';
import CheckBoxFilter from './CheckBoxFilter';

const BOOLEAN_AS_STRING_FROM_QUERY_URL = "true";
const ShelterAvailabilityStatusMapped: Record<
ShelterAvailabilityStatus,
string
Expand All @@ -35,6 +39,11 @@ const ShelterAvailabilityStatusMapped: Record<
waiting: 'Sem informação de disponibilidade',
};

const shelterAvailabilityStatus = Object.keys(ShelterAvailabilityStatusMapped);
const AVAILABLE_STATUS = shelterAvailabilityStatus[0] as ShelterAvailabilityStatus;
const UNAVAILABLE_STATUS = shelterAvailabilityStatus[1] as ShelterAvailabilityStatus;
const WAITING_STATUS = shelterAvailabilityStatus[2] as ShelterAvailabilityStatus;

const priorityOpts = Object.entries(priorityOptions).reduce(
(prev, [priority, label]) =>
priority === `${SupplyPriority.NotNeeded}`
Expand All @@ -43,6 +52,9 @@ const priorityOpts = Object.entries(priorityOptions).reduce(
{} as Record<SupplyPriority, string>
);

const ensureTrueAsString = (data: string): string =>
data === "true" ? data : "";

const Filter = (props: IFilterProps) => {
const { data, onClose, onSubmit, open } = props;
const { data: supplies, loading: loadingSupplies } = useSupplies();
Expand Down Expand Up @@ -82,6 +94,8 @@ const Filter = (props: IFilterProps) => {
value: id,
label: mappedSupplies[id]?.name,
})),
pix: ensureTrueAsString(data.pix),
contact: ensureTrueAsString(data.contact),
},
enableReinitialize: true,
validateOnChange: false,
Expand All @@ -98,6 +112,8 @@ const Filter = (props: IFilterProps) => {
supplies,
supplyCategories,
cities,
pix,
contact,
} = values;
onSubmit({
priorities: priorities.map((p) => p.value),
Expand All @@ -106,6 +122,8 @@ const Filter = (props: IFilterProps) => {
supplyCategoryIds: supplyCategories.map((s) => s.value),
supplyIds: supplies.map((s) => s.value),
cities,
pix,
contact,
});
},
}
Expand Down Expand Up @@ -142,8 +160,43 @@ const Filter = (props: IFilterProps) => {
[setFieldValue, values.shelterStatus]
);

const handleToggleTo = useCallback(
(data: string, checked: boolean, ) => {
setFieldValue(data, checked ? String(checked) : undefined);
},
[setFieldValue]
);

const toggleShelterStatusTo = (status: ShelterAvailabilityStatus) =>
(ev: React.ChangeEvent<HTMLInputElement>) =>
handleToggleShelterStatus(ev.target.checked, status);

const someShelterStatusEqualTo = (status: ShelterAvailabilityStatus): boolean =>
values.shelterStatus.some((s) => s.value === status);

const ensureBooleanValueTo = (data: string): boolean =>
data === BOOLEAN_AS_STRING_FROM_QUERY_URL;

if (loadingSupplies || loadingSupplyCategories) return <LoadingScreen />;

function helpFromDistanceSection(): import("react").ReactNode {
return (
<Section>
<TitleSection title="Ajuda a distância" />
<CheckBoxFilter
label="Possui chave pix"
onChangeCheck={(ev) => handleToggleTo('pix', ev.target.checked)}
defaultChecked={ensureBooleanValueTo(values.pix)}
/>
<CheckBoxFilter
label="Possui contato telefônico"
onChangeCheck={(ev) => handleToggleTo('contact', ev.target.checked)}
defaultChecked={ensureBooleanValueTo(values.contact)}
/>
</Section>
);
}

return (
<Dialog open={open} onOpenChange={onClose}>
<DialogContent className="rounded-md overflow-y-scroll max-h-[85vh] mt-8">
Expand All @@ -154,12 +207,12 @@ const Filter = (props: IFilterProps) => {
</DialogHeader>
<form onSubmit={handleSubmit}>
<div className="pl-4 pr-4 pb-4 flex flex-col max-w-5xl w-full items-start">
<div className="flex flex-col gap-2 w-full my-4">
<Section>
<SearchInput
value={values.search}
onChange={(v) => setFieldValue('search', v)}
/>
</div>
</Section>
<Separator className="mt-2" />
<CitiesFilter
cities={values.cities}
Expand All @@ -168,7 +221,7 @@ const Filter = (props: IFilterProps) => {
}}
/>
<Separator className="mt-2" />
<div className="flex flex-col gap-2 w-full my-4">
<Section>
<p className="text-sm md:text-lg font-medium">Busca avançada</p>
<p className="text-muted-foreground text-sm md:text-lg font-medium">
Você pode buscar pelo item que os abrigos precisam com urgência
Expand Down Expand Up @@ -221,61 +274,28 @@ const Filter = (props: IFilterProps) => {
onChange={(v) => setFieldValue('supplies', v)}
/>
</div>
</div>
</Section>
<Separator className="mt-2" />
<div className="flex flex-col gap-2 w-full my-4">
<p className="text-muted-foreground text-sm md:text-lg font-medium">
Status do abrigo
</p>
<div>
<label className="flex items-center mb-4">
<input
type="checkbox"
className="mr-2 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onChange={(ev) =>
handleToggleShelterStatus(ev.target.checked, 'available')
}
defaultChecked={values.shelterStatus.some(
(s) => s.value === 'available'
)}
/>
Abrigo Disponivel
</label>
</div>
<div>
<label className="flex items-center mb-4">
<input
type="checkbox"
className="mr-2 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onChange={(ev) =>
handleToggleShelterStatus(
ev.target.checked,
'unavailable'
)
}
defaultChecked={values.shelterStatus.some(
(s) => s.value === 'unavailable'
)}
/>
Abrigo Indisponível
</label>
</div>
<div>
<label className="flex items-center mb-4">
<input
type="checkbox"
className="mr-2 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
onChange={(ev) =>
handleToggleShelterStatus(ev.target.checked, 'waiting')
}
defaultChecked={values.shelterStatus.some(
(s) => s.value === 'waiting'
)}
/>
Sem informação de disponibilidade
</label>
</div>
</div>
<Section>
<TitleSection title="Status do abrigo" />
<CheckBoxFilter
label="Abrigo Disponivel"
onChangeCheck={toggleShelterStatusTo(AVAILABLE_STATUS)}
defaultChecked={someShelterStatusEqualTo(AVAILABLE_STATUS)}
/>
<CheckBoxFilter
label="Abrigo Indisponivel"
onChangeCheck={toggleShelterStatusTo(UNAVAILABLE_STATUS)}
defaultChecked={someShelterStatusEqualTo(UNAVAILABLE_STATUS)}
/>
<CheckBoxFilter
label="Sem informação de disponibilidade"
onChangeCheck={toggleShelterStatusTo(WAITING_STATUS)}
defaultChecked={someShelterStatusEqualTo(WAITING_STATUS)}
/>
</Section>
<Separator className="mt-2" />
{helpFromDistanceSection()}
</div>
<DialogFooter className="sticky bg-white -bottom-6">
<div className="flex flex-1 flex-col justify-end md:justify-start w-full py-6">
Expand Down
15 changes: 15 additions & 0 deletions src/pages/Home/components/Filter/Section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { ReactNode } from 'react';

type SectionProps = {
children: ReactNode;
};

const Section: React.FC<SectionProps> = ({ children }) => {
return (
<div className="flex flex-col gap-2 w-full my-4">
{children}
</div>
);
};

export default Section;
15 changes: 15 additions & 0 deletions src/pages/Home/components/Filter/TitleSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';

interface TitleSectionProps {
title: string;
}

const TitleSection: React.FC<TitleSectionProps> = ({ title }) => {
return (
<p className="text-muted-foreground text-sm md:text-lg font-medium">
{title}
</p>
);
};

export default TitleSection;
4 changes: 4 additions & 0 deletions src/pages/Home/components/Filter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export interface IFilterFormProps {
supplyIds: string[];
shelterStatus: ShelterAvailabilityStatus[];
cities: string[];
pix: string;
contact: string;
}

export interface IFilterSubmittionForm extends Omit<IFilterFormProps, 'priority'>{
Expand All @@ -25,6 +27,8 @@ export interface IFilterFormikProps {
supplies: ISelectField[];
shelterStatus: ISelectField<ShelterAvailabilityStatus>[];
cities: string[];
pix: string;
contact: string;
}

export interface IFilterProps {
Expand Down