From 6c33de3d87135843926c96a86e26ce80dcc3b4ee Mon Sep 17 00:00:00 2001 From: Tobias Zoghaib Date: Sat, 12 Oct 2024 19:40:12 +0200 Subject: [PATCH] New page for all concerts --- misc/database.drawio | 25 +++--- software/backend/database.ts | 2 +- software/backend/models/acts/band.model.ts | 14 +-- software/backend/models/acts/concert.model.ts | 19 ++-- software/backend/models/acts/genre.model.ts | 2 +- software/backend/models/acts/member.model.ts | 6 +- software/backend/models/acts/rating.model.ts | 6 +- .../models/exercises/exercise.model.ts | 14 +-- .../models/exercises/exerciseGroup.model.ts | 6 +- .../backend/models/locations/city.model.ts | 4 +- .../models/locations/location.model.ts | 12 +-- .../backend/models/locations/seat.model.ts | 2 +- .../models/locations/seatGroup.model.ts | 10 +-- software/backend/routes/band.routes.ts | 51 ++++++----- software/backend/routes/city.routes.ts | 17 +--- software/backend/routes/concert.routes.ts | 15 +++- software/backend/routes/location.routes.ts | 16 ++-- software/backend/scripts/calcScripts.ts | 41 +++++++++ software/backend/server.ts | 6 +- .../navigation/navigationPrependItems.vue | 16 +++- .../src/components/pageParts/bandListItem.vue | 16 ++-- .../components/pageParts/concertListItem.vue | 33 +++++-- .../components/pageParts/eventListItem.vue | 86 ------------------- .../components/pageParts/locationListItem.vue | 10 +-- .../components/pageParts/ticketListItem.vue | 8 +- .../components/seatPlanMap/seatPlanMap.vue | 10 ++- software/src/data/api/concertApi.ts | 8 ++ software/src/data/api/locationApi.ts | 3 +- software/src/data/models/acts/bandApiModel.ts | 11 ++- .../data/models/acts/bandDetailsApiModel.ts | 15 ++++ software/src/data/models/acts/bandModel.ts | 1 + .../src/data/models/acts/concertApiModel.ts | 4 +- software/src/data/models/acts/concertModel.ts | 5 +- .../src/data/models/acts/eventApiModel.ts | 8 -- software/src/data/models/acts/eventModel.ts | 6 -- software/src/data/models/acts/ratingModel.ts | 4 +- .../data/models/locations/locationApiModel.ts | 5 +- .../locations/locationDetailsApiModel.ts | 13 +++ software/src/data/stores/basketStore.ts | 42 ++++----- software/src/data/stores/concertStore.ts | 24 ++++++ software/src/data/stores/locationStore.ts | 36 ++++++++ software/src/data/stores/shopStore.ts | 60 +++++++++++++ software/src/data/stores/shoppingStore.ts | 2 - software/src/locales/de.json | 4 +- software/src/locales/en.json | 4 +- .../bands/bandDetailPage/ratingSection.vue | 8 +- software/src/pages/bands/bandsPage/index.vue | 2 +- .../concerts/concertBookingPage/index.vue | 6 +- .../src/pages/concerts/concertsPage/index.vue | 65 +++++++++++++- .../src/pages/events/eventsPage/index.vue | 1 - software/src/pages/homePage/index.vue | 26 +++--- .../locations/locationDetailPage/index.vue | 13 +-- .../pages/locations/locationsPage/index.vue | 43 ++++++---- software/src/pages/misc/searchPage/index.vue | 3 +- software/src/router/routes.ts | 4 +- software/src/scripts/concertScripts.ts | 63 -------------- 56 files changed, 531 insertions(+), 405 deletions(-) create mode 100644 software/backend/scripts/calcScripts.ts delete mode 100644 software/src/components/pageParts/eventListItem.vue create mode 100644 software/src/data/models/acts/bandDetailsApiModel.ts delete mode 100644 software/src/data/models/acts/eventApiModel.ts delete mode 100644 software/src/data/models/acts/eventModel.ts create mode 100644 software/src/data/models/locations/locationDetailsApiModel.ts create mode 100644 software/src/data/stores/concertStore.ts create mode 100644 software/src/data/stores/locationStore.ts create mode 100644 software/src/data/stores/shopStore.ts diff --git a/misc/database.drawio b/misc/database.drawio index e5696f3..181f373 100644 --- a/misc/database.drawio +++ b/misc/database.drawio @@ -1,6 +1,6 @@ - + @@ -140,7 +140,7 @@ - + @@ -562,8 +562,8 @@ - - + + @@ -584,7 +584,7 @@ - + @@ -599,15 +599,15 @@ - + - - + + @@ -618,7 +618,7 @@ - + @@ -645,8 +645,8 @@ - - + + @@ -838,6 +838,9 @@ + + + diff --git a/software/backend/database.ts b/software/backend/database.ts index b8beded..e60cbdf 100644 --- a/software/backend/database.ts +++ b/software/backend/database.ts @@ -43,7 +43,7 @@ export const sequelize = new Sequelize({ }) export function startDatabase() { - let recreateDb = true + let recreateDb = false // Create database and tables sequelize.sync({ force: recreateDb }) diff --git a/software/backend/models/acts/band.model.ts b/software/backend/models/acts/band.model.ts index c09d20b..0c784ca 100644 --- a/software/backend/models/acts/band.model.ts +++ b/software/backend/models/acts/band.model.ts @@ -8,16 +8,16 @@ import { Concert } from "./concert.model"; @Table({ timestamps: false }) export class Band extends Model { @Column - name: String + name: string @Column - foundingYear: Number + foundingYear: number @Column - descriptionEn: String + descriptionEn: string @Column - descriptionDe: String + descriptionDe: string @Column({ type: DataType.STRING, @@ -28,13 +28,13 @@ export class Band extends Model { this.setDataValue('images', value.join(';')) } }) - images: Array + images: Array @Column - imageMembers: String + imageMembers: string @Column - logo: String + logo: string // Relations diff --git a/software/backend/models/acts/concert.model.ts b/software/backend/models/acts/concert.model.ts index 692c30e..4b3348f 100644 --- a/software/backend/models/acts/concert.model.ts +++ b/software/backend/models/acts/concert.model.ts @@ -6,34 +6,37 @@ import { Band } from "./band.model"; @Table({ timestamps: false }) export class Concert extends Model { @Column - date: String + date: string @Column - name: String + name: string @Column - price: Number + price: number @Column - image: String + image: string @Column - inStock: Number + inStock: number @Column - offered: Boolean + offered: boolean @ForeignKey(() => Band) @Column - bandId: Number + bandId: number @ForeignKey(() => Location) @Column - locationId: Number + locationId: number // Relations + @BelongsTo(() => Band) + band: Band + @BelongsTo(() => Location) location: Location diff --git a/software/backend/models/acts/genre.model.ts b/software/backend/models/acts/genre.model.ts index 43358bd..55fb2e4 100644 --- a/software/backend/models/acts/genre.model.ts +++ b/software/backend/models/acts/genre.model.ts @@ -5,7 +5,7 @@ import { BandGenre } from "./bandGenre.model"; @Table({ timestamps: false }) export class Genre extends Model { @Column - name: String + name: string // Relations diff --git a/software/backend/models/acts/member.model.ts b/software/backend/models/acts/member.model.ts index f4dc997..725b816 100644 --- a/software/backend/models/acts/member.model.ts +++ b/software/backend/models/acts/member.model.ts @@ -4,14 +4,14 @@ import { Band } from "./band.model"; @Table({ timestamps: false }) export class Member extends Model { @Column - name: String + name: string @ForeignKey(() => Band) @Column - bandId: Number + bandId: number @Column - image: String + image: string // Relations diff --git a/software/backend/models/acts/rating.model.ts b/software/backend/models/acts/rating.model.ts index fe0bfc1..1b35879 100644 --- a/software/backend/models/acts/rating.model.ts +++ b/software/backend/models/acts/rating.model.ts @@ -7,14 +7,14 @@ export class Rating extends Model { @ForeignKey(() => Account) @Column - accountId: Number + accountId: number @Column - rating: Number + rating: number @ForeignKey(() => Band) @Column - bandId: Number + bandId: number // Relations diff --git a/software/backend/models/exercises/exercise.model.ts b/software/backend/models/exercises/exercise.model.ts index b779dea..03de7dc 100644 --- a/software/backend/models/exercises/exercise.model.ts +++ b/software/backend/models/exercises/exercise.model.ts @@ -4,26 +4,26 @@ import { ExerciseGroup } from "./exerciseGroup.model"; @Table({ timestamps: false }) export class Exercise extends Model { @Column - nameDe: String + nameDe: string @Column - nameEn: String + nameEn: string @Column - exerciseNr: Number + exerciseNr: number @Column - descriptionDe: String + descriptionDe: string @Column - descriptionEn: String + descriptionEn: string @Column - solved: Boolean + solved: boolean @ForeignKey(() => ExerciseGroup) @Column - exerciseGroupId: Number + exerciseGroupId: number // Relations diff --git a/software/backend/models/exercises/exerciseGroup.model.ts b/software/backend/models/exercises/exerciseGroup.model.ts index 70af2d1..06c985a 100644 --- a/software/backend/models/exercises/exerciseGroup.model.ts +++ b/software/backend/models/exercises/exerciseGroup.model.ts @@ -4,13 +4,13 @@ import { Exercise } from "./exercise.model"; @Table({ timestamps: false }) export class ExerciseGroup extends Model { @Column - nameDe: String + nameDe: string @Column - nameEn: String + nameEn: string @Column - groupNr: Number + groupNr: number // Relations diff --git a/software/backend/models/locations/city.model.ts b/software/backend/models/locations/city.model.ts index fe574d8..622ac5e 100644 --- a/software/backend/models/locations/city.model.ts +++ b/software/backend/models/locations/city.model.ts @@ -4,10 +4,10 @@ import { Location } from "./location.model"; @Table({ timestamps: false }) export class City extends Model { @Column - name: String + name: string @Column - country: String + country: string // Relations diff --git a/software/backend/models/locations/location.model.ts b/software/backend/models/locations/location.model.ts index 47e394b..c42a816 100644 --- a/software/backend/models/locations/location.model.ts +++ b/software/backend/models/locations/location.model.ts @@ -9,20 +9,20 @@ export class Location extends Model { urlName: string @Column - name: String + name: string @Column - address: String + address: string @ForeignKey(() => City) @Column - cityId: Number + cityId: number @Column - imageIndoor: String + imageIndoor: string @Column - imageOutdoor: String + imageOutdoor: string /** * Layout identifier of the location @@ -31,7 +31,7 @@ export class Location extends Model { * 3 = Stage in the middle of the stay area, seat places all around */ @Column - layout: Number + layout: number // Relations diff --git a/software/backend/models/locations/seat.model.ts b/software/backend/models/locations/seat.model.ts index eb106da..bf123df 100644 --- a/software/backend/models/locations/seat.model.ts +++ b/software/backend/models/locations/seat.model.ts @@ -9,7 +9,7 @@ export class Seat extends Model { @ForeignKey(() => SeatRow) @Column - seatRowId: Number + seatRowId: number // Relations diff --git a/software/backend/models/locations/seatGroup.model.ts b/software/backend/models/locations/seatGroup.model.ts index 6416a6a..63d3b46 100644 --- a/software/backend/models/locations/seatGroup.model.ts +++ b/software/backend/models/locations/seatGroup.model.ts @@ -5,21 +5,21 @@ import { SeatRow } from "./seatRow.model"; @Table({ timestamps: false }) export class SeatGroup extends Model { @Column - name: String + name: string @Column - surcharge: Number + surcharge: number @Column - capacity: Number + capacity: number @Default(false) @Column - standingArea: Boolean + standingArea: boolean @ForeignKey(() => Location) @Column - locationId: Number + locationId: number // Relations diff --git a/software/backend/routes/band.routes.ts b/software/backend/routes/band.routes.ts index fd4cd47..f6aeafa 100644 --- a/software/backend/routes/band.routes.ts +++ b/software/backend/routes/band.routes.ts @@ -7,44 +7,41 @@ import { Concert } from "../models/acts/concert.model"; import { Location } from "../models/locations/location.model"; import { City } from "../models/locations/city.model"; import { Op } from "sequelize"; +import { calcOverallRating, calcRatingValues } from "../scripts/calcScripts"; export const band = Router() // Get all bands band.get("/", (req: Request, res: Response) => { Band.findAll({ - include: [ - { - model: Member, - attributes: { - exclude: [ "id", "bandId" ] - } - }, + include: [ { model: Rating, - attributes: { - exclude: [ "id", "bandId" ] - } }, { - model: Concert, - include: [ - { - model: Location, - include: [ City ], - attributes: { - exclude: [ "id" ] - } - } - ], + model: Genre, attributes: { - exclude: [ "id", "tourId", "locationId" ] + exclude: [ "id" ] } }, - Genre + Concert ] }) .then(bands => { + for (let band of bands) { + band.dataValues["nrOfConcerts"] = band.dataValues.concerts.length + band.dataValues["rating"] = calcOverallRating(band.dataValues.ratings) + + + // Delete unnecessary Arrays + delete band.dataValues.ratings + delete band.dataValues.concerts + + for (let genre of band.dataValues.genres) { + delete genre.dataValues.BandGenre + } + } + res.status(200).json(bands) }) }) @@ -90,6 +87,16 @@ band.get("/band/:name", (req: Request, res: Response) => { } }) .then(band => { + band.dataValues["rating"] = calcOverallRating(band.dataValues.ratings) + band.dataValues["ratingValues"] = calcRatingValues(band.dataValues.ratings) + + // Delete unnecessary Arrays + delete band.dataValues.ratings + + for (let genre of band.dataValues.genres) { + delete genre.dataValues.BandGenre + } + res.status(200).json(band) }) }) diff --git a/software/backend/routes/city.routes.ts b/software/backend/routes/city.routes.ts index 893c645..ed8e52c 100644 --- a/software/backend/routes/city.routes.ts +++ b/software/backend/routes/city.routes.ts @@ -1,26 +1,11 @@ -import { Location } from "../models/locations/location.model"; import { City } from "../models/locations/city.model"; import { Request, Response, Router } from "express"; -import { Concert } from "../models/acts/concert.model"; export const city = Router() city.get("/", (req: Request, res: Response) => { - City.findAll({ - include: [ - { - model: Location, - include: [ Concert ] - } - ] - }) + City.findAll() .then(cities => { - // for (let city of cities) { - // for (let location of city.dataValues.locations) { - // location.dataValues.nrOfConcerts = location.dataValues.concerts.length - // delete location.dataValues.concerts - // } - // } res.status(200).json(cities) }) }) \ No newline at end of file diff --git a/software/backend/routes/concert.routes.ts b/software/backend/routes/concert.routes.ts index 0251939..38ee75c 100644 --- a/software/backend/routes/concert.routes.ts +++ b/software/backend/routes/concert.routes.ts @@ -7,10 +7,23 @@ import { SeatRow } from "../models/locations/seatRow.model"; import { Seat } from "../models/locations/seat.model"; import { Ticket } from "../models/ordering/ticket.model"; import { Band } from "../models/acts/band.model"; -import { Op } from "sequelize"; export const concert = Router() + +concert.get("/", (req: Request, res: Response) => { + Concert.findAll({ + include: [ Band, Location ], + order: [ + [ 'date', 'ASC' ] + ] + }) + .then(concerts => { + res.status(200).json(concerts) + }) +}) + + concert.get("/concert/:id", (req: Request, res: Response) => { Concert.findByPk(req.params.id, { include: [ diff --git a/software/backend/routes/location.routes.ts b/software/backend/routes/location.routes.ts index bb2f82a..e77b5fd 100644 --- a/software/backend/routes/location.routes.ts +++ b/software/backend/routes/location.routes.ts @@ -20,15 +20,6 @@ location.get("/", (req: Request, res: Response) => { { model: Concert, include: [ Band ], - }, - { - model: SeatGroup, - include: [ - { - model: SeatRow, - include: [ Seat ] - } - ] } ], attributes: { @@ -46,6 +37,12 @@ location.get("/", (req: Request, res: Response) => { }) } + for (let location of locations) { + location.dataValues["nrOfConcerts"] = location.dataValues.concerts.length + delete location.dataValues.concerts + } + + // Limit number of items if (count != undefined) { locations.splice(Number(count)) } @@ -86,7 +83,6 @@ location.get("/location/:urlName", (req: Request, res: Response) => { } } - res.status(200).json(location) }) }) diff --git a/software/backend/scripts/calcScripts.ts b/software/backend/scripts/calcScripts.ts new file mode 100644 index 0000000..6b17838 --- /dev/null +++ b/software/backend/scripts/calcScripts.ts @@ -0,0 +1,41 @@ +import { Rating } from "../models/acts/rating.model"; + +/** + * Calculate the average of an Array of ratings + * + * @param ratings Array of ratings + * + * @returns Average rating as number + */ +export function calcOverallRating(ratings: Array): number { + let sum = 0 + + for (let rating of ratings) { + sum += rating.dataValues.rating + } + + return sum / ratings.length +} + +/** + * Classifies a bunch of ratings to groups from 1 to 5 stars + * + * @param ratings Array of RatingModels + * + * @returns Array of Objects: { value: number[1-5], count: number } + */ +export function calcRatingValues(ratings: Array) { + let ratingValues = [ + { value: 1, count: 0 }, + { value: 2, count: 0 }, + { value: 3, count: 0 }, + { value: 4, count: 0 }, + { value: 5, count: 0 } + ] + + for (let rating of ratings) { + ratingValues[rating.dataValues.rating - 1].count += 1 + } + + return ratingValues +} \ No newline at end of file diff --git a/software/backend/server.ts b/software/backend/server.ts index 625247d..73445fc 100644 --- a/software/backend/server.ts +++ b/software/backend/server.ts @@ -29,9 +29,9 @@ const path = require('path') app.use('/static', express.static(path.join(__dirname, 'images'))) // Add delay for more realistic response times -app.use((req, res, next) => { - setTimeout(next, Math.floor((Math.random () * 2000) + 100)) -}) +// app.use((req, res, next) => { +// setTimeout(next, Math.floor((Math.random () * 2000) + 100)) +// }) // Routes app.use("/api", api) diff --git a/software/src/components/navigation/navigationPrependItems.vue b/software/src/components/navigation/navigationPrependItems.vue index 9a4464d..ae4205b 100644 --- a/software/src/components/navigation/navigationPrependItems.vue +++ b/software/src/components/navigation/navigationPrependItems.vue @@ -10,19 +10,29 @@ + {{ $t('allBands', 2) }} + + + + + - {{ $t('allEvents', 2) }} + {{ $t('allConcerts', 2) }} import { BandModel } from '@/data/models/acts/bandModel'; -import { lowestTicketPrice, lowestTicketPriceEvents } from '@/scripts/concertScripts'; +import { lowestTicketPrice } from '@/scripts/concertScripts'; import cardViewHorizontal from '@/components/basics/cardViewHorizontal.vue'; -import { EventModel } from '@/data/models/acts/eventModel'; import { useRouter } from 'vue-router'; import { GenreModel } from '@/data/models/acts/genreModel'; -import { EventApiModel } from '@/data/models/acts/eventApiModel'; +import { ConcertModel } from '@/data/models/acts/concertModel'; const router = useRouter() @@ -16,9 +15,8 @@ defineProps({ required: true }, - /** Events where the band participate */ - events: { - type: Array, + concerts: { + type: Array, required: true }, @@ -37,7 +35,7 @@ defineProps({ v-if="!loading" :title="band.name" :image="'http://localhost:3000/static/' + band.logo" - @click="router.push('/bands/' + band.name.replaceAll(' ', '-').toLowerCase())" + @click="router.push('/bands/details/' + band.name.replaceAll(' ', '-').toLowerCase())" >