Skip to content
Snippets Groups Projects
Commit 45fe4deb authored by Tomáš Havlíček's avatar Tomáš Havlíček
Browse files

Merge branch 'frontend-api-connect' into 'main'

Frontend api connect

See merge request xhavlic/pb138-film-database-group-project!5
parents 5de725cd d1dc42ea
No related branches found
No related tags found
No related merge requests found
......@@ -12,7 +12,8 @@
"antd": "^4.21.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.3.0"
"react-router-dom": "^6.3.0",
"swr": "^1.3.0"
},
"devDependencies": {
"@types/react": "^18.0.12",
......@@ -2198,6 +2199,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/swr": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz",
"integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==",
"peerDependencies": {
"react": "^16.11.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
......@@ -3763,6 +3772,12 @@
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true
},
"swr": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz",
"integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==",
"requires": {}
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
......
......@@ -12,7 +12,8 @@
"antd": "^4.21.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.3.0"
"react-router-dom": "^6.3.0",
"swr": "^1.3.0"
},
"devDependencies": {
"@types/react": "^18.0.12",
......
......@@ -6,11 +6,12 @@ import { Routes, Route, Outlet, Link, BrowserRouter } from "react-router-dom";
import { NavigationBar } from "./components/NavigationBar";
import { About } from "./components/About";
import React from "react";
import { Browse } from "./components/Browse";
import { BrowseMovies } from "./components/BrowseMovies";
import { SearchPage } from "./components/SearchPage";
import { ErrorPage } from "./components/ErrorPage";
import { MoviePage } from "./components/MoviePage";
import { DirectorPage } from "./components/DirectorPage";
import { BrowseDirectors } from "./components/BrowseDirectors";
function App() {
return (
......@@ -19,7 +20,8 @@ function App() {
<Routes>
<Route path="/" element={<MainPage />}></Route>
<Route path="/browse" element={<Browse />}></Route>
<Route path="/movies" element={<BrowseMovies />}></Route>
<Route path="/directors" element={<BrowseDirectors/>}></Route>
<Route path="/search" element={<SearchPage />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="/movie/:id" element={<MoviePage></MoviePage>}></Route>
......
import { Space, Card, Table } from "antd";
import React from "react"
import { Link } from "react-router-dom";
import { DirectorIO } from "./Preview"
//TODO replace by API CALL - get ALL directors
const exampleDirectors: DirectorIO[] = [{
id: "123",
name: "Karel",
surname: "Macka",
birthdate: "20.2.1987",
},
{
id: "456",
name: "Jan",
surname: "Vomacka",
birthdate: "20.12.1990",
},
{
id: "890",
name: "Karel",
surname: "Vomacka",
birthdate: "1.2.1987",
},
{
id: "666",
name: "Pan",
surname: "Natas",
birthdate: "20.2.1687",
},
]
export const BrowseDirectors = () => {
const columns = [
{
title: "Name",
dataIndex: "name",
sorter: (a:DirectorIO, b:DirectorIO) => {
//surname has higher priority
if(a.surname < b.surname){return -1;}
if(a.surname > b.surname){return 1;}
if(a.name < b.name){return -1;}
if(a.name > b.name){return 1;}
return 0;
},
render: (text: string, record: DirectorIO) => (
<Link to={`/director/${record.id}`}>
<a>{record.name} {record.surname}</a>
</Link>
),
},
{
title: "Birthdate",
className: "birthdate",
dataIndex: "birthdate",
sorter: (a:DirectorIO, b:DirectorIO) => {
const first = a.birthdate.split('.').reverse();
const second = b.birthdate.split('.').reverse();
if(first[0] > second[0]){return 1 ;}
if(first[0] < second[0]){return -1 ;}
if(first[1] > second[1]){return 1 ;}
if(first[1] < second[1]){return -1 ;}
if(first[2] > second[2]){return 1 ;}
if(first[2] < second[2]){return -1 ;}
return 0;},
}
];
return (
<div className="browse-container">
<Space direction="vertical" size="middle" style={{ padding: "4%" }}>
<Table
columns={columns}
dataSource={exampleDirectors}
>
</Table>
</Space>
</div>
);
}
\ No newline at end of file
......@@ -10,6 +10,8 @@ const gridStyle: React.CSSProperties = {
textAlign: "center",
};
// TODO replace this with API call for all categories with movies inside
const categories: CategoryIO[] = [
{
id: "12345",
......@@ -23,7 +25,7 @@ const categories: CategoryIO[] = [
picture:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse3.mm.bing.net%2Fth%3Fid%3DOIP.Jo6M-3oyAlMsB4-F__Z9bwHaHa%26pid%3DApi&f=1",
published: "1.1.2000",
runTimeMinutes: 120,
runtimeMinutes: 120,
director: {
id: "123456789",
name: "Karel",
......@@ -39,7 +41,7 @@ const categories: CategoryIO[] = [
picture:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fimages01.kaleidescape.com%2Ftransformed%2Fcovers%2F1134x1624s%2F189%2F18976008.jpg&f=1&nofb=1",
published: "1.1.2002",
runTimeMinutes: 150,
runtimeMinutes: 150,
director: {
id: "123456789",
name: "Karel",
......@@ -61,7 +63,7 @@ const categories: CategoryIO[] = [
picture:
"https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2F2ht1mik98ka4dogie28vqc4y.wpengine.netdna-cdn.com%2Fwp-content%2Fuploads%2F2015%2F10%2FWho-Killed-Capt-Alex.jpg&f=1&nofb=1",
published: "8.8.2015",
runTimeMinutes: 60,
runtimeMinutes: 60,
director: {
id: "2323",
name: "Pastor",
......@@ -73,7 +75,7 @@ const categories: CategoryIO[] = [
},
];
export const Browse = () => {
export const BrowseMovies = () => {
return (
<div className="browse-container">
<Space direction="vertical" size="middle" style={{ padding: "4%" }}>
......
......@@ -2,6 +2,8 @@ import { Descriptions } from "antd";
import React from "react";
import { DirectorIO } from "./Preview";
// TODO replace this with API call by director id
const exampleDirector: DirectorIO = {
name: "Karel",
surname: "Vomacka",
......
......@@ -19,7 +19,6 @@ const MainPage = () => (
textAlign: "center",
}}
>
Ant Design ©2018 Created by Ant UED
</Footer>
</Layout>
);
......
......@@ -5,8 +5,8 @@ import { MovieIO } from "./Preview";
export const MoviePage = () => {
const { id, name } = useParams();
//need to fetch /channel/${id} here to preview data
//replace this with /channel/${id} API call
const exampleMovie: MovieIO = {
id: "789",
name: "Saw",
......@@ -15,7 +15,7 @@ export const MoviePage = () => {
picture:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse3.mm.bing.net%2Fth%3Fid%3DOIP.Jo6M-3oyAlMsB4-F__Z9bwHaHa%26pid%3DApi&f=1",
published: "1.1.2000",
runTimeMinutes: 120,
runtimeMinutes: 120,
director: {
id: "123456789",
name: "Karel",
......@@ -47,7 +47,7 @@ export const MoviePage = () => {
{exampleMovie.published}
</Descriptions.Item>
<Descriptions.Item label="Runtime" span={2}>
{exampleMovie.runTimeMinutes} minutes
{exampleMovie.runtimeMinutes} minutes
</Descriptions.Item>
</Descriptions>
<Descriptions title="Director" bordered style={{ padding: "5%" }}>
......
......@@ -8,15 +8,19 @@ import { Link } from "react-router-dom";
export const NavigationBar = () => {
return (
<div className="navigation-bar">
<Header>
<Header style={{display: "flex"}}>
<Image src={logo} width={48} height={48} style={{width:"48", height: "48"}} preview={false}></Image>
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={["2"]}>
<Image src={logo} width={50} preview={false}></Image>
<Menu.Item>
<Link to="/">Home</Link>
</Menu.Item>
<Menu.Item>
<Link to="/browse">Browse</Link>
<Link to="/movies">Movies</Link>
</Menu.Item>
<Menu.Item>
<Link to="/directors">Directors</Link>
</Menu.Item>
<Menu.Item>
<Link to="/search">Search</Link>
......
import { Card, Carousel, Image, Space } from "antd";
import { Card, Carousel, Divider, Image, Space } from "antd";
import Meta from "antd/lib/card/Meta";
import Title from "antd/lib/skeleton/Title";
import React from "react";
......@@ -25,7 +25,7 @@ export interface MovieIO {
intro: string;
picture: string;
published: string;
runTimeMinutes: number;
runtimeMinutes: number;
director: DirectorIO;
}
......@@ -36,7 +36,7 @@ export interface DirectorIO {
birthdate: string;
}
//example
//example - TODO replace this with API preview call - get POPULAR movies (probably 6 is enough)
export const cardsDataExample: MovieIO[] = [
{
id: "1",
......@@ -44,7 +44,7 @@ export const cardsDataExample: MovieIO[] = [
name: "Auta",
intro: "auta ve filmu",
published: "7.8.2005",
runTimeMinutes: 125,
runtimeMinutes: 125,
director: {
id: "xd123",
name: "Kenny",
......@@ -59,7 +59,7 @@ export const cardsDataExample: MovieIO[] = [
name: "V tom domě straší",
intro: "jo ten dum je docela spooky",
published: "4.4.1994",
runTimeMinutes: 80,
runtimeMinutes: 80,
picture:
"https://images-na.ssl-images-amazon.com/images/S/pv-target-images/9a996123e0b01f618ab2291b479f9d5034de354b2d1bb58979ddc6937588dfa8._RI_V_TTW_.jpg",
director: {
......@@ -75,7 +75,7 @@ export const cardsDataExample: MovieIO[] = [
name: "Pokémon",
intro: "Gotta catch them all.",
published: "9.9.1970",
runTimeMinutes: 600,
runtimeMinutes: 600,
picture:
"https://www.obchod.crew.cz/im/coc/1280/0/content/629080/cover_image.1607432614.jpg",
director: {
......@@ -91,7 +91,7 @@ export const cardsDataExample: MovieIO[] = [
name: "Gympl",
intro: "VO SEDUMNÁCT METRŮ?",
published: "2.2.2005",
runTimeMinutes: 96,
runtimeMinutes: 96,
picture:
"https://img.csfd.cz/files/images/user/profile/162/847/162847510_91e839.jpg",
director: {
......@@ -107,7 +107,7 @@ export const cardsDataExample: MovieIO[] = [
name: "Příběh hraček",
intro: "Hmm the floor here is made of floor",
published: "4.5.1999",
runTimeMinutes: 90,
runtimeMinutes: 90,
picture:
"https://m.media-amazon.com/images/M/MV5BMDU2ZWJlMjktMTRhMy00ZTA5LWEzNDgtYmNmZTEwZTViZWJkXkEyXkFqcGdeQXVyNDQ2OTk4MzI@._V1_.jpg",
director: {
......@@ -124,7 +124,107 @@ export const cardsDataExample: MovieIO[] = [
intro:
"Jedu dál stále s tebou víme kam cesty vedou je to fajn fajn fajn je to fajn fajnový",
published: "17.11.1989",
runTimeMinutes: 50,
runtimeMinutes: 50,
picture:
"https://img.csfd.cz/files/images/user/profile/164/556/164556101_d8e43b.jpg",
director: {
id: "xx787",
name: "Zdenda",
surname: "Pohlreich",
birthdate: "4.4.1985",
},
},
];
//example - TODO replace this with API preview call - get RECENT movies (probably 6-7 is enough)
export const cardsDataExample2: MovieIO[] = [
{
id: "1",
originalName: "Cars",
name: "Auta",
intro: "auta ve filmu",
published: "7.8.2005",
runtimeMinutes: 125,
director: {
id: "xd123",
name: "Kenny",
surname: "Omega",
birthdate: "9.9.1980",
},
picture: "https://upload.wikimedia.org/wikipedia/en/3/34/Cars_2006.jpg",
},
{
id: "2",
originalName: "Monster House",
name: "V tom domě straší",
intro: "jo ten dum je docela spooky",
published: "4.4.1994",
runtimeMinutes: 80,
picture:
"https://images-na.ssl-images-amazon.com/images/S/pv-target-images/9a996123e0b01f618ab2291b479f9d5034de354b2d1bb58979ddc6937588dfa8._RI_V_TTW_.jpg",
director: {
id: "xp234",
name: "Bray",
surname: "Wyatt",
birthdate: "unknown",
},
},
{
id: "3",
originalName: "Pokemon",
name: "Pokémon",
intro: "Gotta catch them all.",
published: "9.9.1970",
runtimeMinutes: 600,
picture:
"https://www.obchod.crew.cz/im/coc/1280/0/content/629080/cover_image.1607432614.jpg",
director: {
id: "xc456",
name: "Kazuchika",
surname: "Okada",
birthdate: "17.2.1984",
},
},
{
id: "4",
originalName: "Gympl",
name: "Gympl",
intro: "VO SEDUMNÁCT METRŮ?",
published: "2.2.2005",
runtimeMinutes: 96,
picture:
"https://img.csfd.cz/files/images/user/profile/162/847/162847510_91e839.jpg",
director: {
id: "xs789",
name: "Tomáš",
surname: "Vorel",
birthdate: "někdy minulé století",
},
},
{
id: "5",
originalName: "Toy Story",
name: "Příběh hraček",
intro: "Hmm the floor here is made of floor",
published: "4.5.1999",
runtimeMinutes: 90,
picture:
"https://m.media-amazon.com/images/M/MV5BMDU2ZWJlMjktMTRhMy00ZTA5LWEzNDgtYmNmZTEwZTViZWJkXkEyXkFqcGdeQXVyNDQ2OTk4MzI@._V1_.jpg",
director: {
id: "xl753",
name: "Tomohiro",
surname: "Ishii",
birthdate: "19.9.1970",
},
},
{
id: "6",
name: "Smoke",
originalName: "Kouř",
intro:
"Jedu dál stále s tebou víme kam cesty vedou je to fajn fajn fajn je to fajn fajnový",
published: "17.11.1989",
runtimeMinutes: 50,
picture:
"https://img.csfd.cz/files/images/user/profile/164/556/164556101_d8e43b.jpg",
director: {
......@@ -137,10 +237,34 @@ export const cardsDataExample: MovieIO[] = [
];
const Preview: React.FC = () => (
<div>
<h1>Popular movies</h1>
<Space>
<Space className="preview" direction="vertical" style={{display: "flex"}}>
<Card title="Popular movies" >
<Space style={{ display: 'flex', padding: "5 %", justifyContent: "flex-end", width:"fit-content", overflow: "auto"}}>
{cardsDataExample.map((movie) => {
return (
<>
<Link to={`/movie/${movie.id}`}>
<Card
hoverable
style={{
width: "240px",
}}
cover={<img alt={movie.name} src={movie.picture} />}
>
<Meta title={movie.name} description={movie.originalName} />
</Card>
</Link>
</>
);
})}
</Space>
</Card>
<Divider/>
<Card title="Recent movies" >
<Space style={{ display: 'flex', padding: "5 %", justifyContent: "flex-end", width:"fit-content", overflow: "auto"}}>
{cardsDataExample2.map((movie) => {
return (
<>
<Link to={`/movie/${movie.id}`}>
......@@ -158,28 +282,8 @@ const Preview: React.FC = () => (
);
})}
</Space>
<Carousel autoplay>
<div>
<h3 style={contentStyle}>Avengers</h3>
</div>
<div>
<h3 style={contentStyle}>Morbius</h3>
</div>
<div>
<h3 style={contentStyle}>Princezna a Bubeník</h3>
</div>
<div>
<h3 style={contentStyle}>Scary Movie</h3>
</div>
<div>
<h3 style={contentStyle}>Scary Movie 2</h3>
</div>
<div>
<h3 style={contentStyle}>Scary Movie 3</h3>
</div>
</Carousel>
</div>
</Card>
</Space>
);
export default Preview;
......@@ -6,6 +6,8 @@ import { cardsDataExample, MovieIO } from "./Preview";
const { Search } = Input;
//TODO replace with result of input search and API call
const resultsExample: MovieIO[] = [
{
id: "789",
......@@ -14,12 +16,12 @@ const resultsExample: MovieIO[] = [
intro: "Jigsaw is the bad guy and this is the game",
picture:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse3.mm.bing.net%2Fth%3Fid%3DOIP.Jo6M-3oyAlMsB4-F__Z9bwHaHa%26pid%3DApi&f=1",
published: "1.1.2000",
runTimeMinutes: 120,
published: "1.6.2000",
runtimeMinutes: 120,
director: {
id: "123456789",
name: "Karel",
surname: "Vomacka",
surname: "Macka",
birthdate: "20.2.1987",
},
},
......@@ -31,7 +33,7 @@ const resultsExample: MovieIO[] = [
picture:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fimages01.kaleidescape.com%2Ftransformed%2Fcovers%2F1134x1624s%2F189%2F18976008.jpg&f=1&nofb=1",
published: "1.1.2002",
runTimeMinutes: 150,
runtimeMinutes: 150,
director: {
id: "123456789",
name: "Karel",
......@@ -44,17 +46,24 @@ const resultsExample: MovieIO[] = [
//for searching movies
export const SearchPage = () => {
const [pressed, setPressed] = useState(false);
const [searchValue, setSearch] = useState('');
//function that happens when search button is pressed
const onSearch = (value: string) => {
console.log(value);
console.log(searchValue); // just debug tool
setPressed(true);
}; // API request search goes here
}; // API request search goes here - request search with value inside variable "searchValue"
//columns stays the same
const columns = [
{
title: "Name",
dataIndex: "name",
sorter: (a:MovieIO, b:MovieIO) => {
if(a.name < b.name){return -1;}
if(a.name > b.name){return 1;}
return 0;
},
render: (text: string, record: MovieIO) => (
<Link to={`/movie/${record.id}`}>
<a>{record.name}</a>
......@@ -65,18 +74,54 @@ export const SearchPage = () => {
title: "Original name",
className: "original-name",
dataIndex: "originalName",
sorter: (a:MovieIO, b:MovieIO) => {
if(a.originalName < b.originalName){return -1;}
if(a.originalName > b.originalName){return 1;}
return 0;
},
},
{
title: "Release Date",
dataIndex: "published",
sorter: (a:MovieIO, b:MovieIO) => {
const first = a.published.split('.').reverse();
const second = b.published.split('.').reverse();
if(first[0] > second[0]){return 1 ;}
if(first[0] < second[0]){return -1 ;}
if(first[1] > second[1]){return 1 ;}
if(first[1] < second[1]){return -1 ;}
if(first[2] > second[2]){return 1 ;}
if(first[2] < second[2]){return -1 ;}
return 0;
}
},
{
title: "Runtime",
dataIndex: "runTimeMinutes",
dataIndex: "runtimeMinutes",
sorter: (a:MovieIO, b:MovieIO) => a.runtimeMinutes - b.runtimeMinutes,
},
{
title: "Director Surname",
title: "Director",
dataIndex: ["director", "surname"],
sorter: (a:MovieIO, b:MovieIO) => {
//surname has higher priority
if(a.director.surname < b.director.surname){return -1;}
if(a.director.surname > b.director.surname){return 1;}
if(a.director.name < b.director.name){return -1;}
if(a.director.name > b.director.name){return 1;}
return 0;
},
render: (text: string, record: MovieIO) => (
<Link to={`/director/${record.director.id}`}>
<a>{record.director.name} {record.director.surname}</a>
</Link>
),
},
];
return (
......@@ -90,6 +135,7 @@ export const SearchPage = () => {
allowClear
enterButton="Search"
size="large"
onChange={(e) => setSearch(e.target.value)}
onSearch={onSearch}
width="400 px"
/>
......@@ -103,7 +149,7 @@ export const SearchPage = () => {
onRow={(record, rowIndex) => {
return {
onClick: (event) => {
console.log(record.id);
console.log(record.id); //remove later
},
}; //here change to view movie
}}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment