Compare commits

..

6 Commits

10 changed files with 871 additions and 58 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.vscode/

View File

@ -1,56 +1,154 @@
body {
background: white;
color: black;
background: #f0f4f8;
color: #1b1b2f;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
line-height: 1.6;
margin-bottom: 1rem;
padding: 0;
}
p.image {
text-align: center;
/* Navigation Styles */
.navbar {
background: linear-gradient(90deg, #1b1b2f, #4a6fa5)
}
.container {
display: flex;
.navbar .nav-link {
color: #fff;
transition: color 0.3s;
}
.navbar .nav-link:hover {
color: #ffd166;
}
/* Main content styles */
.container-dashboard {
flex-wrap: wrap;
justify-content: center;
background-color: dodgerblue;
}
.container div {
background-color:#f1f1f1;
margin: 10px;
gap: 20px;
padding: 20px;
}
/* Cards/Scores styles */
.container > div {
background-color:#ffffff;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
padding: 25px;
font-size: 30px;
color: black;
flex: 1 1 100%;
text-align: center;
transition: transform 0.3s, box-shadow 0.3s;
}
.container > div:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
@media (min-width: 768px) {
body {
background-color: steelblue;
/* Überschriften und Abstände */
h1, h2, h3, h4, h5, h6 {
margin-top: 1rem;
margin-bottom: 20px;
color: #1b1b2f;
}
p {
margin-top: 0.5rem;
margin-bottom: 1rem;
color: #333;
}
/* Button Styles */
button, .btn {
background-color: #4a6fa5;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
button:hover, .btn:hover {
background-color: #2b4a7c;
}
#page-wrapper {
display: flex;
min-height: 100vh;
font-family: 'Segoe UI', sans-serif;
}
/* Sidebar Styles */
#sidebar {
width: 240px;
min-height: 100vh;
background: linear-gradient(180deg, #1b1b2f, #4a6fa5);
color: white;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
padding: 25px;
}
.container div {
.logo {
font-size: 24px;
margin-bottom: 30px;
}
#sidebar .nav-link {
margin: 0.5rem 0;
transition: color 0.3s background-color 0.3s;
}
#main-area {
flex: 1;
background: #f3f4f6;
display: flex;
flex-direction: column;
}
/* Topbar Styles */
#topbar {
height: 70px;
background: white;
padding: 0px 30px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
#main-content {
background-color: #f0f4f8;
padding: 30px;
}
/* Card Styles */
.card {
background: white;
border-radius: 12px;
box-shadow: 0 5px 15px rgba(0,0,0,0.08);
padding: 25px;
margin-bottom: 20px;
}
.card h2 {
margin-bottom: 10px;
}
/* Responsive Styles */
@media (max-width: 768px) {
.container > div {
flex: 1 1 calc(50% - 40px);
}
#page-wrapper {
flex-direction: column;
}
#sidebar {
width: 100%;
display: flex;
overflow-x: auto;
}
}
@media (min-width: 1200px) {
body {
background-color: darkblue;
color: white;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
font-size: 1.1rem;
}
p {
.container div {
flex: 1 1 calc(25% - 40px);
}
p.columns{
column-count: 2;
column-gap: 2rem;
}
p.dotted {
column-gap: 2rem;
column-rule: 5px dotted black;
outline-style: dotted;
}
.container div {
flex: 1 1 calc(25% - 20px);
#sidebar .nav-link {
flex: 0 0 auto;
margin: 0 15px;
}
}

View File

@ -1,7 +1,7 @@
var exampleLog = () => {
console.log('This is an example log message.');
}
console.log("This is an example log message.");
};
var aFunctionCall = () => {
alert('You have clicked the primary button!');
}
alert("You have clicked the primary button!");
};

View File

@ -0,0 +1,5 @@
const config = {
API_BASE_URL: "https://316214-1.web.fhgr.education/10001/api/"
}
window.config = config;

View File

