commit front 3
This commit is contained in:
parent
1331a59414
commit
83f8e345fe
81
front/src/pages/FilmPage.jsx
Normal file
81
front/src/pages/FilmPage.jsx
Normal file
@ -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 = (
|
||||
<div>
|
||||
<div className="container pt-4">
|
||||
<div className="container d-block text-start">
|
||||
<img className="row posterFilmPage img-fluid float-start me-3 mt-3" src={items.image} alt={items.name} align="left" />
|
||||
<a className="col text-white fw-bold fs-2" onClick={() => window.location.reload()} style={{ cursor: "pointer" }}>{items.name}, 2020 г. </a>
|
||||
<span className="col badge green-mark text-white fw-bold fs-5 mx-2 p-2">9.2</span>
|
||||
<button className="col badge willSee text-white fw-bold fs-5 mx-2 p-2 border border-0">
|
||||
Буду смотреть
|
||||
</button>
|
||||
</div>
|
||||
<div className="container table text-start fs-4">
|
||||
<div className="row text-white fw-bold fs-3">О фильме</div>
|
||||
<div className="row">
|
||||
<div className="col-xs-6 col-sm-3">Год производства</div>
|
||||
<div className="col-xs-6 col-sm-3">1000</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xs-6 col-sm-3">Страна</div>
|
||||
<div className="col-xs-6 col-sm-3">Россия</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xs-6 col-sm-3">Жанр</div>
|
||||
<div className="col-xs-6 col-sm-3">Драма</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xs-6 col-sm-3">Длительность</div>
|
||||
<div className="col-xs-6 col-sm-3">189 мин. / 03:09</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xs-6 col-sm-3">Возраст</div>
|
||||
<div className="col-xs-6 col-sm-3">16+</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-white fw-bold m-auto p-1 fs-3 text-start">Описание</h3>
|
||||
<div className="description text-start fs-4">
|
||||
Пол Эджкомб — начальник блока смертников в тюрьме «Холодная гора», каждыйиз узников которого однажды проходит «зеленую милю» по пути к месту казни. Пол повидал много заключённых
|
||||
и надзирателей за время работы. Однако гигант Джон Коффи, обвинённый в страшном преступлении,
|
||||
стал одним из самых необычных обитателей блока.
|
||||
</div>
|
||||
</div>
|
||||
<hr className="border border-0 bg-black" />
|
||||
<div className="container">
|
||||
<h1 className="fs-1 fw-bold text-white ms-2 text-start">Трейлер</h1>
|
||||
<nav className="ratio ratio-16x9">
|
||||
<iframe className="p-2" src="https://www.youtube.com/embed/Ca3mUSDJlgM" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ContentBlock valueBlock={content} title='Страница фильма' />
|
||||
</div>
|
||||
)
|
||||
}
|
177
front/src/pages/Films.jsx
Normal file
177
front/src/pages/Films.jsx
Normal file
@ -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 = (
|
||||
<form className="row g-3 fs-4 description fw-bold needs-validation-content" id="frm-items" onSubmit={handleSubmitCreate}>
|
||||
<div className="col-md-3">
|
||||
<label className="form-label" htmlFor="filmPicture">Изображение</label>
|
||||
<input required className="form-control" name="filmPicture" id="filmPicture"
|
||||
type="file"
|
||||
onChange={changePicture} />
|
||||
</div>
|
||||
<div className="col">
|
||||
<label className="form-label" htmlFor="filmName">Название</label>
|
||||
<input required className="form-control" name="filmName" id="filmName" type="text" value={filmName} onChange={e => setFilmName(e.target.value)} placeholder="Введите название" />
|
||||
</div>
|
||||
<div className="form-check mx-2">
|
||||
<input required className="form-check-input" name="film16" id="film16" type="checkbox" />
|
||||
<label className="form-check-label" htmlFor="film16">Мне уже 16 лет</label>
|
||||
<div className="invalid-feedback">Подтвердите, что вам уже есть 16 лет</div>
|
||||
</div>
|
||||
<div className="text-start">
|
||||
<button className="willSee p-1 border border-0 rounded text-white fw-bold fs-4" id="btn-add-item" type="submit">Добавить</button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
|
||||
const Content = (
|
||||
<div>
|
||||
{Form}
|
||||
<hr className="border border-0 bg-black" />
|
||||
<table className="table" id="tbl-items">
|
||||
<tbody>
|
||||
{items.map((item) =>
|
||||
<FilmItem
|
||||
item={item}
|
||||
key={item.id}
|
||||
removeFunc={handleDeleteFilm}
|
||||
editFunc={handleEditFilm}
|
||||
openFilmPageFunc={(index) => navigate(`/films/${index}`)}
|
||||
/>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
<ModalEdit visible={modalTable} setVisible={setModalTable}>
|
||||
<form className="g-3 fs-4 description fw-bold container" id="frm-items-edit" onSubmit={(e) => handleSubmitEdit(e, currEditItem)}>
|
||||
<div className="row">
|
||||
<label className="form-label" htmlFor="filmPictureEdit">Изображение</label>
|
||||
<input required className="form-control" name="filmPictureEdit" id="filmPictureEdit"
|
||||
type="file"
|
||||
onChange={changePicture} />
|
||||
</div>
|
||||
<div className="row">
|
||||
<label className="form-label" htmlFor="filmNameEdit">Название</label>
|
||||
<input value={filmNameEdit} onChange={e => setFilmNameEdit(e.target.value)} className="form-control" name='filmNameEdit' id="filmNameEdit" type="text" placeholder="Введите название" required />
|
||||
</div>
|
||||
<div className="text-center mt-3">
|
||||
<button className="btn btn-primary mx-1" type="submit" id="buttonSaveChanges">Сохранить изменения</button>
|
||||
<button className="btn btn-secondary mx-1" type="button" data-bs-dismiss="modal" onClick={() => setModalTable(false)}>Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalEdit>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Banner />
|
||||
<ContentBlock valueBlock={Content} title='Фильмы' />
|
||||
</div>
|
||||
)
|
||||
}
|
226
front/src/pages/Orders.jsx
Normal file
226
front/src/pages/Orders.jsx
Normal file
@ -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 = (
|
||||
<>
|
||||
<select required className="form-select" name="customer" id="customer" value={customer.value} onChange={e => {
|
||||
setCustomerName(e.target.value)
|
||||
getCustomerOrders(e.target.value)
|
||||
}} >
|
||||
<option value='' defaultValue disabled>Выберите значение</option>
|
||||
{customer ? customer.map(elem =>
|
||||
<option key={elem.id} value={elem.id}>{elem.login}</option>
|
||||
) : null}
|
||||
</select>
|
||||
<form className="d-flex flex-column fs-4 fw-bold text-white text-center align-items-center">
|
||||
<div>
|
||||
<button className="btn btn-success my-3" type="button" onClick={handleSubmit}>Добавить</button>
|
||||
</div>
|
||||
</form>
|
||||
<table className="table mt-3 text-white">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Customer</th>
|
||||
<th scope="col">DateOfPurchase</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
{users.map((user) => (
|
||||
<OrderItem
|
||||
item={user}
|
||||
key={user.id}
|
||||
editFunc={handleEdit}
|
||||
removeFunc={handleDelete}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<ModalEdit visible={modalTable} setVisible={setModalTable}>
|
||||
<form className="fs-4 description fw-bold d-flex flex-column align-items-center" id="frm-items-edit">
|
||||
<div className="col-6">
|
||||
<label className="form-label" htmlFor="session">Сеанс</label>
|
||||
<select required className="form-control" name="session" id="session" value={session.value} onChange={e => setSessionName(e.target.value)} >
|
||||
<option value='' defaultValue disabled>Выберите значение</option>
|
||||
{session ? session.map(elem =>
|
||||
<option key={elem.id} value={elem.id}>{elem.cinema.name} {new Date(elem.timestamp).toLocaleString('RU-ru')}</option>
|
||||
) : null}
|
||||
</select>
|
||||
</div>
|
||||
<div className="col-6">
|
||||
<label className="form-label" htmlFor="count">Количество</label>
|
||||
<input required className="form-control" name="count" id="count" type="number" min="1" value={count} onChange={e => setCount(e.target.value)} placeholder="Введите количество" />
|
||||
</div>
|
||||
<div className="text-center mt-3">
|
||||
<button className="btn btn-success mx-1" type="button" onClick={e => handleSubmitAdd(e, currEditItem)}>Добавить</button>
|
||||
<button className="btn btn-danger mx-1" type="button" onClick={e => handleSubmitDelete(e, currEditItem)}>Удалить</button>
|
||||
<button className="btn btn-secondary mx-1" type="button" data-bs-dismiss="modal" onClick={() => setModalTable(false)}>Отмена</button>
|
||||
</div>
|
||||
<p>Мои сеансы</p>
|
||||
<table className="table fs-6 table-bordered" id="tbl-items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Price</th>
|
||||
<th scope="col">Cinema</th>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{orderSessions ? orderSessions.map((item) =>
|
||||
<OrderSessionItem
|
||||
item={item}
|
||||
key={parseInt(item.sessionId+''+item.orderId)}
|
||||
/>
|
||||
) : null}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</ModalEdit>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<ContentBlock className="d-flex justify-content-center flex-wrap" valueBlock={Content} title='Заказы' />
|
||||
)
|
||||
}
|
169
front/src/pages/Registration.jsx
Normal file
169
front/src/pages/Registration.jsx
Normal file
@ -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 = (
|
||||
<>
|
||||
<form onSubmit={handleSubmit} className="d-flex flex-column fs-4 fw-bold text-white text-center align-items-center">
|
||||
<div>
|
||||
<label className="form-label">Логин</label>
|
||||
<input className="form-control mainInput" type="text" value={login} onChange={e => setLogin(e.target.value)} placeholder="Введите логин" />
|
||||
</div>
|
||||
{error && login.length <= 0 ? <label className="fs-6 text-danger">Неправильный ввод логина</label> : null}
|
||||
<div>
|
||||
<label className="form-label">Пароль</label>
|
||||
<input className="form-control mainInput" type="text" value={password} onChange={e => setPassword(e.target.value)} placeholder="Введите пароль" />
|
||||
</div>
|
||||
{error && password.length <= 0 ? <label className="fs-6 text-danger">Неправильный ввод пароля</label> : null}
|
||||
<div>
|
||||
<button className="btn btn-success my-3" type="submit">Регистрация</button>
|
||||
</div>
|
||||
</form>
|
||||
<table className="table mt-3 text-white">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Login</th>
|
||||
<th scope="col">Password</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
{users.map((user) => (
|
||||
<UserItem
|
||||
item={user}
|
||||
key={user.id}
|
||||
editFunc={handleEdit}
|
||||
removeFunc={handleDelete} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<ModalEdit visible={modalTable} setVisible={setModalTable}>
|
||||
<form className="g-3 fs-4 description fw-bold container" id="frm-items-edit" onSubmit={(e) => handleSubmitEdit(e, currEditItem)}>
|
||||
<div className="row">
|
||||
<label className="form-label" htmlFor="loginEdit">Логин</label>
|
||||
<input value={loginEdit} onChange={e => setLoginEdit(e.target.value)} className="form-control" name='loginEdit' id="loginEdit" type="text" placeholder="Введите логин" required />
|
||||
</div>
|
||||
<div className="row">
|
||||
<label className="form-label" htmlFor="passwordEdit">Пароль</label>
|
||||
<input value={passwordEdit} onChange={e => setPasswordEdit(e.target.value)} className="form-control" name='passwordEdit' id="passwordEdit" type="text" placeholder="Введите пароль" required />
|
||||
</div>
|
||||
<div className="text-center mt-3">
|
||||
<button className="btn btn-primary mx-1" type="submit" id="buttonSaveChanges">Сохранить изменения</button>
|
||||
<button className="btn btn-secondary mx-1" type="button" data-bs-dismiss="modal" onClick={() => setModalTable(false)}>Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalEdit>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<ContentBlock className="d-flex justify-content-center flex-wrap" valueBlock={Content} title='Регистрация' />
|
||||
)
|
||||
}
|
53
front/src/pages/SearchSame.jsx
Normal file
53
front/src/pages/SearchSame.jsx
Normal file
@ -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 = (
|
||||
<table className="table" id="tbl-items">
|
||||
<tbody>
|
||||
{items.map((item) =>
|
||||
<FilmItem
|
||||
item={item}
|
||||
key={item.id}
|
||||
openFilmPageFunc={(index) => navigate(`/films/${index}`)}
|
||||
/>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ContentBlock valueBlock={Content} title='Похожие результаты'/>
|
||||
</div>
|
||||
)
|
||||
}
|
191
front/src/pages/Sessions.jsx
Normal file
191
front/src/pages/Sessions.jsx
Normal file
@ -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 = (
|
||||
<>
|
||||
<form className="d-flex flex-column fs-4 fw-bold text-white text-center align-items-center">
|
||||
<div>
|
||||
<label className="form-label">Цена</label>
|
||||
<input className="form-control mainInput" min="1" type="number" step="0.01" value={price} onChange={e => setPrice(e.target.value)} placeholder="Введите цену" />
|
||||
</div>
|
||||
{error && price.length <= 0 ? <label className="fs-6 text-danger">Неправильный ввод цены</label> : null}
|
||||
<div>
|
||||
<label className="form-label">Фильм</label>
|
||||
<select required className="form-select" name="filmCountry" id="filmCountry" value={cinema.value} onChange={e => setCinemaName(e.target.value)} >
|
||||
<option value='' defaultValue disabled>Выберите значение</option>
|
||||
{cinema ? cinema.map(elem =>
|
||||
<option key={elem.id} value={elem.id}>{elem.name}</option>
|
||||
) : null }
|
||||
</select>
|
||||
</div>
|
||||
{error && cinema.length <= 0 ? <label className="fs-6 text-danger">Неправильный ввод фильма</label> : null}
|
||||
<div>
|
||||
<label className="form-label">Кол-во сеансов</label>
|
||||
<input className="form-control mainInput" min="1" type="number" value={maxCount} onChange={e => setMaxCount(e.target.value)} placeholder="Введите количество" />
|
||||
</div>
|
||||
{error && price.length <= 0 ? <label className="fs-6 text-danger">Неправильный ввод цены</label> : null}
|
||||
<div>
|
||||
<label className="form-label">Дата</label>
|
||||
<input className="form-control mainInput" type="datetime-local" value={timestamp} onChange={e => setTimestamp(e.target.value)} placeholder="Введите дату" />
|
||||
</div>
|
||||
{error && timestamp.length <= 0 ? <label className="fs-6 text-danger">Неправильный ввод даты</label> : null}
|
||||
<div>
|
||||
<button className="btn btn-success my-3" type="button" onClick={handleSubmit}>Сохранить</button>
|
||||
</div>
|
||||
</form>
|
||||
<table className="table mt-3 text-white">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Price</th>
|
||||
<th scope="col">Cinema</th>
|
||||
<th scope="col">Timestamp</th>
|
||||
<th scope="col">Capacity</th>
|
||||
<th scope="col">MaxCount</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="tbody">
|
||||
{users.map((user) => (
|
||||
<SessionItem
|
||||
item={user}
|
||||
key={user.id}
|
||||
editFunc={handleEdit}
|
||||
removeFunc={handleDelete}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<ModalEdit visible={modalTable} setVisible={setModalTable}>
|
||||
<form className="g-3 fs-4 description fw-bold container" id="frm-items-edit" onSubmit={(e) => handleSubmitEdit(e, currEditItem)}>
|
||||
<div className="row">
|
||||
<label className="form-label" htmlFor="priceEdit">Цена</label>
|
||||
<input value={priceEdit} onChange={e => setPriceEdit(e.target.value)} className="form-control" name='priceEdit' id="priceEdit" type="number" step="0.01" min="1" placeholder="Введите цену" required />
|
||||
</div>
|
||||
<div className="text-center mt-3">
|
||||
<button className="btn btn-primary mx-1" type="submit" id="buttonSaveChanges">Сохранить изменения</button>
|
||||
<button className="btn btn-secondary mx-1" type="button" data-bs-dismiss="modal" onClick={() => setModalTable(false)}>Отмена</button>
|
||||
</div>
|
||||
</form>
|
||||
</ModalEdit>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<ContentBlock className="d-flex justify-content-center flex-wrap" valueBlock={Content} title='Сеансы' />
|
||||
)
|
||||
}
|
46
front/src/pages/components/Banner.jsx
Normal file
46
front/src/pages/components/Banner.jsx
Normal file
@ -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 (
|
||||
<div className="d-flex align-items-center flex-column" id="banner">
|
||||
<a className={bannerState[0]} onClick={() => navigate("/films/0")} style={{ cursor: "pointer" }}>
|
||||
<img src={banner1} />
|
||||
</a>
|
||||
<a className={bannerState[1]} onClick={() => navigate("/films/0")} style={{ cursor: "pointer" }}>
|
||||
<img src={banner2} />
|
||||
</a>
|
||||
<a className={bannerState[2]} onClick={() => navigate("/films/0")} style={{ cursor: "pointer" }}>
|
||||
<img src={banner3} />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
15
front/src/pages/components/ContentBlock.jsx
Normal file
15
front/src/pages/components/ContentBlock.jsx
Normal file
@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
import '../../styles/styleBlock.css'
|
||||
|
||||
export default function ContentBlock(props) {
|
||||
|
||||
return (
|
||||
<div className="container rounded my-5 p-4 content">
|
||||
<div className="content_header rounded-top p-2 mb-2">
|
||||
<h1 className="fs-1 fw-bold text-white ms-5">{props.title}</h1>
|
||||
</div>
|
||||
{props.valueBlock}
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
27
front/src/pages/components/FilmItem.jsx
Normal file
27
front/src/pages/components/FilmItem.jsx
Normal file
@ -0,0 +1,27 @@
|
||||
import React from "react"
|
||||
import '../../styles/styleFilmItem.css'
|
||||
import MyButton from './MyButton'
|
||||
|
||||
export default function FilmItem(props) {
|
||||
return (
|
||||
<tr>
|
||||
<td>
|
||||
<img className="posterItem me-3" src={props.item.image} alt={props.item.name} align="left" />
|
||||
<div className="d-flex flex-row flex-wrap flex-grow-1 align-items-center">
|
||||
<div className="pt-3 description d-flex flex-column justify-content-start align-items-center mb-3 fs-6 fw-bold">
|
||||
<p className="text-start description">
|
||||
<a className="text-white fs-5 fw-bold pt-3" onClick={() => props.openFilmPageFunc(props.item.id)} style={{ cursor: "pointer" }}>
|
||||
{props.item.name}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div id="rightPanel" className="d-flex flex-wrap justify-content-end text-white fw-bold fs-4 flex-grow-1">
|
||||
<div className="rounded p-1 mx-2 green-mark">9.2</div>
|
||||
<MyButton value={props}/>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="border border-0 bg-black" />
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
}
|
11
front/src/pages/components/Footer.jsx
Normal file
11
front/src/pages/components/Footer.jsx
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react'
|
||||
import vk from '../../images/vk.jpg'
|
||||
import '../../styles/styleFooter.css'
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="d-flex align-items-center fw-bold fs-4 p-2 ps-5">2022 г.
|
||||
<nav className="d-flex justify-content-center flex-grow-1"><a href="https://vk.com/id0" target="_blank"><img className="icon" src={vk} alt="VK" /></a></nav>
|
||||
</footer>
|
||||
)
|
||||
}
|
43
front/src/pages/components/Header.jsx
Normal file
43
front/src/pages/components/Header.jsx
Normal file
@ -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 (
|
||||
<div>
|
||||
<header className="fs-4 fw-bold p-1">
|
||||
<nav className="navbar navbar-expand-md navbar-dark">
|
||||
<div className="container-fluid">
|
||||
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span className="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div className="navbar-collapse collapse justify-content-end" id="navbarNav">
|
||||
<div id="main"> <a onClick={() => navigate("/films")} className="text-decoration-none mx-5" style={{ cursor: "pointer" }}>Главная</a></div>
|
||||
<form onSubmit={handleSubmit} className="col d-flex align-items-center needs-validation">
|
||||
<input value={searchName} onChange={e => setSearchName(e.target.value)} className="form-control mainInput" type="text" name="text" search="true" rounded="true" required placeholder="Введите название" />
|
||||
<button className="border border-0 p-0 ms-2" type="submit"><img className="icon" src={searchImage} alt="Поиск" /></button>
|
||||
</form>
|
||||
<div className="d-flex justify-content-end flex-grow-1 navbar-nav">
|
||||
<a onClick={() => navigate("/registration")} className="text-decoration-none mx-3" style={{ cursor: "pointer" }}>Регистрация</a>
|
||||
<a onClick={() => navigate("/orders")} className="text-decoration-none mx-3" style={{ cursor: "pointer" }}>Заказы</a>
|
||||
<a onClick={() => navigate("/sessions")} className="text-decoration-none mx-3" style={{ cursor: "pointer" }}>Сеансы</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
</div>
|
||||
)
|
||||
}
|
18
front/src/pages/components/ModalEdit.jsx
Normal file
18
front/src/pages/components/ModalEdit.jsx
Normal file
@ -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 (
|
||||
<div className={rootClasses.join(' ')} >
|
||||
<div className={classes.myModalContent}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
26
front/src/pages/components/MyButton.jsx
Normal file
26
front/src/pages/components/MyButton.jsx
Normal file
@ -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 = (
|
||||
<button onClick={() => value.removeFunc(value.item.id)} type="button" className="m-1 btn btn-danger">
|
||||
<FontAwesomeIcon icon={faRemove} />
|
||||
</button>
|
||||
)
|
||||
|
||||
const editButton = (
|
||||
<button onClick={() => value.editFunc(value.item.id)} type="button" className="m-1 btn btn-primary">
|
||||
<FontAwesomeIcon icon={faEdit} />
|
||||
</button>
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{value.editFunc ? editButton : null}
|
||||
{value.removeFunc ? delButton : null}
|
||||
</div>
|
||||
)
|
||||
}
|
27
front/src/pages/components/OrderItem.jsx
Normal file
27
front/src/pages/components/OrderItem.jsx
Normal file
@ -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 (
|
||||
<tr>
|
||||
<td>{props.item.id}</td>
|
||||
<td>{customer.login}</td>
|
||||
<td>{props.item.dateOfPurchase}</td>
|
||||
<td><MyButton value={props} /></td>
|
||||
</tr>
|
||||
)
|
||||
}
|
37
front/src/pages/components/OrderSessionItem.jsx
Normal file
37
front/src/pages/components/OrderSessionItem.jsx
Normal file
@ -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 ?
|
||||
<tr>
|
||||
<td>{item.id}</td>
|
||||
<td>{item.price}</td>
|
||||
<td>{item.cinema.name}</td>
|
||||
<td>{date}</td>
|
||||
<td>{props.item.count}</td>
|
||||
</tr> : null}
|
||||
</>
|
||||
)
|
||||
}
|
18
front/src/pages/components/SessionItem.jsx
Normal file
18
front/src/pages/components/SessionItem.jsx
Normal file
@ -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 (
|
||||
<tr>
|
||||
<td>{props.item.id}</td>
|
||||
<td>{props.item.price}</td>
|
||||
<td>{props.item.cinema.name}</td>
|
||||
<td>{date}</td>
|
||||
<td>{props.item.capacity}</td>
|
||||
<td>{props.item.maxCount}</td>
|
||||
<td><MyButton value={props} /></td>
|
||||
</tr>
|
||||
)
|
||||
}
|
13
front/src/pages/components/UserItem.jsx
Normal file
13
front/src/pages/components/UserItem.jsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from "react"
|
||||
import MyButton from './MyButton'
|
||||
|
||||
export default function UserItem(props) {
|
||||
return (
|
||||
<tr>
|
||||
<td>{props.item.id}</td>
|
||||
<td>{props.item.login}</td>
|
||||
<td>{props.item.password}</td>
|
||||
<td><MyButton value={props} /></td>
|
||||
</tr>
|
||||
)
|
||||
}
|
10
front/src/pages/models/CinemaDto.js
Normal file
10
front/src/pages/models/CinemaDto.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
10
front/src/pages/models/CustomerDto.js
Normal file
10
front/src/pages/models/CustomerDto.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
11
front/src/pages/models/SessionDto.js
Normal file
11
front/src/pages/models/SessionDto.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
42
front/src/pages/services/Service.jsx
Normal file
42
front/src/pages/services/Service.jsx
Normal file
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user