diff --git a/components/markdown/viewer/MD-viewer.tsx b/components/markdown/viewer/MD-viewer.tsx index 6491c72d..e675602f 100644 --- a/components/markdown/viewer/MD-viewer.tsx +++ b/components/markdown/viewer/MD-viewer.tsx @@ -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 ( = ({ className, type }) => {
-
- +
+ @@ -345,12 +357,17 @@ const AnimeFilters: FC = ({ 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))} /> - +
diff --git a/features/filters/year-filter-input.tsx b/features/filters/year-filter-input.tsx new file mode 100644 index 00000000..77e695d0 --- /dev/null +++ b/features/filters/year-filter-input.tsx @@ -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 = ({ + years, + setSelectingYears, + handleChangeParam, + range, +}) => { + const [yearValue, setYearValue] = useState( + 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) => { + 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 ( + + ); +}; + +export default YearFilterInput;