@ -0,0 +1,29 @@
class LeaderboardService {
constructor(config) {
this.baseUrl = config.API_BASE_URL;
this.urlTail = "leaderboard";
}
async getLeaderboard(offset, limit) {
const response = await fetch(
`${this.baseUrl}${this.urlTail}?offset=${offset}&limit=${limit}`,
{
method: "GET",
},
);
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in getLeaderboard");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
}
window.LeaderboardService = LeaderboardService;

View File

@ -0,0 +1,79 @@
class ScoreService {
constructor(config) {
this.baseUrl = config.API_BASE_URL;
this.urlTail = "score";
}
async getScoreByName(username) {
// Note: When user does not exist, we get a 200 with empty array, not a 404
const response = await fetch(`${this.baseUrl}${this.urlTail}/${username}`, {
method: "GET",
});
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in getScoreByName");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
async postScore(username, password, score, time, text, userWrittenText) {
const response = await fetch(`${this.baseUrl}${this.urlTail}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Username": username,
"X-Password": password,
},
body: JSON.stringify({
score: score,
time: time,
text: text,
userWrittenText: userWrittenText,
}),
});
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in postScore");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
async deleteScore(username, password, scoreId) {
const response = await fetch(`${this.baseUrl}${this.urlTail}/${scoreId}`, {
method: "DELETE",
headers: {
"X-Username": username,
"X-Password": password,
},
});
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in deleteScore");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
}
window.ScoreService = ScoreService;

View File

@ -0,0 +1,77 @@
class UserService {
constructor(config) {
this.baseUrl = config.API_BASE_URL;
this.urlTail = "user";
}
async getUser(username, password) {
const response = await fetch(`${this.baseUrl}${this.urlTail}`, {
method: "GET",
headers: {
"X-Username": username,
"X-Password": password,
},
});
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in getUser");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
async deleteUser(username, password) {
const response = await fetch(`${this.baseUrl}${this.urlTail}`, {
method: "DELETE",
headers: {
"X-Username": username,
"X-Password": password,
},
});
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in deleteUser");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
async postUser(username) {
const response = await fetch(`${this.baseUrl}${this.urlTail}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: username,
}),
});
let body = null;
try {
body = await response.json();
} catch {
console.error("Error in postUser");
}
return {
status: response.status,
ok: response.ok,
body: body,
};
}
}
window.UserService = UserService;

View File

@ -0,0 +1,122 @@
const userService = new UserService(config);
const scoreService = new ScoreService(config);
const leaderboardService = new LeaderboardService(config);
document.addEventListener("DOMContentLoaded", () => {
const usernameForm = document.getElementById("usernameForm");
const loginForm = document.getElementById("loginForm");
const postFormScore = document.getElementById("postScoreForm");
const getScoreForm = document.getElementById("getScoreForm");
const deleteScoreForm = document.getElementById("deleteScoreForm");
const getLeaderboardForm = document.getElementById("getLeaderboardForm");
usernameForm.addEventListener("submit", handleUsernameSubmit);
loginForm.addEventListener("submit", handleLoginSubmit);
postFormScore.addEventListener("submit", handlePostScoreSubmit);
getScoreForm.addEventListener("submit", handleGetScoreSubmit);
deleteScoreForm.addEventListener("submit", handleDeleteScoreSubmit);
getLeaderboardForm.addEventListener("submit", handleGetLeaderboardSubmit);
});
async function handleUsernameSubmit(event) {
event.preventDefault();
const username = document.getElementById("desiredUsername").value;
console.log("Username form submitted:", username);
const result = userService.postUser(username);
console.log("API response:", result);
}
async function handleLoginSubmit(event) {
event.preventDefault();
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
console.log("Login form submitted:", username, password);
const result = await userService.getUser(username, password);
console.log("API response:", result);
}
async function handleDeleteUserSubmit(event) {
event.preventDefault();
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
console.log("Delete User form submitted:", username, password);
const result = await userService.deleteUser(username, password);
console.log("API response:", result);
}
async function handlePostScoreSubmit(event) {
event.preventDefault();
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const score = document.getElementById("score").value;
const time = document.getElementById("time").value;
const text = document.getElementById("text").value;
const userWrittenText = document.getElementById("userWrittenText").value;
console.log(
"Post Score form submitted:",
username,
password,
score,
time,
text,
userWrittenText,
);
const result = await scoreService.postScore(
username,
password,
score,
time,
text,
userWrittenText,
);
console.log("API response:", result);
}
async function handleGetScoreSubmit(event) {
event.preventDefault();
const username = document.getElementById("scoreUsername").value;
console.log("Get Score form submitted:", username);
const result = await scoreService.getScoreByName(username);
console.log("API response:", result);
}
async function handleDeleteScoreSubmit(event) {
event.preventDefault();
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const scoreId = document.getElementById("scoreId").value;
console.log("Delete Score form submitted:", username, password, scoreId);
const result = await scoreService.deleteScore(username, password, scoreId);
console.log("API response:", result);
}
async function handleGetLeaderboardSubmit(event) {
event.preventDefault();
const offset = document.getElementById("offset").value;
const limit = document.getElementById("limit").value;
console.log("Get Leaderboard form submitted:", offset, limit);
const result = await leaderboardService.getLeaderboard(offset, limit);
console.log("API response:", result);
}

310
exampleAPI.html Normal file
View File

