|
@@ -5,41 +5,16 @@ import { QueryTypes } from 'src/interfaces/shared/search';
|
|
|
import { resultTypes, resultTitleTypes } from 'src/utils/constants/find';
|
|
|
import styles from 'src/styles/modules/components/form/find.module.scss';
|
|
|
|
|
|
-/**
|
|
|
- * helper function to render similar radio btns. saves from boilerplate.
|
|
|
- * @param data radio btn obj
|
|
|
- * @param parentClass class under which radio input and label will be
|
|
|
- * @returns JSX array of radios
|
|
|
- */
|
|
|
-const renderRadioBtns = (
|
|
|
- data: typeof resultTypes | typeof resultTitleTypes,
|
|
|
- parentClass: string
|
|
|
-) => {
|
|
|
- return data.types.map(({ name, val }) => (
|
|
|
- <p className={parentClass} key={val}>
|
|
|
- <input
|
|
|
- type='radio'
|
|
|
- name={data.key}
|
|
|
- id={`${data.key}:${val}`}
|
|
|
- value={val}
|
|
|
- className='visually-hidden'
|
|
|
- />
|
|
|
- <label htmlFor={`${data.key}:${val}`}>{name}</label>
|
|
|
- </p>
|
|
|
- ));
|
|
|
-};
|
|
|
-
|
|
|
type Props = {
|
|
|
className?: string;
|
|
|
};
|
|
|
|
|
|
-// MAIN FUNCTION
|
|
|
const Form = ({ className }: Props) => {
|
|
|
const router = useRouter();
|
|
|
const formRef = useRef<HTMLFormElement>(null);
|
|
|
const [isDisabled, setIsDisabled] = useState(false);
|
|
|
|
|
|
- // title types can't be selected unless type selected is 'title'. below is the logic for disabling/enabling titleTypes.
|
|
|
+ // title types can't be selected unless type selected is 'title'
|
|
|
const typesChangeHandler: ChangeEventHandler<HTMLFieldSetElement> = e => {
|
|
|
const el = e.target as unknown as HTMLInputElement; // we have only radios that'll fire change event.
|
|
|
const value = el.value as QueryTypes;
|
|
@@ -60,6 +35,7 @@ const Form = ({ className }: Props) => {
|
|
|
const queryStr = cleanQueryStr(entries);
|
|
|
|
|
|
if (query) router.push(`/find?${queryStr}`);
|
|
|
+ else setIsDisabled(false);
|
|
|
formEl.reset();
|
|
|
};
|
|
|
|
|
@@ -87,22 +63,20 @@ const Form = ({ className }: Props) => {
|
|
|
name='q'
|
|
|
placeholder='movies, people...'
|
|
|
className={styles.searchbar__input}
|
|
|
+ required
|
|
|
+ minLength={2}
|
|
|
/>
|
|
|
<label className='visually-hidden' htmlFor='searchbar'>
|
|
|
Search for anything
|
|
|
</label>
|
|
|
</p>
|
|
|
<fieldset className={styles.types} onChange={typesChangeHandler}>
|
|
|
- <legend className={`heading ${styles.types__heading}`}>
|
|
|
- Filter by Type
|
|
|
- </legend>
|
|
|
- {renderRadioBtns(resultTypes, styles.type)}
|
|
|
+ <legend className={`heading ${styles.types__heading}`}>Filter by Type</legend>
|
|
|
+ <RadioBtns data={resultTypes} className={styles.type} />
|
|
|
</fieldset>
|
|
|
<fieldset className={styles.titleTypes} disabled={isDisabled}>
|
|
|
- <legend className={`heading ${styles.titleTypes__heading}`}>
|
|
|
- Filter by Title Type
|
|
|
- </legend>
|
|
|
- {renderRadioBtns(resultTitleTypes, styles.titleType)}
|
|
|
+ <legend className={`heading ${styles.titleTypes__heading}`}>Filter by Title Type</legend>
|
|
|
+ <RadioBtns data={resultTitleTypes} className={styles.titleType} />
|
|
|
</fieldset>
|
|
|
<p className={styles.exact}>
|
|
|
<label htmlFor='exact'>Exact Matches</label>
|
|
@@ -120,4 +94,28 @@ const Form = ({ className }: Props) => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
+const RadioBtns = ({
|
|
|
+ data,
|
|
|
+ className,
|
|
|
+}: {
|
|
|
+ data: typeof resultTypes | typeof resultTitleTypes;
|
|
|
+ className: string;
|
|
|
+}) => (
|
|
|
+ <>
|
|
|
+ {data.types.map(({ name, val }) => (
|
|
|
+ <p className={className} key={val}>
|
|
|
+ <input
|
|
|
+ type='radio'
|
|
|
+ name={data.key}
|
|
|
+ id={`${data.key}:${val}`}
|
|
|
+ value={val}
|
|
|
+ className='visually-hidden'
|
|
|
+ />
|
|
|
+ <label htmlFor={`${data.key}:${val}`}>{name}</label>
|
|
|
+ </p>
|
|
|
+ ))}
|
|
|
+ </>
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
export default Form;
|