Remove EventModel in frontend

This commit is contained in:
2024-10-12 21:00:42 +02:00
parent 60a9cea147
commit b490d058e4
33 changed files with 313 additions and 377 deletions

View File

@@ -13,6 +13,9 @@ export const band = Router()
// Get all bands // Get all bands
band.get("/", (req: Request, res: Response) => { band.get("/", (req: Request, res: Response) => {
let sort = req.query.sort
let count = req.query.count
Band.findAll({ Band.findAll({
include: [ include: [
{ {
@@ -35,13 +38,28 @@ band.get("/", (req: Request, res: Response) => {
// Delete unnecessary Arrays // Delete unnecessary Arrays
delete band.dataValues.ratings delete band.dataValues.ratings
delete band.dataValues.concerts
for (let genre of band.dataValues.genres) { for (let genre of band.dataValues.genres) {
delete genre.dataValues.BandGenre delete genre.dataValues.BandGenre
} }
} }
// Sort ascending/descending by number of concerts
if (sort != undefined) {
bands.sort((band1, band2) => {
if (sort == "desc") {
return band2.dataValues.concerts.length - band1.dataValues.concerts.length
} else if (sort == "asc") {
return band1.dataValues.concerts.length - band2.dataValues.concerts.length
}
})
}
// Limit number of items
if (count != undefined) {
bands.splice(Number(count))
}
res.status(200).json(bands) res.status(200).json(bands)
}) })
}) })

View File

@@ -12,6 +12,8 @@ export const concert = Router()
concert.get("/", (req: Request, res: Response) => { concert.get("/", (req: Request, res: Response) => {
let count = req.query.count
Concert.findAll({ Concert.findAll({
include: [ Band, Location ], include: [ Band, Location ],
order: [ order: [
@@ -19,6 +21,11 @@ concert.get("/", (req: Request, res: Response) => {
] ]
}) })
.then(concerts => { .then(concerts => {
// Limit number of items
if (count != undefined) {
concerts.splice(Number(count))
}
res.status(200).json(concerts) res.status(200).json(concerts)
}) })
}) })

View File

@@ -27,6 +27,7 @@ location.get("/", (req: Request, res: Response) => {
} }
}) })
.then(async locations => { .then(async locations => {
// Sort ascending/descending by number of concerts
if (sort != undefined) { if (sort != undefined) {
locations.sort((location1, location2) => { locations.sort((location1, location2) => {
if (sort == "desc") { if (sort == "desc") {

View File

@@ -226,7 +226,7 @@ export async function prepopulateDatabase() {
date: concert.date, date: concert.date,
name: concertGroup.name, name: concertGroup.name,
price: concert.price, price: concert.price,
image: concertGroup.name, image: concertGroup.image,
inStock: concert.inStock, inStock: concert.inStock,
offered: true, offered: true,
bandId: dataset.dataValues.id, bandId: dataset.dataValues.id,

View File

@@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useAccountStore } from '@/data/stores/accountStore'; import { useAccountStore } from '@/data/stores/accountStore';
import { useBasketStore } from '@/data/stores/basketStore'; import { useBasketStore } from '@/data/stores/basketStore';
import router from '@/plugins/router';
const accountStore = useAccountStore() const accountStore = useAccountStore()
const basketStore = useBasketStore() const basketStore = useBasketStore()
@@ -11,7 +10,7 @@ const basketStore = useBasketStore()
<v-btn variant="plain" icon="mdi-magnify" to="/search" /> <v-btn variant="plain" icon="mdi-magnify" to="/search" />
<v-btn v-if="accountStore.userAccount.id == 0" variant="plain" icon="mdi-account" to="/account/login" /> <v-btn v-if="accountStore.userAccount.id == 0" variant="plain" icon="mdi-account" to="/account/login" />
<v-btn v-else variant="plain" icon="mdi-account" to="/account/home" /> <v-btn v-else variant="plain" icon="mdi-account" to="/account" />
<div> <div>
<v-badge <v-badge
@@ -23,6 +22,6 @@ const basketStore = useBasketStore()
</v-badge> </v-badge>
</div> </div>
<v-btn variant="plain" icon="mdi-help" to="/system/help" /> <v-btn variant="plain" icon="mdi-help" to="/help" />
<v-btn variant="plain" icon="mdi-cog" to="/system/preferences"/> <v-btn variant="plain" icon="mdi-cog" to="/preferences"/>
</template> </template>

View File

@@ -57,7 +57,7 @@ defineProps({
<div> <div>
<v-btn variant="flat" color="secondary"> <v-btn variant="flat" color="secondary">
{{ concerts.length }} {{ $t('event', concerts.length) }} {{ $t('more') }}
</v-btn> </v-btn>
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@ import axios from "axios"
let BASE_URL = "http://localhost:3000/bands" let BASE_URL = "http://localhost:3000/bands"
export async function getAllBands() { export async function fetchAllBands() {
return await axios.get(BASE_URL) return await axios.get(BASE_URL)
} }

View File

@@ -6,7 +6,7 @@ export async function fetchConcerts() {
return await axios.get(BASE_URL) return await axios.get(BASE_URL)
} }
export async function getConcert(id: number) { export async function fetchConcert(id: number) {
if (id != undefined) { if (id != undefined) {
return await axios.get(BASE_URL + "/concert/" + id) return await axios.get(BASE_URL + "/concert/" + id)
} else { } else {
@@ -14,6 +14,19 @@ export async function getConcert(id: number) {
} }
} }
/**
* Returns events with the most concerts
*
* @param nrOfConcerts Limit number of returned objects
*
* @returns Limited number of objects with the most concerts in it
*/
export async function fetchUpcomingConcerts(nrOfConcerts: number) {
let url = BASE_URL + "?count=" + nrOfConcerts
return await axios.get(url)
}
export async function searchConcert(searchTerm: string) { export async function searchConcert(searchTerm: string) {
return await axios.get(BASE_URL + '/search?value=' + searchTerm) return await axios.get(BASE_URL + '/search?value=' + searchTerm)
} }

View File

@@ -1,36 +0,0 @@
import axios from "axios"
const BASE_URL = "http://localhost:3000/events"
/**
* Request all events in the database
*
* @param city Filter by name of city where the concert is
* @param genre Filter by genre of the band
*
* @returns All events which fulfill the params
*/
export async function fetchEvents(city: string = "", genre: string = "") {
let url = BASE_URL + "?"
url += (city.length > 0) ? "city=" + city + "&" : ""
url += (genre.length > 0) ? "genre=" + genre : ""
return await axios.get(url)
}
/**
* Returns events with the most concerts
*
* @param nrOfEvents Limit number of returned objects
*
* @returns Limited number of objects with the most concerts in it
*/
export async function getTopEvents(nrOfEvents: number) {
let url = BASE_URL + "?sort=desc&count=" + nrOfEvents
return await axios.get(url)
}
export async function searchEvent(searchTerm: string) {
return await axios.get(BASE_URL + "/search?value=" + searchTerm)
}

View File

@@ -7,11 +7,10 @@ export async function fetchAllLocations() {
} }
export async function getLocation(locationName: string) { export async function getLocation(locationName: string) {
console.log(locationName)
return await axios.get(BASE_URL + "/location/" + locationName) return await axios.get(BASE_URL + "/location/" + locationName)
} }
export async function getTopLocations(nrOfLocations: number) { export async function fetchTopLocations(nrOfLocations: number) {
let url = BASE_URL + "?sort=desc&count=" + nrOfLocations let url = BASE_URL + "?sort=desc&count=" + nrOfLocations
return await axios.get(url) return await axios.get(url)

View File

@@ -1,4 +1,5 @@
import { BandModel } from "./bandModel"; import { BandModel } from "./bandModel";
import { ConcertModel } from "./concertModel";
import { GenreModel } from "./genreModel" import { GenreModel } from "./genreModel"
/** /**
@@ -7,5 +8,5 @@ import { GenreModel } from "./genreModel"
export class BandApiModel extends BandModel { export class BandApiModel extends BandModel {
genres: Array<GenreModel> = [] genres: Array<GenreModel> = []
rating: number = 0 rating: number = 0
nrOfConcerts: number = 0 concerts: Array<ConcertModel> = []
} }

View File

@@ -0,0 +1,9 @@
import { LocationDetailsApiModel } from "../locations/locationDetailsApiModel";
import { BandModel } from "./bandModel";
import { ConcertModel } from "./concertModel";
export class ConcertDetailsApiModel extends ConcertModel {
location: LocationDetailsApiModel = new LocationDetailsApiModel()
band: BandModel = new BandModel()
}

View File

@@ -0,0 +1,35 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { BandApiModel } from "../models/acts/bandApiModel";
import { fetchAllBands, getBand } from "../api/bandApi";
import { BandDetailsApiModel } from "../models/acts/bandDetailsApiModel";
export const useBandStore = defineStore("bandStore", {
state: () => ({
bands: ref<Array<BandApiModel>>([]),
band: ref<BandDetailsApiModel>(new BandDetailsApiModel()),
fetchInProgress: ref(false)
}),
actions: {
async getBands() {
this.fetchInProgress = true
fetchAllBands()
.then(result => {
this.bands = result.data
this.fetchInProgress = false
})
},
async getBand(name: string) {
this.fetchInProgress = true
getBand(name)
.then(result => {
this.band = result.data
this.fetchInProgress = false
})
}
}
})

View File

@@ -9,6 +9,7 @@ import { ref } from "vue";
import { SelectedSeatModel } from "../models/ordering/selectedSeatModel"; import { SelectedSeatModel } from "../models/ordering/selectedSeatModel";
import { calcPrice } from "@/scripts/concertScripts"; import { calcPrice } from "@/scripts/concertScripts";
import { BandModel } from "../models/acts/bandModel"; import { BandModel } from "../models/acts/bandModel";
import { ConcertModel } from "../models/acts/concertModel";
export const useBasketStore = defineStore('basketStore', { export const useBasketStore = defineStore('basketStore', {
state: () => ({ state: () => ({
@@ -50,7 +51,7 @@ export const useBasketStore = defineStore('basketStore', {
) )
}, },
moveSeatSelectionsToBasket(event, band: BandModel) { moveSeatSelectionsToBasket(concert: ConcertModel, band: BandModel) {
// todo // todo
// for (let selectedSeat of this.selectedSeats) { // for (let selectedSeat of this.selectedSeats) {
// let itemInBasket: BasketItemModel = this.itemsInBasket.find((basketItem: BasketItemModel) => { // let itemInBasket: BasketItemModel = this.itemsInBasket.find((basketItem: BasketItemModel) => {

View File

@@ -1,23 +1,48 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
import { ConcertApiModel } from "../models/acts/concertApiModel"; import { ConcertApiModel } from "../models/acts/concertApiModel";
import { useFeedbackStore } from "./feedbackStore"; import { fetchConcert, fetchConcerts, fetchUpcomingConcerts } from "../api/concertApi";
import { fetchConcerts } from "../api/concertApi"; import { ConcertDetailsApiModel } from "../models/acts/concertDetailsApiModel";
export const useConcertStore = defineStore("concertStore", { export const useConcertStore = defineStore("concertStore", {
state: () => ({ state: () => ({
concerts: ref<Array<ConcertApiModel>>([]) concerts: ref<Array<ConcertApiModel>>([]),
upcomingConcerts: ref<Array<ConcertApiModel>>([]),
concert: ref<ConcertDetailsApiModel>(new ConcertDetailsApiModel()),
fetchInProgress: ref(false)
}), }),
actions: { actions: {
/**
* Download all concerts from server
*/
async getConcerts() { async getConcerts() {
const feedbackStore = useFeedbackStore() this.fetchInProgress = true
feedbackStore.fetchDataFromServerInProgress = true
await fetchConcerts() fetchConcerts()
.then(result => { .then(result => {
this.concerts = result.data this.concerts = result.data
feedbackStore.fetchDataFromServerInProgress = false this.fetchInProgress = false
})
},
async getConcert(id: number) {
this.fetchInProgress = true
fetchConcert(id)
.then(result => {
this.concert = result.data
this.fetchInProgress = false
})
},
async getUpcomingConcerts() {
this.fetchInProgress = true
fetchUpcomingConcerts(4)
.then(result => {
this.upcomingConcerts = result.data
this.fetchInProgress = false
}) })
} }
} }

View File

@@ -1,7 +1,6 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
import { useFeedbackStore } from "./feedbackStore"; import { fetchAllLocations, fetchTopLocations } from "../api/locationApi";
import { fetchAllLocations } from "../api/locationApi";
import { LocationApiModel } from "../models/locations/locationApiModel"; import { LocationApiModel } from "../models/locations/locationApiModel";
import { CityModel } from "../models/locations/cityModel"; import { CityModel } from "../models/locations/cityModel";
import { fetchAllCities } from "../api/cityApi"; import { fetchAllCities } from "../api/cityApi";
@@ -9,13 +8,17 @@ import { fetchAllCities } from "../api/cityApi";
export const useLocationStore = defineStore("locationStore", { export const useLocationStore = defineStore("locationStore", {
state: () => ({ state: () => ({
locations: ref<Array<LocationApiModel>>([]), locations: ref<Array<LocationApiModel>>([]),
cities: ref<Array<CityModel>>([]) topLocations: ref<Array<LocationApiModel>>([]),
cities: ref<Array<CityModel>>([]),
fetchInProgress: ref(false)
}), }),
actions: { actions: {
/**
* Download all cities/locations from server
*/
async getLocations() { async getLocations() {
const feedbackStore = useFeedbackStore() this.fetchInProgress = true
feedbackStore.fetchDataFromServerInProgress = true
await fetchAllLocations() await fetchAllLocations()
.then(result => { .then(result => {
@@ -25,12 +28,29 @@ export const useLocationStore = defineStore("locationStore", {
await fetchAllCities() await fetchAllCities()
.then(result => { .then(result => {
this.cities = result.data this.cities = result.data
feedbackStore.fetchDataFromServerInProgress = false this.fetchInProgress = false
}) })
}, },
/**
* Get all locations in a specific city
*
* @param city City to filter for
*
* @returns Array of cities which are in the target city
*/
getLocationsByCity(city: string): Array<LocationApiModel> { getLocationsByCity(city: string): Array<LocationApiModel> {
return this.locations.filter(location => location.city.name == city) return this.locations.filter((location: LocationApiModel) => {
return location.city.name == city
})
},
async getTopLocations() {
await fetchTopLocations(8)
.then(result => {
this.topLocations = result.data
})
} }
}, },
}) })

View File

@@ -2,14 +2,14 @@ import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
import { searchBand } from "../api/bandApi"; import { searchBand } from "../api/bandApi";
import { searchLocation } from "../api/locationApi"; import { searchLocation } from "../api/locationApi";
import { searchEvent } from "../api/eventApi"; import { searchConcert } from "../api/concertApi";
export const useSearchStore = defineStore("searchStore", { export const useSearchStore = defineStore("searchStore", {
state: () => ({ state: () => ({
searchTerm: ref(""), searchTerm: ref(""),
bands: ref(), bands: ref(),
locations: ref(), locations: ref(),
events: ref(), concerts: ref(),
alreadySearched: ref(false), alreadySearched: ref(false),
searchInProgress: ref(false) searchInProgress: ref(false)
}), }),
@@ -32,9 +32,9 @@ export const useSearchStore = defineStore("searchStore", {
this.locations = result.data this.locations = result.data
}) })
await searchEvent(this.searchTerm) await searchConcert(this.searchTerm)
.then(result => { .then(result => {
this.events = result.data this.concerts = result.data
}) })
this.searchInProgress = false this.searchInProgress = false

View File

@@ -1,12 +1,14 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
import { fetchEvents } from "../api/eventApi";
import { fetchAllCities } from "../api/cityApi"; import { fetchAllCities } from "../api/cityApi";
import { fetchAllGenres } from "../api/genreApi"; import { fetchAllGenres } from "../api/genreApi";
import { useFeedbackStore } from "./feedbackStore"; import { useFeedbackStore } from "./feedbackStore";
import { CityApiModel } from "../models/locations/cityApiModel"; import { CityApiModel } from "../models/locations/cityApiModel";
import { GenreApiModel } from "../models/acts/genreApiModel"; import { GenreApiModel } from "../models/acts/genreApiModel";
/**
* @deprecated
*/
export const useShoppingStore = defineStore("shoppingStore", { export const useShoppingStore = defineStore("shoppingStore", {
state: () => ({ state: () => ({
cities: ref<Array<CityApiModel>>([]), cities: ref<Array<CityApiModel>>([]),
@@ -19,15 +21,6 @@ export const useShoppingStore = defineStore("shoppingStore", {
async getEvents() { async getEvents() {
const feedbackStore = useFeedbackStore() const feedbackStore = useFeedbackStore()
feedbackStore.fetchDataFromServerInProgress = true feedbackStore.fetchDataFromServerInProgress = true
await fetchEvents(
this.cityFilterName != null && this.cityFilterName != "undefined" && !this.cityFilterName.startsWith("<") ? this.cityFilterName : "",
this.genreFilterName != null && this.genreFilterName != "undefined" && !this.genreFilterName.startsWith("<") ? this.genreFilterName : ""
)
.then(result => {
this.events = result.data
feedbackStore.fetchDataFromServerInProgress = false
})
}, },
async getCities() { async getCities() {

View File

@@ -175,5 +175,7 @@
"noBandFound": "Keine Band gefunden", "noBandFound": "Keine Band gefunden",
"noLocationsFound": "Keine Veranstaltungsorte gefunden", "noLocationsFound": "Keine Veranstaltungsorte gefunden",
"allBands": "Alle Bands", "allBands": "Alle Bands",
"allConcerts": "Alle Konzerte" "allConcerts": "Alle Konzerte",
"more": "Mehr",
"upcomingConcerts": "Nächste Konzerte"
} }

View File

@@ -175,5 +175,7 @@
"noBandFound": "No band found", "noBandFound": "No band found",
"noLocationsFound": "No location found", "noLocationsFound": "No location found",
"allBands": "All Bands", "allBands": "All Bands",
"allConcerts": "All Concerts" "allConcerts": "All Concerts",
"more": "More",
"upcomingConcerts": "Upcoming Concerts"
} }

View File

@@ -1,48 +1,34 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRouter } from 'vue-router';
import { useFeedbackStore } from '@/data/stores/feedbackStore';
import concertListItem from '@/components/pageParts/concertListItem.vue'; import concertListItem from '@/components/pageParts/concertListItem.vue';
import { ConcertApiModel } from '@/data/models/acts/concertApiModel';
import { BandApiModel } from '@/data/models/acts/bandApiModel'; import { BandApiModel } from '@/data/models/acts/bandApiModel';
import { EventApiModel } from '@/data/models/acts/eventApiModel'; import { ConcertApiModel } from '@/data/models/acts/concertApiModel';
import CardViewHorizontal from '@/components/basics/cardViewHorizontal.vue';
import { useConcertStore } from '@/data/stores/concertStore';
const router = useRouter() const concertStore = useConcertStore()
const feedbackStore = useFeedbackStore()
defineProps({ defineProps({
band: BandApiModel, band: BandApiModel,
events: Array<EventApiModel> concerts: Array<ConcertApiModel>
}) })
</script> </script>
<template> <template>
<v-row v-if="feedbackStore.fetchDataFromServerInProgress" v-for="i in 3"> <v-row v-if="concertStore.fetchInProgress" v-for="i in 3">
<v-col> <v-col>
<!-- <concert-list-item <card-view-horizontal :loading="true" />
:loading="true" /> -->
</v-col> </v-col>
</v-row> </v-row>
<div v-else v-for="event of events"> <v-row v-for="concert of concerts">
<v-row v-for="concert of event.concerts"> <v-col>
<v-col> <concert-list-item
<concert-list-item :concert="concert"
:concert="concert" :band="band"
:title="concert.location.city.name" :location="concert.location"
:link="concert.inStock > 0" :title="concert.location.city.name"
:onClick="() => router.push('/concert/' + concert.id)" :link="concert.inStock > 0"
> />
<template #description> </v-col>
<div> </v-row>
{{ concert.location.name }}
</div>
<div>
{{ band.name }} - {{ band.events[0].name }}
</div>
</template>
</concert-list-item>
</v-col>
</v-row>
</div>
</template> </template>

View File

@@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { BandModel } from '@/data/models/acts/bandModel'; import { BandModel } from '@/data/models/acts/bandModel';
import { useFeedbackStore } from '@/data/stores/feedbackStore'; import { useBandStore } from '@/data/stores/bandStore';
const feedbackStore = useFeedbackStore() const bandStore = useBandStore()
defineProps({ defineProps({
band: { band: {
@@ -17,7 +17,7 @@ defineProps({
<v-col> <v-col>
<v-skeleton-loader <v-skeleton-loader
type="image" type="image"
:loading="feedbackStore.fetchDataFromServerInProgress" :loading="bandStore.fetchInProgress"
> >
<v-carousel <v-carousel
show-arrows show-arrows

View File

@@ -6,35 +6,22 @@ import gallerySection from './gallerySection.vue';
import concertSection from './concertSection.vue'; import concertSection from './concertSection.vue';
import heroImage from '@/components/pageParts/heroImage.vue'; import heroImage from '@/components/pageParts/heroImage.vue';
import sectionDivider from '@/components/basics/sectionDivider.vue'; import sectionDivider from '@/components/basics/sectionDivider.vue';
import { useShoppingStore } from '@/data/stores/shoppingStore'; import { useBandStore } from '@/data/stores/bandStore';
import { ref } from 'vue';
import { useFeedbackStore } from '@/data/stores/feedbackStore';
import { getBand } from '@/data/api/bandApi';
import { BandApiModel } from '@/data/models/acts/bandApiModel';
import { genre } from 'backend/routes/genre.routes';
const router = useRouter() const router = useRouter()
const shoppingStore = useShoppingStore() const bandStore = useBandStore()
const feedbackStore = useFeedbackStore()
const band = ref<BandApiModel>(new BandApiModel())
feedbackStore.fetchDataFromServerInProgress = true bandStore.getBand(String(router.currentRoute.value.params.name).replaceAll('-', ' '))
getBand(String(router.currentRoute.value.params.bandName).replaceAll('-', ' '))
.then(result => {
band.value = result.data
feedbackStore.fetchDataFromServerInProgress = false
})
</script> </script>
<template> <template>
<hero-image <hero-image
:image="band.imageMembers" :image="bandStore.band.imageMembers"
:logo="band.logo" :logo="bandStore.band.logo"
:title="band.name" :title="bandStore.band.name"
:chips="band.genres.map(genre => genre.name)" :chips="bandStore.band.genres.map(genre => genre.name)"
:description="band.descriptionDe" :description="bandStore.band.descriptionDe"
:loading="feedbackStore.fetchDataFromServerInProgress" :loading="bandStore.fetchInProgress"
/> />
<v-container> <v-container>
@@ -49,8 +36,8 @@ getBand(String(router.currentRoute.value.params.bandName).replaceAll('-', ' '))
</v-row> </v-row>
<concert-section <concert-section
:band="band" :band="bandStore.band"
:events="band.events" :concerts="bandStore.band.concerts"
/> />
<v-row> <v-row>
@@ -59,7 +46,9 @@ getBand(String(router.currentRoute.value.params.bandName).replaceAll('-', ' '))
</v-col> </v-col>
</v-row> </v-row>
<band-member-section :band="band" /> <band-member-section
:band="bandStore.band"
/>
<v-row> <v-row>
@@ -68,7 +57,10 @@ getBand(String(router.currentRoute.value.params.bandName).replaceAll('-', ' '))
</v-col> </v-col>
</v-row> </v-row>
<rating-section :ratings="band.ratings" /> <rating-section
:rating="bandStore.band.rating"
:ratings="bandStore.band.ratingValues"
/>
<v-row> <v-row>
@@ -77,7 +69,9 @@ getBand(String(router.currentRoute.value.params.bandName).replaceAll('-', ' '))
</v-col> </v-col>
</v-row> </v-row>
<gallery-section :band="band" /> <gallery-section
:band="bandStore.band"
/>
</v-col> </v-col>
<v-spacer /> <v-spacer />

View File

@@ -1,9 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { BandApiModel } from '@/data/models/acts/bandApiModel';
import { RatingModel } from '@/data/models/acts/ratingModel'; import { RatingModel } from '@/data/models/acts/ratingModel';
defineProps({ defineProps({
/**
* Overall rating of the band
*/
rating: Number, rating: Number,
/**
* Array of rating steps from 1 to 5
*/
ratings: { ratings: {
type: Array<RatingModel>, type: Array<RatingModel>,
required: true required: true

View File

@@ -1,6 +1,49 @@
<script setup lang="ts"> <script setup lang="ts">
import { useBandStore } from '@/data/stores/bandStore';
import cardViewHorizontal from '@/components/basics/cardViewHorizontal.vue';
import bandListItem from '@/components/pageParts/bandListItem.vue';
const bandStore = useBandStore()
bandStore.getBands()
</script> </script>
<template> <template>
Bands <v-container>
<v-row>
<v-spacer />
<v-col cols="10">
<v-row>
<v-col>
Filterbar
</v-col>
</v-row>
<v-row
v-if="bandStore.fetchInProgress"
v-for="i in 3"
>
<v-col>
<card-view-horizontal :loading="true" />
</v-col>
</v-row>
<v-row
v-else-if="bandStore.bands.length > 0"
v-for="band in bandStore.bands"
>
<v-col>
<band-list-item
:band="band"
:concerts="band.concerts"
:genres="band.genres"
/>
</v-col>
</v-row>
</v-col>
<v-spacer />
</v-row>
</v-container>
</template> </template>

View File

@@ -1,30 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import seatPlanMap from '@/components/seatPlanMap/seatPlanMap.vue'; import seatPlanMap from '@/components/seatPlanMap/seatPlanMap.vue';
import { ref } from 'vue';
import { SeatGroupModel } from '@/data/models/locations/seatGroupModel';
import { getConcert } from '@/data/api/concertApi';
import { useFeedbackStore } from '@/data/stores/feedbackStore';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import sectionDivider from '@/components/basics/sectionDivider.vue'; import sectionDivider from '@/components/basics/sectionDivider.vue';
import { useBasketStore } from '@/data/stores/basketStore'; import { useBasketStore } from '@/data/stores/basketStore';
import concertListItem from '@/components/pageParts/concertListItem.vue'; import concertListItem from '@/components/pageParts/concertListItem.vue';
import outlinedButton from '@/components/basics/outlinedButton.vue'; import outlinedButton from '@/components/basics/outlinedButton.vue';
import { ConcertApiModel } from '@/data/models/acts/concertApiModel'; import { useConcertStore } from '@/data/stores/concertStore';
const router = useRouter() const router = useRouter()
const seatGroups = ref<Array<SeatGroupModel>>()
const concertModel = ref<ConcertApiModel>(new ConcertApiModel())
const feedbackStore = useFeedbackStore()
const basketStore = useBasketStore() const basketStore = useBasketStore()
const concertStore = useConcertStore()
feedbackStore.fetchDataFromServerInProgress = true concertStore.getConcert(Number(router.currentRoute.value.params.id))
getConcert(Number(router.currentRoute.value.params.id))
.then(result => {
seatGroups.value = result.data.location.seatGroups
concertModel.value = result.data
feedbackStore.fetchDataFromServerInProgress = false
})
</script> </script>
<template> <template>
@@ -42,14 +29,16 @@ getConcert(Number(router.currentRoute.value.params.id))
<v-row> <v-row>
<v-col> <v-col>
<concert-list-item <concert-list-item
:concert="concertModel" :concert="concertStore.concert"
:loading="feedbackStore.fetchDataFromServerInProgress" :band="concertStore.concert.band"
:location="concertStore.concert.location"
:loading="concertStore.fetchInProgress"
:link="false" :link="false"
:title="concertModel.location.city.name" :title="concertStore.concert.location.city.name"
:show-button="false" :show-button="false"
> >
<template #description> <template #description>
<p>{{ concertModel.location.name }}</p> <p>{{ concertStore.concert.location.name }}</p>
<!-- todo <p>{{ concertModel.event.band.name }} - {{ concertModel.event.name }}</p> --> <!-- todo <p>{{ concertModel.event.band.name }} - {{ concertModel.event.name }}</p> -->
</template> </template>
</concert-list-item> </concert-list-item>
@@ -62,7 +51,7 @@ getConcert(Number(router.currentRoute.value.params.id))
</v-row> </v-row>
<v-row > <v-row >
<v-col class="text-center" v-if="feedbackStore.fetchDataFromServerInProgress"> <v-col class="text-center" v-if="concertStore.fetchInProgress">
<v-progress-circular <v-progress-circular
size="x-large" size="x-large"
width="10" width="10"
@@ -77,9 +66,9 @@ getConcert(Number(router.currentRoute.value.params.id))
<v-col v-else> <v-col v-else>
<seat-plan-map <seat-plan-map
:concert="concertModel" :concert="concertStore.concert"
:seat-groups="seatGroups" :seat-groups="concertStore.concert.location.seatGroups"
:location="concertModel.location" :location="concertStore.concert.location"
/> />
</v-col> </v-col>
</v-row> </v-row>
@@ -102,15 +91,15 @@ getConcert(Number(router.currentRoute.value.params.id))
</v-row> </v-row>
<v-row class="pb-5"> <v-row class="pb-5">
<!-- <outlined-button todo <outlined-button todo
prepend-icon="mdi-basket-plus" prepend-icon="mdi-basket-plus"
@click="basketStore.moveSeatSelectionsToBasket(concertModel.event, concertModel.event.band); @click="basketStore.moveSeatSelectionsToBasket(concertStore.concert, concertStore.concert.band);
router.push('/basket')" router.push('/basket')"
:disabled="basketStore.selectedSeats.length == 0" :disabled="basketStore.selectedSeats.length == 0"
block block
> >
{{ $t('addToBasket') }} {{ $t('addToBasket') }}
</outlined-button> --> </outlined-button>
</v-row> </v-row>
</v-col> </v-col>

View File

@@ -1,12 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { useConcertStore } from '@/data/stores/concertStore'; import { useConcertStore } from '@/data/stores/concertStore';
import concertListItem from '@/components/pageParts/concertListItem.vue'; import concertListItem from '@/components/pageParts/concertListItem.vue';
import { useFeedbackStore } from '@/data/stores/feedbackStore';
import cardViewHorizontal from '@/components/basics/cardViewHorizontal.vue'; import cardViewHorizontal from '@/components/basics/cardViewHorizontal.vue';
import sectionDivider from '@/components/basics/sectionDivider.vue'; import sectionDivider from '@/components/basics/sectionDivider.vue';
const concertStore = useConcertStore() const concertStore = useConcertStore()
const feedbackStore = useFeedbackStore()
concertStore.getConcerts() concertStore.getConcerts()
</script> </script>
@@ -25,7 +23,7 @@ concertStore.getConcerts()
</v-row> </v-row>
<v-row <v-row
v-if="feedbackStore.fetchDataFromServerInProgress" v-if="concertStore.fetchInProgress"
v-for="i in 3" v-for="i in 3"
> >
<v-col> <v-col>

View File

@@ -1,92 +0,0 @@
<script setup lang="ts">
import cardView from '@/components/basics/cardView.vue';
import outlinedButton from '@/components/basics/outlinedButton.vue';
import { GenreModel } from '@/data/models/acts/genreModel';
import { CityModel } from '@/data/models/locations/cityModel';
import { useShoppingStore } from '@/data/stores/shoppingStore';
import { useRoute, useRouter } from 'vue-router';
const shoppingStore = useShoppingStore()
const router = useRouter()
shoppingStore.getCities()
shoppingStore.getGenres()
function itemPropsCity(city: CityModel) {
return {
title: city.name
}
}
function itemPropsGenre(genre: GenreModel) {
return {
title: genre.name
}
}
function filter() {
let queries = {}
if (shoppingStore.cityFilterName != null && shoppingStore.cityFilterName != "undefined") {
queries["city"] = shoppingStore.cityFilterName
}
if (shoppingStore.genreFilterName != null && shoppingStore.genreFilterName != "undefined") {
queries["genre"] = shoppingStore.genreFilterName
}
router.push({ path: '/events', query: queries})
shoppingStore.getEvents()
}
</script>
<template>
<card-view
variant="tonal"
:title="$t('filtering')"
icon="mdi-cog"
>
<v-row class="d-flex justify-center" >
<v-col cols="3">
<v-select
variant="outlined"
:items="shoppingStore.cities"
:item-props="itemPropsCity"
v-model="shoppingStore.cityFilterName"
:label="$t('city')"
class="mb-n5"
:clearable="shoppingStore.cityFilterName != ''"
base-color="secondary"
color="secondary"
item-value="name"
/>
</v-col>
<v-col cols="4">
<v-select
variant="outlined"
:items="shoppingStore.genres"
:item-props="itemPropsGenre"
v-model="shoppingStore.genreFilterName"
label="Genre"
:clearable="shoppingStore.genreFilterName != ''"
class="mb-n5"
base-color="secondary"
color="secondary"
item-value="name"
/>
</v-col>
<v-col cols="2">
<outlined-button
height="100%"
append-icon="mdi-chevron-right"
@click="filter"
>
{{ $t('filtering') }}
</outlined-button>
</v-col>
</v-row>
</card-view>
</template>

View File

@@ -1,68 +0,0 @@
<script setup lang="ts">
import filterBar from './filterBar.vue';
import { useRoute } from 'vue-router';
import { useShoppingStore } from '@/data/stores/shoppingStore';
import { useFeedbackStore } from '@/data/stores/feedbackStore';
const route = useRoute()
const shoppingStore = useShoppingStore()
const feedbackStore = useFeedbackStore()
// Load query attributes
shoppingStore.cityFilterName = String(route.query.city)
shoppingStore.genreFilterName = String(route.query.genre)
shoppingStore.getEvents()
</script>
<template>
<v-container>
<v-row>
<v-spacer />
<v-col cols="10">
<v-row>
<v-col>
<filter-bar />
</v-col>
</v-row>
<v-row
v-if="feedbackStore.fetchDataFromServerInProgress"
v-for="i in 3"
>
<v-col>
Loading...
<!-- todo <event-list-item
:loading="true"
/> -->
</v-col>
</v-row>
<v-row
v-else-if="shoppingStore.events.length > 0"
v-for="event of shoppingStore.events"
>
<v-col>
<event-list-item
:event="event"
:band="event.band"
:concerts="event.concerts"
/>
</v-col>
</v-row>
<v-row v-else>
<v-col>
<v-empty-state
:title="$t('noEventsFound')"
icon="mdi-magnify"
/>
</v-col>
</v-row>
</v-col>
<v-spacer />
</v-row>
</v-container>
</template>

View File

@@ -10,7 +10,7 @@ shoppingStore.getEvents()
</script> </script>
<template> <template>
<v-carousel <!-- <v-carousel
hide-delimiters hide-delimiters
hide-delimiter-background hide-delimiter-background
height="700" height="700"
@@ -30,10 +30,10 @@ shoppingStore.getEvents()
@click="props.onClick" @click="props.onClick"
icon="mdi-chevron-right" icon="mdi-chevron-right"
/> />
</template> </template> -->
<v-carousel-item <!-- <v-carousel-item
v-for="event in shoppingStore.events" v-for="event in shoppingStore.concerts"
:src="'http://localhost:3000/static/' + event.band.imageMembers" :src="'http://localhost:3000/static/' + event.band.imageMembers"
cover cover
> >
@@ -60,7 +60,7 @@ shoppingStore.getEvents()
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-carousel-item> </v-carousel-item>
</v-carousel> </v-carousel> -->
</template> </template>
<style scoped> <style scoped>

View File

@@ -5,27 +5,17 @@ import cardWithTopImage from '@/components/basics/cardViewTopImage.vue';
import { lowestTicketPrice } from '@/scripts/concertScripts'; import { lowestTicketPrice } from '@/scripts/concertScripts';
import OutlinedButton from '@/components/basics/outlinedButton.vue'; import OutlinedButton from '@/components/basics/outlinedButton.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useFeedbackStore } from '@/data/stores/feedbackStore'; import { useConcertStore } from '@/data/stores/concertStore';
import { ref } from 'vue'; import { useLocationStore } from '@/data/stores/locationStore';
import { getTopLocations } from '@/data/api/locationApi'; import { useBandStore } from '@/data/stores/bandStore';
import { LocationApiModel } from '@/data/models/locations/locationApiModel';
const router = useRouter() const router = useRouter()
const feedbackStore = useFeedbackStore() const concertStore = useConcertStore()
const topLocations = ref<Array<LocationApiModel>>(Array.from({length: 8}, () => new LocationApiModel())) const locationStore = useLocationStore()
const bandStore = useBandStore()
feedbackStore.fetchDataFromServerInProgress = true concertStore.getUpcomingConcerts()
locationStore.getTopLocations()
// todo getTopEvents(4)
// .then(events => {
// topEvents.value = events.data
// getTopLocations(8)
// .then(locations => {
// topLocations.value = locations.data
// feedbackStore.fetchDataFromServerInProgress = false
// })
// })
</script> </script>
<template> <template>
@@ -38,32 +28,32 @@ feedbackStore.fetchDataFromServerInProgress = true
<v-col cols="10"> <v-col cols="10">
<v-row> <v-row>
<v-col> <v-col>
<section-divider :title="$t('topEvents')" /> <section-divider :title="$t('upcomingConcerts')" />
</v-col> </v-col>
</v-row> </v-row>
<!-- <v-row> todo <v-row>
<v-col v-for="i in 4" cols="3"> <v-col v-for="concert in concertStore.upcomingConcerts" cols="3">
<card-with-top-image <card-with-top-image
:image="topEvents[i - 1].image" :image="concert.image"
:title="topEvents[i - 1].band.name" :title="concert.band.name"
smaller-title smaller-title
@click="router.push('/bands/' + topEvents[i - 1].band.name.replaceAll(' ', '-').toLowerCase())" @click="router.push('/bands/details/' + concert.band.name.replaceAll(' ', '-').toLowerCase())"
:loading="feedbackStore.fetchDataFromServerInProgress" :loading="concertStore.fetchInProgress"
> >
ab {{ lowestTicketPrice(topEvents[i - 1].concerts) }} <!-- ab todo -->
</card-with-top-image> </card-with-top-image>
</v-col> </v-col>
</v-row> --> </v-row>
<v-row> <v-row>
<v-col> <v-col>
<outlined-button <outlined-button
append-icon="mdi-chevron-right" append-icon="mdi-chevron-right"
@click="router.push('/events')" @click="router.push('/concerts')"
block block
> >
{{ $t('allEvents') }} {{ $t('allConcerts') }}
</outlined-button> </outlined-button>
</v-col> </v-col>
</v-row> </v-row>
@@ -75,15 +65,15 @@ feedbackStore.fetchDataFromServerInProgress = true
</v-row> </v-row>
<v-row> <v-row>
<v-col v-for="i in 8" cols="3"> <v-col v-for="location in locationStore.topLocations" cols="3">
<card-with-top-image <card-with-top-image
:image="topLocations[i - 1].imageOutdoor" :image="location.imageOutdoor"
:title="topLocations[i - 1].name" :title="location.name"
smaller-title smaller-title
@click="router.push('/locations/' + topLocations[i - 1].name.replaceAll(' ', '-').toLowerCase())" @click="router.push('/locations/details/' + location.name.replaceAll(' ', '-').toLowerCase())"
:loading="feedbackStore.fetchDataFromServerInProgress" :loading="locationStore.fetchInProgress"
> >
{{ topLocations[i - 1].city.name }}, {{ topLocations[i - 1].city.country }} {{ location.city.name }}, {{ location.city.country }}
</card-with-top-image> </card-with-top-image>
</v-col> </v-col>
</v-row> </v-row>

View File

@@ -8,6 +8,7 @@ import { useFeedbackStore } from '@/data/stores/feedbackStore';
import heroImage from '@/components/pageParts/heroImage.vue'; import heroImage from '@/components/pageParts/heroImage.vue';
import concertListItem from '@/components/pageParts/concertListItem.vue'; import concertListItem from '@/components/pageParts/concertListItem.vue';
import { LocationDetailsApiModel } from '@/data/models/locations/locationDetailsApiModel'; import { LocationDetailsApiModel } from '@/data/models/locations/locationDetailsApiModel';
import cardViewHorizontal from '@/components/basics/cardViewHorizontal.vue';
const router = useRouter() const router = useRouter()
const feedbackStore = useFeedbackStore() const feedbackStore = useFeedbackStore()
@@ -49,8 +50,7 @@ getLocation(String(router.currentRoute.value.params.name))
<v-row v-if="feedbackStore.fetchDataFromServerInProgress" v-for="i in 3"> <v-row v-if="feedbackStore.fetchDataFromServerInProgress" v-for="i in 3">
<v-col class="text-center"> <v-col class="text-center">
Loading... <card-view-horizontal :loading="true" />
<!-- todo <concert-list-item :loading="feedbackStore.fetchDataFromServerInProgress" /> -->
</v-col> </v-col>
</v-row> </v-row>
@@ -61,8 +61,9 @@ getLocation(String(router.currentRoute.value.params.name))
<v-col> <v-col>
<concert-list-item <concert-list-item
:concert="concert" :concert="concert"
:band="concert.band"
:location="location"
:title="concert.name" :title="concert.name"
:onClick="() => router.push('/bands/' + concert.band.name.replaceAll(' ', '-').toLowerCase())"
> >
<template #description> <template #description>
{{ concert.band.name }} {{ concert.band.name }}

View File

@@ -34,7 +34,7 @@ const routes = [
// Concerts // Concerts
{ path: '/concerts', component: ConcertsPage }, { path: '/concerts', component: ConcertsPage },
{ path: '/concert/booking/:id', component: ConcertBookingPage }, { path: '/concerts/booking/:id', component: ConcertBookingPage },
// Locations // Locations
{ path: '/locations', component: LocationsPage }, { path: '/locations', component: LocationsPage },