New locationDetailPage displays concert in a location, new datasets, images, URL path changed
This commit is contained in:
@@ -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
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
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>
|
||||
Reference in New Issue
Block a user