@ -0,0 +1,310 @@
<!doctype html>
<html lang="de">
<head>
<title>My Web Page</title>
<meta charset="UTF-8" />
<link
rel="stylesheet"
href="assets/bootstrap-5.3.8-dist/css/bootstrap.min.css"
/>
<link
rel="stylesheet"
href="assets/css/custom.css"
/>
</head>
<body class="bg-light">
<div class="container mt-5">
<div class="row">
<!-- AuthForm-->
<div class="col-md-12">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Login Form</h4>
<form id="loginForm">
<div class="mb-3">
<label
for="username"
class="form-label"
>Username</label
>
<input
type="text"
class="form-control"
id="username"
placeholder="Enter username"
/>
</div>
<div class="mb-3">
<label
for="password"
class="form-label"
>Password</label
>
<input
type="password"
class="form-control"
id="password"
placeholder="Enter password"
/>
</div>
<button
type="submit"
class="btn btn-success"
>
Login
</button>
</form>
</div>
</div>
</div>
</div>
<!-- User Endpoint -->
<div class="container mt-5">
<h2 class="text-center mb-4">User endpoint</h2>
<div class="row">
<!-- Post User -->
<div class="col-md-6">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Username Form</h4>
<form id="usernameForm">
<div class="mb-3">
<label
for="desiredUsername"
class="form-label"
>Username</label
>
<input
type="text"
class="form-control"
id="desiredUsername"
placeholder="Enter username"
/>
</div>
<button
type="submit"
class="btn btn-primary"
>
Submit
</button>
</form>
</div>
</div>
<!-- Delete User -->
<div class="col-md-6">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Delete User</h4>
<button
class="btn btn-danger"
onclick="handleDeleteUserSubmit(event)"
>
Delete User
</button>
</form>
</div>
</div>
</div>
</div>
<!-- Score Endpoint -->
<div class="container mt-5">
<h2 class="text-center mb-4">Score endpoint</h2>
<div class="row">
<!-- Post Score -->
<div class="col-md-4">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Post Score</h4>
<form id="postScoreForm">
<div class="mb-3">
<label
for="score"
class="form-label"
>Score</label
>
<input
type="number"
class="form-control"
id="score"
placeholder="Enter score"
/>
</div>
<div class="mb-3">
<label
for="time"
class="form-label"
>Time</label
>
<input
type="number"
class="form-control"
id="time"
placeholder="Enter time"
/>
</div>
<div class="mb-3">
<label
for="text"
class="form-label"
>Text</label
>
<input
type="text"
class="form-control"
id="text"
placeholder="Enter text"
/>
</div>
<div class="mb-3">
<label
for="userWrittenText"
class="form-label"
>User Written Text</label
>
<input
type="text"
class="form-control"
id="userWrittenText"
placeholder="Enter text"
/>
</div>
<button
type="submit"
class="btn btn-primary"
>
Submit
</button>
</form>
</div>
</div>
<!-- Get Score -->
<div class="col-md-4">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Get Score</h4>
<form id="getScoreForm">
<div class="mb-3">
<label
for="scoreUsername"
class="form-label"
>Score Username</label
>
<input
type="text"
class="form-control"
id="scoreUsername"
placeholder="Enter score username"
/>
</div>
<button
type="submit"
class="btn btn-primary"
>
Get Score
</button>
</form>
</div>
</div>
<!-- Delete Score -->
<div class="col-md-4">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Delete Score</h4>
<form id="deleteScoreForm">
<div class="mb-3">
<label
for="scoreId"
class="form-label"
>ScoreId</label
>
<input
type="number"
class="form-control"
id="scoreId"
placeholder="Enter score ID"
/>
</div>
<button
type="submit"
class="btn btn-danger"
>
Delete Score
</button>
</form>
</div>
</div>
</div>
</div>
<!-- Leaderboard Endpoint -->
<div class="container mt-5">
<h2 class="text-center mb-4">Leaderboard endpoint</h2>
<div class="row">
<!-- Get Leaderboard -->
<div class="col-md-12">
<div class="card p-4 shadow-sm">
<h4 class="mb-3">Get Leaderboard</h4>
<form id="getLeaderboardForm">
<div class="mb-3">
<label
for="offset"
class="form-label"
>Offset</label
>
<input
type="number"
class="form-control"
id="offset"
placeholder="Enter offset"
/>
</div>
<div class="mb-3">
<label
for="limit"
class="form-label"
>Limit</label
>
<input
type="number"
class="form-control"
id="limit"
placeholder="Enter Limit for Leaderboard"
/>
</div>
<button
type="submit"
class="btn btn-primary"
>
Get Leaderboard
</button>
</form>
</div>
</div>
</div>
</div>
<script src="assets/bootstrap-5.3.8-dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/src/service/user-service.js"></script>
<script src="assets/src/service/score-service.js"></script>
<script src="assets/src/service/leaderboard-service.js"></script>
<script src="assets/src/service/config-service.js"></script>
<script src="assets/src/sites/exampleAPI.js"></script>
</body>
</html>

