Skip to content

Commit

Permalink
fix filters on category pages
Browse files Browse the repository at this point in the history
  • Loading branch information
jamalsoueidan committed Jul 14, 2024
1 parent 8528d9a commit 11e6b7b
Show file tree
Hide file tree
Showing 13 changed files with 559 additions and 106 deletions.
6 changes: 2 additions & 4 deletions app/components/artist/PriceBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,15 @@ export function PriceBadge({
}, [compareAtPrice?.amount, price.amount, t]);

return (
<Flex direction="column" gap="4px" justify="flex-start" align="flex-end">
<Flex direction="column" gap="4px" justify="flex-start">
<Text size="sm" {...props}>
{options ? t('from') : ''} {price.amount} kr
</Text>
{discountString ? (
<Text c="green.9" size="sm">
{discountString}
</Text>
) : (
<br />
)}
) : null}
</Flex>
);
}
61 changes: 59 additions & 2 deletions app/components/filters/CityFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import {Button, Select} from '@mantine/core';
import {IconWorld, IconX} from '@tabler/icons-react';
import {
Button,
Checkbox,
Group,
InputLabel,
Select,
Stack,
} from '@mantine/core';
import {useSearchParams} from '@remix-run/react';
import {IconLocation, IconWorld, IconX} from '@tabler/icons-react';
import {useTranslation} from 'react-i18next';
import {type UserCollectionFilterFragment} from 'storefrontapi.generated';
import {useFilterCounts} from '~/hooks/useFilterCounts';
import {useChangeFilter} from './useChangeFilter';

export function RemoveCityFilterButton() {
Expand Down Expand Up @@ -50,3 +60,50 @@ export function AddCityFilter({tags}: {tags: string[] | null}) {
/>
);
}

export function CityFilter({
filters,
}: {
filters: UserCollectionFilterFragment[];
}) {
const [searchParams, setSearchParams] = useSearchParams();
const {t} = useTranslation(['global']);
const cities = useFilterCounts(filters as any, 'city');

return (
<Stack>
<Group gap="xs">
<IconLocation />
<InputLabel size="md">{t('city_label')}</InputLabel>
</Group>
<Checkbox.Group
value={searchParams.getAll('city')}
onChange={(cities: string[]) =>
setSearchParams(
(prev) => {
prev.delete('city');
cities.forEach((item) => {
prev.append('city', item);
});
return prev;
},
{preventScrollReset: true},
)
}
>
<Stack gap="xs">
{Object.keys(cities).map((city) => (
<Checkbox
key={city}
value={city}
label={`${city[0].toUpperCase()}${city.substring(1)} (${
cities[city]
})`}
disabled={cities[city] === 0}
/>
))}
</Stack>
</Checkbox.Group>
</Stack>
);
}
123 changes: 122 additions & 1 deletion app/components/filters/LocationFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import {Button, Group, InputLabel, Radio, Stack, Text} from '@mantine/core';
import {
Button,
Checkbox,
type CheckboxProps,
Group,
InputLabel,
Radio,
Stack,
Text,
} from '@mantine/core';
import {useSearchParams} from '@remix-run/react';
import {
IconBiohazard,
IconBuilding,
IconCar,
IconHome,
Expand All @@ -8,6 +19,8 @@ import {
IconX,
} from '@tabler/icons-react';
import {useTranslation} from 'react-i18next';
import {type UserCollectionFilterFragment} from 'storefrontapi.generated';
import {useFilterCounts} from '~/hooks/useFilterCounts';
import {CustomerLocationBaseLocationType} from '~/lib/api/model';
import {useChangeFilter} from './useChangeFilter';

Expand Down Expand Up @@ -120,3 +133,111 @@ export function AddLocationFilter({tags}: {tags: string[] | null}) {
</div>
);
}

