diff --git a/src/App.tsx b/src/App.tsx index 34be670b0..6a403ae7d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,16 +2,31 @@ import './App.scss'; import { MoviesList } from './components/MoviesList'; import { NewMovie } from './components/NewMovie'; import moviesFromServer from './api/movies.json'; +import { useState } from 'react'; + +export type State = { + title: string, + description: string, + imgUrl: string, + imdbUrl: string, + imdbId: string +}; export const App = () => { + const [movieList, setMovieList] = useState([...moviesFromServer]); + + const handleAddMovie = (newMovie: State) => { + setMovieList((prevMovies) => [...prevMovies, newMovie]); + }; + return (
- +
- {}} */ /> +
-
+ ); }; diff --git a/src/components/NewMovie/NewMovie.tsx b/src/components/NewMovie/NewMovie.tsx index 34f22fb0a..bcec5cfc0 100644 --- a/src/components/NewMovie/NewMovie.tsx +++ b/src/components/NewMovie/NewMovie.tsx @@ -1,45 +1,102 @@ import { useState } from 'react'; import { TextField } from '../TextField'; -export const NewMovie = () => { - // Increase the count after successful form submission - // to reset touched status of all the `Field`s - const [count] = useState(0); +interface Props { + onAdd: ( + movie: { + title: string, + description: string, + imgUrl: string, + imdbUrl: string, + imdbId: string, + } + ) => void +} + +export const NewMovie: React.FC = ({ onAdd }) => { + const [count, setCount] = useState(0); + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [imgUrl, setImgUrl] = useState(''); + const [imdbUrl, setimdbUrl] = useState(''); + const [imdbId, setImdbId] = useState(''); + + const urlValidator = (urlString: string): boolean => { + // eslint-disable-next-line max-len + const pattern = /^((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@,.\w_]*)#?(?:[,.!/\\\w]*))?)$/; + + if (!urlString.match(pattern)) { + return false; + } + + return true; + }; + + function addMovie(event: React.FormEvent) { + event.preventDefault(); + onAdd({ + title: title.trim(), + description: description.trim(), + imgUrl: imgUrl.trim(), + imdbUrl: imdbUrl.trim(), + imdbId: imdbId.trim(), + }); + + setTitle(''); + setDescription(''); + setImgUrl(''); + setimdbUrl(''); + setImdbId(''); + + setCount(prev => prev + 1); + } return ( -
+

Add a movie

{}} + value={title} + onChange={setTitle} required />
@@ -48,6 +105,10 @@ export const NewMovie = () => { type="submit" data-cy="submit-button" className="button is-link" + disabled={!title + || !urlValidator(imgUrl) + || !urlValidator(imdbUrl) + || !imdbId} > Add diff --git a/src/components/TextField/TextField.tsx b/src/components/TextField/TextField.tsx index 307b19865..0a641b6b6 100644 --- a/src/components/TextField/TextField.tsx +++ b/src/components/TextField/TextField.tsx @@ -8,6 +8,7 @@ type Props = { placeholder?: string, required?: boolean, onChange?: (newValue: string) => void, + checkUrl?: (urlString: string) => boolean, }; function getRandomDigits() { @@ -23,6 +24,7 @@ export const TextField: React.FC = ({ placeholder = `Enter ${label}`, required = false, onChange = () => {}, + checkUrl = undefined, }) => { // generage a unique id once on component load const [id] = useState(() => `${name}-${getRandomDigits()}`); @@ -55,6 +57,8 @@ export const TextField: React.FC = ({ {hasError && (

{`${label} is required`}

)} + + {((touched && value) && (checkUrl && !checkUrl(value))) && (

{`${label} incorrect URL`}

)}
); };