diff --git a/api/main.py b/api/main.py index 380543e..9a45d41 100644 --- a/api/main.py +++ b/api/main.py @@ -22,11 +22,14 @@ def get_movies(): @app.post("/movies", response_model=schemas.Movie) -def add_movie(movie: schemas.MovieBase): - movie = models.Movie.create(**movie.dict()) +def add_movie(movie: schemas.MovieCreate): + movie_instance = models.Movie.create(**movie.dict(exclude={"actors"})) + for actor in movie.actors: + if (actor.name is not None) or (actor.surname is not None): + actor_instance = models.Actor.create(**actor.dict()) + models.ActorMovie.create(actor=(actor_instance), movie=(movie_instance)) return movie - @app.get("/movies/{movie_id}", response_model=schemas.Movie) def get_movie(movie_id: int): db_movie = models.Movie.filter(models.Movie.id == movie_id).first() @@ -34,11 +37,30 @@ def get_movie(movie_id: int): raise HTTPException(status_code=404, detail="Movie not found") return db_movie +@app.get("/actors", response_model=List[schemas.Actor]) +def get_actors(): + return list(models.Actor.select()) + +@app.post("/actors", response_model=schemas.Actor) +def add_actor(movie: schemas.ActorBase): + if (movie.name is None) or (movie.surname is None): + raise HTTPException(status_code=400, detail="Actor name and surname is required") + else: + movie = models.Actor.create(**movie.dict()) + return movie @app.delete("/movies/{movie_id}", response_model=schemas.Movie) def get_movie(movie_id: int): db_movie = models.Movie.filter(models.Movie.id == movie_id).first() + db_movie_actors = models.ActorMovie.filter(models.ActorMovie.movie_id == movie_id) + if db_movie is None: raise HTTPException(status_code=404, detail="Movie not found") - db_movie.delete_instance() + else: + for actor in db_movie_actors: + db_actor = models.Actor.filter(models.Actor.id == actor.actor_id).first() + db_actor.delete_instance() + actor.delete_instance() + db_movie.delete_instance() + return db_movie diff --git a/api/movies.db b/api/movies.db index c2a64ad..79ae40c 100644 Binary files a/api/movies.db and b/api/movies.db differ diff --git a/api/schemas.py b/api/schemas.py index 38649fb..1cefbbc 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -35,7 +35,7 @@ class MovieBase(BaseModel): class MovieCreate(MovieBase): - pass + actors: List[ActorBase] = [] class Movie(MovieBase): @@ -46,4 +46,8 @@ class Config: orm_mode = True getter_dict = PeeweeGetterDict +class ActorMovieBase(BaseModel): + actor_id: int + movie_id: int + diff --git a/ui/src/ActorForm.js b/ui/src/ActorForm.js new file mode 100644 index 0000000..518624b --- /dev/null +++ b/ui/src/ActorForm.js @@ -0,0 +1,40 @@ +import {useState} from "react"; + +// export default function ActorForm(props) { + +// const [actorFields, setActorFields] = useState( { name: '', surname: '' }) +// // const [actors, setActors] = useState([]); +// const handleAddActor = () => { +// const actor = { ...actorFields }; +// console.log('actor', actor); +// setActors([...actors, actor]); +// setActorFields({ name: '', surname: '' }); +// console.log('actorOut', actors); +// }; + +// const handleRemoveActor = (index) => { +// let actor = [...actors ]; +// actor.splice(index, 1); +// setActors(actor); +// }; + + +// return

Actors:

+//
+// +// +//
+//
; +// } \ No newline at end of file diff --git a/ui/src/App.js b/ui/src/App.js index 8b633d1..661dd4d 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -1,31 +1,99 @@ import './App.css'; -import {useState} from "react"; +import {useEffect, useState} from "react"; import "milligram"; import MovieForm from "./MovieForm"; import MoviesList from "./MoviesList"; +// import ActorForm from "./ActorForm"; + function App() { const [movies, setMovies] = useState([]); const [addingMovie, setAddingMovie] = useState(false); + const [addActor, setAddActor] = useState([]); + // const [removeMovie, setRemoveMovie] = useState(false); + + //current issue to fix read ID from backend that we can remove directly after adding + async function handleAddMovie(movie) { + const response = await fetch(`/movies`, { + method: 'POST', + body: JSON.stringify(movie), + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + // fixed issue by adding reading (async) response deserialized from recived json + const movieFromServer = await response.json(); + setMovies([...movies, movieFromServer]); + console.log(movies); + setAddingMovie(false); + } + + } + + async function handleRemoveMovie(movie) { + const response = await fetch(`/movies/${movie.id}`, { + method: 'DELETE' + }); + + if (response.ok) { + setMovies([...movies, movie]); + const removeMovie = movies.filter(m => m !== movie); - function handleAddMovie(movie) { - setMovies([...movies, movie]); - setAddingMovie(false); + setMovies(removeMovie); + } + } + async function handleAddActor(actor) { + const response = await fetch(`/actors`, { + method: 'POST', + body: JSON.stringify(actor), + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + // fixed issue by adding reading (async) response deserialized from recived json + const actorFromServer = await response.json(); + setAddActor([...addActor, actorFromServer]);; + } + + } + + //use effect = it will fetch data from backend only on start + // + useEffect(() => { + const fetchMovies = async () => { + const response = await fetch(`/movies`); + + if (response.ok) { + const movies = await response.json(); + setMovies(movies); + } + }; + + fetchMovies(); +// empty array [] gives option that it is executed only onece because array is empty and it guarantte thei1 execution +// in other word effect worka on changes of array so if it is empty never change + }, []); + return (

My favourite movies to watch

{movies.length === 0 ?

No movies yet. Maybe add something?

: setMovies(movies.filter(m => m !== movie))} + onDeleteMovie={handleRemoveMovie} />} {addingMovie - ? + ?
+ + {/* */} +
: } +
); } diff --git a/ui/src/MovieForm.js b/ui/src/MovieForm.js index ee733f0..fa67498 100644 --- a/ui/src/MovieForm.js +++ b/ui/src/MovieForm.js @@ -1,40 +1,87 @@ import {useState} from "react"; +// import ActorForm from "./ActorForm"; export default function MovieForm(props) { const [title, setTitle] = useState(''); const [year, setYear] = useState(''); const [director, setDirector] = useState(''); const [description, setDescription] = useState(''); + const [name, setName] = useState(''); + const [surname, setSurname] = useState(''); + const [actors, setActors] = useState([]); + const [actorFields, setActorFields] = useState( { name: '', surname: '' }) + function addMovie(event) { event.preventDefault(); - if (title.length < 5) { - return alert('Tytuł jest za krótki'); - } - props.onMovieSubmit({title, year, director, description}); + // if (title.length < 5) { + // return alert('Tytuł jest za krótki'); + // } + + props.onMovieSubmit({title, year, director, description, actors}); + setTitle(''); setYear(''); setDirector(''); setDescription(''); + setActors([]); + console.log('movieOut', {title, year, director, description}); } + + const handleAddActor = () => { + const actor = { ...actorFields }; + console.log('actor', actor); + setActors([...actors, actor]); + setActorFields({ name: '', surname: '' }); + console.log('actorOut', actors); + }; + + const handleRemoveActor = (index) => { + let actor = [...actors ]; + actor.splice(index, 1); + setActors(actor); + }; + + + return

Add movie

- setTitle(event.target.value)}/> + setTitle(event.target.value)}/>
- setYear(event.target.value)}/> + setYear(event.target.value)}/>
- setDirector(event.target.value)}/> + setDirector(event.target.value)}/>
-