Display all bands grouped by genre, create m:n association between Band and Genre in database
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
"descriptionDe": "Red Hot Chili Peppers (Abkürzung: RHCP) ist eine 1983 gegründete US-amerikanische Funk- und Alternative-Rockband. Sie zählt zu den kommerziell erfolgreichsten Vertretern des Crossover. Ihr Album Blood Sugar Sex Magik gilt als eines der bedeutendsten dieses Genres.",
|
||||
"images": [ "red-hot-chili-peppers-1.jpg" ],
|
||||
"logo": "red-hot-chili-peppers-logo.png",
|
||||
"genreId": 0,
|
||||
"genreId": [ 0, 2, 3 ],
|
||||
"members": [
|
||||
{
|
||||
"name": "Anthony Kiedis",
|
||||
@@ -47,7 +47,7 @@
|
||||
"descriptionDe": "Radiohead ist eine britische Rockband, die 1985 in Oxford, England gegründet wurde. Die Band besteht aus Thom Yorke (Gesang, Rhythmusgitarre, Piano), Jonny Greenwood (Lead-Gitarre, Keyboard, Ondes Martenot), Colin Greenwood (E-Bass, Keyboard), Ed O’Brien (Gitarre, Backgroundvocals) und Phil Selway (Schlagzeug, Backgroundvocals). Radioheads experimenteller Ansatz gilt als Wegbereiter für den Sound des Alternative Rocks.",
|
||||
"images": [ "radiohead-1.jpg" ],
|
||||
"logo": "radiohead-logo.jpg",
|
||||
"genreId": 1,
|
||||
"genreId": [ 1, 2, 4, 5, 6 ],
|
||||
"members": [
|
||||
{
|
||||
"name": "Thom Yorke",
|
||||
@@ -96,7 +96,7 @@
|
||||
"descriptionDe": "Die Arctic Monkeys sind eine vierköpfige britische Alternative-Rock-Band mit Einflüssen aus Post-Punk und Garage Rock. Sie wurde 2002 im englischen Sheffield gegründet und veröffentlichte 2006 ihr Debütalbum, das Platz eins der britischen Charts erreichte. 2007, 2009, 2011, 2013 und 2018 erschienen jeweils weitere Alben der Musikgruppe, die alle ebenfalls die Spitzenposition in Großbritannien erreichten. Aktuelles Album der Band ist das am 21. Oktober 2022 erschienene The Car.",
|
||||
"images": [ "arctic-monkeys-1.jpg", "arctic-monkeys-2.jpg" ],
|
||||
"logo": "arctic-monkeys-logo.png",
|
||||
"genreId": 2,
|
||||
"genreId": [ 2, 7, 8 ],
|
||||
"members": [
|
||||
{
|
||||
"name": "Glyn Jones",
|
||||
@@ -150,7 +150,7 @@
|
||||
"descriptionDe": "Coldplay ist eine britische Pop-Rock-Band, bestehend aus Chris Martin, Jonny Buckland, Will Champion und Guy Berryman. Sie ist eine der weltweit erfolgreichsten Bands der 2000er-Jahre und hat knapp 80 Millionen Tonträger weltweit verkauft, davon 50 Millionen Alben.",
|
||||
"images": [ "coldplay-1.jpg" ],
|
||||
"logo": "coldplay-logo.jpg",
|
||||
"genreId": 2,
|
||||
"genreId": [ 2, 9 ],
|
||||
"members": [
|
||||
{
|
||||
"name": "Chris Martin",
|
||||
@@ -174,7 +174,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Phil Harvey",
|
||||
"bandId": 2,
|
||||
"bandId": 3,
|
||||
"image": "phil-harvey.jpg"
|
||||
}
|
||||
],
|
||||
@@ -199,7 +199,7 @@
|
||||
"descriptionDe": "Foo Fighters ist eine US-amerikanische Rockband. Prominentestes Mitglied und Band-Gründer ist der ehemalige Nirvana-Schlagzeuger Dave Grohl. ",
|
||||
"images": [ "foo-fighters-1.jpg" ],
|
||||
"logo": "foo-fighters-logo.png",
|
||||
"genreId": 2,
|
||||
"genreId": [ 2, 10 ],
|
||||
"members": [
|
||||
{
|
||||
"name": "Dave Grohl",
|
||||
|
||||
@@ -2,15 +2,47 @@
|
||||
"data": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Funk rock"
|
||||
"name": "Funk Rock"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Art rock"
|
||||
"name": "Art Rock"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Alternative Rock"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Crossover"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Electronica"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Post-Rock"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Britpop"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Post-Punk"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Garage Rock"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Pop-Rock"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Post-Grunge"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import { Member } from "./models/acts/member.model"
|
||||
import { Rating } from "./models/acts/rating.model"
|
||||
import { Tour } from "./models/acts/tour.model"
|
||||
import { City } from "./models/acts/city.model"
|
||||
import { BandGenre } from "./models/acts/bandGenre.model"
|
||||
|
||||
const dbName = "database"
|
||||
const dbUser = "root"
|
||||
@@ -30,7 +31,7 @@ export const sequelize = new Sequelize({
|
||||
storage: "database.sqlite",
|
||||
models: [
|
||||
AccountRole, Account, Payment, Address,
|
||||
City, Location, Genre, Band, Rating, Member, Tour, Show,
|
||||
City, Location, Genre, Band, BandGenre, Rating, Member, Tour, Show,
|
||||
Order, OrderItem
|
||||
]
|
||||
})
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { BelongsTo, Column, DataType, ForeignKey, HasMany, Model, Table } from "sequelize-typescript";
|
||||
import { BelongsTo, BelongsToMany, Column, DataType, ForeignKey, HasMany, Model, Table } from "sequelize-typescript";
|
||||
import { Member } from "./member.model";
|
||||
import { Genre } from "./genre.model";
|
||||
import { Rating } from "./rating.model";
|
||||
import { Tour } from "./tour.model";
|
||||
import { BandGenre } from "./bandGenre.model";
|
||||
|
||||
@Table({ timestamps: false })
|
||||
export class Band extends Model {
|
||||
@@ -32,10 +33,6 @@ export class Band extends Model {
|
||||
@Column
|
||||
logo: String
|
||||
|
||||
@ForeignKey(() => Genre)
|
||||
@Column
|
||||
genreId: Number
|
||||
|
||||
|
||||
// Relations
|
||||
|
||||
@@ -48,6 +45,6 @@ export class Band extends Model {
|
||||
@HasMany(() => Tour)
|
||||
tours: Tour[]
|
||||
|
||||
@BelongsTo(() => Genre)
|
||||
genre: Genre
|
||||
@BelongsToMany(() => Genre, () => BandGenre)
|
||||
genres: Genre[]
|
||||
}
|
||||
16
software/backend/models/acts/bandGenre.model.ts
Normal file
16
software/backend/models/acts/bandGenre.model.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table, Unique } from "sequelize-typescript";
|
||||
import { Genre } from "./genre.model";
|
||||
import { Band } from "./band.model";
|
||||
|
||||
@Table({ timestamps: false })
|
||||
export class BandGenre extends Model {
|
||||
@PrimaryKey
|
||||
@Column({autoIncrement: true})
|
||||
declare id: number
|
||||
|
||||
@ForeignKey(() => Genre)
|
||||
genreId: number
|
||||
|
||||
@ForeignKey(() => Band)
|
||||
bandId: number
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Column, HasMany, Model, Table } from "sequelize-typescript";
|
||||
import { BelongsToMany, Column, Model, Table } from "sequelize-typescript";
|
||||
import { Band } from "./band.model";
|
||||
import { BandGenre } from "./bandGenre.model";
|
||||
|
||||
@Table({ timestamps: false })
|
||||
export class Genre extends Model {
|
||||
@@ -9,6 +10,6 @@ export class Genre extends Model {
|
||||
|
||||
// Relations
|
||||
|
||||
@HasMany(() => Band)
|
||||
@BelongsToMany(() => Band, () => BandGenre)
|
||||
bands: Band[]
|
||||
}
|
||||
@@ -1,10 +1,19 @@
|
||||
import { Rating } from "../models/acts/rating.model";
|
||||
import { Band } from "../models/acts/band.model";
|
||||
import { Genre } from "../models/acts/genre.model";
|
||||
import { Request, Response, Router } from "express";
|
||||
|
||||
export const genre = Router()
|
||||
|
||||
genre.get("/", (req: Request, res: Response) => {
|
||||
Genre.findAll()
|
||||
Genre.findAll({
|
||||
include: [
|
||||
{
|
||||
model: Band,
|
||||
include: [ Rating ]
|
||||
}
|
||||
]
|
||||
})
|
||||
.then(genres => {
|
||||
res.status(200).json(genres)
|
||||
})
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Location } from '../models/acts/location.model'
|
||||
import { Show } from '../models/acts/show.model'
|
||||
import { Tour } from '../models/acts/tour.model'
|
||||
import { City } from '../models/acts/city.model'
|
||||
import { BandGenre } from '../models/acts/bandGenre.model'
|
||||
|
||||
import accounts from "./../data/accounts.json"
|
||||
import orders from "./../data/orders.json"
|
||||
@@ -69,8 +70,17 @@ export async function prepopulateDatabase() {
|
||||
|
||||
|
||||
for(let band of bands.data) {
|
||||
// Create a band dataset
|
||||
await Band.create(band)
|
||||
.then(dataset => {
|
||||
.then(async dataset => {
|
||||
// Create the m:n associations for the genres
|
||||
for (let genreId of band.genreId) {
|
||||
await BandGenre.create({
|
||||
genreId: Number(genreId),
|
||||
bandId: dataset.dataValues.id
|
||||
})
|
||||
}
|
||||
|
||||
Rating.bulkCreate(band.ratings)
|
||||
Member.bulkCreate(band.members)
|
||||
})
|
||||
|
||||
@@ -65,16 +65,10 @@ watch(() => preferencesStore.language, () => {
|
||||
|
||||
<!-- Here changes the router the content -->
|
||||
<v-container max-width="1200" class="pt-0 pb-5">
|
||||
<v-sheet>
|
||||
<v-sheet color="sheet">
|
||||
<router-view></router-view>
|
||||
</v-sheet>
|
||||
</v-container>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.v-sheet {
|
||||
background-color: #333333;
|
||||
}
|
||||
</style>
|
||||
@@ -7,7 +7,7 @@ defineProps({
|
||||
|
||||
<template>
|
||||
<v-card
|
||||
variant="outlined"
|
||||
variant="tonal"
|
||||
link
|
||||
>
|
||||
<v-img
|
||||
|
||||
@@ -15,7 +15,20 @@
|
||||
height="100%"
|
||||
:rounded="false"
|
||||
>
|
||||
{{ $t('menu.shopping.allEvents', 2) }}
|
||||
{{ $t('menu.allEvents', 2) }}
|
||||
</v-btn>
|
||||
|
||||
<v-divider vertical />
|
||||
|
||||
|
||||
<v-btn
|
||||
variant="text"
|
||||
to="/shows/bands"
|
||||
prepend-icon="mdi-music-clef-treble"
|
||||
height="100%"
|
||||
:rounded="false"
|
||||
>
|
||||
{{ $t('menu.allBands') }}
|
||||
</v-btn>
|
||||
|
||||
<v-divider vertical />
|
||||
@@ -28,20 +41,7 @@
|
||||
height="100%"
|
||||
:rounded="false"
|
||||
>
|
||||
{{ $t('menu.shopping.allLocations', 2) }}
|
||||
</v-btn>
|
||||
|
||||
<v-divider vertical />
|
||||
|
||||
|
||||
<v-btn
|
||||
variant="text"
|
||||
to="/shows/genres"
|
||||
prepend-icon="mdi-music-clef-treble"
|
||||
height="100%"
|
||||
:rounded="false"
|
||||
>
|
||||
{{ $t('menu.shopping.allGenres', 2) }}
|
||||
{{ $t('menu.allLocations', 2) }}
|
||||
</v-btn>
|
||||
|
||||
<v-divider vertical />
|
||||
|
||||
@@ -3,7 +3,7 @@ defineProps({
|
||||
prependIcon: String,
|
||||
color: {
|
||||
type: String,
|
||||
default: "primary"
|
||||
default: "secondary"
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -3,13 +3,6 @@ defineProps({
|
||||
title: String,
|
||||
image: String
|
||||
})
|
||||
|
||||
function backgroundStyle(image: string) {
|
||||
return {
|
||||
"background-image": 'http://localhost:3000/static/cities/hannover.jpg',
|
||||
height: `100px`
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -29,7 +22,7 @@ function backgroundStyle(image: string) {
|
||||
<v-spacer />
|
||||
|
||||
<v-col class="v-col-auto">
|
||||
<span class="text-h3" style="color: white;">{{ title }}</span>
|
||||
<span class="text-h4" style="color: white;">{{ title }}</span>
|
||||
</v-col>
|
||||
|
||||
<v-spacer />
|
||||
@@ -44,7 +37,7 @@ function backgroundStyle(image: string) {
|
||||
</v-col>
|
||||
|
||||
<v-col class="v-col-auto">
|
||||
<span class="text-h6">{{ title }}</span>
|
||||
<span class="text-h4">{{ title }}</span>
|
||||
</v-col>
|
||||
|
||||
<v-col class="d-flex justify-center align-center">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import axios from "axios"
|
||||
import { OrderModel } from "../models/orderModel"
|
||||
import { BasketItemModel } from "../models/basketItemModel"
|
||||
import { calcPrice } from "@/scripts/productScripts"
|
||||
|
||||
const BASE_URL = "http://localhost:3000/orders"
|
||||
|
||||
@@ -17,13 +16,13 @@ export async function addOrder(
|
||||
) {
|
||||
let orderItems = []
|
||||
|
||||
for (let basketItem of basketItems) {
|
||||
orderItems.push({
|
||||
productId: basketItem.product.id,
|
||||
quantity: basketItem.quantity,
|
||||
orderPrice: calcPrice(basketItem.product.price, basketItem.product.discount)
|
||||
})
|
||||
}
|
||||
// for (let basketItem of basketItems) {
|
||||
// orderItems.push({
|
||||
// productId: basketItem.product.id,
|
||||
// quantity: basketItem.quantity,
|
||||
// orderPrice: calcPrice(basketItem.product.price, basketItem.product.discount)
|
||||
// })
|
||||
// }
|
||||
|
||||
return axios.post(BASE_URL, {
|
||||
accountId: accountId,
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
export enum ThemeEnum {
|
||||
DARKRED = "darkRed",
|
||||
LIGHTRED = "lightRed",
|
||||
DARKBLUE = "darkBlue",
|
||||
LIGHTBLUE = "lightBlue",
|
||||
DARKGREEN = "darkGreen",
|
||||
LIGHTGREEN = "lightGreen"
|
||||
DARKBLUE = "dark",
|
||||
LIGHTBLUE = "light",
|
||||
|
||||
}
|
||||
@@ -10,7 +10,9 @@ export class BandModel {
|
||||
descriptionDe: string
|
||||
images: Array<string>
|
||||
logo: string
|
||||
genre: GenreModel
|
||||
ratings: Array<RatingModel>
|
||||
members: Array<MemberModel>
|
||||
genre: {
|
||||
name: string
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,19 @@
|
||||
import { MemberModel } from "./memberModel"
|
||||
import { RatingModel } from "./ratingModel"
|
||||
|
||||
export class GenreModel {
|
||||
id: number
|
||||
name: string
|
||||
bands: Array<
|
||||
{
|
||||
name: string
|
||||
foundingYear: number
|
||||
descriptionEn: string
|
||||
descriptionDe: string
|
||||
images: Array<string>
|
||||
logo: string
|
||||
ratings: Array<RatingModel>
|
||||
members: Array<MemberModel>
|
||||
}
|
||||
>
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import { useFeedbackStore } from "./feedbackStore";
|
||||
import { loginAccount, registerAccount, updateAccount } from "../api/accountApi";
|
||||
import { getUserOrders } from "../api/orderApi";
|
||||
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
||||
import { calcPrice } from "@/scripts/productScripts";
|
||||
import { AddressModel } from "../models/addressModel";
|
||||
import { PaymentModel } from "../models/paymentModel";
|
||||
|
||||
@@ -86,9 +85,9 @@ export const useAccountStore = defineStore("accountStore", {
|
||||
let totalPrice = 0
|
||||
let order: OrderModel = this.orders.find((order: OrderModel) => order.id == orderId)
|
||||
|
||||
for (let item of order.orderItems) {
|
||||
totalPrice += calcPrice(item.orderPrice, 0, item.quantity)
|
||||
}
|
||||
// for (let item of order.orderItems) {
|
||||
// totalPrice += calcPrice(item.orderPrice, 0, item.quantity)
|
||||
// }
|
||||
|
||||
return Math.round(totalPrice * 100) / 100
|
||||
},
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
import { calcPrice } from "@/scripts/productScripts";
|
||||
import { BasketItemModel } from "../models/basketItemModel";
|
||||
import { useFeedbackStore } from "./feedbackStore";
|
||||
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
||||
@@ -26,9 +25,9 @@ export const useBasketStore = defineStore('basketStore', {
|
||||
getTotalPrice() {
|
||||
let result = 0
|
||||
|
||||
for (let item of this.itemsInBasket) {
|
||||
result += calcPrice(item.product.price, item.product.discount, item.quantity)
|
||||
}
|
||||
// for (let item of this.itemsInBasket) {
|
||||
// result += calcPrice(item.product.price, item.product.discount, item.quantity)
|
||||
// }
|
||||
|
||||
return Math.round(result * 100) / 100
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"menu": {
|
||||
"shopping": {
|
||||
"allEvents": "Alle Events",
|
||||
"allLocations": "Alle Orte",
|
||||
"allGenres": "Alle Genres"
|
||||
}
|
||||
"allLocations": "Alle Veranstaltungsorte",
|
||||
"allBands": "Alle Bands"
|
||||
},
|
||||
"shows": {
|
||||
"tickets": "Ticket | Tickets"
|
||||
"tickets": "Ticket | Tickets",
|
||||
"topEvents": "Top Events",
|
||||
"topBands": "Top Bands",
|
||||
"topLocations": "Top Veranstaltungsorte"
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"menu": {
|
||||
"shopping": {
|
||||
"allEvents": "All Events",
|
||||
"allLocations": "All Locations",
|
||||
"allGenres": "All Genres"
|
||||
}
|
||||
"allBands": "All Bands"
|
||||
},
|
||||
"shows": {
|
||||
"tickets": "Ticket | Tickets"
|
||||
"tickets": "Ticket | Tickets",
|
||||
"topEvents": "Top Events",
|
||||
"topBands": "Top Bands",
|
||||
"topLocations": "Top Locations"
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { BasketItemModel } from '@/data/models/basketItemModel';
|
||||
import { useBasketStore } from '@/data/stores/basketStore';
|
||||
import { calcPrice } from '@/scripts/productScripts';
|
||||
|
||||
const basketStore = useBasketStore()
|
||||
|
||||
@@ -58,7 +57,7 @@ function editQuantity(basketItem: BasketItemModel) {
|
||||
</td>
|
||||
|
||||
<!-- Price per unit -->
|
||||
<td class="text-right">
|
||||
<!-- <td class="text-right">
|
||||
<div v-if="basketItem.product.discount > 0">
|
||||
<strong class="font-weight-bold text-body-1 text-red-lighten-1">
|
||||
{{ calcPrice(basketItem.product.price, basketItem.product.discount) }} €
|
||||
@@ -70,7 +69,7 @@ function editQuantity(basketItem: BasketItemModel) {
|
||||
<div v-else>
|
||||
{{ basketItem.product.price }} €
|
||||
</div>
|
||||
</td>
|
||||
</td> -->
|
||||
|
||||
<!-- Total price -->
|
||||
<td class="text-right">
|
||||
|
||||
@@ -3,19 +3,11 @@ 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';
|
||||
import { calcRating } from '@/scripts/showsScripts';
|
||||
import OutlinedButton from '@/components/outlinedButton.vue';
|
||||
import router from '@/plugins/router';
|
||||
|
||||
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>
|
||||
@@ -24,7 +16,7 @@ function calcRating(ratings: Array<RatingModel>) {
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider title="Top Tours" />
|
||||
<section-divider :title="$t('shows.topEvents')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -41,7 +33,20 @@ function calcRating(ratings: Array<RatingModel>) {
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider title="Top Bands" />
|
||||
<outlined-button
|
||||
append-icon="mdi-chevron-right"
|
||||
@click="router.push('/shows/events')"
|
||||
block
|
||||
>
|
||||
{{ $t('menu.allEvents') }}
|
||||
</outlined-button>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="$t('shows.topBands')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -69,21 +74,46 @@ function calcRating(ratings: Array<RatingModel>) {
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider title="Top Locations" />
|
||||
<outlined-button
|
||||
append-icon="mdi-chevron-right"
|
||||
@click="router.push('/shows/bands')"
|
||||
block
|
||||
>
|
||||
{{ $t('menu.allBands') }}
|
||||
</outlined-button>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="$t('shows.topLocations')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col v-for="location in showStore.locations" cols="3">
|
||||
<v-col v-for="i in 4" cols="3">
|
||||
<card-with-top-image
|
||||
:image="'locations/' + location.image"
|
||||
:title="location.name"
|
||||
:image="'locations/' + showStore.locations[i + 2].image"
|
||||
:title="showStore.locations[i + 2].name"
|
||||
>
|
||||
{{ location.address }}
|
||||
{{ location.city.name }}, {{ location.city.country }}
|
||||
<div>{{ showStore.locations[i + 2].address }}</div>
|
||||
{{ showStore.locations[i + 2].city.name }}, {{ showStore.locations[i + 2].city.country }}
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<outlined-button
|
||||
append-icon="mdi-chevron-right"
|
||||
@click="router.push('/shows/locations')"
|
||||
block
|
||||
>
|
||||
{{ $t('menu.allLocations') }}
|
||||
</outlined-button>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
|
||||
42
software/src/pages/shows/bandsPage/index.vue
Normal file
42
software/src/pages/shows/bandsPage/index.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import sectionDivider from '@/components/sectionDivider.vue';
|
||||
import { useShowStore } from '@/data/stores/showStore';
|
||||
import cardWithTopImage from '@/components/cardWithTopImage.vue';
|
||||
import { calcRating } from '@/scripts/showsScripts';
|
||||
|
||||
const showStore = useShowStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container>
|
||||
<div v-for="genre in showStore.genres">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider
|
||||
:title="genre.name"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col v-for="band in genre.bands" cols="3">
|
||||
<card-with-top-image
|
||||
:image="'bands/' + band.images[0]"
|
||||
:title="band.name"
|
||||
>
|
||||
<div class="d-flex justify-center pt-3">
|
||||
<v-rating
|
||||
density="compact"
|
||||
readonly
|
||||
size="large"
|
||||
half-increments
|
||||
active-color="orange"
|
||||
:model-value="calcRating(band.ratings)"
|
||||
/>
|
||||
</div>
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
@@ -1,18 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import sectionDivider from '@/components/sectionDivider.vue';
|
||||
import { useShowStore } from '@/data/stores/showStore';
|
||||
|
||||
const showStore = useShowStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container>
|
||||
<div v-for="genre in showStore.genres">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="genre.name" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
@@ -13,7 +13,6 @@ const showStore = useShowStore()
|
||||
<v-col>
|
||||
<section-divider
|
||||
:title="city.name"
|
||||
:image="'cities/' + city.image"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -13,48 +13,22 @@ const vuetify = createVuetify({
|
||||
theme: {
|
||||
defaultTheme: 'dark',
|
||||
themes: {
|
||||
darkRed: {
|
||||
dark: true,
|
||||
colors: {
|
||||
primary: colors.red.darken1,
|
||||
secondary: colors.red.lighten2
|
||||
}
|
||||
},
|
||||
lightRed: {
|
||||
dark: false,
|
||||
colors: {
|
||||
primary: colors.red.darken1,
|
||||
secondary: colors.red.darken4
|
||||
}
|
||||
},
|
||||
darkBlue: {
|
||||
dark: {
|
||||
dark: true,
|
||||
colors: {
|
||||
primary: colors.blue.darken4,
|
||||
secondary: colors.blue.lighten2
|
||||
secondary: colors.blue.lighten2,
|
||||
sheet: colors.grey.darken4
|
||||
}
|
||||
},
|
||||
lightBlue: {
|
||||
light: {
|
||||
dark: false,
|
||||
colors: {
|
||||
primary: colors.blue.darken1,
|
||||
secondary: colors.blue.darken4
|
||||
primary: colors.blue.darken4,
|
||||
secondary: colors.blue.darken2,
|
||||
sheet: colors.grey.lighten3
|
||||
}
|
||||
},
|
||||
darkGreen: {
|
||||
dark: true,
|
||||
colors: {
|
||||
primary: colors.green.darken1,
|
||||
secondary: colors.green.lighten2
|
||||
}
|
||||
},
|
||||
lightGreen: {
|
||||
dark: false,
|
||||
colors: {
|
||||
primary: colors.green.darken1,
|
||||
secondary: colors.green.darken4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import EventsPage from "@/pages/shows/eventsPage/index.vue";
|
||||
import GenresPage from "@/pages/shows/genresPage/index.vue";
|
||||
import BandsPage from "@/pages/shows/bandsPage/index.vue";
|
||||
import LocationsPage from "@/pages/shows/locationsPage/index.vue"
|
||||
import SearchPage from "@/pages/shows/searchPage/index.vue"
|
||||
|
||||
export const showRoutes = [
|
||||
{ path: '/shows/events', component: EventsPage },
|
||||
{ path: '/shows/genres', component: GenresPage },
|
||||
{ path: '/shows/bands', component: BandsPage },
|
||||
{ path: '/shows/locations', component: LocationsPage },
|
||||
{ path: '/shows/search', component: SearchPage },
|
||||
]
|
||||
@@ -1,3 +1,5 @@
|
||||
import { RatingModel } from "@/data/models/ratingModel"
|
||||
|
||||
/**
|
||||
* Calculate a price based on parameters
|
||||
*
|
||||
@@ -10,3 +12,20 @@
|
||||
export function calcPrice(price: number, discount: number = 0, quantity: number = 1): number {
|
||||
return Math.round(quantity * price * ((100 - discount) / 100) * 100) / 100
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the average of an Array of ratings
|
||||
*
|
||||
* @param ratings Array of ratings
|
||||
*
|
||||
* @returns Average rating as number
|
||||
*/
|
||||
export function calcRating(ratings: Array<RatingModel>) {
|
||||
let sum = 0
|
||||
|
||||
for (let rating of ratings) {
|
||||
sum += rating.rating
|
||||
}
|
||||
|
||||
return sum / ratings.length
|
||||
}
|
||||
Reference in New Issue
Block a user