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
;
+// }
\ 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 ;
diff --git a/ui/src/MoviesList.js b/ui/src/MoviesList.js
index 09166ef..b0ce2cd 100644
--- a/ui/src/MoviesList.js
+++ b/ui/src/MoviesList.js
@@ -4,7 +4,8 @@ export default function MoviesList(props) {
return
Movies
- {props.movies.map(movie => -
+ {/* map by id it avoid issue when title is the same */}
+ {props.movies.map(movie =>
-
props.onDeleteMovie(movie)}/>
)}