Merge branch 'lab4' of http://student.git.athene.tech/maxKarme/PIbd-22_Karamushko_M_K_IP_Labs into lab5
This commit is contained in:
commit
e4c17f1642
15946
frontend/package-lock.json
generated
15946
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,19 +8,15 @@ import Contacts from './components/pages/Contacts';
|
||||
import Catalogs from './components/pages/Catalogs';
|
||||
import CatalogFilms from './components/catalogs/CatalogFilms';
|
||||
import CatalogGenres from './components/catalogs/CatalogGenres';
|
||||
import Reports from './components/pages/Reports';
|
||||
import ReportsFilms from './components/reports/ReportsFilms';
|
||||
import CatalogActors from './components/catalogs/CatalogActors';
|
||||
|
||||
const links = [
|
||||
{id: 1, text: "Главная", path: ""},
|
||||
{id: 2, text: "Фильмы", path: "films"},
|
||||
{id: 3, text: "Контакты", path: "contacts"},
|
||||
{id: 4, text: "Каталог", path: "catalogs"},
|
||||
{id: 5, text: "Отчеты", path: "reports"},
|
||||
];
|
||||
|
||||
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
@ -34,8 +30,7 @@ function App() {
|
||||
<Route path="catalogs" element={<Catalogs/>}/>
|
||||
<Route path="catalogs/catalogFilms" element={<CatalogFilms />}/>
|
||||
<Route path="catalogs/catalogGenres" element={<CatalogGenres />}/>
|
||||
<Route path="reports" element={<Reports />}/>
|
||||
<Route path="reports/reportsFilms" element={<ReportsFilms />}/>
|
||||
<Route path="catalogs/catalogActors" element={<CatalogActors />}/>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</>
|
||||
|
51
frontend/src/components/catalogs/CatalogActors.jsx
Normal file
51
frontend/src/components/catalogs/CatalogActors.jsx
Normal file
@ -0,0 +1,51 @@
|
||||
import Catalog from "../common/Catalog";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import DataService from "../../services/DataService";
|
||||
|
||||
let headers = [
|
||||
{label: "name", text: "Имя"},
|
||||
{label: "surname", text: "Фамилия"}
|
||||
]
|
||||
|
||||
export default function CatalogActors() {
|
||||
const url = "/actors";
|
||||
|
||||
const [data, setData] = useState({
|
||||
name: "",
|
||||
surname: ""
|
||||
});
|
||||
|
||||
const [actors, setActors] = useState([]);
|
||||
|
||||
function handleFormChange(e) {
|
||||
setData({ ...data, [e.target.id]: e.target.value })
|
||||
}
|
||||
|
||||
function onAdd() {
|
||||
setData({name: "", genre: actors[0]});
|
||||
}
|
||||
|
||||
|
||||
function onChange(data) {
|
||||
setData(data);
|
||||
}
|
||||
|
||||
function validate(data) {
|
||||
if(data.name === "") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
<Catalog url={url} headers={headers} data={data} onAdd={onAdd} onChange={onChange} validate={validate}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="name" className="form-label">Имя</label>
|
||||
<input type="text" value={data.name} id="name" className="form-control" required autoComplete="off"
|
||||
onChange={handleFormChange}/>
|
||||
<label htmlFor="surname" className="form-label">Фамилия</label>
|
||||
<input type="text" value={data.surname} id="surname" className="form-control" required autoComplete="off"
|
||||
onChange={handleFormChange}/>
|
||||
</div>
|
||||
</Catalog>
|
||||
)
|
||||
}
|
@ -5,7 +5,8 @@ import DataService from "../../services/DataService"
|
||||
|
||||
let headers = [
|
||||
{label: "name", text: "Имя"},
|
||||
{label: "genre", text: "Жанр"}
|
||||
{label: "genre", text: "Жанр"},
|
||||
{label: "fullNames", text: "Актеры"}
|
||||
]
|
||||
|
||||
|
||||
@ -14,15 +15,28 @@ export default function CatalogFilms() {
|
||||
|
||||
const [data, setData] = useState({
|
||||
name: "",
|
||||
genre: ""
|
||||
genre: [],
|
||||
fullNames: []
|
||||
});
|
||||
|
||||
const [selectedData, setSelectedData] = useState({
|
||||
genre: "",
|
||||
actor: ""
|
||||
});
|
||||
|
||||
const [genres, setGenres] = useState([]);
|
||||
const [actors, setActors] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
let genre;
|
||||
DataService.readAll("/genres").then(res => {
|
||||
setGenres(res)
|
||||
setData({...data, genre: res[0].genre})
|
||||
genre = res[0].name;
|
||||
}).then(() => (
|
||||
DataService.readAll("/actors")
|
||||
)).then(res => {
|
||||
setActors(res)
|
||||
setSelectedData({genre, actor: res[0].name + " " + res[0].surname});
|
||||
});
|
||||
}, [])
|
||||
|
||||
@ -32,8 +46,42 @@ export default function CatalogFilms() {
|
||||
setData({ ...data, [e.target.id]: e.target.value })
|
||||
}
|
||||
|
||||
function handleChangeSelected(e) {
|
||||
setSelectedData({...selectedData, [e.target.id]: e.target.value});
|
||||
}
|
||||
|
||||
function addGenre() {
|
||||
for(let g of data.genre) {
|
||||
if(g == selectedData.genre) return;
|
||||
}
|
||||
let temp = data.genre.slice(0);
|
||||
temp.push(selectedData.genre);
|
||||
setData({...data, genre: temp});
|
||||
}
|
||||
|
||||
function addActor() {
|
||||
for(let a of data.fullNames) {
|
||||
if(a == selectedData.actor) return;
|
||||
}
|
||||
let temp = data.fullNames.slice(0);
|
||||
temp.push(selectedData.actor);
|
||||
setData({...data, fullNames: temp});
|
||||
}
|
||||
|
||||
function deleteGenre(e) {
|
||||
let genreName = e.target.previousSibling.textContent;
|
||||
let temp = data.genre.filter(x => (x != genreName));
|
||||
setData({...data, genre: temp})
|
||||
}
|
||||
|
||||
function deleteActor(e) {
|
||||
let actorName = e.target.previousSibling.textContent;
|
||||
let temp = data.fullNames.filter(x => (x != actorName));
|
||||
setData({...data, fullNames: temp})
|
||||
}
|
||||
|
||||
function onAdd() {
|
||||
setData({name: "", genre: genres[0].genre});
|
||||
setData({name: "", genre: [], fullNames: []});
|
||||
}
|
||||
|
||||
|
||||
@ -55,14 +103,44 @@ export default function CatalogFilms() {
|
||||
onChange={handleFormChange}/>
|
||||
</div>
|
||||
<select id="genre" className="form-select" required
|
||||
value={data.genre} onChange={handleFormChange}>
|
||||
value={selectedData.genre} onChange={handleChangeSelected}>
|
||||
<option disabled value="">Укажите жанр</option>
|
||||
{
|
||||
genres.map(({genre, id}) =>
|
||||
<option key={id} value={genre}>{genre}</option>
|
||||
genres.map(({name, id}) =>
|
||||
<option key={id} value={name}>{name}</option>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
{
|
||||
data.genre.map(value => (
|
||||
<div className="badge bg-secondary m-1" key={value}>
|
||||
<span>{value}</span>
|
||||
<button className="btn-close bg-danger m-1" onClick={deleteGenre}></button>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
<br></br>
|
||||
<button onClick={addGenre} className="btn btn-success">Добавить жанр</button>
|
||||
|
||||
<select id="actor" className="form-select" required
|
||||
value={selectedData.actor} onChange={handleChangeSelected}>
|
||||
<option disabled value="">Укажите актера</option>
|
||||
{
|
||||
actors.map(({name, surname, id}) =>
|
||||
<option key={id} value={name + " " + surname}>{name + " " + surname}</option>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
{
|
||||
data.fullNames.map(value => (
|
||||
<div className="badge bg-secondary m-1" key={value}>
|
||||
<span>{value}</span>
|
||||
<button className="btn-close bg-danger m-1" onClick={deleteActor}></button>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
<br></br>
|
||||
<button onClick={addActor} className="btn btn-success">Добавить актера</button>
|
||||
</div>
|
||||
</Catalog>
|
||||
)
|
||||
|
@ -4,14 +4,14 @@ import { useEffect, useState } from "react";
|
||||
import DataService from "../../services/DataService"
|
||||
|
||||
let headers = [
|
||||
{label: "genre", text: "Жанр"}
|
||||
{label: "name", text: "Жанр"}
|
||||
]
|
||||
|
||||
export default function CatalogGenres() {
|
||||
const url = "/genres";
|
||||
|
||||
const [data, setData] = useState({
|
||||
genre: ""
|
||||
name: ""
|
||||
});
|
||||
|
||||
const [genres, setGenres] = useState([]);
|
||||
@ -30,15 +30,15 @@ export default function CatalogGenres() {
|
||||
}
|
||||
|
||||
function validate(data) {
|
||||
if(data.genre === "") return false;
|
||||
if(data.name === "") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
<Catalog url={url} headers={headers} data={data} onAdd={onAdd} onChange={onChange} validate={validate}>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="genre" className="form-label">Название</label>
|
||||
<input type="text" value={data.genre} id="genre" className="form-control" required autoComplete="off"
|
||||
<label htmlFor="name" className="form-label">Название</label>
|
||||
<input type="text" value={data.name} id="name" className="form-control" required autoComplete="off"
|
||||
onChange={handleFormChange}/>
|
||||
</div>
|
||||
</Catalog>
|
||||
|
@ -37,7 +37,7 @@ export default function Catalog(props) {
|
||||
}
|
||||
|
||||
function addHandler() {
|
||||
setModalHeader("Добавление фильма");
|
||||
setModalHeader("Добавление");
|
||||
setModalConfirm("Добавить");
|
||||
setEdit(false);
|
||||
setVisible(true);
|
||||
@ -60,7 +60,7 @@ export default function Catalog(props) {
|
||||
|
||||
selectedItems = new Set();
|
||||
|
||||
setModalHeader("Изменение фильма");
|
||||
setModalHeader("Изменение");
|
||||
setModalConfirm("Изменить");
|
||||
setEdit(true);
|
||||
setVisible(true);
|
||||
@ -68,11 +68,13 @@ export default function Catalog(props) {
|
||||
|
||||
function removeHandler() {
|
||||
let queries = [];
|
||||
for(let id of selectedItems.keys()) {
|
||||
for(let id of selectedItems.values()) {
|
||||
queries.push(DataService.remove(props.url, id));
|
||||
}
|
||||
|
||||
Promise.all(queries).then(() => loadItems());
|
||||
Promise.all(queries).then(() => {
|
||||
loadItems()
|
||||
});
|
||||
}
|
||||
|
||||
function confirmHandler() {
|
||||
|
@ -27,11 +27,12 @@ export default function Table(props) {
|
||||
let trClass = "";
|
||||
if(props.selectable && props.selected.has(elem.id)) trClass = "selected";
|
||||
return (
|
||||
<tr key={elem.id} onClick={click.bind(this, elem.id)} className={trClass}>
|
||||
<tr key={elem.id} onClick={click.bind(this, elem.id)} className={trClass}>
|
||||
<td>{index + 1}</td>
|
||||
{props.headers.map(({label}) => (
|
||||
<td key={label}>{elem[label]}</td>
|
||||
))}
|
||||
{props.headers.map(({label}) => {
|
||||
return <td key={label}>{(Array.isArray(elem[label])) ? elem[label].join(", ") : elem[label]}</td>
|
||||
}
|
||||
)}
|
||||
</tr>
|
||||
)})}
|
||||
</tbody>
|
||||
|
@ -2,7 +2,8 @@ import LinksList from "../common/LinksList";
|
||||
|
||||
export default function Catalogs() {
|
||||
let items = [
|
||||
{text: "фильмы", link: "catalogFilms"},
|
||||
{text: "фильмы", link: "catalogFilms"},,
|
||||
{text: "актеры", link: "catalogActors"},
|
||||
{text: "жанры", link: "catalogGenres"}
|
||||
];
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
export default class DataSirvice {
|
||||
static urlPrefix = "http://localhost:8079";
|
||||
static urlPrefix = "http://localhost:8080";
|
||||
|
||||
static async readAll(url) {
|
||||
let data = await fetch(this.urlPrefix + url);
|
||||
return data.json();
|
||||
let res = await data.json();
|
||||
return res;
|
||||
}
|
||||
|
||||
static create(url, data) {
|
||||
@ -22,7 +23,7 @@ export default class DataSirvice {
|
||||
console.log(data);
|
||||
data.id = id;
|
||||
return fetch(this.urlPrefix + url + "/" + id, {
|
||||
method: "PUT",
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
@ -32,7 +33,7 @@ export default class DataSirvice {
|
||||
}
|
||||
|
||||
static remove(url, id) {
|
||||
fetch(this.urlPrefix + url + "/" + id, {
|
||||
return fetch(this.urlPrefix + url + "/" + id, {
|
||||
method: "DELETE"
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user