Added dynamic loading for every page

This commit is contained in:
2025-05-07 15:53:18 +02:00
parent 5b6a46d81b
commit 60a054a4bb
6 changed files with 143 additions and 50 deletions

View File

@@ -11,6 +11,15 @@ export const getCoasters = (): Promise<any[]> => {
}); });
}; };
export const getCoastersByPark = (id: number): Promise<any[]> => {
return new Promise((resolve, reject) => {
db.all("SELECT * FROM coasters WHERE park_id = ?", [id], (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
};
export const getCoasterById = (id: number): Promise<any> => { export const getCoasterById = (id: number): Promise<any> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.get("SELECT * FROM coasters WHERE id = ?", [id], (err, row) => { db.get("SELECT * FROM coasters WHERE id = ?", [id], (err, row) => {

View File

@@ -1,5 +1,5 @@
import { Router } from 'express'; import { Router } from 'express';
import { getCoasters, getCoasterById } from '../models/coaster.js'; import { getCoasters, getCoasterById, getCoastersByPark } from '../models/coaster.js';
const router = Router(); const router = Router();
@@ -14,6 +14,18 @@ router.get('/', async (req, res) => {
} }
}); });
// Alle Achterbahnen eines Parks anzeigen
router.get('/p/:id', async (req, res) => {
const { id } = req.params;
try {
const coasters = await getCoastersByPark(Number(id));
res.json(coasters);
} catch (err) {
console.error('Fehler beim Abrufen der Achterbahnen:', err);
res.status(500).json({ message: 'Fehler beim Abrufen der Achterbahnen' });
}
});
// Achterbahn nach ID anzeigen // Achterbahn nach ID anzeigen
router.get('/:id', async (req, res) => { router.get('/:id', async (req, res) => {
const { id } = req.params; const { id } = req.params;

View File

@@ -36,7 +36,7 @@ const routes: Array<RouteRecordRaw> = [
component: () => import('./views/app/coasters/Coasters.vue') component: () => import('./views/app/coasters/Coasters.vue')
}, },
{ {
path: '/app/coaster/:coasterId', path: '/app/coaster/:id',
component: () => import('./views/app/coasters/Coaster.vue') component: () => import('./views/app/coasters/Coaster.vue')
}, },
@@ -46,7 +46,7 @@ const routes: Array<RouteRecordRaw> = [
component: () => import('./views/app/parks/Parks.vue') component: () => import('./views/app/parks/Parks.vue')
}, },
{ {
path: '/app/park/:parkId', path: '/app/park/:id',
component: () => import('./views/app/parks/Park.vue') component: () => import('./views/app/parks/Park.vue')
}, },

View File

@@ -3,29 +3,64 @@ import Header from '../../../components/app/AppHeader.vue'
import Sidebar from '../../../components/app/AppSidebar.vue' import Sidebar from '../../../components/app/AppSidebar.vue'
export default { export default {
components: { components: {
Header, Header,
Sidebar Sidebar
}, },
data() { data() {
return { return {
coaster: { coaster: {
name: "Blue Fire", name: '',
park: "Europa Park", park: '',
length: "1050 m", length: '',
height: "38 m", height: '',
speed: "100 km/h", speed: '',
launch: "LSM-Launch", launch: '',
inversions: 4, inversions: 0,
duration: "2:30 min", duration: '',
manufacturer: "MACK Rides", manufacturer: '',
opened: "2009" opened: '',
} video_key: '',
}; park_id: 0
}
};
},
async mounted() {
const coasterId = this.$route.params.id;
try {
// Coaster-Daten laden
const coasterRes = await fetch(`http://localhost:3000/api/coasters/${coasterId}`);
if (!coasterRes.ok) throw new Error('Fehler beim Laden des Coasters');
const coasterData = await coasterRes.json();
// Parkname holen
const parkRes = await fetch(`http://localhost:3000/api/parks/${coasterData.park_id}`);
if (!parkRes.ok) throw new Error('Fehler beim Laden des Parks');
const parkData = await parkRes.json();
this.coaster = {
name: coasterData.name,
park: parkData.name,
length: `${coasterData.length} m`,
height: `${coasterData.height} m`,
speed: `${coasterData.velocity} km/h`,
launch: coasterData.type,
inversions: coasterData.inversions,
duration: `${coasterData.duration} min`,
manufacturer: coasterData.manufacturer,
opened: `${coasterData.release_year}`,
video_key: coasterData.video_key,
park_id: coasterData.park_id
};
} catch (err) {
console.error(err);
} }
}
}; };
</script> </script>
<template> <template>
<title>{{ coaster.name }} - CoasterDB</title> <title>{{ coaster.name }} - CoasterDB</title>
@@ -47,7 +82,7 @@ export default {
<p class="text-sm text-gray-500 dark:text-gray-400 mb-6"> <p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
Park: Park:
<span class="font-medium text-gray-900 dark:text-white"> <span class="font-medium text-gray-900 dark:text-white">
<a :href="`/app/park/${coaster.park.replace(' ', '_')}`">{{ coaster.park }}</a> <a :href="`/app/park/${coaster.park_id}`">{{ coaster.park }}</a>
</span> </span>
</p> </p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
@@ -75,7 +110,7 @@ export default {
<iframe <iframe
width="560" width="560"
height="315" height="315"
src="https://www.youtube.com/embed/P7m8SNRj_hI" :src="`https://www.youtube.com/embed/${ coaster.video_key }`"
title="Blue Fire On-Ride Video" title="Blue Fire On-Ride Video"
frameborder="0" frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"

View File

@@ -9,20 +9,51 @@ export default {
}, },
data() { data() {
return { return {
park: { park: {} as {
name: 'Europa Park', name: string;
location: 'Rust, Deutschland', location: string;
averageVisitorsPerMonth: 450000, averageVisitorsPerMonth: number;
averageTicketPrice: 57.5, averageTicketPrice: number;
area: '95 Hektar', area: string;
openingYear: 1975 openingYear: number;
}, },
coasters: [ coasters: [] as { name: string, id: number }[]
{ name: 'Silver Star' }, }
{ name: 'Blue Fire Megacoaster' }, },
{ name: 'Wodan Timburcoaster' }, async mounted() {
{ name: 'Eurosat - CanCan Coaster' } const parkId = this.$route.params.id; // Park ID aus der URL
]
try {
// Abrufen der Parkdaten
const parkResponse = await fetch(`http://localhost:3000/api/parks/${parkId}`);
if (parkResponse.ok) {
const parkData = await parkResponse.json();
this.park = {
name: parkData.name,
location: parkData.location,
averageVisitorsPerMonth: parkData.average_visitor_count,
averageTicketPrice: parkData.ticket_price,
area: parkData.area,
openingYear: parkData.opening_year
};
} else {
console.error('Fehler beim Laden des Parks:', parkResponse.statusText);
}
// Abrufen der Achterbahndaten
const coastersResponse = await fetch(`http://localhost:3000/api/coasters/p/${parkId}`);
if (coastersResponse.ok) {
const coastersData = await coastersResponse.json();
this.coasters = coastersData.map((coaster: { name: string, id: number }) => ({
name: coaster.name,
id: coaster.id
}));
} else {
console.error('Fehler beim Laden der Achterbahnen:', coastersResponse.statusText);
}
} catch (error) {
console.error('Fehler beim Abrufen der Daten:', error);
} }
} }
} }
@@ -49,11 +80,11 @@ export default {
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 text-gray-700 dark:text-gray-300 mt-4"> <div class="grid grid-cols-1 sm:grid-cols-2 gap-4 text-gray-700 dark:text-gray-300 mt-4">
<div> <div>
<span class="font-semibold">Ø Besucher / Monat:</span> <span class="font-semibold">Ø Besucher / Monat:</span>
{{ park.averageVisitorsPerMonth.toLocaleString() }} {{ park.averageVisitorsPerMonth }}
</div> </div>
<div> <div>
<span class="font-semibold">Ø Ticketpreis:</span> <span class="font-semibold">Ø Ticketpreis:</span>
{{ park.averageTicketPrice.toFixed(2) }} {{ park.averageTicketPrice }}
</div> </div>
<div> <div>
<span class="font-semibold">Fläche:</span> <span class="font-semibold">Fläche:</span>
@@ -74,7 +105,7 @@ export default {
v-for="coaster in coasters" v-for="coaster in coasters"
:key="coaster.name" :key="coaster.name"
class="bg-white dark:bg-gray-800 shadow p-4 rounded-lg hover:shadow-lg transition-shadow" class="bg-white dark:bg-gray-800 shadow p-4 rounded-lg hover:shadow-lg transition-shadow"
:href="`/app/coaster/${coaster.name.replace(' ', '_')}`" :href="`/app/coaster/${coaster.id}`"
> >
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">{{ coaster.name }}</h3> <h3 class="text-lg font-semibold text-gray-900 dark:text-white">{{ coaster.name }}</h3>
</a> </a>
@@ -85,6 +116,5 @@ export default {
</div> </div>
</template> </template>
<style scoped> <style scoped>
</style> </style>

View File

@@ -9,12 +9,20 @@ export default {
}, },
data() { data() {
return { return {
parks: [ parks: [] as { id: number; name: string; location: string; average_visitor_count: number; ticket_price: string }[]
{ name: 'Europa Park', location: 'Rust, Deutschland' }, }
{ name: 'Phantasialand', location: 'Brühl, Deutschland' }, },
{ name: 'Erlebnispark Tripsdrill', location: 'Cleebronn, Deutschland' }, async mounted() {
{ name: 'Heide Park', location: 'Soltau, Deutschland' } try {
] const response = await fetch('http://localhost:3000/api/parks');
if (response.ok) {
const data = await response.json();
this.parks = data;
} else {
console.error('Fehler beim Laden der Parks:', response.statusText);
}
} catch (error) {
console.error('Fehler beim Abrufen der Parks:', error);
} }
} }
} }
@@ -35,8 +43,8 @@ export default {
<a <a
v-for="park in parks" v-for="park in parks"
:key="park.name" :key="park.name"
:href="`/app/park/${park.id}`"
class="bg-white dark:bg-gray-800 shadow-md sm:rounded-lg p-6 hover:shadow-lg transition-shadow" class="bg-white dark:bg-gray-800 shadow-md sm:rounded-lg p-6 hover:shadow-lg transition-shadow"
:href="`/app/park/${park.name.replace(' ', '_')}`"
> >
<h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2">{{ park.name }}</h2> <h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2">{{ park.name }}</h2>
<p class="text-gray-700 dark:text-gray-300"> <p class="text-gray-700 dark:text-gray-300">
@@ -47,8 +55,7 @@ export default {
</div> </div>
</main> </main>
</div> </div>
</template> </template>
<style scoped> <style scoped>
</style> </style>