Skip to content
This repository has been archived by the owner on Oct 7, 2023. It is now read-only.

Commit

Permalink
feat: adds new query filter by city
Browse files Browse the repository at this point in the history
  • Loading branch information
rwietter committed Jul 5, 2023
1 parent 3d747dd commit b0061c9
Show file tree
Hide file tree
Showing 18 changed files with 173 additions and 28 deletions.
9 changes: 6 additions & 3 deletions domains/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type FC, type ReactNode } from 'react';
import { memo, type FC, type ReactNode } from 'react';
import { ApolloError } from '@apollo/client';
import { useFetchDataset } from '@/domains/dashboard/hooks';

Expand Down Expand Up @@ -35,7 +35,10 @@ const Dashboard: FC<Props> = ({ clinicalData }): ReactNode => {
<div className='bg-primary overflow-hidden w-screen min-h-screen text-foreground font-sans'>
<Header.Root>
<Header.Icon />
<Header.DatePicker />
<div className='flex max-w-sm'>
<Header.City />
<Header.DatePicker />
</div>
</Header.Root>
<Sidebar />
<main
Expand Down Expand Up @@ -65,4 +68,4 @@ const Dashboard: FC<Props> = ({ clinicalData }): ReactNode => {
);
};

export { Dashboard };
export default memo(Dashboard);
25 changes: 21 additions & 4 deletions domains/dashboard/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,43 @@
/* eslint-disable no-extra-boolean-cast */
import { type FC, type PropsWithChildren, type ReactNode } from 'react';
import dayjs from 'dayjs';
import { useSelectDate } from '@/domains/dashboard/hooks/useSelectDate';
import { useSelectCityStore } from '../../store';

interface Props extends PropsWithChildren<unknown> {}

