Finished entire frontend
This commit is contained in:
@@ -2,6 +2,8 @@ import express from 'express';
|
||||
import cors from 'cors';
|
||||
import pathRoutes from './routes/parkRoutes.js';
|
||||
import coasterRoutes from './routes/coasterRoutes.js';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
@@ -15,6 +17,22 @@ app.use(cors());
|
||||
app.use('/api/parks', pathRoutes);
|
||||
app.use('/api/coasters', coasterRoutes);
|
||||
|
||||
app.get('/api/filesize', (req, res) => {
|
||||
const dbPath = path.join('./database.db');
|
||||
|
||||
fs.stat(dbPath, (err, stats) => {
|
||||
if (err) {
|
||||
console.error('Fehler beim Abrufen der Dateigröße:', err);
|
||||
return res.status(500).json({ error: 'Dateigröße konnte nicht ermittelt werden' });
|
||||
}
|
||||
|
||||
res.json({
|
||||
sizeBytes: stats.size,
|
||||
sizeMB: (stats.size / (1024 * 1024)).toFixed(2)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Start des Servers
|
||||
app.listen(port, () => {
|
||||
console.log(`Server läuft auf http://localhost:${port}`);
|
||||
|
||||
@@ -45,26 +45,8 @@ export default {
|
||||
<li class="mb-4">
|
||||
<a href="https://github.com/MiauRizius/CoasterDB" target="_blank" class="hover:underline ">GitHub</a>
|
||||
</li>
|
||||
<!--
|
||||
<li>
|
||||
<a href="https://discord.gg/7fVXR2g7DG" target="_blank" class="hover:underline">Discord</a>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</div>
|
||||
<!--
|
||||
<div>
|
||||
<h2 class="mb-6 text-sm font-semibold text-gray-900 uppercase dark:text-white">Rechtliches</h2>
|
||||
<ul class="text-gray-600 dark:text-gray-400">
|
||||
<li class="mb-4">
|
||||
<a href="#" class="hover:underline">Hier könnte was stehe, tut's aber nicht</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="hover:underline">Gleiches gilt hier</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-6 border-gray-200 sm:mx-auto dark:border-gray-700 lg:my-8" />
|
||||
|
||||
@@ -238,79 +238,8 @@ export default {
|
||||
>Technische Infos</a
|
||||
>
|
||||
</li>
|
||||
<!--
|
||||
<li>
|
||||
<a
|
||||
href="/database/admin"
|
||||
class="flex items-center p-2 pl-11 w-full text-base font-medium text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
|
||||
>Admin-Panel</a
|
||||
>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
</li>
|
||||
<!-- <li>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center p-2 w-full text-base font-medium text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
|
||||
aria-controls="dropdown-authentication"
|
||||
data-collapse-toggle="dropdown-authentication"
|
||||
id="dropdown-authentication-button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 group-hover:text-gray-900 dark:text-gray-400 dark:group-hover:text-white"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
<span class="flex-1 ml-3 text-left whitespace-nowrap"
|
||||
>Authentication</span
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<ul id="dropdown-authentication" class="hidden py-2 space-y-2">
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center p-2 pl-11 w-full text-base font-medium text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
|
||||
>Sign In</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center p-2 pl-11 w-full text-base font-medium text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
|
||||
>Sign Up</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
class="flex items-center p-2 pl-11 w-full text-base font-medium text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
|
||||
>Forgot Password</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</li>-->
|
||||
</ul>
|
||||
<ul
|
||||
class="pt-5 mt-5 space-y-2 border-t border-gray-200 dark:border-gray-700"
|
||||
@@ -362,52 +291,5 @@ export default {
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- <div
|
||||
class="hidden absolute bottom-0 left-0 justify-center p-4 space-x-4 w-full lg:flex bg-white dark:bg-gray-800 z-20"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
class="inline-flex justify-center p-2 text-gray-500 rounded cursor-pointer dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-600"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 4a1 1 0 00-2 0v7.268a2 2 0 000 3.464V16a1 1 0 102 0v-1.268a2 2 0 000-3.464V4zM11 4a1 1 0 10-2 0v1.268a2 2 0 000 3.464V16a1 1 0 102 0V8.732a2 2 0 000-3.464V4zM16 3a1 1 0 011 1v7.268a2 2 0 010 3.464V16a1 1 0 11-2 0v-1.268a2 2 0 010-3.464V4a1 1 0 011-1z"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
data-tooltip-target="tooltip-settings"
|
||||
class="inline-flex justify-center p-2 text-gray-500 rounded cursor-pointer dark:text-gray-400 dark:hover:text-white hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-600"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
|
||||
clip-rule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<div
|
||||
id="tooltip-settings"
|
||||
role="tooltip"
|
||||
class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip"
|
||||
>
|
||||
Settings page
|
||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||
</div>
|
||||
</div>-->
|
||||
</aside>
|
||||
</template>
|
||||
@@ -1,35 +0,0 @@
|
||||
<script lang="ts">
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="p-6 bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700">
|
||||
<div class="flex justify-between items-center mb-5 text-gray-500">
|
||||
<span class="bg-primary-100 text-primary-800 text-xs font-medium inline-flex items-center px-2.5 py-0.5 rounded dark:bg-primary-200 dark:text-primary-800">
|
||||
<svg class="mr-1 w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M2 6a2 2 0 012-2h6a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6zM14.553 7.106A1 1 0 0014 8v4a1 1 0 00.553.894l2 1A1 1 0 0018 13V7a1 1 0 00-1.447-.894l-2 1z"></path></svg>
|
||||
Tutorial
|
||||
</span>
|
||||
<span class="text-sm">14 days ago</span>
|
||||
</div>
|
||||
<h2 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white"><a href="#">How to quickly deploy a static website</a></h2>
|
||||
<p class="mb-5 font-light text-gray-500 dark:text-gray-400">Static websites are now used to bootstrap lots of websites and are becoming the basis for a variety of tools that even influence both web designers and developers influence both web designers and developers.</p>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex items-center space-x-4">
|
||||
<img class="w-7 h-7 rounded-full" src="https://flowbite.s3.amazonaws.com/blocks/marketing-ui/avatars/jese-leos.png" alt="Jese Leos avatar" />
|
||||
<span class="font-medium dark:text-white">
|
||||
Jese Leos
|
||||
</span>
|
||||
</div>
|
||||
<a href="#" class="inline-flex items-center font-medium text-primary-600 dark:text-primary-500 hover:underline">
|
||||
Read more
|
||||
<svg class="ml-2 w-4 h-4" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
@@ -1,26 +0,0 @@
|
||||
<script lang="ts">
|
||||
|
||||
export default {
|
||||
props: {
|
||||
name: String,
|
||||
park: String,
|
||||
length: String,
|
||||
height: String,
|
||||
speed: String
|
||||
},
|
||||
components: {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tr class="border-b dark:border-gray-700">
|
||||
<th scope="row" class="px-4 py-3 font-medium text-gray-900 whitespace-nowrap dark:text-white">{{ name }}</th>
|
||||
<td class="px-4 py-3">{{ park }}</td>
|
||||
<td class="px-4 py-3">{{ length }}</td>
|
||||
<td class="px-4 py-3">{{ height }}</td>
|
||||
<td class="px-4 py-3">{{ speed }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
|
||||
import Navbar from '../components/Navbar.vue'
|
||||
import Footer from '../components/Footer.vue'
|
||||
|
||||
@@ -7,6 +6,30 @@ export default {
|
||||
components: {
|
||||
Navbar,
|
||||
Footer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
parkCount: 0,
|
||||
coasterCount: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
totalEntries(): number {
|
||||
return this.parkCount + this.coasterCount;
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
const parkRes = await fetch('http://localhost:3000/api/parks');
|
||||
const parks = await parkRes.json();
|
||||
this.parkCount = parks.length;
|
||||
|
||||
const coasterRes = await fetch('http://localhost:3000/api/coasters');
|
||||
const coasters = await coasterRes.json();
|
||||
this.coasterCount = coasters.length;
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden der Statistiken:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -23,7 +46,9 @@ export default {
|
||||
<p class="mb-4 font-medium">In dieser Web-Anwendung findest du viele Fakten, technische Daten und anderes Material zu verschiedene Achterbahnen und Parks in Deutschland.</p>
|
||||
<a href="/app" class="inline-flex items-center font-medium text-primary-600 hover:text-primary-800 dark:text-primary-500 dark:hover:text-primary-700">
|
||||
Öffne die Web-App
|
||||
<svg class="ml-1 w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
|
||||
<svg class="ml-1 w-6 h-6" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,15 +57,15 @@ export default {
|
||||
<div class="max-w-screen-xl px-4 py-8 mx-auto text-center lg:py-16 lg:px-6">
|
||||
<dl class="grid max-w-screen-md gap-8 mx-auto text-gray-900 sm:grid-cols-3 dark:text-white">
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<dt class="mb-2 text-3xl md:text-4xl font-extrabold">27</dt>
|
||||
<dt class="mb-2 text-3xl md:text-4xl font-extrabold">{{ parkCount }}</dt>
|
||||
<dd class="font-light text-gray-500 dark:text-gray-400">Parks</dd>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<dt class="mb-2 text-3xl md:text-4xl font-extrabold">400</dt>
|
||||
<dt class="mb-2 text-3xl md:text-4xl font-extrabold">{{ coasterCount }}</dt>
|
||||
<dd class="font-light text-gray-500 dark:text-gray-400">Achterbahnen</dd>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center">
|
||||
<dt class="mb-2 text-3xl md:text-4xl font-extrabold">785</dt>
|
||||
<dt class="mb-2 text-3xl md:text-4xl font-extrabold">{{ totalEntries }}</dt>
|
||||
<dd class="font-light text-gray-500 dark:text-gray-400">Datenbankeinträge</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
@@ -12,30 +12,42 @@ export default {
|
||||
stats: {
|
||||
totalParks: 0,
|
||||
totalCoasters: 0,
|
||||
totalVisitorsPerMonth: 500000, // bleibt statisch, da nicht aus API
|
||||
averageTicketPrice: 45.99, // bleibt statisch, da nicht aus API
|
||||
totalInversions: 0
|
||||
totalVisitorsPerMonth: 0,
|
||||
averageTicketPrice: 0,
|
||||
totalInversions: 0,
|
||||
databaseSize: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
try {
|
||||
// Parks abrufen
|
||||
const parksRes = await fetch('http://localhost:3000/api/parks');
|
||||
const parks = await parksRes.json();
|
||||
this.stats.totalParks = parks.length;
|
||||
|
||||
// Coaster abrufen
|
||||
const totalVisitors = parks.reduce((sum: number, park: any) => sum + Number(park.average_visitor_count), 0);
|
||||
this.stats.totalVisitorsPerMonth = Math.round(totalVisitors / parks.length);
|
||||
|
||||
const totalPrice = parks.reduce((sum: number, park: any) => {
|
||||
const price = parseFloat(park.ticket_price.replace('€', '').replace(',', '.'));
|
||||
return sum + price;
|
||||
}, 0);
|
||||
this.stats.averageTicketPrice = parseFloat((totalPrice / parks.length).toFixed(2));
|
||||
|
||||
const coastersRes = await fetch('http://localhost:3000/api/coasters');
|
||||
const coasters = await coastersRes.json();
|
||||
this.stats.totalCoasters = coasters.length;
|
||||
|
||||
// Summe der Inversionen berechnen
|
||||
this.stats.totalInversions = coasters.reduce((sum: number, coaster: any) => sum + coaster.inversions, 0);
|
||||
|
||||
const sizeRes = await fetch('http://localhost:3000/api/filesize');
|
||||
const size = await sizeRes.json();
|
||||
this.stats.databaseSize = size.sizeMB;
|
||||
|
||||
} catch (err) {
|
||||
console.error('Fehler beim Laden der Statistiken:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -76,6 +88,10 @@ export default {
|
||||
<p class="text-gray-600 dark:text-gray-300">Anzahl der Inversionen:</p>
|
||||
<p class="text-lg font-semibold text-gray-900 dark:text-white">{{ stats.totalInversions }}</p>
|
||||
</div>
|
||||
<div class="bg-gray-100 dark:bg-gray-700 p-4 rounded-lg shadow-sm">
|
||||
<p class="text-gray-600 dark:text-gray-300">Größe der Datenbank:</p>
|
||||
<p class="text-lg font-semibold text-gray-900 dark:text-white">{{ stats.databaseSize }} MB</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
<script lang="ts">
|
||||
|
||||
/**
|
||||
*
|
||||
* use this for template:
|
||||
* https://flowbite.com/blocks/
|
||||
* https://flowbite.com/blocks/marketing/blog/
|
||||
* https://flowbite.com/blocks/application/advanced-tables/
|
||||
*
|
||||
*/
|
||||
|
||||
import Header from '../../components/app/AppHeader.vue'
|
||||
import Sidebar from '../../components/app/AppSidebar.vue'
|
||||
import ListItem from '../../components/app/ListItem.vue'
|
||||
import Entry from '../../components/app/Entry.vue'
|
||||
import Documentation from "../../views/app/Documentation.vue"
|
||||
import Help from "../../views/app/Help.vue"
|
||||
|
||||
@@ -20,8 +9,6 @@ export default {
|
||||
components: {
|
||||
Header,
|
||||
Sidebar,
|
||||
ListItem,
|
||||
Entry,
|
||||
Documentation,
|
||||
Help
|
||||
},
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
<script lang="ts">
|
||||
|
||||
/**
|
||||
*
|
||||
* use this for template:
|
||||
* https://flowbite.com/blocks/
|
||||
* https://flowbite.com/blocks/marketing/blog/
|
||||
* https://flowbite.com/blocks/application/advanced-tables/
|
||||
*
|
||||
*/
|
||||
|
||||
import Header from '../../components/app/AppHeader.vue'
|
||||
import Sidebar from '../../components/app/AppSidebar.vue'
|
||||
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
<script lang="ts">
|
||||
|
||||
/**
|
||||
*
|
||||
* use this for template:
|
||||
* https://flowbite.com/blocks/
|
||||
* https://flowbite.com/blocks/marketing/blog/
|
||||
* https://flowbite.com/blocks/application/advanced-tables/
|
||||
*
|
||||
*/
|
||||
|
||||
import Header from '../../components/app/AppHeader.vue'
|
||||
import Sidebar from '../../components/app/AppSidebar.vue'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user