diff --git a/front/src/pages/FilmPage.jsx b/front/src/pages/FilmPage.jsx new file mode 100644 index 0000000..01429d3 --- /dev/null +++ b/front/src/pages/FilmPage.jsx @@ -0,0 +1,81 @@ +import { React, useEffect, useState } from 'react' +import ContentBlock from './components/ContentBlock' +import { useParams } from 'react-router-dom' +import axios from 'axios' + +export default function FilmPage() { + const params = useParams() + const [items, setItems] = useState({}); + + useEffect(() => { + fetch("http://localhost:8080/cinema/" + params.id) + .then(function (response) { + return response.json(); + }) + .then(function (data) { + console.info('Get film success'); + setItems(data); + }) + .catch(function (error) { + console.error('Error:', error); + throw "Can't get film"; + }); + }, []); + + const content = ( +
+
+
+ {items.name} + window.location.reload()} style={{ cursor: "pointer" }}>{items.name}, 2020 г. + 9.2 + +
+
+
О фильме
+
+
Год производства
+
1000
+
+
+
Страна
+
Россия
+
+
+
Жанр
+
Драма
+
+
+
Длительность
+
189 мин. / 03:09
+
+
+
Возраст
+
16+
+
+
+

Описание

+
+ Пол Эджкомб — начальник блока смертников в тюрьме «Холодная гора», каждыйиз узников которого однажды проходит «зеленую милю» по пути к месту казни. Пол повидал много заключённых + и надзирателей за время работы. Однако гигант Джон Коффи, обвинённый в страшном преступлении, + стал одним из самых необычных обитателей блока. +
+
+
+
+

Трейлер

+ +
+
+ ); + + return ( +
+ +
+ ) +} diff --git a/front/src/pages/Films.jsx b/front/src/pages/Films.jsx new file mode 100644 index 0000000..996c341 --- /dev/null +++ b/front/src/pages/Films.jsx @@ -0,0 +1,177 @@ +import { React, useState, useEffect } from 'react' +import { useNavigate } from 'react-router-dom' +import FilmItem from './components/FilmItem' +import ContentBlock from './components/ContentBlock' +import ModalEdit from './components/ModalEdit' +import Banner from './components/Banner' +import '../styles/banner.css' +import CinemaDto from './models/CinemaDto' +import Service from './services/Service' + +export default function Films() { + const navigate = useNavigate(); + const fileReader = new FileReader() + const [items, setItems] = useState([]); + const [modalTable, setModalTable] = useState(false); + const [selectedImage, setSelectedImage] = useState(); + // для инпутов + const [filmName, setFilmName] = useState(''); + + const [filmNameEdit, setFilmNameEdit] = useState(''); + // хук для запоминания индекса элемента, вызвавшего модальное окно + const [currEditItem, setCurrEditItem] = useState(0); + + // фильмы, страны, жанры + useEffect(() => { + Service.readAll('cinema') + .then(data => setItems(data)); + }, []); + + function handleDeleteFilm(id) { + console.info('Try to remove item'); + Service.delete(`cinema/${id}`) + .then(() => { + setItems(items.filter(elem => elem.id !== id)) + console.log("Removed") + }); + }; + + function handleEditFilm(id) { + console.info(`Start edit script`); + + Service.read(`cinema/${id}`) + .then(function (data) { + setFilmNameEdit(data.name); + setCurrEditItem(data.id); + setModalTable(true) + console.info('End edit script'); + }) + }; + + // принимаем событие от кнопки "добавить" + const handleSubmitCreate = (e) => { + e.preventDefault(); // страница перестает перезагружаться + const itemObject = new CinemaDto(selectedImage, filmName); + console.info('Try to add item'); + + Service.create('cinema', itemObject) + .then((data) => { + setItems([...items, data]); + + setFilmName(''); + console.info('Added'); + }) + .catch(function (error) { + console.error('Error:', error); + throw "Can't add item"; + }); + }; + + // принимаем событие от кнопки "сохранить изменения" + const handleSubmitEdit = (e, id) => { + console.info('Start synchronize edit'); + e.preventDefault(); // страница перестает перезагружаться + const itemObject = new CinemaDto(selectedImage, filmNameEdit, id); + + Service.update("cinema/" + id, itemObject) + .then((data) => { + setItems( + items.map(item => + item.id === id ? { + ...item, + image: data.image, + name: data.name, + } : item) + ) + console.info('End synchronize edit'); + setModalTable(false) + }) + .catch((error) => { + console.error('Error:', error); + }); + + }; + + fileReader.onloadend = () => ( + setSelectedImage(fileReader.result) + ) + function changePicture(e) { + e.preventDefault(); + const file = e.target.files[0] + fileReader.readAsDataURL(file) + } + + function handleAddFilmToWillSee(data) { + const elem = CinemaDto.createFrom(data) + Service.create('willSee/', data) + } + + // форма для добавления данных + const Form = ( +
+
+ + +
+
+ + setFilmName(e.target.value)} placeholder="Введите название" /> +
+
+ + +
Подтвердите, что вам уже есть 16 лет
+
+
+ +
+
+ ) + + const Content = ( +
+ {Form} +
+ + + {items.map((item) => + navigate(`/films/${index}`)} + /> + )} + +
+ +
handleSubmitEdit(e, currEditItem)}> +
+ + +
+
+ + setFilmNameEdit(e.target.value)} className="form-control" name='filmNameEdit' id="filmNameEdit" type="text" placeholder="Введите название" required /> +
+
+ + +
+
+
+
+ ); + + return ( +
+ + +
+ ) +} diff --git a/front/src/pages/Orders.jsx b/front/src/pages/Orders.jsx new file mode 100644 index 0000000..dffc089 --- /dev/null +++ b/front/src/pages/Orders.jsx @@ -0,0 +1,226 @@ +import { React, useState, useEffect } from 'react' +import ContentBlock from './components/ContentBlock' +import Service from './services/Service'; +import ModalEdit from './components/ModalEdit'; +import OrderItem from './components/OrderItem'; +import OrderSessionItem from './components/OrderSessionItem'; + +export default function Orders() { + const [users, setUsers] = useState([]); + const [error, setError] = useState(false); + const [modalTable, setModalTable] = useState(false); + // хук для запоминания индекса элемента, вызвавшего модальное окно + const [currEditItem, setCurrEditItem] = useState(0); + // для выпадающих значений + const [customerName, setCustomerName] = useState(''); + const [customer, setCustomer] = useState([]); + const [sessionName, setSessionName] = useState(''); + const [count, setCount] = useState(1); + const [session, setSession] = useState([]); + const [orderSessions, setOrderSessions] = useState([]); + + useEffect(() => { + setError(false) + getAll('customer').then((data) => setCustomer(data)) + getAll('session').then((data) => setSession(data)) + getAll('order').then((data) => setUsers(data)) + }, []) + + async function getAll(elem) { + const requestUrl = `http://localhost:8080/${elem}` + const response = await fetch(requestUrl) + const result = await response.json() + return result + } + + function handleSubmit(e) { + e.preventDefault(); + if (customer.length <= 0) { + setError(true) + throw 'Form not submit' + } + handleSubmitCreate(e) + console.log('Form submit') + setError(false) + setCustomer('') + } + + // принимаем событие от кнопки "добавить" + const handleSubmitCreate = async (e) => { + e.preventDefault() + console.info('Try to add item'); + const requestParams = { + method: "POST", + headers: { + "Content-Type": "application/json" + } + }; + await fetch(`http://localhost:8080/order?customer=${customerName}`, requestParams) + .then((data) => { + getCustomerOrders(customerName) + getAll('customer').then((data) => setCustomer(data)) + }) + .catch(function (error) { + console.error('Error:', error); + throw "Can't add order"; + }); + }; + + function handleEdit(id) { + console.info(`Start edit script`); + + Service.read(`order/${id}`) + .then(function (data) { + setCurrEditItem(data.id); + setOrderSessions(data.sessions) + setModalTable(true) + console.info('End edit script'); + }) + }; + + const handleSubmitAdd = async (e, id) => { + console.info('Start add session'); + e.preventDefault(); // страница перестает перезагружаться + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json" + } + }; + const requestUrl = `http://localhost:8080/order/${id}?session=${sessionName}&count=${count}` + const response = await fetch(requestUrl, requestParams) + await response.json() + .then((data) => { + console.log(data.sessions) + setOrderSessions(data.sessions) + console.info('End add session'); + }) + .catch((error) => { + console.error('Error:', error); + }); + }; + + const handleSubmitDelete = async (e, id) => { + console.info('Start delete session'); + e.preventDefault(); // страница перестает перезагружаться + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json" + } + }; + const requestUrl = `http://localhost:8080/order/${id}?session=${sessionName}&count=-${count}` + const response = await fetch(requestUrl, requestParams) + await response.json() + .then((data) => { + console.info('End delete session') + setOrderSessions(data.sessions) + }) + .catch((error) => { + console.error('Error:', error); + }); + }; + + function handleDelete(id) { + console.info('Try to remove item'); + Service.delete(`order/${id}`) + .then(() => { + setUsers(users.filter(elem => elem.id !== id)) + console.log("Removed") + }); + }; + + async function getCustomerOrders(id) { + Service.read(`customer/${id}`) + .then(function (data) { + setUsers(data.orders); + console.info('End'); + }) + .catch(e => { console.log('Error get orders') }) + } + + const Content = ( + <> + +
+
+ +
+
+ + + + + + + + + + + {users.map((user) => ( + + ))} + +
#CustomerDateOfPurchase
+ +
+
+ + +
+
+ + setCount(e.target.value)} placeholder="Введите количество" /> +
+
+ + + +
+

