diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index b6e3d23..eff9721 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -28,6 +28,9 @@ const Index: React.FC = () => { Home + + Admin + @@ -45,8 +48,14 @@ const Index: React.FC = () => { {user && user.is_admin ? ( - - Create Movie + + Manage Movies + + + Manage Promotions + + + Manage Users ) : null} diff --git a/src/pages/Admin/index.tsx b/src/pages/Admin/index.tsx new file mode 100644 index 0000000..9037a56 --- /dev/null +++ b/src/pages/Admin/index.tsx @@ -0,0 +1,23 @@ +import PageContainer from 'components/PageContainer' +import { Link } from 'react-router-dom' + + +const Index: React.FC = () => { + return ( + + + + Manage Movies + + + Manage Users + + + Manage Promotions + + + + ); +} + +export default Index diff --git a/src/pages/MovieManage/index.tsx b/src/pages/MovieManage/index.tsx new file mode 100644 index 0000000..7c9ff78 --- /dev/null +++ b/src/pages/MovieManage/index.tsx @@ -0,0 +1,240 @@ +import { useRequest } from 'ahooks' +import PageContainer from 'components/PageContainer' +import { useState } from 'react' +import Button from 'react-bootstrap/Button' +import Form from 'react-bootstrap/Form' +import { useNavigate } from 'react-router-dom' +import Backend from 'utils/service' +import { Col, Modal, Row } from 'react-bootstrap' +import type { SchemaMovie } from 'client' +import Card from 'react-bootstrap/Card' +import { Link } from 'react-router-dom' +import { ListGroup } from 'react-bootstrap' + +interface LeftHalfProps { + // Props +} + +const Movie: React.FC<{ movie: SchemaMovie }> = ({ movie }) => { + const [show, setShow] = useState(false) + + const handleClose = () => setShow(false) + const handleShow = () => setShow(true) + + return ( + + + + {movie.title} + + + + Edit + + + + + Trailer of {movie.title} + + + {/* eslint-disable-next-line react/iframe-missing-sandbox */} + + + + + ) +} + +const MovieList: React.FC<{ movies: SchemaMovie[] }> = ({ movies }) => ( + + {movies.map(movie => ( + + + + ))} + +) + +const SearchList: React.FC<{ search: string }> = ({ search }) => { + const { data, loading } = useRequest( + async () => Backend.movie.v1MoviesList({ running: true, search }), + { refreshDeps: [search], debounceWait: 200 } + ) + return ( + !loading && (data?.data.data ? : null) + ) +} + +const LeftHalf: React.FC = () => { + const [search, setSearch] = useState(''); + const [showEditPopup, setShowEditPopup] = useState(false); + + const handleEditClick = () => { + setShowEditPopup(true); + }; + + const handleCloseEditPopup = () => { + setShowEditPopup(false); + }; + + return ( + + + Edit Movie + {/* Only here due to a lack of backend functionality!!! */} + Edit + + + + + + Edit Movie + + + + + + + + setSearch(e.target.value)} + /> + + + + + + ); +}; + + +interface RightHalfProps { + // Props +} + +const RightHalf: React.FC = () => { + const navigate = useNavigate(); + const [movieTitle, setMovieTitle] = useState(''); + const { run: create } = useRequest( + async () => + // TODO: replace the movie with user input + Backend.movie.v1MoviesCreate({ + title: movieTitle, + cast: 'cast', + category: 'category', + director: 'director', + producer: 'producer', + rating_code: 'rating_code', + reviews: 'reviews', + show_time: '2016-01-02T15:04:05Z', + synopsis: 'synopsis', + trailer_picture: 'https://placehold.co/400x592', + trailer_video: + 'https://www.youtube.com/embed/NpEaa2P7qZI?si=Ev2ybUCHzVxQPIO1&controls=0' + }), + { + manual: true, + onSuccess: () => { + navigate('/') + } + } + ); + + return ( + + + + Movie Details + + + + Movie Title + setMovieTitle(e.target.value)} + /> + + + Add cast members + + + + Category + + + + Director + + + + Producer + + + + Rating + + + + + Submit + + + + + + ); +}; + +const Index: React.FC = () => { + return ( + + + + + Add Movie + + + + + ); +} + +export default Index diff --git a/src/pages/PromoManage/index.tsx b/src/pages/PromoManage/index.tsx new file mode 100644 index 0000000..0a49f18 --- /dev/null +++ b/src/pages/PromoManage/index.tsx @@ -0,0 +1,184 @@ +import PageContainer from 'components/PageContainer' +import { useState } from 'react' +import { ListGroup, Button } from 'react-bootstrap' +import Card from 'react-bootstrap/Card' +import React, {useEffect } from 'react'; +import 'bootstrap/dist/css/bootstrap.min.css'; + +interface User { + id: string; + created_at: string; + updated_at: string; + is_active: boolean; + is_admin: boolean; + username: string; + email: string; + first_name: string; + last_name: string; + // other user properties...? +} + +function UserList() { + + const listyle = { + padding: '10px', + border: '1px solid #ccc', + marginBottom: '10px', + cursor: 'pointer', + }; + + const users = [ + { username: "demo", email: 'demo@example.com' }, + { username: "user2", email: 'user@example.com' }, + + ]; + + return( + + User List + + {users.map((user) => ( + + {user.email} : {user.username} + + ))} + + + ); +}; + +const EditPromo: React.FC<{ onClose: () => void; selectedPromoTitle: string;}> = ({ + onClose, + selectedPromoTitle +}) => { + return ( + + + + {selectedPromoTitle === "New Promo" ? "Add " : "Edit: "} {selectedPromoTitle} + + + + + + + + + Submit + + + Close + + + {selectedPromoTitle === "New Promo" ? "Cancel " : "Delete"} + + + + + ); +}; + +const LeftHalf: React.FC<{ onOpenTextInput: (promoTitle: string) => void }> = ({ onOpenTextInput }) => { + const listyle = { + padding: '10px', + border: '1px solid #ccc', + marginBottom: '10px', + cursor: 'pointer', + }; + const promotions = [ + { id: 1, title: 'Promo 1' }, + { id: 2, title: 'Promo 2' }, + { id: 3, title: 'Promo 3' }, + { id: 4, title: 'Promo 4' }, + { id: 5, title: 'Promo 5' }, + { id: 6, title: 'Promo 6' }, + { id: 7, title: 'Promo 7' }, + { id: 8, title: 'Promo 8' }, + ]; + + return ( + + + + Subscribed Users + + + + + + Active Promotions + onOpenTextInput("New Promo")}> + + Add + + + + + {promotions.map((promo) => ( + onOpenTextInput(promo.title)}> + {promo.title} + onOpenTextInput(promo.title)} + > + Edit + + + ))} + + + + + ); +}; + +const RightHalf: React.FC<{ showTextInput: boolean; onCloseTextInput: () => void; selectedPromoTitle: string }> = ({ + showTextInput, + onCloseTextInput, + selectedPromoTitle +}) => { + return ( + + {!showTextInput && + Add a new promotion, or select one to begin editing. + } + {showTextInput && } + + ); +}; + +const Index: React.FC = () => { + const [showTextInput, setShowTextInput] = useState(false); + const [selectedPromoTitle, setSelectedPromoTitle] = useState(''); + + + const openTextInput = (promoTitle: string) => { + setSelectedPromoTitle(promoTitle); + setShowTextInput(true); + }; + + const closeTextInput = () => { + setShowTextInput(false); + }; + + return ( + + + + + + + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/pages/UserManage/index.tsx b/src/pages/UserManage/index.tsx new file mode 100644 index 0000000..95e1560 --- /dev/null +++ b/src/pages/UserManage/index.tsx @@ -0,0 +1,23 @@ +import { useRequest } from 'ahooks' +import PageContainer from 'components/PageContainer' +import { useState } from 'react' +import Button from 'react-bootstrap/Button' +import Form from 'react-bootstrap/Form' +import { useNavigate } from 'react-router-dom' +import Backend from 'utils/service' +import { Col, Modal, Row } from 'react-bootstrap' +import type { SchemaMovie } from 'client' +import Card from 'react-bootstrap/Card' +import { Link } from 'react-router-dom' + +const Index: React.FC = () => { + return ( + + + User management in progress! + + + ); +} + +export default Index diff --git a/src/routes.tsx b/src/routes.tsx index ae5d95d..c013fd3 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -1,8 +1,12 @@ import { ProtectedRoute } from 'components/ProtectedRoute' import Login from 'pages/Login' +import Admin from 'pages/Admin' import Logout from 'pages/Logout' import Main from 'pages/Main' import MovieCreate from 'pages/MovieCreate' +import MovieManage from 'pages/MovieManage' +import UserManage from 'pages/UserManage' +import PromoManage from 'pages/PromoManage' import NotFound from 'pages/NotFound' import Register from 'pages/Register' import RegisterConfirm from 'pages/RegisterConfirm' @@ -25,6 +29,22 @@ const children: RouteObject[] = [ path: '/register/confirm', element: }, + { + path: '/admin', + element: + }, + { + path:'/ManageMovies', + element: + }, + { + path:'/ManageUsers', + element: + }, + { + path:'/ManagePromos', + element: + }, { path: '/', element:
Add a new promotion, or select one to begin editing.