diff --git a/data.mv.db b/data.mv.db index a23c3a5..c494343 100644 Binary files a/data.mv.db and b/data.mv.db differ diff --git a/front/index.html b/front/index.html new file mode 100644 index 0000000..dc60526 --- /dev/null +++ b/front/index.html @@ -0,0 +1,15 @@ + + + + + + + + + ReManga + + +
+ + + diff --git a/front/src/App.jsx b/front/src/App.jsx new file mode 100644 index 0000000..a95a1f5 --- /dev/null +++ b/front/src/App.jsx @@ -0,0 +1,37 @@ +import { useRoutes, Outlet, BrowserRouter } from 'react-router-dom'; +import Creator from './components/Creator'; +import Reader from './components/Reader'; +import Header from './components/Header'; +import Manga from './components/Manga'; + +function Router(props) { + return useRoutes(props.rootRoute); +} + +export default function App() { + const routes = [ + { index: true, element: }, + { path: 'creator', element: , label: 'Creator' }, + { path: 'reader', element: , label: 'Reader' }, + { path: 'manga', element: , label: 'Manga' }, + ]; + const links = routes.filter(route => route.hasOwnProperty('label')); + const rootRoute = [ + { path: '/', element: render(links), children: routes } + ]; + + function render(links) { + return ( + <> +
+ + + ); + } + + return ( + + + + ); +} \ No newline at end of file diff --git a/front/src/components/Adding.jsx b/front/src/components/Adding.jsx new file mode 100644 index 0000000..36bfa1a --- /dev/null +++ b/front/src/components/Adding.jsx @@ -0,0 +1,58 @@ +import { useEffect, useState } from "react"; + +export default function Adding() { + + const [outcome, setOutcome] = useState(0); + + const [first, setFirst] = useState(0); + + const [second, setSecond] = useState(0); + + const sum = (e) =>{ + e.preventDefault() + fetch('http://localhost:8080/sum?first=' + first + '&second=' + second) + .then(response=>response.text()) + .then(result=>setOutcome(result)) + } + + const ras = (e) =>{ + e.preventDefault() + fetch('http://localhost:8080/ras?first=' + first + '&second=' + second) + .then(response=>response.text()) + .then(result=>setOutcome(result)) + } + const del = (e) =>{ + e.preventDefault() + fetch('http://localhost:8080/del?first=' + first + '&second=' + second) + .then(response=>response.text()) + .then(result=>setOutcome(result)) + } + const pros = (e) =>{ + e.preventDefault() + fetch('http://localhost:8080/pros?first=' + first + '&second=' + second) + .then(response=>response.text()) + .then(result=>setOutcome(result)) + } + + return ( +
+
+
+
+ + setFirst(event.target.value)} className="form-control"/> +
+
+ + setSecond(event.target.value)} className="form-control"/> +
+ + + + + {outcome} +
+
+
+ ); +} diff --git a/front/src/components/Creator.jsx b/front/src/components/Creator.jsx new file mode 100644 index 0000000..ea60f69 --- /dev/null +++ b/front/src/components/Creator.jsx @@ -0,0 +1,175 @@ +import { useEffect, useState } from "react"; +import TableCreator from './TableCreator'; + +export default function Creator() { + + const host = "http://localhost:8080"; + + const [creatorId, setCreatorId] = useState(0); + + const [creatorName, setCreatorName] = useState(""); + + const [password, setPassword] = useState(""); + + + const [data, setData] = useState([]); + + + const table = document.getElementById("tbody"); + + useEffect(() => { + getData() + .then(_data =>setData(_data)) ; + console.log(2); + },[]); + + + const getData = async function () { + const response = await fetch(host + "/creator"); + const _data = await response.json() + console.log(data); + return _data; + + //table.innerHTML = ""; + // data.forEach(Creator => { + // let temp = "" + // table.innerHTML += + // ` + // ${Creator.id} + // ${Creator.creatorName} + // ${Creator.hashedPassword} + // ${temp} + // `; + // }) + } + + const create = async function (){ + const requestParams = { + method: "POST", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/creator?creatorName=${creatorName}&password=${password}`, requestParams); + getData(); + } + + const remove = async function (){ + console.info('Try to remove item'); + if (creatorId !== 0) { + if (!confirm('Do you really want to remove this item?')) { + console.info('Canceled'); + return; + } + } + const requestParams = { + method: "DELETE", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/creator/` + creatorId, requestParams); + console.log("REMOVE"); + getData(); + return await response.json(); + } + + const removeAll = async function (){ + console.info('Try to remove item'); + if (!confirm('Do you really want to remove this item?')) { + console.info('Canceled'); + return; + } + const requestParams = { + method: "DELETE", + }; + await fetch(host + `/creator/`, requestParams); + } + + const update = async function (){ + console.info('Try to update item'); + if (creatorId === 0 || creatorName == null || password === 0) { + return; + } + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/creator/${creatorId}?creatorName=${creatorName}&password=${password}`, requestParams); + getData(); + return await response.json(); + } + const createButton = (e) =>{ + e.preventDefault() + create(); + } + + const removeButton = (e) =>{ + e.preventDefault() + remove(); + } + + const updateButton = (e) =>{ + e.preventDefault() + update(); + } + + return ( +
+
+
+

Creator

+
+
+
+ + setCreatorId(event.target.value)} className="form-control"/> +
+
+ + setCreatorName(event.target.value)} className="form-control"/> +
+
+ + setPassword(event.target.value)} className="form-control"/> +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + {/* + */} +
#CreatorNamePasswordMangs
+
+
+
+
+ ); +} diff --git a/front/src/components/Header.jsx b/front/src/components/Header.jsx new file mode 100644 index 0000000..16c3443 --- /dev/null +++ b/front/src/components/Header.jsx @@ -0,0 +1,27 @@ +import { NavLink } from 'react-router-dom'; + +export default function Header(props) { + return ( + + ); +} \ No newline at end of file diff --git a/front/src/components/Manga.jsx b/front/src/components/Manga.jsx new file mode 100644 index 0000000..cb5ab84 --- /dev/null +++ b/front/src/components/Manga.jsx @@ -0,0 +1,171 @@ +import { useEffect, useState } from "react"; +import TableManga from './TableManga'; + +export default function Manga() { + + const host = "http://localhost:8080"; + + const [creatorId, setCreatorId] = useState(0); + + const [mangaId, setMangaId] = useState(0); + + const [mangaName, setMangaName] = useState(""); + + const [chapterCount, setChapterCount] = useState(0); + + + const [data, setData] = useState([]); + + + const table = document.getElementById("tbody"); + + useEffect(() => { + getData(); + },[]); + + + const getData = async function () { + const response = await fetch(host + "/manga"); + setData(await response.json()) + console.log(data); + //table.innerHTML = ""; + // data.forEach(Manga => { + // let temp = "" + // table.innerHTML += + // ` + // ${Manga.id} + // ${Manga.mangaName} + // ${Manga.hashedPassword} + // ${temp} + // `; + // }) + } + + const create = async function (){ + const requestParams = { + method: "POST", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/manga?creatorId=${creatorId}&chapterCount=${chapterCount}&mangaName=${mangaName}`, requestParams); + return await response.json(); + } + + const remove = async function (){ + console.info('Try to remove item'); + if (mangaId !== 0) { + if (!confirm('Do you really want to remove this item?')) { + console.info('Canceled'); + return; + } + } + const requestParams = { + method: "DELETE", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/manga/` + mangaIdInput.value, requestParams); + console.log("REMOVE"); + getData(); + } + + const update = async function (){ + console.info('Try to update item'); + if (mangaId === 0 || mangaName == null || password === 0) { + return; + } + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/manga/${mangaIdInput.value}?chapterCount=${chapterCountInput.value}`, requestParams); + return await response.json(); + } + const createButton = (e) =>{ + e.preventDefault() + create().then((result) => { + getData(); + alert(`Manga[id=${result.id}, mangaName=${result.mangaName}, chapterCount=${result.chapterCount}]`); + }); + } + + const removeButton = (e) =>{ + e.preventDefault() + remove(); + getData(); + } + + const updateButton = (e) =>{ + e.preventDefault() + update(); + getData(); + } + + + + return ( +
+
+
+

Manga

+
+
+
+ + setCreatorId(event.target.value)} className="form-control"/> +
+
+ + setMangaId(event.target.value)} className="form-control"/> +
+
+ + setMangaName(event.target.value)} className="form-control"/> +
+
+ + setChapterCount(event.target.value)} className="form-control"/> +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + {/* + */} +
#mangaNamechapterCountmangaIdreaders
+
+
+
+
+ ); +} diff --git a/front/src/components/Reader.jsx b/front/src/components/Reader.jsx new file mode 100644 index 0000000..4ce69d8 --- /dev/null +++ b/front/src/components/Reader.jsx @@ -0,0 +1,226 @@ +import { useEffect, useState } from "react"; +import TableReader from './TableReader'; + +export default function Reader() { + + const host = "http://localhost:8080"; + + const [readerId, setReaderId] = useState(0); + + const [mangaId, setMangaId] = useState(0); + + const [readerName, setReaderName] = useState(""); + + const [password, setPassword] = useState(""); + + + const [data, setData] = useState([]); + + + const table = document.getElementById("tbody"); + + useEffect(() => { + getData(); + console.log(2); + },[]); + + + const getData = async function () { + const response = await fetch(host + "/reader"); + setData(await response.json()) + console.log(data); + //table.innerHTML = ""; + // data.forEach(Reader => { + // let temp = "" + // table.innerHTML += + // ` + // ${Reader.id} + // ${Reader.readerName} + // ${Reader.hashedPassword} + // ${temp} + // `; + // }) + } + + const create = async function (){ + const requestParams = { + method: "POST", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/reader?readerName=${readerName}&password=${password}`, requestParams); + getData(); + } + + const remove = async function (){ + console.info('Try to remove item'); + if (readerId !== 0) { + if (!confirm('Do you really want to remove this item?')) { + console.info('Canceled'); + return; + } + } + const requestParams = { + method: "DELETE", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/reader/` + readerId, requestParams); + getData(); + return await response.json(); + } + + const removeAll = async function (){ + console.info('Try to remove item'); + if (!confirm('Do you really want to remove this item?')) { + console.info('Canceled'); + return; + } + const requestParams = { + method: "DELETE", + }; + await fetch(host + `/reader/`, requestParams); + getData(); + } + + const update = async function (){ + console.info('Try to update item'); + if (readerId === 0 || readerName == null || password === 0) { + return; + } + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json", + } + }; + const response = await fetch(host + `/reader/${readerId}?readerName=${readerName}&password=${password}`, requestParams); + getData(); + return await response.json(); + } + + const removeManga = async function (){ + console.info('Try to remove item'); + if (!confirm('Do you really want to remove this item?')) { + console.info('Canceled'); + return; + } + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json", + } + }; + console.log(host + `/reader/${readerId}/removeManga?mangaId=${mangaId}`, requestParams); + const response = await fetch(host + `/reader/${readerId}/removeManga?mangaId=${mangaId}`, requestParams); + return await response.json(); + } + + const addManga = async function () { + const requestParams = { + method: "PUT", + headers: { + "Content-Type": "application/json", + } + }; + console.log(host + `/reader/${readerId}/addManga?mangaId=${mangaId}`, requestParams); + const response = await fetch(host + `/reader/${readerId}/addManga?mangaId=${mangaId}`, requestParams); + return await response.json(); + } + const createButton = (e) =>{ + e.preventDefault() + create(); + } + + const removeButton = (e) =>{ + e.preventDefault() + remove(); + + } + + const updateButton = (e) =>{ + e.preventDefault() + update(); + } + + const removeMangaButton = (e) =>{ + e.preventDefault() + removeManga(); + } + + const addMangaButton = (e) =>{ + e.preventDefault() + addManga(); + } + + + + return ( +
+
+
+

Reader

+
+
+
+ + setReaderId(event.target.value)} className="form-control"/> +
+
+ + setMangaId(event.target.value)} className="form-control"/> +
+
+ + setReaderName(event.target.value)} className="form-control"/> +
+
+ + setPassword(event.target.value)} className="form-control"/> +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + {/* + */} +
#readerNamePasswordMangs
+
+
+
+
+ ); +} diff --git a/front/src/components/TableCreator.jsx b/front/src/components/TableCreator.jsx new file mode 100644 index 0000000..1b42a13 --- /dev/null +++ b/front/src/components/TableCreator.jsx @@ -0,0 +1,26 @@ +import { useState } from 'react'; + + +export default function TableCreator(props) { + + return ( + + { + props.items.map((item, index) => + + {item.id} + {item.creatorName} + {item.hashedPassword} + + + + + + + ) + } + + ); +} \ No newline at end of file diff --git a/front/src/components/TableManga.jsx b/front/src/components/TableManga.jsx new file mode 100644 index 0000000..d2ea6bd --- /dev/null +++ b/front/src/components/TableManga.jsx @@ -0,0 +1,25 @@ +import { useState } from 'react'; + + +export default function TableCreator(props) { + + return ( + + { + props.items.map((item, index) => + + {item.id} + {item.mangaName} + {item.chapterCount} + {item.creatorId} + + + + + ) + } + + ); +} \ No newline at end of file diff --git a/front/src/components/TableReader.jsx b/front/src/components/TableReader.jsx new file mode 100644 index 0000000..d4e1668 --- /dev/null +++ b/front/src/components/TableReader.jsx @@ -0,0 +1,24 @@ +import { useState } from 'react'; + + +export default function TableReader(props) { + + return ( + + { + props.items.map((item, index) => + + {item.id} + {item.readerName} + {item.hashedPassword} + + + + + ) + } + + ); +} \ No newline at end of file diff --git a/front/src/main.jsx b/front/src/main.jsx new file mode 100644 index 0000000..edd296f --- /dev/null +++ b/front/src/main.jsx @@ -0,0 +1,8 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' +import './style.css' + +ReactDOM.createRoot(document.getElementById('app')).render( + +) diff --git a/front/src/style.css b/front/src/style.css new file mode 100644 index 0000000..4f47273 --- /dev/null +++ b/front/src/style.css @@ -0,0 +1,102 @@ +/* html, +body { + background-color: #000000; + color: #ffffff; + padding: 0; + margin: 0; + font-family: sans-serif; + line-height: 1.15; + height: 100%; +} +header { + background-color: #3c3c3c; + color: #ffffff; +} +header a { + color: #ffffff; + text-decoration: none; + margin: 0 0.5em; +} +header a:hover { + text-decoration: underline; +} +#logo { + margin-left: 0.5em; +} +article a { + color: #ffffff; + text-decoration: none; + margin: 0.5em 0.5em; +} +header a:hover { + text-decoration: underline; +} +h1 { + font-size: 1.5em; +} +h2 { + font-size: 1.25em; +} +h3 { + font-size: 1.1em; +} +footer { + background-color: #9c9c9c; + color: #ffffff; + height: 32px; + padding: 0.5em; +} +.manga_pages{ + display: flex; + flex-direction: column; + align-items: center; +} +.catalog_wrapper{ + display: flex; + width: 73%; + flex-direction: column; +} +.catalog_article{ + display: flex; +} +.poster{ + width:140px; +} +th { + border: 0px solid rgb(255, 255, 255); +} +.added_manga{ + display: flex; + flex-direction: column; +} +@media (min-width: 992px) { + .manga_pages img{ + max-width: 900px; + width: auto; + height: auto; + } + } + .flex_grow { + flex-grow: 1; + display: flex; + align-items: center; +} + @media (min-width: 1024px){ +.article_1 { + max-width: -webkit-calc(1600px + (100vw/64*7)*2); + max-width: -moz-calc(1600px + (100vw/64*7)*2); + max-width: calc(1600px + (100vw/64*7)*2); + padding-left: -webkit-calc(100vw/64*7); + padding-left: -moz-calc(100vw/64*7); + padding-left: calc(100vw/64*7); + padding-right: -webkit-calc(100vw/64*7); + padding-right: -moz-calc(100vw/64*7); + padding-right: calc(100vw/64*7); +} +} + + +.registration_div { + width: 100%; + height: 100%; +} */ \ No newline at end of file