Мои сеансы

+ + + + + + + + + + + + {orderSessions ? orderSessions.map((item) => + + ) : null} + +
#PriceCinemaTimestampCount
+
+
+ + ) + + return ( + + ) +} diff --git a/front/src/pages/Registration.jsx b/front/src/pages/Registration.jsx new file mode 100644 index 0000000..543c1f3 --- /dev/null +++ b/front/src/pages/Registration.jsx @@ -0,0 +1,169 @@ +import { React, useState, useEffect } from 'react' +import ContentBlock from './components/ContentBlock' +import Service from './services/Service'; +import ModalEdit from './components/ModalEdit'; +import MyButton from './components/MyButton'; +import UserItem from './components/UserItem'; + +export default function Registration() { + const [login, setLogin] = useState(''); + const [password, setPassword] = useState(''); + const [loginEdit, setLoginEdit] = useState(''); + const [passwordEdit, setPasswordEdit] = useState(''); + const [users, setUsers] = useState([]); + const [error, setError] = useState(false); + const [modalTable, setModalTable] = useState(false); + // хук для запоминания индекса элемента, вызвавшего модальное окно + const [currEditItem, setCurrEditItem] = useState(0); + + useEffect(() => { + setError(false) + getAll() + }, []) + + async function getAll() { + const requestUrl = "http://localhost:8080/customer" + const response = await fetch(requestUrl) + const temp = await response.json() + setUsers(temp) + } + + function handleSubmit(e) { + e.preventDefault(); + if (login.length <= 0 || password.length <= 0) { + setError(true) + throw 'Form not submit' + } + handleSubmitCreate(e) + console.log('Form submit') + setError(false) + setLogin('') + setPassword('') + } + + // принимаем событие от кнопки "добавить" + const handleSubmitCreate = async (e) => { + e.preventDefault() + console.info('Try to add item'); + const requestParams = { + method: "POST", + headers: { + "Content-Type": "application/json" + } + }; + await fetch(`http://localhost:8080/customer?login=${login}&password=${password}`, requestParams) + .then(() => { + getAll() + }) + }; + + function handleEdit(id) { + console.info(`Start edit script`); + + Service.read(`customer/${id}`) + .then(function (data) { + setLoginEdit(data.login); + setPasswordEdit(data.password); + setCurrEditItem(data.id); + setModalTable(true) + console.info('End edit script'); + }) + }; + + const handleSubmitEdit = async (e, id) => { + console.info('Start synchronize edit'); + e.preventDefault(); // страница перестает перезагружаться + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json" + } + }; + const requestUrl = `http://localhost:8080/customer/${id}?login=${loginEdit}&password=${passwordEdit}` + const response = await fetch(requestUrl, requestParams) + const temp = await response.json() + .then((data) => { + setUsers( + users.map(item => + item.id === id ? { + ...item, + login: data.login, + password: data.password + } : item) + ) + console.info('End synchronize edit'); + setModalTable(false) + }) + .catch((error) => { + console.error('Error:', error); + }); + }; + + function handleDelete(id) { + console.info('Try to remove item'); + Service.delete(`customer/${id}`) + .then(() => { + setUsers(users.filter(elem => elem.id !== id)) + console.log("Removed") + }); + }; + + const Content = ( + <> +
+
+ + setLogin(e.target.value)} placeholder="Введите логин" /> +
+ {error && login.length <= 0 ? : null} +
+ + setPassword(e.target.value)} placeholder="Введите пароль" /> +
+ {error && password.length <= 0 ? : null} +
+ +
+
+ + + + + + + + + + + {users.map((user) => ( + + ))} + +
#LoginPassword
+ +
handleSubmitEdit(e, currEditItem)}> +
+ + setLoginEdit(e.target.value)} className="form-control" name='loginEdit' id="loginEdit" type="text" placeholder="Введите логин" required /> +
+
+ + setPasswordEdit(e.target.value)} className="form-control" name='passwordEdit' id="passwordEdit" type="text" placeholder="Введите пароль" required /> +
+
+ + +
+
+
+ + ) + + return ( + + ) +} diff --git a/front/src/pages/SearchSame.jsx b/front/src/pages/SearchSame.jsx new file mode 100644 index 0000000..a01ac2c --- /dev/null +++ b/front/src/pages/SearchSame.jsx @@ -0,0 +1,53 @@ +import { React, useState, useEffect } from 'react' +import FilmItem from './components/FilmItem' +import { useParams, useNavigate } from "react-router-dom"; +import ContentBlock from './components/ContentBlock'; + +export default function SearchSame() { + const navigate = useNavigate(); + // массив полученных фильмов + const [searchResult, setSearchResult] = useState([]); + const params = useParams() + const [items, setItems] = useState([]) + + useEffect(() => { + let temp = JSON.stringify(searchResult); + temp = JSON.parse(temp); + setItems(temp.filter(elem => elem.name.toLowerCase().includes(params.request.toLowerCase()))); + }, [searchResult, params]); + + useState(() => { + const fetchData = async () => { + const url = new URL('http://localhost:8080/cinema') + try { + const response = await fetch(url.href); + const json = await response.json(); + setSearchResult(json); + console.info('Search success'); + } catch (error) { + return; + } + }; + fetchData(); + }, []) + + const Content = ( + + + {items.map((item) => + navigate(`/films/${index}`)} + /> + )} + +
+ ) + + return ( +
+ +
+ ) +} diff --git a/front/src/pages/Sessions.jsx b/front/src/pages/Sessions.jsx new file mode 100644 index 0000000..20986cc --- /dev/null +++ b/front/src/pages/Sessions.jsx @@ -0,0 +1,191 @@ +import { React, useState, useEffect } from 'react' +import ContentBlock from './components/ContentBlock' +import Service from './services/Service'; +import ModalEdit from './components/ModalEdit'; +import SessionItem from './components/SessionItem'; +import CinemaDto from './models/CinemaDto' + +export default function Sessions() { + const [price, setPrice] = useState(1); + const [timestamp, setTimestamp] = useState(new Date()); + const [maxCount, setMaxCount] = useState(1); + const [priceEdit, setPriceEdit] = useState(''); + const [users, setUsers] = useState([]); + const [error, setError] = useState(false); + const [modalTable, setModalTable] = useState(false); + // хук для запоминания индекса элемента, вызвавшего модальное окно + const [currEditItem, setCurrEditItem] = useState(0); + // для выпадающих значений + const [cinemaName, setCinemaName] = useState(''); + const [cinema, setCinema] = useState([]); + + useEffect(() => { + setError(false) + getAll('cinema').then((data) => setCinema(data)) + getAll('session').then((data) => setUsers(data)) + }, []) + + async function getAll(elem) { + const requestUrl = `http://localhost:8080/${elem}` + const response = await fetch(requestUrl) + const result = await response.json() + return result + } + + function handleSubmit(e) { + e.preventDefault(); + if (price.length <= 0 || cinema.length <= 0) { + setError(true) + throw 'Form not submit' + } + handleSubmitCreate(e) + console.log('Form submit') + setError(false) + setPrice('') + setCinema('') + } + + // принимаем событие от кнопки "добавить" + const handleSubmitCreate = async (e) => { + e.preventDefault() + console.info('Try to add item'); + const requestParams = { + method: "POST", + headers: { + "Content-Type": "application/json" + } + }; + await fetch(`http://localhost:8080/session?price=${price}×tamp=${timestamp}&cinemaid=${cinemaName}&capacity=${maxCount}`, requestParams) + .then(() => { + getAll('session').then((data) => setUsers(data)) + getAll('cinema').then((data) => setCinema(data)) + }) + .catch(function (error) { + console.error('Error:', error); + throw "Can't add session"; + }); + }; + + function handleEdit(id) { + console.info(`Start edit script`); + + Service.read(`session/${id}`) + .then(function (data) { + setPriceEdit(data.price); + setCurrEditItem(data.id); + setModalTable(true) + console.info('End edit script'); + }) + }; + + const handleSubmitEdit = async (e, id) => { + console.info('Start synchronize edit'); + e.preventDefault(); // страница перестает перезагружаться + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json" + } + }; + const requestUrl = `http://localhost:8080/session/${id}?price=${priceEdit}` + const response = await fetch(requestUrl, requestParams) + await response.json() + .then((data) => { + setUsers( + users.map(item => + item.id === id ? { + ...item, + price: data.price + } : item) + ) + console.info('End synchronize edit'); + setModalTable(false) + }) + .catch((error) => { + console.error('Error:', error); + }); + }; + + function handleDelete(id) { + console.info('Try to remove item'); + Service.delete(`session/${id}`) + .then(() => { + setUsers(users.filter(elem => elem.id !== id)) + console.log("Removed") + }); + }; + + const Content = ( + <> +
+
+ + setPrice(e.target.value)} placeholder="Введите цену" /> +
+ {error && price.length <= 0 ? : null} +
+ + +
+ {error && cinema.length <= 0 ? : null} +
+ + setMaxCount(e.target.value)} placeholder="Введите количество" /> +
+ {error && price.length <= 0 ? : null} +
+ + setTimestamp(e.target.value)} placeholder="Введите дату" /> +
+ {error && timestamp.length <= 0 ? : null} +
+ +
+
+ + + + + + + + + + + + + + {users.map((user) => ( + + ))} + +
#PriceCinemaTimestampCapacityMaxCount
+ +
handleSubmitEdit(e, currEditItem)}> +
+ + setPriceEdit(e.target.value)} className="form-control" name='priceEdit' id="priceEdit" type="number" step="0.01" min="1" placeholder="Введите цену" required /> +
+
+ + +
+
+
+ + ) + + return ( + + ) +} diff --git a/front/src/pages/components/Banner.jsx b/front/src/pages/components/Banner.jsx new file mode 100644 index 0000000..19c2e06 --- /dev/null +++ b/front/src/pages/components/Banner.jsx @@ -0,0 +1,46 @@ +import { React, useEffect, useState } from 'react' +import { useNavigate } from 'react-router-dom' +import banner1 from '../../images/banner1.jpg' +import banner2 from '../../images/banner2.jpg' +import banner3 from '../../images/banner3.jpg' + +export default function Banner() { + const length = 3; + var old = 0; + var current = 1; + const navigate = useNavigate(); + const [bannerState, setBannerState] = useState(['show', 'hide', 'hide']); + + useEffect(() => { + const timer = window.setInterval(() => { + setBannerState([...bannerState, bannerState[current] = 'show', bannerState[old] = 'hide']); + + console.info('Banner changed'); + + old = current; + current++; + + if (current === length) { + current = 0; + } + }, 5000) + + return () => { + window.clearInterval(timer); + } + }, []) + + return ( + + ) +} \ No newline at end of file diff --git a/front/src/pages/components/ContentBlock.jsx b/front/src/pages/components/ContentBlock.jsx new file mode 100644 index 0000000..63209c2 --- /dev/null +++ b/front/src/pages/components/ContentBlock.jsx @@ -0,0 +1,15 @@ +import React from 'react' +import '../../styles/styleBlock.css' + +export default function ContentBlock(props) { + + return ( +
+
+

{props.title}

+
+ {props.valueBlock} +
+ ) + +} diff --git a/front/src/pages/components/FilmItem.jsx b/front/src/pages/components/FilmItem.jsx new file mode 100644 index 0000000..9d9f685 --- /dev/null +++ b/front/src/pages/components/FilmItem.jsx @@ -0,0 +1,27 @@ +import React from "react" +import '../../styles/styleFilmItem.css' +import MyButton from './MyButton' + +export default function FilmItem(props) { + return ( + + + {props.item.name} +
+
+

+ props.openFilmPageFunc(props.item.id)} style={{ cursor: "pointer" }}> + {props.item.name} + +

+
+
+
9.2
+ +
+
+
+ + + ) +} \ No newline at end of file diff --git a/front/src/pages/components/Footer.jsx b/front/src/pages/components/Footer.jsx new file mode 100644 index 0000000..5c5acbd --- /dev/null +++ b/front/src/pages/components/Footer.jsx @@ -0,0 +1,11 @@ +import React from 'react' +import vk from '../../images/vk.jpg' +import '../../styles/styleFooter.css' + +export default function Footer() { + return ( +
2022 г. + +
+ ) +} diff --git a/front/src/pages/components/Header.jsx b/front/src/pages/components/Header.jsx new file mode 100644 index 0000000..e3740ff --- /dev/null +++ b/front/src/pages/components/Header.jsx @@ -0,0 +1,43 @@ +import { React, useState } from 'react' +import { useNavigate } from 'react-router-dom' +import searchImage from '../../images/search.jpg' +import '../../styles/styleHeader.css' + +export default function Header() { + const navigate = useNavigate(); + + const [searchName, setSearchName] = useState(''); + + function handleSubmit(e) { + console.info('Try to search data'); + e.preventDefault(); + navigate(`/search-same/${searchName}`) + setSearchName(''); + } + + return ( +
+
+ +
+
+ ) +} diff --git a/front/src/pages/components/ModalEdit.jsx b/front/src/pages/components/ModalEdit.jsx new file mode 100644 index 0000000..1f6f897 --- /dev/null +++ b/front/src/pages/components/ModalEdit.jsx @@ -0,0 +1,18 @@ +import React from 'react' +import * as classes from "../../styles/ModalEdit.module.css" + +export default function ModalEdit({children, visible, setVisible}) { + + const rootClasses = [classes.myModal] + if (visible) { + rootClasses.push(classes.active); + } + //onClick={()=>setVisible(false)} + return ( +
+
+ {children} +
+
+ ) +} diff --git a/front/src/pages/components/MyButton.jsx b/front/src/pages/components/MyButton.jsx new file mode 100644 index 0000000..6b1ffdb --- /dev/null +++ b/front/src/pages/components/MyButton.jsx @@ -0,0 +1,26 @@ +import React from "react" +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faEdit } from "@fortawesome/free-solid-svg-icons" +import { faRemove } from "@fortawesome/free-solid-svg-icons" + +export default function MyButton({ value }) { + + const delButton = ( + + ) + + const editButton = ( + + ) + + return ( +
+ {value.editFunc ? editButton : null} + {value.removeFunc ? delButton : null} +
+ ) +} \ No newline at end of file diff --git a/front/src/pages/components/OrderItem.jsx b/front/src/pages/components/OrderItem.jsx new file mode 100644 index 0000000..c2b08dc --- /dev/null +++ b/front/src/pages/components/OrderItem.jsx @@ -0,0 +1,27 @@ +import React, { useEffect, useState } from "react" +import MyButton from './MyButton' +import CustomerDto from "../models/CustomerDto"; +import Service from "../services/Service"; + +export default function OrderItem(props) { + const [customer, setCustomer] = useState(new CustomerDto()); + + useEffect(() => { + Service.read("customer/" + props.item.customer.id) + .then((data) => { + setCustomer(data) + }) + .catch((error) => { + console.error('Error:', error); + }); + }, []) + + return ( + + {props.item.id} + {customer.login} + {props.item.dateOfPurchase} + + + ) +} \ No newline at end of file diff --git a/front/src/pages/components/OrderSessionItem.jsx b/front/src/pages/components/OrderSessionItem.jsx new file mode 100644 index 0000000..343ed34 --- /dev/null +++ b/front/src/pages/components/OrderSessionItem.jsx @@ -0,0 +1,37 @@ +import React, { useEffect, useState } from "react" +import CinemaDto from "../models/CinemaDto"; +import Service from "../services/Service"; + +export default function OrderSessionItem(props) { + const [item, setItem] = useState(new CinemaDto()) + const [load, setLoad] = useState(false) + const [date, setDate] = useState(new Date()) + + useEffect(() => { + Service.read("session/" + props.item.sessionId) + .then((data) => { + setItem(data) + setLoad(true) + setDate(new Date(data.timestamp).toLocaleString('RU-ru')) + }) + .catch((error) => { + console.error('Error:', error); + }); + return () => { + setLoad(false) + } + }, []) + + return ( + <> + {load ? + + {item.id} + {item.price} + {item.cinema.name} + {date} + {props.item.count} + : null} + + ) +} \ No newline at end of file diff --git a/front/src/pages/components/SessionItem.jsx b/front/src/pages/components/SessionItem.jsx new file mode 100644 index 0000000..24dae49 --- /dev/null +++ b/front/src/pages/components/SessionItem.jsx @@ -0,0 +1,18 @@ +import React, { useEffect, useState } from "react" +import MyButton from './MyButton' + +export default function SessionItem(props) { + const date = new Date(props.item.timestamp).toLocaleString('RU-ru') + + return ( + + {props.item.id} + {props.item.price} + {props.item.cinema.name} + {date} + {props.item.capacity} + {props.item.maxCount} + + + ) +} \ No newline at end of file diff --git a/front/src/pages/components/UserItem.jsx b/front/src/pages/components/UserItem.jsx new file mode 100644 index 0000000..effcd70 --- /dev/null +++ b/front/src/pages/components/UserItem.jsx @@ -0,0 +1,13 @@ +import React from "react" +import MyButton from './MyButton' + +export default function UserItem(props) { + return ( + + {props.item.id} + {props.item.login} + {props.item.password} + + + ) +} \ No newline at end of file diff --git a/front/src/pages/models/CinemaDto.js b/front/src/pages/models/CinemaDto.js new file mode 100644 index 0000000..e9aafe9 --- /dev/null +++ b/front/src/pages/models/CinemaDto.js @@ -0,0 +1,10 @@ +export default class CinemaDto { + constructor(image, name, id) { + this.image = image; + this.name = name; + this.id = parseInt(id); + } + static createFrom(item) { + return new CinemaDto(item.image, item.name, item.id); + } +} \ No newline at end of file diff --git a/front/src/pages/models/CustomerDto.js b/front/src/pages/models/CustomerDto.js new file mode 100644 index 0000000..61ff30e --- /dev/null +++ b/front/src/pages/models/CustomerDto.js @@ -0,0 +1,10 @@ +export default class CustomerDto { + constructor(login, password, id) { + this.login = login; + this.password = password; + this.id = parseInt(id); + } + static createFrom(item) { + return new CustomerDto(item.login, item.password, item.id); + } +} \ No newline at end of file diff --git a/front/src/pages/models/SessionDto.js b/front/src/pages/models/SessionDto.js new file mode 100644 index 0000000..c720b8c --- /dev/null +++ b/front/src/pages/models/SessionDto.js @@ -0,0 +1,11 @@ +export default class SessionDto { + constructor(price, timestamp, maxCount, id) { + this.price = parseFloat(price); + this.timestamp = Date.parse(timestamp); + this.maxCount = parseInt(maxCount); + this.id = parseInt(id); + } + static createFrom(item) { + return new SessionDto(item.image, item.name, item.id); + } +} \ No newline at end of file diff --git a/front/src/pages/services/Service.jsx b/front/src/pages/services/Service.jsx new file mode 100644 index 0000000..43fd77d --- /dev/null +++ b/front/src/pages/services/Service.jsx @@ -0,0 +1,42 @@ +import axios from 'axios' + +function toJSON(data) { + const jsonObj = {}; + const fields = Object.getOwnPropertyNames(data); + for (const field of fields) { + if (data[field] === undefined) { + continue; + } + jsonObj[field] = data[field]; + } + return jsonObj; +} + +export default class Service { + static dataUrlPrefix = 'http://localhost:8080/'; + + static async readAll(url) { + const response = await axios.get(this.dataUrlPrefix + url); + return response.data; + } + + static async read(url) { + const response = await axios.get(this.dataUrlPrefix + url); + return response.data; + } + + static async create(url, data) { + const response = await axios.post(this.dataUrlPrefix + url, toJSON(data)); + return response.data; + } + + static async update(url, data) { + const response = await axios.put(this.dataUrlPrefix + url, toJSON(data)); + return response.data; + } + + static async delete(url) { + const response = await axios.delete(this.dataUrlPrefix + url); + return response.data.id ? response.data.id : response.error; + } +} \ No newline at end of file