View File

@ -1,37 +1,129 @@
<!DOCTYPE html>
<html lang="de">
<head>
<title>My Web Page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lorem Ipsum - Das Spiel</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="assets/bootstrap-5.3.8-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/custom.css">
</head>
<body class="p-4">
<h1 class="text-primary">Hello From Main Page</h1>
<p class="dotted" >Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p class="image"><img src="https://cdn.pixabay.com/photo/2020/04/05/13/22/lorem-5006124_1280.jpg" alt="Lorem ipsum Blumen" width="200px"></p>
<div class="container">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Lorem Ipsum - Das Spiel</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="index.html" id="nav-home">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" id="nav-play">Spiel Starten</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" id="nav-my-scores">Meine Scores</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" id="nav-leaderboard">Leaderboard</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" id="nav-login">Login / Registrieren</a>
</li>
</ul>
</div>
<a href="index.html">Go to Main Page</a>
<a href="secondSite.html">Go to Second Page</a>
<br />
</div>
</nav>
<div id="page-wrapper">
<!-- Sidebar -->
<nav id="sidebar" class="bg-dark text-white p-3">
<h3 class="text-center">Navigation</h3>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link text-white" href="#" id="nav-home">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#" id="nav-play">Spiel Starten</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#" id="nav-my-scores">Meine Scores</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#" id="nav-leaderboard">Leaderboard</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="#" id="nav-login">Login / Registrieren</a>
</li>
</ul>
</nav>
<button class="btn btn-primary">Primary Button</button>
<button class="btn btn-secondary" onclick="exampleLog()">Secondary Button</button>
<button class="btn btn-success">Success Button</button>
<button class="btn btn-danger">Danger Button</button>
<button class="btn btn-warning">Warning Button</button>
<button class="btn btn-info">Info Button</button>
<button class="btn btn-light">Light Button</button>
<button class="btn btn-dark">Dark Button</button>
<button class="btn btn-link">Link Button</button>
<!--Main Area -->
<div id="main-area">
<!--Topbar-->
<header id="topbar">
<h1 class="text-center mb-4">Dashboard</h1>
<div class="user-info">
<span>Guest</span>
</div>
</header>
<!-- Content -->
<main class="container mt-4" id="main-content">
<div class="card">
<h2>Willkommen beim Lorem Ipsum Game</h2>
<p>Teste deine Fähigkeiten im Umgang mit Lorem Ipsum Texten! Je schneller und genauer du bist, desto höher ist dein Score. Viel Spaß beim Spielen!</p>
<p> Wähle eine Option aus der Navigation, um zu starten.</p>
</div>
</main>
</div>
</div>
<!-- Bootstrap JS Bundle -->
<script src="assets/bootstrap-5.3.8-dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/src/example.js"></script>
<!-- Script zum Navigieren zwischen Seiten -->
<script>
const mainContent = document.getElementById('main-content');
document.getElementById('nav-home').addEventListener('click', () => {
mainContent.innerHTML = `
<h1>Willkommen beim Lorem Ipsum Game</h1>
<p>Teste deine Fähigkeiten im Umgang mit Lorem Ipsum Texten! Je schneller und genauer du bist, desto höher ist dein Score. Viel Spaß beim Spielen!</p>
<h2> Wähle eine Option aus der Navigation, um zu starten.</h2>
`;
});
document.getElementById('nav-play').addEventListener('click', () => {
mainContent.innerHTML = `
<h2 class="mb-3">Spiel Starten</h2>
<p class="mt-2">Hier kannst du das Spiel starten. Viel Erfolg!</p>
<!-- Hier könnte der eigentliche Spielinhalt eingebunden werden -->
`;
});
document.getElementById('nav-my-scores').addEventListener('click', () => {
mainContent.innerHTML = `
<h2 class="mb-3">Meine Scores</h2>
<p class="mt-2">Hier kannst du deine bisherigen Scores einsehen.</p>
<!-- Hier könnte eine Score-Tabelle oder ähnliches eingebunden werden -->
`;
});
document.getElementById('nav-leaderboard').addEventListener('click', () => {
mainContent.innerHTML = `
<h2 class="mb-3">Leaderboard</h2>
<p class="mt-2">Hier kannst du die besten Spieler und ihre Scores sehen.</p>
<!-- Hier könnte eine Leaderboard-Tabelle eingebunden werden -->
`;
});
document.getElementById('nav-login').addEventListener('click', () => {
mainContent.innerHTML = `
<h2 class="mb-3">Login / Registrieren</h2>
<p class="mt-2">Hier kannst du dich einloggen oder registrieren, um deine Scores zu speichern.</p>
<!-- Hier könnte ein Login-Formular eingebunden werden -->
`;
});
</script>
</body>
</html>