Improve filterBar on eventsPage, improve API access from frontend

This commit is contained in:
2024-10-03 19:56:44 +02:00
parent 2b7e87a68d
commit c611cc04fc
27 changed files with 170 additions and 164 deletions

View File

@@ -78,8 +78,6 @@ account.post("/", (req: Request, res: Response) => {
})
account.patch("/", (req: Request, res: Response) => {
console.log(req.body)
Account.update(req.body,
{
where: { id: req.body.id }

View File

@@ -6,14 +6,7 @@ import { Request, Response, Router } from "express";
export const genre = Router()
genre.get("/", (req: Request, res: Response) => {
Genre.findAll({
include: [
{
model: Band,
include: [ Rating ]
}
]
})
Genre.findAll()
.then(genres => {
res.status(200).json(genres)
})

View File

@@ -38,12 +38,12 @@ location.get("/", (req: Request, res: Response) => {
.then(async locations => {
for (let location of locations) {
for (let concert of location.dataValues.concerts) {
let tour = concert.dataValues.tour
let event = concert.dataValues.event
await Band.findByPk(tour.dataValues.bandId)
await Band.findByPk(event.dataValues.bandId)
.then(band => {
tour.dataValues.bandName = band.dataValues.name
delete tour.dataValues.bandId
event.dataValues.bandName = band.dataValues.name
delete event.dataValues.bandId
})
}
}

View File

@@ -16,8 +16,8 @@ defineProps({
</script>
<template>
<v-card>
<v-row v-if="prependImage != ''">
<v-card v-if="prependImage != ''">
<v-row>
<v-col cols="3" class="pr-0">
<v-img
:src="prependImage"
@@ -53,26 +53,11 @@ defineProps({
</v-card-actions>
</v-col>
</v-row>
</v-card>
<v-container v-else>
<v-card v-else :title="title" :prepend-icon="icon">
<v-container>
<slot></slot>
</v-container>
<!-- Show default container only, if there is content -->
<!-- <v-container v-if="$slots.default">
<slot></slot>
</v-container> -->
<!-- Slot for content without padding -->
<!-- <slot name="withoutContainer"></slot> -->
<!-- Slot for Action Buttons in the right bottom corner -->
<!-- <v-card-actions v-if="$slots.actions" class="card-actions">
<v-spacer />
<slot name="actions"></slot>
</v-card-actions> -->
</v-card>
</template>

View File

@@ -2,6 +2,13 @@ import axios from "axios"
const BASE_URL = "http://localhost:3000/cities"
/**
* @deprecated Use fetchAllCities
*/
export async function getAllCities() {
return await axios.get(BASE_URL)
}
export async function fetchAllCities() {
return await axios.get(BASE_URL)
}

View File

@@ -4,9 +4,8 @@ const BASE_URL = "http://localhost:3000/events"
export async function fetchEvents(city: string = "", genre: string = "") {
let url = BASE_URL + "?"
url += (city.length > 0) ? "city=" + city : ""
url += (city.length > 0) ? "city=" + city + "&" : ""
url += (genre.length > 0) ? "genre=" + genre : ""
console.log(url)
return await axios.get(url)
}

View File

@@ -2,6 +2,13 @@ import axios from "axios"
let BASE_URL = "http://localhost:3000/genres"
/**
* @deprecated Use fetchAllGenres()
*/
export async function getAllGenres() {
return await axios.get(BASE_URL)
}
export async function fetchAllGenres() {
return await axios.get(BASE_URL)
}

View File

@@ -6,5 +6,5 @@ let BASE_URL = "http://localhost:3000/tours"
* Fetch all tours from API
*/
export async function getAllTours() {
return await axios.get(BASE_URL)
//return await axios.get(BASE_URL)
}

View File

@@ -6,6 +6,6 @@ export class EventModel {
name: string
offered: boolean
image: string
band: BandModel
concerts: Array<ConcertModel>
band: BandModel = new BandModel()
concerts: Array<ConcertModel> = [ new ConcertModel() ]
}

View File

@@ -2,15 +2,21 @@
* Replica of the API endpoint /cities
*/
export class CityModel {
id: number
name: string
country: string
image: string
id: number = -1
name: string = ""
country: string = ""
image: string = ""
locations: Array<{
id: number
name: string
address: string
image: string
nrOfConcerts: number
}>
}> = [{
id: -1,
name: "",
address: "",
image: "",
nrOfConcerts: 0
}]
}

View File

@@ -29,15 +29,15 @@ export const useConcertStore = defineStore("concertStore", {
async fetchAllTours() {
await getAllTours()
.then(result => {
this.tours = result.data
// this.tours = result.data
this.tours.sort((a, b) => {
return new Date(a.concerts[0].date) < new Date(b.concerts[0].date) ? -1 : 1
})
// this.tours.sort((a, b) => {
// return new Date(a.concerts[0].date) < new Date(b.concerts[0].date) ? -1 : 1
// })
this.filteredTours = this.tours
// this.filteredTours = this.tours
this.filterTours()
// this.filterTours()
})
await getAllBands()
@@ -47,7 +47,6 @@ export const useConcertStore = defineStore("concertStore", {
await getAllLocations()
.then(result => {
console.log(result.data)
this.locations = result.data
})

View File

@@ -2,18 +2,43 @@ import { defineStore } from "pinia";
import { ref } from "vue";
import { EventModel } from "../models/acts/eventModel";
import { fetchEvents } from "../api/eventApi";
import { fetchAllCities } from "../api/cityApi";
import { CityModel } from "../models/locations/cityModel";
import { GenreModel } from "../models/acts/genreModel";
import { fetchAllGenres } from "../api/genreApi";
export const useShoppingStore = defineStore("shoppingStore", {
state: () => ({
events: ref<Array<EventModel>>([])
events: ref<Array<EventModel>>([ new EventModel() ]),
cities: ref<Array<CityModel>>([ new CityModel() ]),
genres: ref<Array<GenreModel>>([ new GenreModel() ]),
cityFilterName: ref<String>(),
genreFilterName: ref<String>()
}),
actions: {
getEvents(city: string = "", genre: string = "") {
fetchEvents(city, genre)
async getEvents() {
await fetchEvents(
this.cityFilterName != null ? this.cityFilterName : "",
this.genreFilterName != null ? this.genreFilterName : ""
)
.then(result => {
this.events = result.data
})
},
async getCities() {
await fetchAllCities()
.then(result => {
this.cities = result.data
})
},
async getGenres() {
await fetchAllGenres()
.then(result => {
this.genres = result.data
})
}
}
})

View File

@@ -142,5 +142,6 @@
"soldOut": "Ausverkauft",
"city": "Stadt",
"seatPlan": "Saalplan",
"stage": "Bühne"
"stage": "Bühne",
"filtering": "Filtern"
}

View File

@@ -142,5 +142,6 @@
"soldOut": "Sold Out",
"city": "City",
"seatPlan": "Seat Plan",
"stage": "Stage"
"stage": "Stage",
"filtering": "Filtering"
}

View File

@@ -0,0 +1,75 @@
<script setup lang="ts">
import cardView from '@/components/cardView.vue';
import outlinedButton from '@/components/outlinedButton.vue';
import { GenreModel } from '@/data/models/acts/genreModel';
import { CityModel } from '@/data/models/locations/cityModel';
import { useShoppingStore } from '@/data/stores/shoppingStore';
const shoppingStore = useShoppingStore()
shoppingStore.getCities()
shoppingStore.getGenres()
function itemPropsCity(city: CityModel) {
return {
title: city.name
}
}
function itemPropsGenre(genre: GenreModel) {
return {
title: genre.name
}
}
</script>
<template>
<card-view
variant="tonal"
:title="$t('filtering')"
subtitle="123"
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="shoppingStore.getEvents()"
>
{{ $t('filtering') }}
</outlined-button>
</v-col>
</v-row>
</card-view>
</template>

View File

@@ -25,16 +25,16 @@ shoppingStore.getEvents()
<v-row
v-if="shoppingStore.events.length > 0"
v-for="tour of shoppingStore.events"
v-for="event of shoppingStore.events"
>
<v-col>
<card-with-left-image
:title="tour.band.name + ' - ' + tour.name"
:image="'http://localhost:3000/static/tours/' + tour.image"
@click="router.push('/bands/' + tour.band.name.replaceAll(' ', '-').toLowerCase())"
:title="event.band.name + ' - ' + event.name"
:image="'http://localhost:3000/static/tours/' + event.image"
@click="router.push('/bands/' + event.band.name.replaceAll(' ', '-').toLowerCase())"
>
{{ createDateRangeString(tour) }}
<div>{{ tour.concerts.length }} {{ $t('concert', tour.concerts.length) }}</div>
{{ createDateRangeString(event) }}
<div>{{ event.concerts.length }} {{ $t('concert', event.concerts.length) }}</div>
<template #append>
<div>
@@ -44,7 +44,7 @@ shoppingStore.getEvents()
size="x-large"
/>
</div>
ab {{ lowestTicketPrice(tour) }}
ab {{ lowestTicketPrice(event) }}
</template>
</card-with-left-image>
</v-col>

View File

@@ -1,95 +0,0 @@
<script setup lang="ts">
import cardView from '@/components/cardView.vue';
import { useConcertStore } from '@/data/stores/concertStore';
const concertStore = useConcertStore()
</script>
<template>
<card-view
variant="tonal"
>
<v-row>
<v-col cols="3">
<v-select
variant="outlined"
:items="concertStore.cities"
v-model="concertStore.cityFilter"
:label="$t('city')"
density="compact"
class="mb-n5"
:clearable="concertStore.cityFilter != null && concertStore.cityFilter.id != undefined"
base-color="secondary"
color="secondary"
>
<template #item="{ props, item }">
<v-list-item
v-bind="props"
:title="item.raw.name + ' (' + item.raw.locations.length + ' ' +
$t('location', item.raw.locations.length) + ')'" />
</template>
<template #selection="{ item }">
<v-list-item :title="item.raw.name" />
</template>
</v-select>
</v-col>
<v-col cols="auto" class="d-flex justify-center align-center px-0">
<v-icon icon="mdi-chevron-right" />
</v-col>
<v-col cols="4">
<v-select
variant="outlined"
:items="concertStore.filteredLocations"
v-model="concertStore.locationFilter"
:label="$t('location', 2)"
density="compact"
:clearable="concertStore.locationFilter != null && concertStore.locationFilter.id != undefined"
:disabled="concertStore.cityFilter == null || concertStore.cityFilter.id == undefined"
class="mb-n5"
base-color="secondary"
color="secondary"
>
<template #item="{ props, item }">
<v-list-item
v-bind="props"
:title="item.raw.name + ' (' + item.raw.concerts + ' Locations)'"
/>
</template>
<template #selection="{ item }">
<v-list-item :title="item.raw.name" />
</template>
</v-select>
</v-col>
<v-divider vertical />
<v-col cols="4">
<v-select
variant="outlined"
:items="concertStore.genres"
v-model="concertStore.genreFilter"
label="Genre"
density="compact"
:clearable="concertStore.genreFilter != null && concertStore.genreFilter.id != undefined"
class="mb-n5"
base-color="secondary"
color="secondary"
>
<template #item="{ props, item }">
<v-list-item v-bind="props" :title="item.raw.name + ' (' + item.raw.bands.length +
' ' + $t('band', item.raw.bands.length) + ')'"
/>
</template>
<template #selection="{ item }">
<v-list-item :title="item.raw.name" />
</template>
</v-select>
</v-col>
</v-row>
</card-view>
</template>

View File

@@ -3,10 +3,10 @@ import HomePage from "@/pages/homePage/index.vue"
import { adminRoutes } from "./admin.routes";
import { accountRoutes } from "./account.routes";
import { systemRoutes } from "./system.routes";
import EventsPage from "@/pages/shows/eventsPage/index.vue";
import EventsPage from "@/pages/events/eventsPage/index.vue";
import LocationsPage from "@/pages/locations/locationsPage/index.vue"
import SearchPage from "@/pages/shows/searchPage/index.vue"
import BandDetailPage from "@/pages/shows/bandDetailPage/index.vue"
import SearchPage from "@/pages/events/searchPage/index.vue"
import BandDetailPage from "@/pages/events/bandDetailPage/index.vue"
import LocationDetailPage from "@/pages/locations/locationDetailPage/index.vue"
const routes = [

View File

@@ -1,6 +1,7 @@
import { RatingModel } from "@/data/models/acts/ratingModel"
import { dateToHumanReadableString } from "./dateTimeScripts"
import { TourModel } from "@/data/models/acts/tourModel"
import { EventModel } from "@/data/models/acts/eventModel"
/**
* Calculate a price based on parameters
@@ -68,14 +69,18 @@ export function createDateRangeString(tour: TourModel) {
}
}
export function lowestTicketPrice(tour: TourModel): string {
export function lowestTicketPrice(event: EventModel): string {
const priceArray : Array<number> = []
for (let concert of tour.concerts) {
for (let concert of event.concerts) {
priceArray.push(concert.price)
}
priceArray.sort()
try {
return priceArray[0].toFixed(2)
} catch(e) {
return "0"
}
}