diff --git a/src/App.tsx b/src/App.tsx index 34be670b0..c0661bd45 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,16 +1,24 @@ import './App.scss'; +import { useState } from 'react'; import { MoviesList } from './components/MoviesList'; import { NewMovie } from './components/NewMovie'; import moviesFromServer from './api/movies.json'; +import { Movie } from './types/Movie'; export const App = () => { + const [movies, setMovies] = useState(moviesFromServer); + + const handleAddMovie = (newMovie: Movie) => { + setMovies([...movies, newMovie]); + }; + return (
- +
- {}} */ /> +
); diff --git a/src/components/NewMovie/NewMovie.tsx b/src/components/NewMovie/NewMovie.tsx index 34f22fb0a..0b03d90e4 100644 --- a/src/components/NewMovie/NewMovie.tsx +++ b/src/components/NewMovie/NewMovie.tsx @@ -1,45 +1,137 @@ -import { useState } from 'react'; +import React, { useState } from 'react'; import { TextField } from '../TextField'; +import { Movie } from '../../types/Movie'; -export const NewMovie = () => { - // Increase the count after successful form submission - // to reset touched status of all the `Field`s - const [count] = useState(0); +interface NewMovieProps { + onAdd: (formData: Movie) => void; +} + +export const NewMovie: React.FC = ({ onAdd }) => { + const [formData, setFormData] = useState({ + titles: '', + description: '', + imgUrl: '', + imdbUrl: '', + imdbId: '', + }); + + const [errors, setErrors] = useState({ + titles: false, + description: false, + imgUrl: false, + imdbUrl: false, + imdbId: false, + }); + + const handleBlur = (name: keyof typeof formData) => { + if (name === 'titles' || name === 'imgUrl' || name === 'imdbUrl' + || name === 'imdbId') { + setErrors((prevErrors) => ({ + ...prevErrors, + [name]: formData[name].trim() === '', + })); + } + }; + + const handleInputChange = (name: keyof typeof formData, value: string) => { + setFormData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + const hasErrors = Object.keys(errors).some((name) => { + if (name === 'titles' || name === 'imgUrl' || name === 'imdbUrl' + || name === 'imdbId') { + return formData[name].trim() === ''; + } + + return false; + }); + + if (hasErrors) { + return; + } + + const newMovie: Movie = { + title: formData.titles, + description: formData.description, + imgUrl: formData.imgUrl, + imdbUrl: formData.imdbUrl, + imdbId: formData.imdbId, + }; + + onAdd(newMovie); + + setFormData({ + titles: '', + description: '', + imgUrl: '', + imdbUrl: '', + imdbId: '', + }); + + setErrors({ + titles: false, + description: false, + imgUrl: false, + imdbUrl: false, + imdbId: false, + }); + }; return ( -
+

Add a movie

{}} + value={formData.titles} + onChange={(value) => handleInputChange('titles', value)} + onBlur={() => handleBlur('titles')} + error={errors.titles} + data-cy="movie-title" required /> handleInputChange('description', value)} + error={errors.description} + required /> handleInputChange('imgUrl', value)} + error={errors.imgUrl} + required /> handleInputChange('imdbUrl', value)} + error={errors.imdbUrl} + required /> handleInputChange('imdbId', value)} + error={errors.imdbId} + required />
diff --git a/src/components/TextField/TextField.tsx b/src/components/TextField/TextField.tsx index 307b19865..0acebe7ec 100644 --- a/src/components/TextField/TextField.tsx +++ b/src/components/TextField/TextField.tsx @@ -8,6 +8,8 @@ type Props = { placeholder?: string, required?: boolean, onChange?: (newValue: string) => void, + onBlur?: () => void, + error: boolean; }; function getRandomDigits() { @@ -19,15 +21,15 @@ function getRandomDigits() { export const TextField: React.FC = ({ name, value, + error, label = name, placeholder = `Enter ${label}`, required = false, onChange = () => {}, + onBlur = () => {}, }) => { - // generage a unique id once on component load const [id] = useState(() => `${name}-${getRandomDigits()}`); - // To show errors only if the field was touched (onBlur) const [touched, setTouched] = useState(false); const hasError = touched && required && !value; @@ -43,12 +45,15 @@ export const TextField: React.FC = ({ id={id} data-cy={`movie-${name}`} className={classNames('input', { - 'is-danger': hasError, + 'is-danger': hasError || error, })} placeholder={placeholder} value={value} - onChange={event => onChange(event.target.value)} - onBlur={() => setTouched(true)} + onChange={(event) => onChange(event.target.value)} + onBlur={() => { + setTouched(true); + onBlur(); + }} />