export function LocationFilter({
filters,
}: {
filters: UserCollectionFilterFragment[];
}) {
const [searchParams, setSearchParams] = useSearchParams();
const {t} = useTranslation(['global']);
const locationType = useFilterCounts(filters as any, 'location_type');

const CheckboxIconCar: CheckboxProps['icon'] = ({indeterminate, ...others}) =>
indeterminate ? <IconBiohazard {...others} /> : <IconCar {...others} />;

const CheckboxIconHome: CheckboxProps['icon'] = ({
indeterminate,
...others
}) =>
indeterminate ? <IconBiohazard {...others} /> : <IconHome {...others} />;

const CheckboxIconBuilding: CheckboxProps['icon'] = ({
indeterminate,
...others
}) =>
indeterminate ? (
<IconBiohazard {...others} />
) : (
<IconBuilding {...others} />
);

const CheckboxIconPhone: CheckboxProps['icon'] = ({
indeterminate,
...others
}) =>
indeterminate ? <IconBiohazard {...others} /> : <IconPhone {...others} />;

return (
<Stack>
<Group gap="xs">
<IconLocation />
<InputLabel size="md">{t('location_label')}</InputLabel>
</Group>
<Checkbox.Group
value={searchParams.getAll('locationType')}
onChange={(locationType: string[]) =>
setSearchParams(
(prev) => {
prev.delete('locationType');
locationType.forEach((item) => {
prev.append('locationType', item);
});
return prev;
},
{preventScrollReset: true},
)
}
>
<Stack gap="xs">
<Checkbox
value={CustomerLocationBaseLocationType.destination}
icon={CheckboxIconCar}
label={`${t('location_destination')} (${
locationType[CustomerLocationBaseLocationType.destination] || 0
})`}
disabled={
locationType[CustomerLocationBaseLocationType.destination] ===
0 || !locationType[CustomerLocationBaseLocationType.destination]
}
/>

<Checkbox
icon={CheckboxIconBuilding}
value={CustomerLocationBaseLocationType.commercial}
label={`${t('location_commercial')} (${
locationType[CustomerLocationBaseLocationType.commercial] || 0
})`}
disabled={
locationType[CustomerLocationBaseLocationType.commercial] === 0 ||
!locationType[CustomerLocationBaseLocationType.commercial]
}
/>

<Checkbox
icon={CheckboxIconHome}
value={CustomerLocationBaseLocationType.home}
label={`${t('location_home')} (
${locationType[CustomerLocationBaseLocationType.home] || 0})`}
disabled={
locationType[CustomerLocationBaseLocationType.home] === 0 ||
!locationType[CustomerLocationBaseLocationType.home]
}
/>
<Checkbox
icon={CheckboxIconPhone}
value={CustomerLocationBaseLocationType.virtual}
label={`${t('location_virtual')} (
${
locationType[CustomerLocationBaseLocationType.virtual] || 0
})`}
disabled={
locationType[CustomerLocationBaseLocationType.virtual] === 0 ||
!locationType[CustomerLocationBaseLocationType.virtual]
}
/>
</Stack>
</Checkbox.Group>
</Stack>
);
}
2 changes: 1 addition & 1 deletion app/components/filters/ResetFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function ResetFilter() {
color="gray.3"
bg="white"
onClick={deleteSearchParams}
size="xl"
size="sm"
rightSection={<IconX />}
>
{t('reset_filters')}
Expand Down
12 changes: 0 additions & 12 deletions app/graphql/fragments/UserCollectionOnlyFilters.ts

This file was deleted.

24 changes: 24 additions & 0 deletions app/hooks/useFilterCounts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {useMemo} from 'react';
import {type UserCollectionFilterFragment} from 'storefrontapi.generated';

export const useFilterCounts = (
filters: UserCollectionFilterFragment[],
patternKey: string,
): Record<string, number> => {
return useMemo(() => {
const pattern = new RegExp(`^${patternKey}-(.+)$`);
const counts: Record<string, number> = {};

filters.forEach((filter) => {
filter.values.forEach((value) => {
const match = value.label.match(pattern);
if (match) {
const key = match[1];
counts[key] = value.count || 0; // default to 0 if not found
}
});
});

return counts;
}, [filters, patternKey]);
};
17 changes: 13 additions & 4 deletions app/i18n/@types/resources.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ interface Resources {
"create_business": "Gem og forsæt",
"step": "Step {{step}}",
"location": {
"title": "Hvordan vil du gerne tilbyde dine tjenester?",
"title": "Angiv et mødested",
"commercial": "Salon: dine kunder kommer til en butik",
"home": "Hjemme: dine kunder kommer til dit hjem",
"destination": "Mobil: du tager hjem til din kunder",
Expand All @@ -93,15 +93,15 @@ interface Resources {
"submit": "Gem og forsæt"
},
"schedule": {
"title": "Hvordan ser din arbejdsuge ud?",
"title": "Vælg de tidspunkter, hvor du er tilgængelig",
"submit": "Gem og forsæt"
},
"service": {
"title": "Opret din første ydelse",
"submit": "Gem og forsæt"
},
"profile": {
"title": "...udfyld resten af felterne for at fuldføre din profil",
"title": "Udfyld resten af felterne for at fuldføre din profil",
"description": "Du kan vælge og trykke på AI knappen og autoudfylde felterne udefra de de data du har angivet herunder."
}
}
Expand Down Expand Up @@ -184,7 +184,16 @@ interface Resources {
"price_label": "Pris:",
"reset_filters": "Nulstil filtering",
"man": "Mand",
"woman": "Woman"
"woman": "Woman",
"best_selling": "Bedst Sælgende",
"created_at": "Oprettet Dato",
"id": "ID",
"price": "Pris",
"product_type": "Produkt Type",
"relevance": "Relevans",
"title": "Titel",
"updated_at": "Opdateret dDto",
"vendor": "Leverandør"
},
"index": {
"collection_title": "Hvilken [skønhedsoplevelse] ønsker du?",
Expand Down
26 changes: 26 additions & 0 deletions app/lib/generateQuerySearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {type ProductFilter} from '@shopify/hydrogen/storefront-api-types';

export function generateQuerySearch(filters: ProductFilter[]): string {
const groupedFilters: Record<string, string[]> = {};

filters.forEach((filter) => {
if (filter.tag) {
const [type, value] = filter.tag.split('-');
if (!groupedFilters[type]) {
groupedFilters[type] = [];
}
groupedFilters[type].push(`${type}-${value}`);
}
});

const queryParts: string[] = [];
Object.keys(groupedFilters).forEach((key) => {
if (groupedFilters[key].length > 1) {
queryParts.push(`(${groupedFilters[key].join(' AND ')})`);
} else {
queryParts.push(groupedFilters[key][0]);
}
});

return queryParts.join(' AND ');
}
Loading

0 comments on commit 11e6b7b

Please sign in to comment.