import { useState, ChangeEvent, useEffect, FormEvent } from 'react'; // Redux import { useDispatch, useSelector } from 'react-redux'; import { State } from '../../../store/reducers'; import { bindActionCreators } from 'redux'; import { actionCreators } from '../../../store'; // Typescript import { Bookmark, Category, NewBookmark } from '../../../interfaces'; // UI import { ModalForm, InputGroup, Button } from '../../UI'; // CSS import classes from './Form.module.css'; // Utils import { inputHandler, newBookmarkTemplate } from '../../../utility'; interface Props { modalHandler: () => void; bookmark?: Bookmark; } export const BookmarksForm = ({ bookmark, modalHandler, }: Props): JSX.Element => { const { categories } = useSelector((state: State) => state.bookmarks); const dispatch = useDispatch(); const { addBookmark, updateBookmark, createNotification } = bindActionCreators(actionCreators, dispatch); const [useCustomIcon, toggleUseCustomIcon] = useState(false); const [customIcon, setCustomIcon] = useState(null); const [formData, setFormData] = useState(newBookmarkTemplate); // Load bookmark data if provided for editing useEffect(() => { if (bookmark) { setFormData({ ...bookmark }); } else { setFormData(newBookmarkTemplate); } }, [bookmark]); const inputChangeHandler = ( e: ChangeEvent, options?: { isNumber?: boolean; isBool?: boolean } ) => { inputHandler({ e, options, setStateHandler: setFormData, state: formData, }); }; const fileChangeHandler = (e: ChangeEvent): void => { if (e.target.files) { setCustomIcon(e.target.files[0]); } }; // Bookmarks form handler const formSubmitHandler = (e: FormEvent): void => { e.preventDefault(); const createFormData = (): FormData => { const data = new FormData(); if (customIcon) { data.append('icon', customIcon); } data.append('name', formData.name); data.append('url', formData.url); data.append('categoryId', `${formData.categoryId}`); data.append('isPublic', `${formData.isPublic ? 1 : 0}`); return data; }; const checkCategory = (): boolean => { if (formData.categoryId < 0) { createNotification({ title: 'Error', message: 'Please select category', }); return false; } return true; }; if (!bookmark) { // add new bookmark if (!checkCategory()) return; if (formData.categoryId < 0) { createNotification({ title: 'Error', message: 'Please select category', }); return; } if (customIcon) { const data = createFormData(); addBookmark(data); } else { addBookmark(formData); } setFormData({ ...newBookmarkTemplate, categoryId: formData.categoryId, isPublic: formData.isPublic, }); } else { // update if (!checkCategory()) return; if (customIcon) { const data = createFormData(); updateBookmark(bookmark.id, data, { prev: bookmark.categoryId, curr: formData.categoryId, }); } else { updateBookmark(bookmark.id, formData, { prev: bookmark.categoryId, curr: formData.categoryId, }); } modalHandler(); setFormData(newBookmarkTemplate); setCustomIcon(null); } }; return ( inputChangeHandler(e)} /> inputChangeHandler(e)} /> {!useCustomIcon ? ( // mdi inputChangeHandler(e)} /> Use icon name from MDI or pass a valid URL. {' '} Click here for reference toggleUseCustomIcon(!useCustomIcon)} className={classes.Switch} > Switch to custom icon upload ) : ( // custom fileChangeHandler(e)} accept=".jpg,.jpeg,.png,.svg" /> { setCustomIcon(null); toggleUseCustomIcon(!useCustomIcon); }} className={classes.Switch} > Switch to MDI )} ); };