const Banner: FC<Props> = (props): ReactNode => {
const { selectedDate } = useSelectDate();
const { city } = useSelectCityStore();

const startDate = dayjs(selectedDate.startDate).format('DD/MM/YYYY');
const endDate = dayjs(selectedDate.endDate).format('DD/MM/YYYY');

const hasDate = Boolean(selectedDate.startDate) && Boolean(selectedDate.endDate);
const hasCity = Boolean(city);

return (
<section className='flex justify-between px-5 pt-10'>
<section>
<h1 className='text-3xl text-slate-500 font-sans'>
Covid
<strong className='text-slate-800'>&nbsp;Insights</strong>.
</h1>
<p className='pt-2 block text-slate-500 font-semibold w-full max-w-fit'>
Pesquisa entre <strong className='text-slate-950'>{startDate}</strong> e{' '}
<strong className='text-slate-950'>{endDate}</strong>
</p>
{hasDate ? (
<p className='pt-2 block text-slate-500 font-semibold w-full max-w-fit'>
Pesquisa entre <strong className='text-slate-950'>{startDate}</strong> e{' '}
<strong className='text-slate-950'>{endDate}</strong>{' '}
{hasCity ? (
<span>
na cidade de <strong className='text-slate-950'>{city}</strong>
</span>
) : (
''
)}
</p>
) : (
<div />
)}
</section>
{props.children}
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const DashboardSkeleton = (): ReactNode => (
<div className='bg-primary overflow-hidden w-screen min-h-screen text-foreground font-sans'>
<Header.Root>
<Header.Icon />
<div className='flex max-w-sm'>
<Header.City />
<Header.DatePicker />
</div>
</Header.Root>
<Sidebar />
<main className='px-2 md:px-12 m-auto md:ml-16 mt-16 bg-background rounded-tl-3xl'>
Expand Down
21 changes: 13 additions & 8 deletions domains/dashboard/hooks/useFetchDataset/useFetchDataset.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useEffect, useState } from 'react';
import { useSelectDate } from '../useSelectDate';
import { useSelectDate } from '@/domains/dashboard/hooks';
import { type ApolloError, useLazyQuery } from '@apollo/client';
import { clinicalDataQuery } from '@/services/graphql/query';
import { type QueryProps } from '@/domains/dashboard/types/QueryProps';
import { useSelectCityStore } from '@/domains/dashboard/store';

interface UseFetchDatasetReturn {
data: QueryProps | undefined;
Expand All @@ -13,28 +14,32 @@ interface UseFetchDatasetReturn {
const useFetchDataset = (): UseFetchDatasetReturn => {
const [isMounted, setIsMounted] = useState(false);
const { selectedDate } = useSelectDate();
const { cityCode } = useSelectCityStore();

// !TODO: Invalidate cache if city is changed
const [fetch, { data, loading, error }] = useLazyQuery<QueryProps>(clinicalDataQuery, {
variables: {
startDate: selectedDate?.startDate,
endDate: selectedDate?.endDate,
},
fetchPolicy: 'cache-and-network',
nextFetchPolicy: 'cache-first',
});

// fetch data when the component is mounted && when the date is changed
useEffect(() => {
if (isMounted) {
if (isMounted && selectedDate.startDate !== null && selectedDate.endDate !== null) {
void (async function () {
await fetch();
await fetch({
variables: {
startDate: selectedDate.startDate,
endDate: selectedDate.endDate,
cityCode,
},
});
})();
}
setIsMounted(true);
return () => {
setIsMounted(false);
};
}, [selectedDate]);
}, [selectedDate.startDate, selectedDate.endDate]);

return { data, loading, error };
};
Expand Down
2 changes: 2 additions & 0 deletions domains/dashboard/hooks/useSelectDate/useSelectDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Dayjs } from 'dayjs';
import { useSlectedDateStore } from '@/domains/dashboard/store/useSlectedDateStore';
import { PANDEMIC_START_DATE, LAST_DATABASE_UPDATE } from '@/domains/dashboard/constants';
import dayjs from 'dayjs';
import { useSelectCityStore } from '@/domains/dashboard/store';

type EventValue<DateType> = DateType | null;
type RangeValue<DateType> = [EventValue<DateType>, EventValue<DateType>] | null;
Expand All @@ -11,6 +12,7 @@ interface UseSelectDateReturnType {
startDate: string;
endDate: string;
};

onChangeDate: (date: RangeValue<Dayjs>) => void;
disabledDate: (current: Dayjs) => boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion domains/dashboard/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { Dashboard } from './Dashboard';
export { default as Dashboard } from './Dashboard';
1 change: 1 addition & 0 deletions domains/dashboard/store/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { useSlectedDateStore } from './useSlectedDateStore';
export { useSelectCityStore } from './useSelectCityStore';
1 change: 1 addition & 0 deletions domains/dashboard/store/useSelectCityStore/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useSelectCityStore } from './useSelectCityStore';
27 changes: 27 additions & 0 deletions domains/dashboard/store/useSelectCityStore/useSelectCityStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { create } from 'zustand';

interface City {
city: string;
cityCode: string;
}

interface SelectedCityStore {
city: string;
cityCode: string;
setSelectedCity: ({ city, cityCode }: City) => void;
getSelectedCity: () => { city: string; cityCode: string };
}

const useSelectCityStore = create<SelectedCityStore>((set, get) => ({
city: '',
cityCode: '',
setSelectedCity: ({ city, cityCode }) => {
set({ city, cityCode });
},
getSelectedCity: () => {
const { city, cityCode } = get();
return { city, cityCode };
},
}));

export { useSelectCityStore };
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ interface SelectedDateStore {

const useSlectedDateStore = create<SelectedDateStore>((set, get) => ({
selectedDate: {
startDate: '2022-01-01T10:00:00Z',
endDate: '2022-12-31T10:00:00Z',
startDate: '',
endDate: '',
},
setSelectedDate: (startDate: string, endDate: string) => {
set({ selectedDate: { startDate, endDate } });
Expand Down
10 changes: 10 additions & 0 deletions services/graphql/query/cities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { gql } from '@apollo/client';

export const cities = gql`
query cities {
cities {
name
code
}
}
`;
28 changes: 19 additions & 9 deletions services/graphql/query/clinicalDataQuery.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,52 @@
import { gql } from '@apollo/client';

export const clinicalDataQuery = gql`
query Symptoms($startDate: DateTime, $endDate: DateTime) {
countPatients(filters: { startDate: $startDate, endDate: $endDate })
query Symptoms($startDate: DateTime, $endDate: DateTime, $cityCode: String) {
countPatients(filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode })
countPatientsSymptoms(filters: { startDate: $startDate, endDate: $endDate }) {
countPatientsSymptoms(
filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }
) {
febre
garganta
tosse
dispneia
outros
}
countPatientsByAge(filters: { startDate: $startDate, endDate: $endDate }) {
countPatientsByAge(filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }) {
age
count
}
countPatientsByRecoveryStatus(filters: { startDate: $startDate, endDate: $endDate }) {
countPatientsByRecoveryStatus(
filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }
) {
status
count
}
countPatientsByDiagnosisCriteria(filters: { startDate: $startDate, endDate: $endDate }) {
countPatientsByDiagnosisCriteria(
filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }
) {
criteria
count
}
countDeadPatients(filters: { startDate: $startDate, endDate: $endDate }) {
countDeadPatients(filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }) {
count
}
countDeadPatientsGroupedByMonth(filters: { startDate: $startDate, endDate: $endDate }) {
countDeadPatientsGroupedByMonth(
filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }
) {
month
year
count
}
averageDeadPatientAge(filters: { startDate: $startDate, endDate: $endDate }) {
averageDeadPatientAge(
filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }
) {
avg
}
}
Expand Down
1 change: 1 addition & 0 deletions services/graphql/query/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { symptomsQuery } from './symptomsQuery';
export { clinicalDataQuery } from './clinicalDataQuery';
export { cities } from './cities';
4 changes: 3 additions & 1 deletion services/graphql/query/symptomsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { gql } from '@apollo/client';

export const symptomsQuery = gql`
query Symptoms($startDate: DateTime, $endDate: DateTime) {
countPatientsSymptoms(filters: {startDate: $startDate, endDate: $endDate}) {
countPatientsSymptoms(
filters: { startDate: $startDate, endDate: $endDate, cityCode: $cityCode }
) {
febre
garganta
tosse
Expand Down
1 change: 1 addition & 0 deletions shared/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import locale from 'antd/lib/date-picker/locale/pt_BR';

const DatePicker = (): ReactNode => {
const { onChangeDate, disabledDate } = useSelectDate();

return (
<section>
<DatePickerRoot.RangePicker
Expand Down
2 changes: 2 additions & 0 deletions shared/components/Header/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { DatePicker as HeaderDatePicker } from '@/shared/components/DatePicker';
import { HeaderRoot } from './Header';
import HeaderIcon from './Icon';
import { SelectCity } from '@/shared/components/SelectCity';

export const Header = {
Root: HeaderRoot,
DatePicker: HeaderDatePicker,
Icon: HeaderIcon,
City: SelectCity,
};
58 changes: 58 additions & 0 deletions shared/components/SelectCity/SelectCity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { cities } from '@/services/graphql/query';
import { useQuery } from '@apollo/client';
import { Select } from 'antd';
import { type ComponentProps, type FC } from 'react';
import { useSelectCityStore } from '@/domains/dashboard/store';

interface Props extends ComponentProps<typeof Select> {}

interface City {
name: string;
code: string;
}

interface Data {
cities: City[];
}

const SelectCity: FC<Props> = (props) => {
const { data, error } = useQuery<Data>(cities);
const { setSelectedCity } = useSelectCityStore();

const handleSelectCity = (value: unknown, label: string): void => {
// eslint-disable-next-line no-extra-boolean-cast
if (Boolean(value)) {
setSelectedCity({ city: label, cityCode: String(value) });
}
};

if (error != null || data == null) {
return;
}

const refined = data.cities.map((city) => ({
label: city.name,
value: city.code,
}));

return (
<Select
showSearch
className='mr-3'
style={{ width: 200 }}
placeholder='Pesquise uma cidade'
optionFilterProp='children'
onSelect={(value: string | unknown, { label }) => {
handleSelectCity(value, label);
}}
filterOption={(input, option) => (option?.label ?? '').includes(input)}
filterSort={(optionA, optionB) =>
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase())
}
options={refined}
{...props}
/>
);
};

export { SelectCity };
1 change: 1 addition & 0 deletions shared/components/SelectCity/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { SelectCity } from './SelectCity';

0 comments on commit b0061c9

Please sign in to comment.