Redesign home page
This commit is contained in:
@@ -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>
|
||||
30
software/src/components/cardWithTopImage.vue
Normal file
30
software/src/components/cardWithTopImage.vue
Normal 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>
|
||||
@@ -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>
|
||||
21
software/src/components/sectionDivider.vue
Normal file
21
software/src/components/sectionDivider.vue
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
36
software/src/data/stores/showStore.ts
Normal file
36
software/src/data/stores/showStore.ts
Normal 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
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
66
software/src/pages/homePage/highlightCarousel.vue
Normal file
66
software/src/pages/homePage/highlightCarousel.vue
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user