Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
"author": "Olesia Serban",
"license": "ISC",
"dependencies": {
"@fortawesome/react-fontawesome": "^0.1.16",
"axios": "^0.24.0",
"font-awesome": "^4.7.0",
"formik": "^2.2.9",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hook-form": "^7.21.0",
"react-redux": "^7.2.6",
"redux": "^4.1.2",
"redux-thunk": "^2.4.1"
"redux-thunk": "^2.4.1",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/core": "^7.16.0",
Expand Down
1 change: 1 addition & 0 deletions src/components/UpsertMovieModal.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
.form-input{
display: flex;
flex-direction: column;
color: yellow;
}

.form-input input, .form-input select, .form-input textarea {
Expand Down
154 changes: 118 additions & 36 deletions src/components/UpsertMovieModal.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
import "./UpsertMovieModal.css";
import React from "react";
import { useForm } from "react-hook-form";
import GenresRepo from "../services/GenreRepo";
import { useDispatch } from "react-redux";
import { bindActionCreators } from "redux";
import { actionCreators } from "../store";
import { useFormik } from "formik";
import * as Yup from "yup";

const MovieSchema = Yup.object().shape({
title: Yup.string().required(),
url: Yup.string().required(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be logically if it has url validation, because random string couldn't be a url. Yup has api for it

Suggested change
url: Yup.string().required(),
url: Yup.string().url().required(),

releaseDate: Yup.string().required(),
rating: Yup.number()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For number you can use min() and max()

Suggested change
rating: Yup.number()
rating: Yup.number(),min(0).max(10)

.required()
.test("is more the 0 less then 10",
"Rating must be from 0 to 10 ", (val)=>{
return val >= 0 && val <= 10
}),
runtime: Yup.number()
.required()
.test("more then 0", "runtime should be positive", val=>{
return val >= 0
}),
overview: Yup.string().required()
})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also you can check data types in the backend side, they use Joi library, it's almost the same to Yup



export default function UpsertMovieModal({header, movie, handleCloseModal}){
Expand All @@ -14,25 +33,37 @@ export default function UpsertMovieModal({header, movie, handleCloseModal}){
const genreRepo = new GenresRepo();
const genres = genreRepo.getAllGenres();


const { register, handleSubmit } = useForm();
const onSubmit = (data, e) => {
if (movie === undefined){
handleCreate(data);
} else {
handleUpdate(movie, data);
}
const defaultFormData = {}

handleCloseModal();
};
const onError = (errors, e) => console.log(errors, e);
if(movie !== undefined) {
defaultFormData.title = movie.title;
defaultFormData.url = movie.poster_path;
defaultFormData.rating = movie.vote_average;
defaultFormData.runtime = movie.runtime;
defaultFormData.overview = movie.overview;
defaultFormData.releaseDate = movie.release_date;
}

const formik = useFormik({
initialValues: defaultFormData,
validationSchema: MovieSchema,
onSubmit: values => {
console.log(values)
if (movie === undefined){
handleCreate(values);
} else {
handleUpdate(movie, values);
}
handleCloseModal();
}
})

const handleUpdate = (movie, formData)=>{
if(formData.title){
movie.title = formData.title;
}
if(formData.genre && formData.genre !== "All"){
movie.genres = [{name: formData.genre}];
movie.genres = [formData.genre];
}

if(formData.url){
Expand All @@ -50,6 +81,10 @@ export default function UpsertMovieModal({header, movie, handleCloseModal}){
movie.overview = formData.overview;
}

if(formData.releaseDate){
movie.release_date = formData.releaseDate;
}

updateMovie(movie)
};

Expand All @@ -62,60 +97,108 @@ export default function UpsertMovieModal({header, movie, handleCloseModal}){
newMovie.vote_average = Number(formData.rating);
newMovie.runtime = Number(formData.runtime);
newMovie.overview = formData.overview;
newMovie.release_date = formData.releaseDate;
createMovie(newMovie)
};

const defaultFormData = {}

if(movie !== undefined) {
defaultFormData.title = movie.title;
defaultFormData.url = movie.poster_path;
defaultFormData.rating = movie.vote_average;
defaultFormData.runtime = movie.runtime;
defaultFormData.overview = movie.overview;
}


return (
<>
<h1>{header}</h1>
<form className="addMovieForm" onSubmit={handleSubmit(onSubmit, onError)}>
<form className="addMovieForm" onSubmit={formik.handleSubmit} onReset={formik.handleReset}>
<div className="col1-2 row1 form-input">
<label >TITLE</label>
<input placeholder="Best Movie" {...register("title")} type="text" name="title" defaultValue={defaultFormData.title}/>
<label >TITLE</label>
<input
placeholder="Best Movie"
type="text"
name="title"
onChange={formik.handleChange}
value={formik.values.title}
onBlur={formik.handleBlur('title')}
/>
{formik.touched.title && formik.errors.title}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a simple component which will render error according to mockup

</div>

<div className="col1-2 row2 form-input">
<label>MOVIE URL</label>
<input placeholder="http://picture-url" {...register("url")} type="text" name="url" defaultValue={defaultFormData.url} />
<input
type="text"
placeholder="http://picture-url"
name="url"
onChange={formik.handleChange}
value={formik.values.url}
onBlur={formik.handleBlur('url')}

/>
{formik.touched.url && formik.errors.url}
</div>

<div className="col1-2 row3 form-input">
<label>GENRE</label>
<select {...register("genre")} name="genre">
{genres.map((genre) =>
<option key={genre.id}>{genre.name}</option>
)}
<select
name="genre"
onChange={formik.handleChange}
value={formik.values.genre}
onBlur={formik.handleBlur('genre')}>

{genres.map((genre) =>
<option key={genre.id}>{genre.name}</option>
)}
</select>
{formik.touched.genre && formik.errors.genre}
</div>

<div className="col3 row1 form-input">
<label>RELEASE DATE</label>
<input type="date" {...register("date")} name="releaseDate"/>
<input type="date" onChange={formik.handleChange}
value = {formik.values.releaseDate}
name="releaseDate"
onBlur={formik.handleBlur('releaseDate')}
/>
{formik.touched.releaseDate && formik.errors.releaseDate}

</div>

<div className="col3 row2 form-input">
<label>RATING</label>
<input placeholder="7.8" {...register("rating")} type="text" name="rating" defaultValue={defaultFormData.rating} />
<input
placeholder="7.8"
type="text"
name="rating"
onChange={formik.handleChange}
value={formik.values.rating}
onBlur={formik.handleBlur('rating')}

/>
{formik.touched.rating && formik.errors.rating}
</div>

<div className="col3 row3 form-input">
<label>RUNTIME</label>
<input placeholder="120" {...register("runtime")} type="text" name="runtime" defaultValue={defaultFormData.runtime} />
<input
placeholder="120"
type="text"
name="runtime"
onChange={formik.handleChange}
value={formik.values.runtime}
onBlur={formik.handleBlur('runtime')}

/>
{formik.touched.runtime && formik.errors.runtime}
</div>

<div className="col1-3 row4 form-input">
<label>OVERVIEW</label>
<textarea placeholder="Lorem ipsum" {...register("overview")} type="text" name="overview" defaultValue={defaultFormData.overview}/>
<textarea
placeholder="Lorem ipsum"
type="text"
name="overview"
onChange={formik.handleChange}
value={formik.values.overview}
onBlur={formik.handleBlur('overview')}

/>
{formik.touched.overview && formik.errors.overview}
</div>

<div className="col2-3 row5 form-control">
Expand All @@ -128,4 +211,3 @@ export default function UpsertMovieModal({header, movie, handleCloseModal}){
</>
);
}

2 changes: 0 additions & 2 deletions src/store/movie/movieActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ export const turnOnMovieInfo = (movieInfo) => {
export const fetchMovies = () => {
return (dispatch, getState) => {
dispatch(fetchMoviesRequest())
console.log(getState())
console.log(`${MOVIE_BASE_URL}${getState().movie.sortParams}${getState().movie.filterParam}`)
axios
.get(`${MOVIE_BASE_URL}${getState().movie.sortParams}${getState().movie.filterParam}`)
.then(response => {
Expand Down
3 changes: 0 additions & 3 deletions src/store/movie/movieReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,18 @@ const initialState = {
const reducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_MOVIES_REQUEST:
console.log(FETCH_MOVIES_REQUEST)
return {
...state,
loading: true
}
case FETCH_MOVIES_SUCCESS:
console.log(FETCH_MOVIES_SUCCESS)
return {
...state,
loading: false,
movies: action.payload,
error: ''
}
case MOVIES_REQUEST_FAILURE:
console.log(MOVIES_REQUEST_FAILURE)
return {
...state,
loading: false,
Expand Down