Skip to content

Commit

Permalink
Merge pull request #28 from jebbaited/update-years-filter
Browse files Browse the repository at this point in the history
feature: add the ability to enter start and end years on the filter section
  • Loading branch information
olexh authored May 22, 2024
2 parents f3b2d04 + a1c2741 commit dc079ac
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 15 deletions.
9 changes: 2 additions & 7 deletions components/markdown/viewer/MD-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ interface Props extends Options {
disableSpoiler?: boolean;
}

const Component = ({
children,
className,
disableSpoiler,
...props
}: Props) => {
const MDViewer = ({ children, className, disableSpoiler, ...props }: Props) => {
return (
<Markdown
className={cn('markdown w-full', className)}
Expand Down Expand Up @@ -54,4 +49,4 @@ const Component = ({
);
};

export default memo(Component);
export default memo(MDViewer);
33 changes: 25 additions & 8 deletions features/filters/anime-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ import {
renderSelectOptions,
} from '@/components/ui/select';
import { Slider } from '@/components/ui/slider';

import BadgeFilter from '@/features/filters/badge-filter';
import { Switch } from '@/components/ui/switch';

import getAnimeGenres from '@/services/api/anime/getAnimeGenres';
import useCompanies from '@/services/hooks/companies/useCompanies';
Expand All @@ -39,9 +38,17 @@ import {
import createQueryString from '@/utils/createQueryString';
import { cn } from '@/utils/utils';

import { Switch } from '../../components/ui/switch';
import BadgeFilter from './badge-filter';
import YearFilterInput from './year-filter-input';

const YEARS: [number, number] = [1965, new Date().getFullYear()];
const DEFAULT_YEAR_START = YEARS[0].toString();
const DEFAULT_YEAR_END = YEARS[1].toString();

enum RANGE {
MIN = 'min',
MAX = 'max',
}

interface Props {
className?: string;
Expand Down Expand Up @@ -330,8 +337,13 @@ const AnimeFilters: FC<Props> = ({ className, type }) => {
</div>
<div className="flex w-full flex-col gap-4">
<Label className="text-muted-foreground">Рік виходу</Label>
<div className="flex items-center gap-4">
<Label className="w-9">{selectingYears[0]}</Label>
<div className="flex items-center gap-2">
<YearFilterInput
years={selectingYears}
setSelectingYears={setSelectingYears}
range={RANGE.MIN}
handleChangeParam={handleChangeParam}
/>
<Slider
className="flex-1"
onValueCommit={(value) =>
Expand All @@ -345,12 +357,17 @@ const AnimeFilters: FC<Props> = ({ className, type }) => {
(value as number[]).map(String),
)
}
min={YEARS[0]}
max={YEARS[1]}
min={Number(DEFAULT_YEAR_START)}
max={Number(DEFAULT_YEAR_END)}
minStepsBetweenThumbs={0}
value={selectingYears.map((y) => Number(y))}
/>
<Label className="w-9">{selectingYears[1]}</Label>
<YearFilterInput
years={selectingYears}
setSelectingYears={setSelectingYears}
range={RANGE.MAX}
handleChangeParam={handleChangeParam}
/>
</div>
</div>
</div>
Expand Down
138 changes: 138 additions & 0 deletions features/filters/year-filter-input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { FC, useEffect, useState } from 'react';

import { Input } from '@/components/ui/input';

import { cn } from '@/utils/utils';

enum RANGE {
MIN = 'min',
MAX = 'max',
}

const YEARS: [number, number] = [1965, new Date().getFullYear()];
const DEFAULT_YEAR_START = YEARS[0].toString();
const DEFAULT_YEAR_END = YEARS[1].toString();

interface YearFilterInputProps {
years: string[];
setSelectingYears: (years: string[]) => void;
handleChangeParam: (
name: string,
value: string | string[] | boolean,
) => void;
range: RANGE;
}

const YearFilterInput: FC<YearFilterInputProps> = ({
years,
setSelectingYears,
handleChangeParam,
range,
}) => {
const [yearValue, setYearValue] = useState<string>(
range === RANGE.MIN ? years[0] : years[1],
);

const changeYearsParams = (value: string[]) => {
setSelectingYears(value);
handleChangeParam('years', value);
};

const debouncedChangeYearsParams = (
value: string[],
delay: number = 400,
) => {
setTimeout(() => {
changeYearsParams(value);
}, delay);
};

const resetYearIfInvalid = (
yearValue: string,
defaultYear: string,
years: string[],
) => {
if (
yearValue === '' ||
Number(yearValue) < Number(DEFAULT_YEAR_START) ||
Number(yearValue) > Number(DEFAULT_YEAR_END)
) {
setYearValue(defaultYear);
debouncedChangeYearsParams(
range === RANGE.MIN
? [defaultYear, years[1]]
: [years[0], defaultYear],
);
}
};

const handleYearChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
const digitsOnlyRegex = /^(?!0)\d+$/;
const isInRange =
Number(value) >= Number(DEFAULT_YEAR_START) &&
Number(value) <= Number(DEFAULT_YEAR_END);

if (!digitsOnlyRegex.test(value)) {
if (range === RANGE.MIN && !value) {
debouncedChangeYearsParams([DEFAULT_YEAR_START, years[1]]);
}

if (range === RANGE.MAX && !value) {
debouncedChangeYearsParams([years[0], DEFAULT_YEAR_END]);
}

return setYearValue('');
}

if (range === RANGE.MIN) {
if (isInRange) {
if (Number(value) > Number(years[1])) {
return debouncedChangeYearsParams([years[1], value]);
}

debouncedChangeYearsParams([value, years[1]]);
}
}

if (range === RANGE.MAX) {
if (isInRange) {
if (Number(value) < Number(years[0])) {
return debouncedChangeYearsParams([value, years[0]]);
}

debouncedChangeYearsParams([years[0], value]);
}
}

setYearValue(value);
};

const handleBlur = () => {
if (range === RANGE.MIN) {
resetYearIfInvalid(yearValue, DEFAULT_YEAR_START, years);
}

if (range === RANGE.MAX) {
resetYearIfInvalid(yearValue, DEFAULT_YEAR_END, years);
}
};

useEffect(() => {
if (yearValue) setYearValue(range === RANGE.MIN ? years[0] : years[1]);
}, [years]);

return (
<Input
value={yearValue}
onChange={handleYearChange}
maxLength={4}
className={cn(
'h-auto w-14 p-1 text-center focus-visible:ring-0 focus-visible:ring-offset-0',
)}
onBlur={handleBlur}
/>
);
};

export default YearFilterInput;

0 comments on commit dc079ac

Please sign in to comment.