New locationDetailPage displays concert in a location, new datasets, images, URL path changed
@@ -426,6 +426,59 @@
|
||||
"bandId": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Muse",
|
||||
"foundingYear": 1994,
|
||||
"descriptionEn": "Muse are an English rock band from Teignmouth, Devon, formed in 1994. The band consists of Matt Bellamy (lead vocals, guitar, keyboards), Chris Wolstenholme (bass guitar, backing vocals), and Dominic Howard (drums, percussion).",
|
||||
"descriptionDe": "Muse ist eine britische Rockband, die 1994 in Teignmouth, England gegründet wurde. Die Band besteht aus Matthew Bellamy (Gesang, Gitarre, Klavier und Synthesizers), Chris Wolstenholme (E-Bass, Gesang, Synthesizer) und Dominic Howard (Schlagzeug und Perkussion). Muse verbindet stilistisch Alternative, Hard und Progressive Rock sowie Electronica mit Elementen klassischer Musik zu Rockballaden und wird dem Subgenre New Prog zugeordnet.",
|
||||
"images": [
|
||||
"muse-1.jpg",
|
||||
"muse-2.jpg",
|
||||
"muse-3.jpg"
|
||||
],
|
||||
"imageMembers": "muse-members.jpg",
|
||||
"logo": "muse-logo.jpg",
|
||||
"genreId": [
|
||||
2,
|
||||
15,
|
||||
16
|
||||
],
|
||||
"members": [
|
||||
{
|
||||
"name": "Matthew Bellamy",
|
||||
"bandId": 7,
|
||||
"image": "matthew-bellamy.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Dominic Howard",
|
||||
"bandId": 7,
|
||||
"image": "dominic-howard.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Chris Wolstenholme",
|
||||
"bandId": 7,
|
||||
"image": "christ-wolstenholme.jpg"
|
||||
}
|
||||
],
|
||||
"ratings": [
|
||||
{
|
||||
"accountId": 0,
|
||||
"rating": 5,
|
||||
"bandId": 7
|
||||
},
|
||||
{
|
||||
"accountId": 1,
|
||||
"rating": 4,
|
||||
"bandId": 7
|
||||
},
|
||||
{
|
||||
"accountId": 2,
|
||||
"rating": 4,
|
||||
"bandId": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
"id": 0,
|
||||
"name": "Hannover",
|
||||
"country": "Germany",
|
||||
"image": "hannover.jpg",
|
||||
"locations": [
|
||||
{
|
||||
"id": 0,
|
||||
@@ -40,7 +39,6 @@
|
||||
"id": 1,
|
||||
"name": "München",
|
||||
"country": "Germany",
|
||||
"image": "munich.jpg",
|
||||
"locations": [
|
||||
{
|
||||
"id": 4,
|
||||
@@ -69,7 +67,6 @@
|
||||
"id": 2,
|
||||
"name": "Hamburg",
|
||||
"country": "Germany",
|
||||
"image": "hamburg.jpg",
|
||||
"locations": [
|
||||
{
|
||||
"id": 7,
|
||||
@@ -105,7 +102,6 @@
|
||||
"id": 3,
|
||||
"name": "Berlin",
|
||||
"country": "Germany",
|
||||
"image": "berlin.jpg",
|
||||
"locations": [
|
||||
{
|
||||
"id": 11,
|
||||
|
||||
@@ -59,6 +59,14 @@
|
||||
{
|
||||
"id": 14,
|
||||
"name": "Bluesrock"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"name": "New Prog"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"name": "Hard Rock"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -11,12 +11,20 @@
|
||||
"id": 0,
|
||||
"date": "2024-10-18",
|
||||
"price": 92,
|
||||
"inStock": 930,
|
||||
"inStock": 0,
|
||||
"locationId": 0,
|
||||
"tourId": 0
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"date": "2024-10-19",
|
||||
"price": 92,
|
||||
"inStock": 170,
|
||||
"locationId": 0,
|
||||
"tourId": 0
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"date": "2024-10-23",
|
||||
"price": 119.90,
|
||||
"inStock": 8736,
|
||||
@@ -24,7 +32,7 @@
|
||||
"tourId": 0
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"id": 3,
|
||||
"date": "2024-10-26",
|
||||
"price": 114.90,
|
||||
"inStock": 2793,
|
||||
@@ -32,7 +40,7 @@
|
||||
"tourId": 0
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"id": 4,
|
||||
"date": "2024-11-02",
|
||||
"price": 124.90,
|
||||
"inStock": 3079,
|
||||
@@ -49,7 +57,7 @@
|
||||
"image": "the-bends-tour.jpg",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 4,
|
||||
"id": 5,
|
||||
"date": "2024-11-30",
|
||||
"price": 108,
|
||||
"inStock": 1200,
|
||||
@@ -57,7 +65,7 @@
|
||||
"tourId": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"id": 6,
|
||||
"date": "2024-12-01",
|
||||
"price": 104,
|
||||
"inStock": 1800,
|
||||
@@ -65,7 +73,7 @@
|
||||
"tourId": 1
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"id": 7,
|
||||
"date": "2024-12-07",
|
||||
"price": 99.90,
|
||||
"inStock": 2438,
|
||||
@@ -82,7 +90,7 @@
|
||||
"image": "european-tour-arctic-monkeys.jpg",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 7,
|
||||
"id": 8,
|
||||
"date": "2025-01-21",
|
||||
"price": 67.90,
|
||||
"inStock": 994,
|
||||
@@ -90,7 +98,7 @@
|
||||
"tourId": 2
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"id": 9,
|
||||
"date": "2024-11-15",
|
||||
"price": 79.90,
|
||||
"inStock": 1073,
|
||||
@@ -107,7 +115,7 @@
|
||||
"image": "music-of-the-spheres.png",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 9,
|
||||
"id": 10,
|
||||
"date": "2024-12-07",
|
||||
"price": 124.90,
|
||||
"inStock": 765,
|
||||
@@ -115,7 +123,7 @@
|
||||
"tourId": 3
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"id": 11,
|
||||
"date": "2025-01-17",
|
||||
"price": 129.90,
|
||||
"inStock": 989,
|
||||
@@ -123,7 +131,7 @@
|
||||
"tourId": 3
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"id": 12,
|
||||
"date": "2025-02-01",
|
||||
"price": 134.90,
|
||||
"inStock": 827,
|
||||
@@ -140,7 +148,7 @@
|
||||
"image": "but-here-we-are.jpg",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 12,
|
||||
"id": 13,
|
||||
"date": "2024-12-05",
|
||||
"price": 80,
|
||||
"inStock": 99,
|
||||
@@ -157,7 +165,7 @@
|
||||
"image": "crisis-of-faith-tour.jpg",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 13,
|
||||
"id": 14,
|
||||
"date": "2025-01-12",
|
||||
"price": 81.90,
|
||||
"inStock": 173,
|
||||
@@ -165,7 +173,7 @@
|
||||
"tourId": 5
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"id": 15,
|
||||
"date": "2025-02-01",
|
||||
"price": 84.90,
|
||||
"inStock": 192,
|
||||
@@ -182,7 +190,7 @@
|
||||
"image": "back-to-the-water-below.jpg",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 15,
|
||||
"id": 16,
|
||||
"date": "2025-02-27",
|
||||
"price": 67.90,
|
||||
"inStock": 847,
|
||||
@@ -190,7 +198,7 @@
|
||||
"tourId": 6
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"id": 17,
|
||||
"date": "2025-03-06",
|
||||
"price": 64.90,
|
||||
"inStock": 245,
|
||||
@@ -198,6 +206,47 @@
|
||||
"tourId": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Will of the People Tour",
|
||||
"bandId": 7,
|
||||
"offered": true,
|
||||
"image": "will-of-the-people-tour.jpg",
|
||||
"concerts": [
|
||||
{
|
||||
"id": 18,
|
||||
"date": "2025-01-15",
|
||||
"price": 67.90,
|
||||
"inStock": 847,
|
||||
"locationId": 2,
|
||||
"tourId": 7
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"date": "2025-01-23",
|
||||
"price": 64.90,
|
||||
"inStock": 245,
|
||||
"locationId": 10,
|
||||
"tourId": 7
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"date": "2025-02-02",
|
||||
"price": 64.90,
|
||||
"inStock": 245,
|
||||
"locationId": 13,
|
||||
"tourId": 7
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"date": "2025-02-05",
|
||||
"price": 64.90,
|
||||
"inStock": 245,
|
||||
"locationId": 13,
|
||||
"tourId": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
software/backend/images/bands/muse-1.jpg
Normal file
|
After Width: | Height: | Size: 425 KiB |
BIN
software/backend/images/bands/muse-2.jpg
Normal file
|
After Width: | Height: | Size: 292 KiB |
BIN
software/backend/images/bands/muse-3.jpg
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
software/backend/images/bands/muse-logo.jpg
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
software/backend/images/bands/muse-members.jpg
Normal file
|
After Width: | Height: | Size: 470 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 426 KiB |
|
Before Width: | Height: | Size: 214 KiB |
BIN
software/backend/images/tours/will-of-the-people-tour.jpg
Normal file
|
After Width: | Height: | Size: 250 KiB |
@@ -9,9 +9,6 @@ export class City extends Model {
|
||||
@Column
|
||||
country: String
|
||||
|
||||
@Column
|
||||
image: String
|
||||
|
||||
|
||||
// Relations
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export class Location extends Model {
|
||||
// Relations
|
||||
|
||||
@HasMany(() => Concert)
|
||||
shows: Concert[]
|
||||
concerts: Concert[]
|
||||
|
||||
@BelongsTo(() => City)
|
||||
city: City
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
import { Location } from "../models/acts/location.model";
|
||||
import { City } from "../models/acts/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: [ Location ]
|
||||
include: [
|
||||
{
|
||||
model: Location,
|
||||
include: [ Concert ]
|
||||
}
|
||||
]
|
||||
})
|
||||
.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)
|
||||
})
|
||||
})
|
||||
@@ -1,17 +1,41 @@
|
||||
import { Concert } from "../models/acts/concert.model";
|
||||
import { City } from "../models/acts/city.model";
|
||||
import { Location } from "../models/acts/location.model";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Tour } from "../models/acts/tour.model";
|
||||
import { Band } from "../models/acts/band.model";
|
||||
|
||||
export const location = Router()
|
||||
|
||||
location.get("/", (req: Request, res: Response) => {
|
||||
Location.findAll({
|
||||
include: [ City ],
|
||||
include: [
|
||||
City,
|
||||
{
|
||||
model: Concert,
|
||||
include: [ Tour ],
|
||||
attributes: {
|
||||
exclude: [ "locationId", "tourId" ]
|
||||
}
|
||||
}
|
||||
],
|
||||
attributes: {
|
||||
exclude: [ "cityId" ]
|
||||
}
|
||||
})
|
||||
.then(locations => {
|
||||
.then(async locations => {
|
||||
for (let location of locations) {
|
||||
for (let concert of location.dataValues.concerts) {
|
||||
let tour = concert.dataValues.tour
|
||||
|
||||
await Band.findByPk(tour.dataValues.bandId)
|
||||
.then(band => {
|
||||
tour.dataValues.bandName = band.dataValues.name
|
||||
delete tour.dataValues.bandId
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json(locations)
|
||||
})
|
||||
})
|
||||
@@ -10,12 +10,12 @@
|
||||
<v-divider vertical />
|
||||
|
||||
<v-btn
|
||||
to="/shows/tours"
|
||||
to="/events"
|
||||
prepend-icon="mdi-ticket"
|
||||
height="100%"
|
||||
:rounded="false"
|
||||
>
|
||||
{{ $t('menu.allConcerts', 2) }}
|
||||
{{ $t('allEvents', 2) }}
|
||||
</v-btn>
|
||||
|
||||
<v-divider vertical />
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
<v-btn
|
||||
variant="text"
|
||||
to="/shows/locations"
|
||||
to="/locations"
|
||||
prepend-icon="mdi-city"
|
||||
height="100%"
|
||||
:rounded="false"
|
||||
>
|
||||
{{ $t('menu.allLocations', 2) }}
|
||||
{{ $t('allLocations', 2) }}
|
||||
</v-btn>
|
||||
|
||||
<v-divider vertical />
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Replica of the API endpoint /cities
|
||||
*/
|
||||
export class CityModel {
|
||||
id: number
|
||||
name: string
|
||||
@@ -8,5 +11,6 @@ export class CityModel {
|
||||
name: string
|
||||
address: string
|
||||
image: string
|
||||
nrOfConcerts: number
|
||||
}>
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
/**
|
||||
* Replica of the API endpoint /locations
|
||||
*/
|
||||
export class LocationModel {
|
||||
id: number
|
||||
name: string
|
||||
@@ -7,4 +10,16 @@ export class LocationModel {
|
||||
name: string
|
||||
country: string
|
||||
}
|
||||
concerts: Array<{
|
||||
id: number
|
||||
date: string
|
||||
price: number
|
||||
inStock: number
|
||||
tour: {
|
||||
name: string
|
||||
offered: boolean
|
||||
image: string
|
||||
bandName: string
|
||||
}
|
||||
}>
|
||||
}
|
||||
@@ -53,6 +53,10 @@ export const useConcertStore = defineStore("concertStore", {
|
||||
await getAllGenres()
|
||||
.then(result => {
|
||||
this.genres = result.data
|
||||
|
||||
this.genres.sort((a, b) => {
|
||||
return a.name > b.name
|
||||
})
|
||||
})
|
||||
|
||||
await getAllCities()
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
{
|
||||
"menu": {
|
||||
"allConcerts": "Alle Konzerte",
|
||||
"allLocations": "Alle Veranstaltungsorte",
|
||||
"allBands": "Alle Bands"
|
||||
},
|
||||
"shows": {
|
||||
"highlights": "Highlights",
|
||||
"tickets": "Ticket | Tickets",
|
||||
"topConcerts": "Top Konzerte",
|
||||
"topBands": "Top Bands",
|
||||
"topLocations": "Top Veranstaltungsorte"
|
||||
},
|
||||
"tours": {
|
||||
"concert": "Konzert | Konzerte"
|
||||
},
|
||||
"allEvents": "Alle Events",
|
||||
"allLocations": "Alle Veranstaltungsorte",
|
||||
"topEvents": "Top Events",
|
||||
"topLocations": "Top Veranstaltungsorte",
|
||||
"tickets": "Ticket | Tickets",
|
||||
"concert": "Konzert | Konzerte",
|
||||
"preferences": {
|
||||
"pageSetup": "Seiteneinstellungen",
|
||||
"selectedTheme": "Ausgewähltes Theme",
|
||||
@@ -143,5 +134,10 @@
|
||||
"brand": "Marke | Marken",
|
||||
"concerts": {
|
||||
"location": "Veranstaltungsort"
|
||||
}
|
||||
},
|
||||
"location": "Veranstaltungsort | Veranstaltungsorte",
|
||||
"band": "Band | Bands",
|
||||
"noEventsFound": "Keine Events gefunden",
|
||||
"from": "ab",
|
||||
"soldOut": "Ausverkauft"
|
||||
}
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
{
|
||||
"menu": {
|
||||
"allConcerts": "All Concerts",
|
||||
"allLocations": "All Locations",
|
||||
"allBands": "All Bands"
|
||||
},
|
||||
"shows": {
|
||||
"highlights": "Highlights",
|
||||
"tickets": "Ticket | Tickets",
|
||||
"topConcerts": "Top Concerts",
|
||||
"topBands": "Top Bands",
|
||||
"topLocations": "Top Locations"
|
||||
},
|
||||
"tours": {
|
||||
"concert": "Concert | Concerts"
|
||||
},
|
||||
"allEvents": "All Events",
|
||||
"allLocations": "All Locations",
|
||||
"topEvents": "Top Events",
|
||||
"topLocations": "Top Locations",
|
||||
"tickets": "Ticket | Tickets",
|
||||
"concert": "Concert | Concerts",
|
||||
"preferences": {
|
||||
"pageSetup": "Page setup",
|
||||
"selectedTheme": "Selected theme",
|
||||
@@ -143,5 +134,10 @@
|
||||
"brand": "Brand | Brands",
|
||||
"concerts": {
|
||||
"location": "Locations"
|
||||
}
|
||||
},
|
||||
"location": "Location | Locations",
|
||||
"band": "Band | Bands",
|
||||
"noEventsFound": "No Events found",
|
||||
"from": "from",
|
||||
"soldOut": "Sold Out"
|
||||
}
|
||||
|
||||
@@ -51,9 +51,9 @@ const router = useRouter()
|
||||
append-icon="mdi-arrow-right"
|
||||
class="mt-2"
|
||||
color="primary"
|
||||
@click="router.push('shows/band/red-hot-chili-peppers')"
|
||||
@click="router.push('bands/' + band.name.replaceAll(' ', '-').toLowerCase())"
|
||||
>
|
||||
{{ $t('shows.tickets', 2) }}
|
||||
{{ $t('tickets', 2) }}
|
||||
</outlined-button>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
@@ -16,63 +16,75 @@ const concertStore = useConcertStore()
|
||||
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="$t('shows.highlights')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-spacer />
|
||||
|
||||
<v-row>
|
||||
<v-col v-for="i in 6" cols="2">
|
||||
<card-with-top-image
|
||||
:image="'tours/' + concertStore.tours[i - 1].image"
|
||||
:title="concertStore.tours[i - 1].band.name"
|
||||
smaller-title
|
||||
>
|
||||
Tickets ab {{ lowestTicketPrice(concertStore.tours[i - 1]) }} €
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-col cols="10">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="$t('topEvents')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<outlined-button
|
||||
append-icon="mdi-chevron-right"
|
||||
@click="router.push('/shows/concerts')"
|
||||
block
|
||||
>
|
||||
{{ $t('menu.allConcerts') }}
|
||||
</outlined-button>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col v-for="i in 4" cols="3">
|
||||
<card-with-top-image
|
||||
:image="'tours/' + concertStore.tours[i - 1].image"
|
||||
:title="concertStore.tours[i - 1].band.name"
|
||||
smaller-title
|
||||
@click="router.push('/bands/' + concertStore.tours[i - 1].band.name.replaceAll(' ', '-').toLowerCase())"
|
||||
>
|
||||
ab {{ lowestTicketPrice(concertStore.tours[i - 1]) }} €
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="$t('shows.topLocations')" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<outlined-button
|
||||
append-icon="mdi-chevron-right"
|
||||
@click="router.push('/events')"
|
||||
block
|
||||
>
|
||||
{{ $t('allEvents') }}
|
||||
</outlined-button>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col v-for="i in 6" cols="2">
|
||||
<card-with-top-image
|
||||
:image="'locations/' + concertStore.locations[i + 2].image"
|
||||
:title="concertStore.locations[i + 2].name"
|
||||
smaller-title
|
||||
>
|
||||
{{ concertStore.locations[i + 2].city.name }}, {{ concertStore.locations[i + 2].city.country }}
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider :title="$t('topLocations')" />
|
||||
</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-row>
|
||||
<v-col v-for="i in 8" cols="3">
|
||||
<card-with-top-image
|
||||
:image="'locations/' + concertStore.locations[i + 2].image"
|
||||
:title="concertStore.locations[i + 2].name"
|
||||
smaller-title
|
||||
>
|
||||
{{ concertStore.locations[i + 2].city.name }}, {{ concertStore.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('/locations')"
|
||||
block
|
||||
>
|
||||
{{ $t('allLocations') }}
|
||||
</outlined-button>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
|
||||
<v-spacer />
|
||||
</v-row>
|
||||
|
||||
|
||||
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
91
software/src/pages/locations/locationDetailPage/index.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<script setup lang="ts">
|
||||
import { LocationModel } from '@/data/models/acts/locationModel';
|
||||
import { useConcertStore } from '@/data/stores/concertStore';
|
||||
import { createDateRangeString, lowestTicketPrice } from '@/scripts/concertScripts';
|
||||
import { useRouter } from 'vue-router';
|
||||
import cardWithLeftImage from '@/components/cardWithLeftImage.vue';
|
||||
import sectionDivider from '@/components/sectionDivider.vue';
|
||||
import { dateStringToHumanReadableString } from '@/scripts/dateTimeScripts';
|
||||
|
||||
const router = useRouter()
|
||||
const concertStore = useConcertStore()
|
||||
|
||||
const location: LocationModel = concertStore.locations.find(location =>
|
||||
location.name.replaceAll(' ', '-').toLowerCase() == router.currentRoute.value.params.locationName
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="position-relative top-0 left-0">
|
||||
<v-img
|
||||
:src="'http://localhost:3000/static/locations/' + location.image"
|
||||
height="500"
|
||||
gradient="to top, rgba(0, 0, 0, .9), rgba(255, 255, 255, 0.1)"
|
||||
cover
|
||||
>
|
||||
<div class="position-absolute bottom-0 pa-5">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<p class="text-h3">{{ location.name }}</p>
|
||||
<p class="text-h6">{{ location.address }}</p>
|
||||
<p class="text-h6">{{ location.city.name }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-img>
|
||||
</div>
|
||||
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-spacer/>
|
||||
|
||||
<v-col cols="10">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider title="Konzerte" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row
|
||||
v-if="location.concerts.length > 0"
|
||||
v-for="concert of location.concerts"
|
||||
>
|
||||
<v-col>
|
||||
<card-with-left-image
|
||||
:title="concert.tour.bandName + ' - ' + concert.tour.name"
|
||||
:image="'http://localhost:3000/static/tours/' + concert.tour.image"
|
||||
@click="router.push('/bands/' + concert.tour.bandName.replaceAll(' ', '-').toLowerCase())"
|
||||
>
|
||||
<div class="text-h6">
|
||||
{{ dateStringToHumanReadableString(concert.date) }}
|
||||
</div>
|
||||
<!-- <div>{{ concert.length }} {{ $t('concert', concert.tour.concerts.length) }}</div> -->
|
||||
|
||||
<template #append>
|
||||
<div>
|
||||
<v-icon
|
||||
icon="mdi-ticket"
|
||||
color="secondary"
|
||||
size="x-large"
|
||||
/>
|
||||
</div>
|
||||
{{ $t('from') }} {{ concert.price.toFixed(2) }} €
|
||||
</template>
|
||||
</card-with-left-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row v-else>
|
||||
<v-col>
|
||||
<v-empty-state
|
||||
icon="mdi-magnify"
|
||||
:title="$t('noEventsFound')"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
|
||||
<v-spacer/>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
48
software/src/pages/locations/locationsPage/index.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import sectionDivider from '@/components/sectionDivider.vue';
|
||||
import { useConcertStore } from '@/data/stores/concertStore';
|
||||
import cardWithTopImage from '@/components/cardWithTopImage.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const concertStore = useConcertStore()
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-spacer />
|
||||
|
||||
<v-col cols="10">
|
||||
<div v-for="city in concertStore.cities">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider
|
||||
:title="city.name"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col v-for="location in city.locations" cols="3">
|
||||
<card-with-top-image
|
||||
:image="'locations/' + location.image"
|
||||
:title="location.name"
|
||||
@click="router.push('locations/' + location.name.replaceAll(' ', '-').toLowerCase())"
|
||||
>
|
||||
<div>
|
||||
{{ location.nrOfConcerts }} {{ $t('concert', location.nrOfConcerts) }}
|
||||
</div>
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-col>
|
||||
|
||||
<v-spacer />
|
||||
</v-row>
|
||||
|
||||
|
||||
|
||||
</v-container>
|
||||
</template>
|
||||
@@ -32,6 +32,15 @@ defineProps({
|
||||
|
||||
<v-col>
|
||||
<p class="text-h3">{{ band.name }}</p>
|
||||
<div>
|
||||
<v-chip
|
||||
v-for="genre in band.genres"
|
||||
class="mr-2 my-1"
|
||||
variant="flat"
|
||||
>
|
||||
{{ genre.name }}
|
||||
</v-chip>
|
||||
</div>
|
||||
<p class="text-h6">{{ band.descriptionDe }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -4,6 +4,9 @@ import { dateStringToHumanReadableString } from '@/scripts/dateTimeScripts';
|
||||
import sectionDivider from '@/components/sectionDivider.vue';
|
||||
import cardWithLeftImage from '@/components/cardWithLeftImage.vue';
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
defineProps({
|
||||
band: {
|
||||
@@ -27,17 +30,26 @@ defineProps({
|
||||
:image="'http://localhost:3000/static/locations/' + concert.location.image"
|
||||
:link="false"
|
||||
>
|
||||
<div>
|
||||
{{ concert.location.name }}
|
||||
</div>
|
||||
<v-row>
|
||||
<v-col cols="auto" class="d-flex justify-center align-center px-0">
|
||||
<v-btn
|
||||
icon="mdi-map"
|
||||
variant="text"
|
||||
size="x-large"
|
||||
@click="router.push('/locations/' + concert.location.name.replaceAll(' ', '-').toLowerCase())"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<div>
|
||||
{{ concert.location.address }}
|
||||
</div>
|
||||
<v-col>
|
||||
<div class="text-h6">
|
||||
{{ concert.location.name }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ concert.location.city.name }}
|
||||
</div>
|
||||
<div class="text-h6">
|
||||
{{ concert.location.city.name }}
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<template #append>
|
||||
<div class="pb-3">
|
||||
@@ -46,11 +58,19 @@ defineProps({
|
||||
|
||||
<div>
|
||||
<outlined-button
|
||||
v-if="concert.inStock > 0"
|
||||
prepend-icon="mdi-basket-plus"
|
||||
>
|
||||
Hinzufügen
|
||||
{{ $t('add') }}
|
||||
</outlined-button>
|
||||
</div>
|
||||
|
||||
<outlined-button v-else
|
||||
color="red"
|
||||
disabled
|
||||
>
|
||||
{{ $t('soldOut') }}
|
||||
</outlined-button>
|
||||
</div>
|
||||
</template>
|
||||
</card-with-left-image>
|
||||
</v-col>
|
||||
|
||||
@@ -23,7 +23,10 @@ const concertStore = useConcertStore()
|
||||
color="secondary"
|
||||
>
|
||||
<template #item="{ props, item }">
|
||||
<v-list-item v-bind="props" :title="item.raw.name" />
|
||||
<v-list-item
|
||||
v-bind="props"
|
||||
:title="item.raw.name + ' (' + item.raw.locations.length + ' ' +
|
||||
$t('location', item.raw.locations.length) + ')'" />
|
||||
</template>
|
||||
|
||||
<template #selection="{ item }">
|
||||
@@ -41,7 +44,7 @@ const concertStore = useConcertStore()
|
||||
variant="outlined"
|
||||
:items="concertStore.filteredLocations"
|
||||
v-model="concertStore.locationFilter"
|
||||
:label="$t('concerts.location')"
|
||||
:label="$t('location', 2)"
|
||||
density="compact"
|
||||
:clearable="concertStore.locationFilter != null && concertStore.locationFilter.id != undefined"
|
||||
:disabled="concertStore.cityFilter == null || concertStore.cityFilter.id == undefined"
|
||||
@@ -50,7 +53,10 @@ const concertStore = useConcertStore()
|
||||
color="secondary"
|
||||
>
|
||||
<template #item="{ props, item }">
|
||||
<v-list-item v-bind="props" :title="item.raw.name" />
|
||||
<v-list-item
|
||||
v-bind="props"
|
||||
:title="item.raw.name + ' (' + item.raw.concerts + ' Locations)'"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #selection="{ item }">
|
||||
@@ -74,7 +80,9 @@ const concertStore = useConcertStore()
|
||||
color="secondary"
|
||||
>
|
||||
<template #item="{ props, item }">
|
||||
<v-list-item v-bind="props" :title="item.raw.name" />
|
||||
<v-list-item v-bind="props" :title="item.raw.name + ' (' + item.raw.bands.length +
|
||||
' ' + $t('band', item.raw.bands.length) + ')'"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #selection="{ item }">
|
||||
@@ -29,12 +29,19 @@ const concertStore = useConcertStore()
|
||||
<card-with-left-image
|
||||
:title="tour.band.name + ' - ' + tour.name"
|
||||
:image="'http://localhost:3000/static/tours/' + tour.image"
|
||||
@click="router.push('/shows/band/' + tour.band.name.replaceAll(' ', '-').toLowerCase())"
|
||||
@click="router.push('/bands/' + tour.band.name.replaceAll(' ', '-').toLowerCase())"
|
||||
>
|
||||
{{ createDateRangeString(tour) }}
|
||||
<div>{{ tour.concerts.length }} {{ $t('tours.concert', tour.concerts.length) }}</div>
|
||||
<div>{{ tour.concerts.length }} {{ $t('concert', tour.concerts.length) }}</div>
|
||||
|
||||
<template #append>
|
||||
<div>
|
||||
<v-icon
|
||||
icon="mdi-ticket"
|
||||
color="secondary"
|
||||
size="x-large"
|
||||
/>
|
||||
</div>
|
||||
ab {{ lowestTicketPrice(tour) }} €
|
||||
</template>
|
||||
</card-with-left-image>
|
||||
@@ -44,7 +51,7 @@ const concertStore = useConcertStore()
|
||||
<v-row v-else>
|
||||
<v-col>
|
||||
<v-empty-state
|
||||
title="Keine Konzerte gefunden"
|
||||
:title="$t('noEventsFound')"
|
||||
icon="mdi-magnify"
|
||||
/>
|
||||
</v-col>
|
||||
@@ -1,32 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import sectionDivider from '@/components/sectionDivider.vue';
|
||||
import { useConcertStore } from '@/data/stores/concertStore';
|
||||
import cardWithTopImage from '@/components/cardWithTopImage.vue';
|
||||
|
||||
const concertStore = useConcertStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container>
|
||||
<div v-for="city in concertStore.cities">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<section-divider
|
||||
:title="city.name"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col v-for="location in city.locations" cols="3">
|
||||
<card-with-top-image
|
||||
:image="'locations/' + location.image"
|
||||
:title="location.name"
|
||||
>
|
||||
{{ location.address }}
|
||||
</card-with-top-image>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
@@ -1,43 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { SortOrder } from '@/data/enums/sortOrderEnum';
|
||||
|
||||
const sortOrderItems = Object.values(SortOrder)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-navigation-drawer location="right" width="300" permanent>
|
||||
<v-list>
|
||||
<v-list-subheader>Filter</v-list-subheader>
|
||||
|
||||
<!-- <v-list-item>
|
||||
<v-select
|
||||
:items="tourStore.genres"
|
||||
:label="$t('category', 2)"
|
||||
>
|
||||
<template v-slot:item="{ props, item }">
|
||||
<v-list-item v-bind="props" :prepend-icon="item.raw.icon" :title="item.raw.name" />
|
||||
</template>
|
||||
|
||||
<template v-slot:selection="{ item }">
|
||||
<v-list-item :prepend-icon="item.raw.icon" :title="item.raw.name" />
|
||||
</template>
|
||||
</v-select>
|
||||
</v-list-item> -->
|
||||
|
||||
<v-divider />
|
||||
<v-list-subheader>Sort</v-list-subheader>
|
||||
|
||||
<!-- <v-list-item>
|
||||
<v-select :label="$t('sortBy')" :items="sortOrderItems" v-model="productStore.sortOrder" >
|
||||
<template v-slot:item="{ props, item }">
|
||||
<v-list-item v-bind="props" :title="item.title" />
|
||||
</template>
|
||||
|
||||
<template v-slot:selection="{ item }">
|
||||
<v-list-item :title="item.title" />
|
||||
</template>
|
||||
</v-select>
|
||||
</v-list-item> -->
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
@@ -1,48 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import tourCard from "./tourCard.vue"
|
||||
import { ref, watch } from "vue";
|
||||
import filterNavDrawer from "./filterNavDrawer.vue";
|
||||
|
||||
|
||||
const showProductDetails = ref(false)
|
||||
// const dialogProduct = ref(new ProductModel())
|
||||
|
||||
// function showProductDialog(product: ProductModel) {
|
||||
// dialogProduct.value = product
|
||||
// showProductDetails.value = true
|
||||
// }
|
||||
|
||||
// watch(() => productStore.filteredCategory, async () => { productStore.filterProducts() })
|
||||
// watch(() => productStore.sortOrder, async () => { productStore.sortProducts() })
|
||||
// watch(() => productStore.onlyDiscounts, async () => { productStore.filterProducts() })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <v-container max-width="1200">
|
||||
<v-row dense>
|
||||
<v-col
|
||||
v-if="tourStore.tours.length > 0"
|
||||
v-for="tour in tourStore.tours"
|
||||
cols="12"
|
||||
>
|
||||
<tour-card
|
||||
:tour="tour"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col v-else>
|
||||
<v-empty-state
|
||||
icon="mdi-magnify"
|
||||
headline="Keine Artikel gefunden"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container> -->
|
||||
|
||||
<filter-nav-drawer />
|
||||
|
||||
<!-- <product-details
|
||||
v-model="showProductDetails"
|
||||
:product="dialogProduct"
|
||||
/> -->
|
||||
</template>
|
||||
@@ -1,157 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { VNumberInput } from 'vuetify/labs/VNumberInput'
|
||||
import { ModelRef, ref, watch } from 'vue';
|
||||
import { useBasketStore } from '@/data/stores/basketStore';
|
||||
import ActionDialog from '@/components/actionDialog.vue'
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
|
||||
// const props = defineProps({
|
||||
// product: {
|
||||
// type: ProductModel,
|
||||
// default: new ProductModel()
|
||||
// }
|
||||
// })
|
||||
|
||||
// const showDialog: ModelRef<boolean> = defineModel()
|
||||
// const nrOfArticles = ref(1)
|
||||
// const basketStore = useBasketStore()
|
||||
// const selectedImage = ref("")
|
||||
|
||||
// function addProductToBasket() {
|
||||
// basketStore.addItemToBasket(props.product, nrOfArticles.value)
|
||||
// nrOfArticles.value = 1
|
||||
// showDialog.value = false
|
||||
// }
|
||||
|
||||
// watch(() => props.product.images, () => {
|
||||
// selectedImage.value = 'http://localhost:3000/static/' + props.product.images[0]
|
||||
// })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <action-dialog
|
||||
:title="product.brand.name + ': ' + product.name"
|
||||
:icon="product.category.icon"
|
||||
:subtitle="product.category.name"
|
||||
v-model="showDialog"
|
||||
>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-row>
|
||||
<v-col class="py-0">
|
||||
<v-sheet color="white">
|
||||
<v-img :src="selectedImage" height="600" />
|
||||
</v-sheet>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-spacer />
|
||||
|
||||
<v-col v-for="image in product.images">
|
||||
<v-card
|
||||
width="60"
|
||||
@click="selectedImage = 'http://localhost:3000/static/' + image"
|
||||
color="white"
|
||||
>
|
||||
<v-img :src="'http://localhost:3000/static/' + image" height="60" />
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-spacer />
|
||||
</v-row>
|
||||
</v-col>
|
||||
|
||||
|
||||
<v-col>
|
||||
<v-row>
|
||||
<v-col class="text-h6 pt-0">
|
||||
{{ $t("product.description") }}
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="text-body-1 mt-0" style="height: 450px; overflow-y: auto;">
|
||||
<div v-if="product.description.length != 0">
|
||||
<v-col class="text-body-1">
|
||||
{{ product.description }}
|
||||
</v-col>
|
||||
</div>
|
||||
|
||||
<div v-if="product.specs.length > 1">
|
||||
<v-list>
|
||||
<v-list-item v-for="spec in product.specs">
|
||||
<v-icon icon="mdi-circle-small" /> {{ spec }}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
</v-row>
|
||||
|
||||
<v-divider class="my-4" />
|
||||
|
||||
<v-row>
|
||||
<v-col class="pb-0">
|
||||
<div class="d-flex align-center flex-column">
|
||||
<div class="text-h3"> {{ product.rating }} <span class="text-h6 ml-n3">/5</span> </div>
|
||||
<v-rating :model-value="product.rating" color="yellow-darken-3" half-increments disabled />
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-divider class="my-4" />
|
||||
|
||||
<v-row>
|
||||
<v-col cols="3">
|
||||
<div class="pt-3">
|
||||
<div v-if="product.inStock > 5" class="text-green-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||
</div>
|
||||
<div v-else-if="product.inStock > 0" class="text-orange-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||
</div>
|
||||
<div v-else class="text-red">
|
||||
{{ $t("product.soldOut") }}
|
||||
</div>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col class="d-flex align-end flex-column my-auto">
|
||||
<div v-if="product.discount == 0" class="text-h3">{{ product.price }} €</div>
|
||||
<div v-else class="d-flex align-center flex-column my-auto">
|
||||
<div class="text-h3">
|
||||
<span class="text-red-lighten-1"> {{ calcPrice(product.price, product.discount) }} €</span>
|
||||
<span class="text-h6 ml-2 text-decoration-line-through">{{ product.price }} € </span>
|
||||
<span class="text-h6 ml-4 mb-1 bg-red">-{{ product.discount }} %</span>
|
||||
</div>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<template #actions>
|
||||
<v-number-input
|
||||
max-width="200"
|
||||
:reverse="false"
|
||||
controlVariant="default"
|
||||
:label="$t('quantity')"
|
||||
:hideInput="false"
|
||||
:inset="true"
|
||||
v-model="nrOfArticles"
|
||||
variant="outlined"
|
||||
:min="1"
|
||||
:max="product.inStock"
|
||||
density="comfortable"
|
||||
:hide-details="true"
|
||||
:disabled="product.inStock == 0"
|
||||
/>
|
||||
|
||||
<outlined-button
|
||||
prepend-icon="mdi-cart-plus"
|
||||
@click="addProductToBasket"
|
||||
height="50"
|
||||
:disabled="product.inStock == 0"
|
||||
>
|
||||
{{ $t('addToBasket') }}
|
||||
</outlined-button>
|
||||
</template>
|
||||
</action-dialog> -->
|
||||
</template>
|
||||
@@ -1,88 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import cardView from '@/components/cardView.vue';
|
||||
import OutlinedButton from '@/components/outlinedButton.vue';
|
||||
|
||||
// defineProps({
|
||||
// tour: {
|
||||
// required: true,
|
||||
// type: TourModel
|
||||
// }
|
||||
// })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <card-view
|
||||
:title="tour.band.name"
|
||||
:subtitle="tour.name"
|
||||
:prepend-image="'http://127.0.0.1:3000/static/bands/' + tour.band.images[0]"
|
||||
link
|
||||
>
|
||||
{{ tour.band.descriptionDe }}
|
||||
|
||||
<template #actions>
|
||||
<OutlinedButton>
|
||||
{{ tour.shows.length }} {{ $t('tours.concert', tour.shows.length) }}
|
||||
</OutlinedButton>
|
||||
</template> -->
|
||||
|
||||
<!-- <template> -->
|
||||
<!-- <div>
|
||||
<v-rating
|
||||
size="medium"
|
||||
:model-value="product.rating"
|
||||
active-color="yellow-darken-1"
|
||||
color="grey-darken-1"
|
||||
half-increments
|
||||
readonly
|
||||
/>
|
||||
|
||||
{{ product.rating }}/5
|
||||
</div> -->
|
||||
|
||||
<!-- <div>
|
||||
<v-list class="pa-0">
|
||||
<v-list-item v-for="i in 2" class="pa-0 ma-0">
|
||||
<v-icon icon="mdi-circle-small" /> {{ product.specs[i - 1] }}
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div> -->
|
||||
<!-- </v-col> -->
|
||||
|
||||
<!-- <v-col cols="2" class="pt-5 pr-7"> -->
|
||||
<!-- <div v-if="product.discount == 0" class="font-weight-bold text-h5 text-right">
|
||||
{{ product.price }} €
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="font-weight-bold text-h5 text-right">
|
||||
{{ (product.price * ( 100 - product.discount) / 100).toFixed(2) }} €
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-decoration-line-through text-right">{{ product.price }} €</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div style="position: absolute; bottom: 0; right: 0;" class="pr-2 pb-2">
|
||||
<div v-if="product.inStock > 5" class="text-green-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||
</div>
|
||||
<div v-else-if="product.inStock > 0" class="text-orange-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||
</div>
|
||||
<div v-else class="text-red">
|
||||
{{ $t("product.soldOut") }}
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- </template> -->
|
||||
<!-- </card-view> -->
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.v-sheet {
|
||||
filter: brightness(60%)
|
||||
}
|
||||
|
||||
.v-card:hover :deep(.v-sheet) {
|
||||
filter: brightness(80%)
|
||||
}
|
||||
</style>
|
||||
@@ -2,13 +2,21 @@ import BasketPage from "@/pages/basketPage/index.vue"
|
||||
import HomePage from "@/pages/homePage/index.vue"
|
||||
import { adminRoutes } from "./admin.routes";
|
||||
import { accountRoutes } from "./account.routes";
|
||||
import { showRoutes } from "./show.routes";
|
||||
import { systemRoutes } from "./system.routes";
|
||||
import EventsPage from "@/pages/shows/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 LocationDetailPage from "@/pages/locations/locationDetailPage/index.vue"
|
||||
|
||||
const routes = [
|
||||
{ path: "/", component: HomePage },
|
||||
{ path: '/basket', component: BasketPage },
|
||||
...showRoutes,
|
||||
{ path: '/locations', component: LocationsPage },
|
||||
{ path: '/locations/:locationName', component: LocationDetailPage },
|
||||
{ path: '/bands/:bandName', component: BandDetailPage },
|
||||
{ path: '/events', component: EventsPage },
|
||||
{ path: '/search', component: SearchPage },
|
||||
...accountRoutes,
|
||||
...adminRoutes,
|
||||
...systemRoutes
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import ToursPage from "@/pages/shows/toursPage/index.vue";
|
||||
import LocationsPage from "@/pages/shows/locationsPage/index.vue"
|
||||
import SearchPage from "@/pages/shows/searchPage/index.vue"
|
||||
import BandDetailPage from "@/pages/shows/bandDetailPage/index.vue"
|
||||
|
||||
export const showRoutes = [
|
||||
{ path: '/shows/tours', component: ToursPage },
|
||||
{ path: '/shows/locations', component: LocationsPage },
|
||||
{ path: '/shows/search', component: SearchPage },
|
||||
{ path: '/shows/band/:bandName', component: BandDetailPage }
|
||||
]
|
||||