|
| 1 | +import { FormEventHandler, useRef } from 'react'; |
| 2 | +import { useRouter } from 'next/router'; |
| 3 | +import { cleanQueryStr } from 'src/utils/helpers'; |
| 4 | +import { direction, keys, ratings, sortBy } from 'src/utils/constants/titleReviewsFilters'; |
| 5 | +import styles from 'src/styles/modules/components/titleReviews/form.module.scss'; |
| 6 | + |
| 7 | +type Props = { |
| 8 | + className?: string; |
| 9 | + titleId: string; |
| 10 | +}; |
| 11 | + |
| 12 | +const Filters = ({ className, titleId }: Props) => { |
| 13 | + const router = useRouter(); |
| 14 | + const formRef = useRef<HTMLFormElement>(null); |
| 15 | + |
| 16 | + const submitHandler: FormEventHandler<HTMLFormElement> = e => { |
| 17 | + e.preventDefault(); |
| 18 | + |
| 19 | + const formEl = formRef.current!; |
| 20 | + const formData = new FormData(formEl); |
| 21 | + |
| 22 | + const entries = Object.fromEntries(formData.entries()) as Record<string, string>; |
| 23 | + const queryStr = cleanQueryStr(entries, keys); |
| 24 | + |
| 25 | + router.push(`/title/${titleId}/reviews?${queryStr}`); |
| 26 | + }; |
| 27 | + |
| 28 | + return ( |
| 29 | + <form |
| 30 | + action={`/title/${titleId}/reviews`} |
| 31 | + onSubmit={submitHandler} |
| 32 | + ref={formRef} |
| 33 | + className={`${className} ${styles.form}`} |
| 34 | + > |
| 35 | + <fieldset className={styles.fieldset}> |
| 36 | + <legend className={`heading ${styles.fieldset__heading}`}>Filter by Rating</legend> |
| 37 | + <RadioBtns data={ratings} className={styles.radio} /> |
| 38 | + </fieldset> |
| 39 | + <fieldset className={styles.fieldset}> |
| 40 | + <legend className={`heading ${styles.fieldset__heading}`}>Sort by</legend> |
| 41 | + <RadioBtns data={sortBy} className={styles.radio} /> |
| 42 | + </fieldset> |
| 43 | + <fieldset className={styles.fieldset}> |
| 44 | + <legend className={`heading ${styles.fieldset__heading}`}>Direction</legend> |
| 45 | + <RadioBtns data={direction} className={styles.radio} /> |
| 46 | + </fieldset> |
| 47 | + <p className={styles.exact}> |
| 48 | + <label htmlFor='spoiler'>Hide Spoilers</label> |
| 49 | + <input type='checkbox' name='spoiler' id='spoiler' value='hide' /> |
| 50 | + </p> |
| 51 | + <div className={styles.buttons}> |
| 52 | + <button type='reset' className={styles.button}> |
| 53 | + Clear |
| 54 | + </button> |
| 55 | + <button type='submit' className={styles.button}> |
| 56 | + Submit |
| 57 | + </button> |
| 58 | + </div> |
| 59 | + </form> |
| 60 | + ); |
| 61 | +}; |
| 62 | + |
| 63 | +const RadioBtns = ({ |
| 64 | + data, |
| 65 | + className, |
| 66 | +}: { |
| 67 | + data: typeof ratings | typeof sortBy | typeof direction; |
| 68 | + className: string; |
| 69 | +}) => ( |
| 70 | + <> |
| 71 | + {data.types.map(({ name, val }) => ( |
| 72 | + <p className={className} key={val}> |
| 73 | + <input |
| 74 | + type='radio' |
| 75 | + name={data.key} |
| 76 | + id={`${data.key}:${val}`} |
| 77 | + value={val} |
| 78 | + className='visually-hidden' |
| 79 | + /> |
| 80 | + <label htmlFor={`${data.key}:${val}`}>{name}</label> |
| 81 | + </p> |
| 82 | + ))} |
| 83 | + </> |
| 84 | +); |
| 85 | + |
| 86 | +export default Filters; |
0 commit comments