Redesign home page

This commit is contained in:
2024-09-27 15:52:22 +02:00
parent e3863058a0
commit 2977c73a10
31 changed files with 587 additions and 161 deletions

View File

@@ -6,17 +6,17 @@ import navigationAppendItems from './components/navigation/navigationAppendItems
import navigationPrependItems from './components/navigation/navigationPrependItems.vue';
import { usePreferencesStore } from './data/stores/preferencesStore';
import { useFeedbackStore } from './data/stores/feedbackStore';
import { useTourStore } from './data/stores/tourStore';
import { useShowStore } from './data/stores/showStore';
const preferencesStore = usePreferencesStore()
const tourStore = useTourStore()
const showStore = useShowStore()
const feedbackStore = useFeedbackStore()
const theme = useTheme()
theme.global.name.value = preferencesStore.theme
tourStore.fetchAllTours()
showStore.fetchAllTours()
// Global watcher
watch(() => preferencesStore.language, () => {
@@ -30,6 +30,7 @@ watch(() => preferencesStore.language, () => {
height="80"
color="primary"
class="px-5"
elevation="0"
>
<template #prepend>
<navigation-prepend-items />
@@ -63,9 +64,17 @@ watch(() => preferencesStore.language, () => {
</v-snackbar>
<!-- Here changes the router the content -->
<v-container max-width="1200">
<router-view></router-view>
<v-container max-width="1200" class="pt-0 pb-5">
<v-sheet>
<router-view></router-view>
</v-sheet>
</v-container>
</v-main>
</v-app>
</template>
<style scoped>
.v-sheet {
background-color: #333333;
}
</style>

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
defineProps({
image: String,
title: String
})
</script>
<template>
<v-card>
<v-img
:src="'http://localhost:3000/static/' + image"
aspect-ratio="1"
style="background-color: aliceblue;"
cover
/>
<v-card-title v-if="title">
{{ title }}
</v-card-title>
<div class="px-4 pb-4" v-if="$slots.default">
<slot></slot>
</div>
<v-card-actions v-if="$slots.actions" class="card-actions position-absolute bottom-0 right-0">
<v-spacer />
<slot name="actions"></slot>
</v-card-actions>
</v-card>
</template>

View File

@@ -1,78 +0,0 @@
<script setup lang="ts">
import { useBasketStore } from '@/data/stores/basketStore';
import { useAccountStore } from '@/data/stores/accountStore';
const accountStore = useAccountStore()
const basketStore = useBasketStore()
const navRail = defineModel("navRail", { type: Boolean })
</script>
<template>
<v-list>
<!-- Shopping Section -->
<v-list-subheader>
<div v-if="!navRail">{{ $t('menu.shopping.shopping') }}</div>
<div v-else></div>
</v-list-subheader>
<v-list-item :title="$t('menu.shopping.ticket', 2)" prepend-icon="mdi-ticket" to="/" link />
<v-list-item :title="$t('menu.shopping.basket')" to="/basket" link >
<template v-slot:prepend>
<v-badge color="primary" :content="basketStore.itemsInBasket.length">
<v-icon icon="mdi-cart" />
</v-badge>
</template>
</v-list-item>
<v-divider />
<!-- Account Section -->
<v-list-subheader>
<div v-if="!navRail">{{ $t('menu.account.accountManagement') }}</div>
<div v-else></div>
</v-list-subheader>
<v-expand-transition>
<div v-if="accountStore.userAccount.id == null">
<v-list-item v-if="accountStore.userAccount.id == null" :title="$t('menu.account.login')" prepend-icon="mdi-login" to="/login" link />
</div>
</v-expand-transition>
<v-expand-transition>
<div v-if="accountStore.userAccount.id != null">
<v-list-item :title="$t('menu.account.account')" prepend-icon="mdi-account" to="/account" link />
<v-list-item :title="$t('menu.account.order', 2)" prepend-icon="mdi-cart-check" to="/orders" link />
<v-list-item :title="$t('menu.account.logout')" prepend-icon="mdi-logout" @click="accountStore.logout" link />
</div>
</v-expand-transition>
<v-divider />
<!-- System and help section -->
<v-list-subheader>
<div v-if="!navRail">{{ $t('menu.systemAndHelp.systemAndHelp') }}</div>
<div v-else></div>
</v-list-subheader>
<v-list-item :title="$t('menu.systemAndHelp.helpInstructions')" prepend-icon="mdi-chat-question" to="/help" link />
<v-list-item :title="$t('menu.systemAndHelp.scoreBoard')" prepend-icon="mdi-podium-gold" to="/scoreBoard" link />
<v-list-item :title="$t('menu.systemAndHelp.preferences')" prepend-icon="mdi-cog" to="/preferences" link />
<div v-if="accountStore.userAccount.accountRole.privilegeAdminPanel">
<v-divider />
<v-list-subheader>
<div v-if="!navRail">{{ $t('menu.admin.admin') }}</div>
<div v-else></div>
</v-list-subheader>
<v-list-item :title="$t('menu.admin.dashboard')" prepend-icon="mdi-view-dashboard" to="/admin/dashboard" link />
</div>
</v-list>
</template>

View File

@@ -0,0 +1,21 @@
<script setup lang="ts">
defineProps({
title: String
})
</script>
<template>
<v-row class="pt-3">
<v-col class="d-flex justify-center align-center">
<v-sheet height="12" width="100%" color="primary" :rounded="true" />
</v-col>
<v-col class="v-col-auto">
<span class="text-h6">{{ title }}</span>
</v-col>
<v-col class="d-flex justify-center align-center">
<v-sheet height="12" width="100%" color="primary" :rounded="true" />
</v-col>
</v-row>
</template>

View File

@@ -3,13 +3,13 @@ import { MemberModel } from "./memberModel"
import { RatingModel } from "./ratingModel"
export class BandModel {
id: Number
id: number
name: string
foundingYear: Number
descriptionEn: String
descriptionDe: String
images: Array<String>
logo: String
foundingYear: number
descriptionEn: string
descriptionDe: string
images: Array<string>
logo: string
genre: GenreModel
ratings: Array<RatingModel>
members: Array<MemberModel>

View File

@@ -1,9 +1,9 @@
import { CityModel } from "./cityModel"
export class LocationModel {
id: Number
name: String
address: String
id: number
name: string
address: string
city: CityModel
image: String
image: string
}

View File

@@ -2,7 +2,7 @@ import { AccountModel } from "./accountModel"
import { BandModel } from "./bandModel"
export class RatingModel {
id: Number
rating: Number
id: number
rating: number
band: BandModel
}

View File

@@ -0,0 +1,36 @@
import { useLocalStorage } from "@vueuse/core";
import { defineStore } from "pinia";
import { TourModel } from "../models/tourModel";
import { getAllTours } from "../api/tourApi";
import { GenreModel } from "../models/genreModel";
import { getAllBands } from "../api/bandApi";
import { BandModel } from "../models/bandModel";
import { LocationModel } from "../models/locationModel";
import { getAllLocations } from "../api/locationApi";
export const useShowStore = defineStore("showStore", {
state: () => ({
tours: useLocalStorage<Array<TourModel>>("hackmycart/showStore/tours", []),
bands: useLocalStorage<Array<BandModel>>("hackmycart/showStore/bands", []),
locations: useLocalStorage<Array<LocationModel>>("hackmycart/showStore/locations", [])
}),
actions: {
async fetchAllTours() {
await getAllTours()
.then(result => {
this.tours = result.data
})
await getAllBands()
.then(result => {
this.bands = result.data
})
await getAllLocations()
.then(result => {
this.locations = result.data
})
}
}
})

View File

@@ -1,21 +0,0 @@
import { useLocalStorage } from "@vueuse/core";
import { defineStore } from "pinia";
import { TourModel } from "../models/tourModel";
import { getAllTours } from "../api/tourApi";
import { GenreModel } from "../models/genreModel";
export const useTourStore = defineStore("tourStore", {
state: () => ({
tours: useLocalStorage<Array<TourModel>>("hackmycart/tourStore/tours", []),
genres: useLocalStorage<Array<GenreModel>>("hackmycart/tourStore/genres", [])
}),
actions: {
async fetchAllTours() {
await getAllTours()
.then(result => {
this.tours = result.data
})
}
}
})

View File

@@ -3,27 +3,19 @@
"shopping": {
"allEvents": "Alle Events",
"allLocations": "Alle Orte",
"allGenres": "Alle Genres",
"basket": "Warenkorb"
},
"account": {
"accountManagement": "Kontoverwaltung",
"account": "Account",
"login": "Login",
"order": "Bestellung | Bestellungen",
"logout": "Ausloggen"
},
"systemAndHelp": {
"systemAndHelp": "System & Hilfe",
"helpInstructions": "Hilfestellung",
"preferences": "Einstellungen",
"scoreBoard": "Score Board"
},
"admin": {
"admin": "Administration",
"dashboard": "Dashboard"
"allGenres": "Alle Genres"
}
},
"shows": {
"tickets": "Ticket | Tickets"
},
"tours": {
"concert": "Konzert | Konzerte"
},

View File

@@ -3,27 +3,19 @@
"shopping": {
"allEvents": "All Events",
"allLocations": "All Locations",
"allGenres": "All Genres",
"basket": "Basket"
},
"account": {
"account": "Account Management",
"login": "Login",
"order": "Order | Orders",
"logout": "Logout",
"accountManagement": "Account Management"
},
"systemAndHelp": {
"systemAndHelp": "System & Help",
"helpInstructions": "Help Instructions",
"preferences": "Preferences",
"scoreBoard": "Score Board"
},
"admin": {
"admin": "Administration",
"dashboard": "Dashboard"
"allGenres": "All Genres"
}
},
"shows": {
"tickets": "Ticket | Tickets"
},
"tours": {
"concert": "Concert | Concerts"
},

View File

@@ -0,0 +1,66 @@
<script setup lang="ts">
import OutlinedButton from '@/components/outlinedButton.vue';
import { useShowStore } from '@/data/stores/showStore';
const tourStore = useShowStore()
</script>
<template>
<v-carousel
hide-delimiters
hide-delimiter-background
height="700"
show-arrows
>
<template #prev="{ props }">
<v-btn
variant="text"
@click="props.onClick"
icon="mdi-chevron-left"
/>
</template>
<template #next="{ props }">
<v-btn
variant="text"
@click="props.onClick"
icon="mdi-chevron-right"
/>
</template>
<v-carousel-item
v-for="tour in tourStore.tours"
:src="'http://localhost:3000/static/bands/' + tour.band.images[0]"
cover
>
<v-card
class="position-absolute bottom-0"
:title="tour.band.name"
width="100%"
:rounded="false"
background-opacity="50%"
>
<v-card-text>
<div>
{{ tour.band.descriptionDe }}
</div>
<outlined-button append-icon="mdi-arrow-right" class="mt-2">
{{ $t('shows.tickets', 2) }}
</outlined-button>
</v-card-text>
</v-card>
</v-carousel-item>
</v-carousel>
</template>
<style scoped>
.v-card {
background: rgba(255, 255, 255, .7);
color: black;
}
.v-card-text {
font-weight: bold;
}
</style>

View File

@@ -1,6 +1,90 @@
<script setup lang="ts">
import { useShowStore } from '@/data/stores/showStore';
import highlightCarousel from './highlightCarousel.vue';
import sectionDivider from '@/components/sectionDivider.vue';
import cardWithTopImage from '@/components/cardWithTopImage.vue';
import { RatingModel } from '@/data/models/ratingModel';
const showStore = useShowStore()
function calcRating(ratings: Array<RatingModel>) {
let sum = 0
for (let rating of ratings) {
sum += rating.rating
}
return sum / ratings.length
}
</script>
<template>
Home
</template>
<highlight-carousel />
<v-container>
<v-row>
<v-col>
<section-divider title="Top Tours" />
</v-col>
</v-row>
<v-row>
<v-col v-for="i in 4" cols="3">
<card-with-top-image
:image="'bands/' + showStore.tours[i].band.images[0]"
:title="showStore.tours[i].name"
>
{{ showStore.bands[i].name }}
</card-with-top-image>
</v-col>
</v-row>
<v-row>
<v-col>
<section-divider title="Top Bands" />
</v-col>
</v-row>
<v-row>
<v-col v-for="i in 4" cols="3">
<card-with-top-image
:image="'bands/' + showStore.bands[i - 1].logo"
:title="showStore.bands[i - 1].name"
>
{{ showStore.bands[i - 1].genre.name }}
<div class="d-flex justify-center pt-3">
<v-rating
density="compact"
readonly
size="large"
half-increments
active-color="orange"
:model-value="calcRating(showStore.bands[i - 1].ratings)"
/>
</div>
</card-with-top-image>
</v-col>
</v-row>
<v-row>
<v-col>
<section-divider title="Top Locations" />
</v-col>
</v-row>
<v-row>
<v-col v-for="location in showStore.locations" cols="3">
<card-with-top-image
:image="'locations/' + location.image"
:title="location.name"
>
{{ location.address }}
{{ location.city.name }}, {{ location.city.country }}
</card-with-top-image>
</v-col>
</v-row>
</v-container>
</template>