Skip to content
Open

done #118

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
113 changes: 112 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
},
"dependencies": {
"@prisma/client": "^5.7.1",
"axios": "^1.6.7",
"bcrypt": "^5.1.1",
"concurrently": "^7.6.0",
"cors": "^2.8.5",
"dotenv": "^16.4.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3"
},
"devDependencies": {
"@types/react": "^18.2.43",
Expand Down
6 changes: 6 additions & 0 deletions src/client/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@
transform: rotate(360deg);
}
}
.grid{
display: grid;

}

ul {
list-style: none;
margin: 0;
padding: 0;
}
15 changes: 15 additions & 0 deletions src/client/App.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { useEffect, useState } from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import MovieList from './components/MovieList';
import './App.css';
import MovieForm from './components/MovieForm';
import UserForm from './components/UserForm';
Expand Down Expand Up @@ -68,6 +71,18 @@ function App() {
);
})}
</ul>
<Routes>
<Route
path='/'
element={<Home apiUrl={apiUrl} />}
>
</Route>
<Route
path='/movie-list'
element={<MovieList apiUrl={apiUrl} />}
>
</Route>
</Routes>
</div>
);
}
Expand Down
40 changes: 40 additions & 0 deletions src/client/components/CreateMovie.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import axios from "axios"
import { useState } from "react"
import MovieForm from "./MovieForm"

function CreateMovie({ apiUrl, movies, setMovies }) {
const [createMovieMessage, setCreateMovieMessage] = useState('')

const handleCreateMovie = async ({ title, description, runtimeMins }) => {
const token = localStorage.getItem('token')

try {
const { data } = await axios.post(`${apiUrl}/movie`, { title,
description,
runtimeMins
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
}
)
const { movie, message } = data
setMovies([...movies, movie])
setCreateMovieMessage(message)
}
catch (err) {
setCreateMovieMessage(err.response.data.error)
}
}

return (
<div className="movie-list--create-movie">
<h1>Create a movie</h1>
<MovieForm handleSubmit={handleCreateMovie} />
{createMovieMessage && <p>{createMovieMessage}</p>}
</div>
)
}

export default CreateMovie
15 changes: 15 additions & 0 deletions src/client/components/Home.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import RegisterUser from "./RegisterUser"
import LoginUser from "./LoginUser"
//import '../styles/home.css'

function Home({ apiUrl }) {

return (
<section className="home--container grid">
<RegisterUser apiUrl={apiUrl} />
<LoginUser apiUrl={apiUrl} />
</section>
)
}

export default Home
37 changes: 37 additions & 0 deletions src/client/components/LoginUser.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import axios from "axios"
import { useState } from "react"
import { useNavigate } from "react-router-dom"
import UserForm from "./UserForm"

function LoginUser({ apiUrl }) {
const navigate = useNavigate()
const [loginMessage, setLoginMessage] = useState('')

const handleLogin = async ({ username, password }) => {
try {
const { data } = await axios.post(`${apiUrl}/user/login`, { username,
password
}, {
headers: { 'Content-Type': 'application/json' },
}
)
const { token, message } = data
localStorage.setItem('token', token)
setLoginMessage(message)
navigate('/movie-list')
}
catch (err) {
setLoginMessage(err.response.data.error)
}
};

return (
<div className="home--form-container home--login-container grid">
<h1>Login</h1>
<UserForm handleSubmit={handleLogin} />
{loginMessage && <p>{loginMessage}</p>}
</div>
)
}

export default LoginUser
21 changes: 21 additions & 0 deletions src/client/components/Logout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import '../styles/logout.css'

import { useNavigate } from "react-router-dom"

function Logout() {
const navigate = useNavigate()

const handleSubmit = () => {
const token = localStorage.getItem('token')
if (token) {
localStorage.clear()
navigate('/')
}
}

return (
<button className='logout-btn' type="submit" onClick={handleSubmit}>Logout</button>
)
}

export default Logout
6 changes: 5 additions & 1 deletion src/client/components/MovieForm.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useState } from "react";
//import '../styles/movie-form.css'


export default function MovieForm({ handleSubmit }) {
const [movie, setMovie] = useState({ title: '', description: '', runtimeMins: 60 });

const handleSubmitDecorator = (e) => {
e.preventDefault();
handleSubmit(movie);
setMovie({ title: '', description: '', runtimeMins: 60 })

}

const handleChange = (e) => {
Expand All @@ -18,7 +22,7 @@ export default function MovieForm({ handleSubmit }) {
}

return (
<form onSubmit={handleSubmitDecorator}>
<form className="movie-form grid" onSubmit={handleSubmitDecorator}>
<input type='text' name='title' placeholder="Title" value={movie.title} onChange={handleChange} />
<input type='text' name='description' placeholder="Description" value={movie.description} onChange={handleChange} />
<input type='number' name='runtimeMins' placeholder="Runtime (minutes)" value={movie.runtimeMins} onChange={handleChange} />
Expand Down
Loading