Refactor frontend, display tours with cards on ToursPage
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
|
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
|
||||||
<diagram name="Page-1" id="WevClHWmhzPAQ7FDN5po">
|
<diagram name="Page-1" id="WevClHWmhzPAQ7FDN5po">
|
||||||
<mxGraphModel dx="3113" dy="447" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
<mxGraphModel dx="3263" dy="534" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||||
<root>
|
<root>
|
||||||
<mxCell id="0" />
|
<mxCell id="0" />
|
||||||
<mxCell id="1" parent="0" />
|
<mxCell id="1" parent="0" />
|
||||||
@@ -572,7 +572,7 @@
|
|||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="EQeajuEG8KHzwlrw_xps-164" value="0..n" style="resizable=0;align=left;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10;strokeColor=#003366;shadow=1;fillColor=#D4E1F5;fontColor=#003366" parent="EQeajuEG8KHzwlrw_xps-163" connectable="0" vertex="1">
|
<mxCell id="EQeajuEG8KHzwlrw_xps-164" value="0..n" style="resizable=0;align=left;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10;strokeColor=#003366;shadow=1;fillColor=#D4E1F5;fontColor=#003366" parent="EQeajuEG8KHzwlrw_xps-163" connectable="0" vertex="1">
|
||||||
<mxGeometry x="-1" relative="1" as="geometry">
|
<mxGeometry x="-1" relative="1" as="geometry">
|
||||||
<mxPoint x="-22" y="-28" as="offset" />
|
<mxPoint x="3" y="-29" as="offset" />
|
||||||
</mxGeometry>
|
</mxGeometry>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="EQeajuEG8KHzwlrw_xps-165" value="1" style="resizable=0;align=right;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10;strokeColor=#003366;shadow=1;fillColor=#D4E1F5;fontColor=#003366" parent="EQeajuEG8KHzwlrw_xps-163" connectable="0" vertex="1">
|
<mxCell id="EQeajuEG8KHzwlrw_xps-165" value="1" style="resizable=0;align=right;verticalAlign=top;labelBackgroundColor=#ffffff;fontSize=10;strokeColor=#003366;shadow=1;fillColor=#D4E1F5;fontColor=#003366" parent="EQeajuEG8KHzwlrw_xps-163" connectable="0" vertex="1">
|
||||||
|
|||||||
@@ -38,6 +38,50 @@
|
|||||||
"bandId": 0
|
"bandId": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Radiohead",
|
||||||
|
"foundingYear": 1985,
|
||||||
|
"descriptionEn": "Radiohead are an English rock band formed in Abingdon, Oxfordshire, in 1985. They comprise Thom Yorke (vocals, guitar, piano, keyboards); brothers Jonny Greenwood (guitar, keyboards, other instruments) and Colin Greenwood (bass); Ed O'Brien (guitar, backing vocals); and Philip Selway (drums, percussion). They have worked with the producer Nigel Godrich and the cover artist Stanley Donwood since 1994. Radiohead's experimental approach is credited with advancing the sound of alternative rock.",
|
||||||
|
"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.jpg" ],
|
||||||
|
"logo": "radiohead-logo.png",
|
||||||
|
"genreId": 1,
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"name": "Thom Yorke",
|
||||||
|
"bandId": 1,
|
||||||
|
"image": "thom-yorke.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jonny Greenwood",
|
||||||
|
"bandId": 1,
|
||||||
|
"image": "jonny-greenwood.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Colin Greenwood",
|
||||||
|
"bandId": 1,
|
||||||
|
"image": "colin-greenwood.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ed O'Brien",
|
||||||
|
"bandId": 1,
|
||||||
|
"image": "ed-o-brien.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Philip Selway",
|
||||||
|
"bandId": 1,
|
||||||
|
"image": "philip-selway.jpg"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ratings": [
|
||||||
|
{
|
||||||
|
"accountId": 0,
|
||||||
|
"rating": 5,
|
||||||
|
"bandId": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,10 @@
|
|||||||
{
|
{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"name": "Funk rock"
|
"name": "Funk rock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Art rock"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,30 @@
|
|||||||
"tourId": 0
|
"tourId": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "The Bends Tour",
|
||||||
|
"bandId": 1,
|
||||||
|
"offered": true,
|
||||||
|
"shows": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"date": "2024-11-30",
|
||||||
|
"price": 104,
|
||||||
|
"inStock": 120,
|
||||||
|
"locationId": 0,
|
||||||
|
"tourId": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"date": "2024-12-01",
|
||||||
|
"price": 104,
|
||||||
|
"inStock": 180,
|
||||||
|
"locationId": 0,
|
||||||
|
"tourId": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
BIN
software/backend/images/bands/radiohead-logo.jpg
Normal file
BIN
software/backend/images/bands/radiohead-logo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
software/backend/images/bands/radiohead.jpg
Normal file
BIN
software/backend/images/bands/radiohead.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
@@ -4,21 +4,19 @@ import { i18n } from './plugins/i18n';
|
|||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import vuetify from './plugins/vuetify';
|
import vuetify from './plugins/vuetify';
|
||||||
import navigationItems from './components/navigationItems.vue';
|
import navigationItems from './components/navigationItems.vue';
|
||||||
import { useProductStore } from './data/stores/productStore';
|
|
||||||
import { usePreferencesStore } from './data/stores/preferencesStore';
|
import { usePreferencesStore } from './data/stores/preferencesStore';
|
||||||
import { useFeedbackStore } from './data/stores/feedbackStore';
|
import { useFeedbackStore } from './data/stores/feedbackStore';
|
||||||
|
import { useTourStore } from './data/stores/tourStore';
|
||||||
|
|
||||||
const preferencesStore = usePreferencesStore()
|
const preferencesStore = usePreferencesStore()
|
||||||
const productStore = useProductStore()
|
const tourStore = useTourStore()
|
||||||
const feedbackStore = useFeedbackStore()
|
const feedbackStore = useFeedbackStore()
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const navRail = ref(vuetify.display.mobile)
|
const navRail = ref(vuetify.display.mobile)
|
||||||
|
|
||||||
theme.global.name.value = preferencesStore.theme
|
theme.global.name.value = preferencesStore.theme
|
||||||
|
|
||||||
productStore.fetchAllProducts()
|
tourStore.fetchAllTours()
|
||||||
productStore.fetchAllCategories()
|
|
||||||
productStore.fetchAllBrands()
|
|
||||||
|
|
||||||
// Global watcher
|
// Global watcher
|
||||||
watch(() => preferencesStore.language, () => {
|
watch(() => preferencesStore.language, () => {
|
||||||
|
|||||||
@@ -7,28 +7,72 @@ defineProps({
|
|||||||
},
|
},
|
||||||
subtitle: {
|
subtitle: {
|
||||||
type: String,
|
type: String,
|
||||||
|
},
|
||||||
|
prependImage: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card
|
<v-card>
|
||||||
:title="title"
|
<v-row v-if="prependImage != ''">
|
||||||
:subtitle="subtitle"
|
<v-col cols="3" class="pr-0">
|
||||||
:prepend-icon="icon"
|
<v-img
|
||||||
>
|
:src="prependImage"
|
||||||
<!-- Show default container only, if there is content -->
|
height="220"
|
||||||
<v-container v-if="$slots.default">
|
cover
|
||||||
|
>
|
||||||
|
<template #placeholder>
|
||||||
|
<v-skeleton-loader
|
||||||
|
type="image"
|
||||||
|
height="300"
|
||||||
|
cover
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-img>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<v-col class="pl-0" >
|
||||||
|
<v-card-title>
|
||||||
|
{{ title }}
|
||||||
|
</v-card-title>
|
||||||
|
|
||||||
|
<v-card-subtitle>
|
||||||
|
{{ subtitle }}
|
||||||
|
</v-card-subtitle>
|
||||||
|
|
||||||
|
<div class="pa-4">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<v-card-actions v-if="$slots.actions" class="card-actions position-absolute bottom-0 right-0">
|
||||||
|
<v-spacer />
|
||||||
|
<slot name="actions"></slot>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-container v-else>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Show default container only, if there is content -->
|
||||||
|
<!-- <v-container v-if="$slots.default">
|
||||||
|
<slot></slot>
|
||||||
|
</v-container> -->
|
||||||
|
|
||||||
<!-- Slot for content without padding -->
|
<!-- Slot for content without padding -->
|
||||||
<slot name="withoutContainer"></slot>
|
<!-- <slot name="withoutContainer"></slot> -->
|
||||||
|
|
||||||
<!-- Slot for Action Buttons in the right bottom corner -->
|
<!-- Slot for Action Buttons in the right bottom corner -->
|
||||||
<v-card-actions v-if="$slots.actions" class="card-actions">
|
<!-- <v-card-actions v-if="$slots.actions" class="card-actions">
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
<slot name="actions"></slot>
|
<slot name="actions"></slot>
|
||||||
</v-card-actions>
|
</v-card-actions> -->
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ const navRail = defineModel("navRail", { type: Boolean })
|
|||||||
<!-- Shopping Section -->
|
<!-- Shopping Section -->
|
||||||
|
|
||||||
<v-list-subheader>
|
<v-list-subheader>
|
||||||
<div v-if="!navRail">{{ $t('menu.shopping') }}</div>
|
<div v-if="!navRail">{{ $t('menu.shopping.shopping') }}</div>
|
||||||
<div v-else></div>
|
<div v-else></div>
|
||||||
</v-list-subheader>
|
</v-list-subheader>
|
||||||
|
|
||||||
<v-list-item :title="$t('menu.products')" prepend-icon="mdi-store" to="/" link />
|
<v-list-item :title="$t('menu.shopping.ticket', 2)" prepend-icon="mdi-ticket" to="/" link />
|
||||||
<v-list-item :title="$t('menu.basket')" to="/basket" link >
|
<v-list-item :title="$t('menu.shopping.basket')" to="/basket" link >
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<v-badge color="primary" :content="basketStore.itemsInBasket.length">
|
<v-badge color="primary" :content="basketStore.itemsInBasket.length">
|
||||||
<v-icon icon="mdi-cart" />
|
<v-icon icon="mdi-cart" />
|
||||||
@@ -31,21 +31,21 @@ const navRail = defineModel("navRail", { type: Boolean })
|
|||||||
<!-- Account Section -->
|
<!-- Account Section -->
|
||||||
|
|
||||||
<v-list-subheader>
|
<v-list-subheader>
|
||||||
<div v-if="!navRail">{{ $t('menu.account') }}</div>
|
<div v-if="!navRail">{{ $t('menu.account.accountManagement') }}</div>
|
||||||
<div v-else></div>
|
<div v-else></div>
|
||||||
</v-list-subheader>
|
</v-list-subheader>
|
||||||
|
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
<div v-if="accountStore.userAccount.id == null">
|
<div v-if="accountStore.userAccount.id == null">
|
||||||
<v-list-item v-if="accountStore.userAccount.id == null" :title="$t('menu.login')" prepend-icon="mdi-login" to="/login" link />
|
<v-list-item v-if="accountStore.userAccount.id == null" :title="$t('menu.account.login')" prepend-icon="mdi-login" to="/login" link />
|
||||||
</div>
|
</div>
|
||||||
</v-expand-transition>
|
</v-expand-transition>
|
||||||
|
|
||||||
<v-expand-transition>
|
<v-expand-transition>
|
||||||
<div v-if="accountStore.userAccount.id != null">
|
<div v-if="accountStore.userAccount.id != null">
|
||||||
<v-list-item :title="$t('menu.account')" prepend-icon="mdi-account" to="/account" link />
|
<v-list-item :title="$t('menu.account.account')" prepend-icon="mdi-account" to="/account" link />
|
||||||
<v-list-item :title="$t('menu.orders')" prepend-icon="mdi-cart-check" to="/orders" link />
|
<v-list-item :title="$t('menu.account.order', 2)" prepend-icon="mdi-cart-check" to="/orders" link />
|
||||||
<v-list-item :title="$t('menu.logout')" prepend-icon="mdi-logout" @click="accountStore.logout" link />
|
<v-list-item :title="$t('menu.account.logout')" prepend-icon="mdi-logout" @click="accountStore.logout" link />
|
||||||
</div>
|
</div>
|
||||||
</v-expand-transition>
|
</v-expand-transition>
|
||||||
|
|
||||||
@@ -55,12 +55,12 @@ const navRail = defineModel("navRail", { type: Boolean })
|
|||||||
<!-- System and help section -->
|
<!-- System and help section -->
|
||||||
|
|
||||||
<v-list-subheader>
|
<v-list-subheader>
|
||||||
<div v-if="!navRail">{{ $t('menu.systemAndHelp') }}</div>
|
<div v-if="!navRail">{{ $t('menu.systemAndHelp.systemAndHelp') }}</div>
|
||||||
<div v-else></div>
|
<div v-else></div>
|
||||||
</v-list-subheader>
|
</v-list-subheader>
|
||||||
<v-list-item :title="$t('menu.helpInstructions')" prepend-icon="mdi-chat-question" to="/help" link />
|
<v-list-item :title="$t('menu.systemAndHelp.helpInstructions')" prepend-icon="mdi-chat-question" to="/help" link />
|
||||||
<v-list-item :title="$t('menu.scoreBoard')" prepend-icon="mdi-podium-gold" to="/scoreBoard" link />
|
<v-list-item :title="$t('menu.systemAndHelp.scoreBoard')" prepend-icon="mdi-podium-gold" to="/scoreBoard" link />
|
||||||
<v-list-item :title="$t('menu.preferences')" prepend-icon="mdi-cog" to="/preferences" link />
|
<v-list-item :title="$t('menu.systemAndHelp.preferences')" prepend-icon="mdi-cog" to="/preferences" link />
|
||||||
|
|
||||||
|
|
||||||
<div v-if="accountStore.userAccount.accountRole.privilegeAdminPanel">
|
<div v-if="accountStore.userAccount.accountRole.privilegeAdminPanel">
|
||||||
@@ -72,10 +72,6 @@ const navRail = defineModel("navRail", { type: Boolean })
|
|||||||
</v-list-subheader>
|
</v-list-subheader>
|
||||||
|
|
||||||
<v-list-item :title="$t('menu.admin.dashboard')" prepend-icon="mdi-view-dashboard" to="/admin/dashboard" link />
|
<v-list-item :title="$t('menu.admin.dashboard')" prepend-icon="mdi-view-dashboard" to="/admin/dashboard" link />
|
||||||
<v-list-item :title="$t('menu.admin.categories')" prepend-icon="mdi-label" to="/admin/categories" link />
|
|
||||||
<v-list-item :title="$t('brand', 2)" prepend-icon="mdi-factory" to="/admin/brands" link />
|
|
||||||
<v-list-item :title="$t('menu.admin.products')" prepend-icon="mdi-store-cog" to="/admin/products" link />
|
|
||||||
<v-list-item :title="$t('menu.admin.accounts')" prepend-icon="mdi-account-multiple" to="/admin/accounts" link />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</v-list>
|
</v-list>
|
||||||
|
|||||||
11
software/src/data/api/bandApi.ts
Normal file
11
software/src/data/api/bandApi.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
let BASE_URL = "http://localhost:3000/bands"
|
||||||
|
|
||||||
|
export async function getAllBands() {
|
||||||
|
return await axios.get(BASE_URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getOneBand(id: number) {
|
||||||
|
return await axios.get(BASE_URL + '/' + id)
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import axios from "axios";
|
|
||||||
|
|
||||||
let BASE_URL = "http://localhost:3000/brands"
|
|
||||||
|
|
||||||
export async function getAllBrands() {
|
|
||||||
return await axios.get(BASE_URL)
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import axios from "axios"
|
|
||||||
|
|
||||||
let BASE_URL = "http://localhost:3000/categories"
|
|
||||||
|
|
||||||
export async function getAllCategories() {
|
|
||||||
return await axios.get(BASE_URL)
|
|
||||||
}
|
|
||||||
7
software/src/data/api/genreApi.ts
Normal file
7
software/src/data/api/genreApi.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
let BASE_URL = "http://localhost:3000/genres"
|
||||||
|
|
||||||
|
export async function getAllGenres() {
|
||||||
|
return await axios.get(BASE_URL)
|
||||||
|
}
|
||||||
7
software/src/data/api/locationApi.ts
Normal file
7
software/src/data/api/locationApi.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
let BASE_URL = "http://localhost:3000/locations"
|
||||||
|
|
||||||
|
export async function getAllLocations() {
|
||||||
|
return await axios.get(BASE_URL)
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import axios from "axios"
|
|
||||||
|
|
||||||
let BASE_URL = "http://localhost:3000/products"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch all products from API
|
|
||||||
*/
|
|
||||||
export async function getAllProducts() {
|
|
||||||
return await axios.get(BASE_URL)
|
|
||||||
}
|
|
||||||
7
software/src/data/api/showApi.ts
Normal file
7
software/src/data/api/showApi.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
let BASE_URL = "http://localhost:3000/shows"
|
||||||
|
|
||||||
|
export async function getAllShows() {
|
||||||
|
return await axios.get(BASE_URL)
|
||||||
|
}
|
||||||
10
software/src/data/api/tourApi.ts
Normal file
10
software/src/data/api/tourApi.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
let BASE_URL = "http://localhost:3000/tours"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch all tours from API
|
||||||
|
*/
|
||||||
|
export async function getAllTours() {
|
||||||
|
return await axios.get(BASE_URL)
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { ProductModel } from "./productModel"
|
import { ShowModel } from "./showModel"
|
||||||
|
|
||||||
export class BasketItemModel {
|
export class BasketItemModel {
|
||||||
id: number = -1
|
id: number = -1
|
||||||
quantity: number = 1
|
quantity: number = 1
|
||||||
product: ProductModel = new ProductModel()
|
product: ShowModel = new ShowModel()
|
||||||
|
|
||||||
constructor(quantity: number, product: ProductModel) {
|
constructor(quantity: number, product: ShowModel) {
|
||||||
this.quantity = quantity
|
this.quantity = quantity
|
||||||
this.product = product
|
this.product = product
|
||||||
}
|
}
|
||||||
|
|||||||
5
software/src/data/models/cityModel.ts
Normal file
5
software/src/data/models/cityModel.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export class CityModel {
|
||||||
|
id: Number
|
||||||
|
name: String
|
||||||
|
country: String
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { CityModel } from "./cityModel"
|
||||||
|
|
||||||
export class LocationModel {
|
export class LocationModel {
|
||||||
id: Number
|
id: Number
|
||||||
name: String
|
name: String
|
||||||
address: String
|
address: String
|
||||||
city: String
|
city: CityModel
|
||||||
image: String
|
image: String
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,5 @@ import { BandModel } from "./bandModel"
|
|||||||
export class MemberModel {
|
export class MemberModel {
|
||||||
id: Number
|
id: Number
|
||||||
name: String
|
name: String
|
||||||
band: BandModel
|
|
||||||
image: String
|
image: String
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@ import { BandModel } from "./bandModel"
|
|||||||
|
|
||||||
export class RatingModel {
|
export class RatingModel {
|
||||||
id: Number
|
id: Number
|
||||||
account: AccountModel
|
|
||||||
rating: Number
|
rating: Number
|
||||||
band: BandModel
|
band: BandModel
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,9 @@ import { BandModel } from "./bandModel"
|
|||||||
import { ShowModel } from "./showModel"
|
import { ShowModel } from "./showModel"
|
||||||
|
|
||||||
export class TourModel {
|
export class TourModel {
|
||||||
id: Number
|
id: number
|
||||||
name: String
|
name: string
|
||||||
|
offered: boolean
|
||||||
band: BandModel
|
band: BandModel
|
||||||
offered: Boolean
|
|
||||||
shows: Array<ShowModel>
|
shows: Array<ShowModel>
|
||||||
}
|
}
|
||||||
@@ -6,8 +6,7 @@ import { useFeedbackStore } from "./feedbackStore";
|
|||||||
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
||||||
import { addOrder } from "../api/orderApi";
|
import { addOrder } from "../api/orderApi";
|
||||||
import { useAccountStore } from "./accountStore";
|
import { useAccountStore } from "./accountStore";
|
||||||
import { ProductModel } from "../models/productModel";
|
import { ShowModel } from "../models/showModel";
|
||||||
import { useProductStore } from "./productStore";
|
|
||||||
import { AddressModel } from "../models/addressModel";
|
import { AddressModel } from "../models/addressModel";
|
||||||
import { PaymentModel } from "../models/paymentModel";
|
import { PaymentModel } from "../models/paymentModel";
|
||||||
|
|
||||||
@@ -53,21 +52,21 @@ export const useBasketStore = defineStore('basketStore', {
|
|||||||
/**
|
/**
|
||||||
* Add an item to the basket. If the product is already in the basket, the quantity will increase
|
* Add an item to the basket. If the product is already in the basket, the quantity will increase
|
||||||
*
|
*
|
||||||
* @param product Product to add
|
* @param show Show to add
|
||||||
* @param quantity Quantity of the product
|
* @param quantity Quantity of the product
|
||||||
*/
|
*/
|
||||||
addItemToBasket(product: ProductModel, quantity: number) {
|
addItemToBasket(show: ShowModel, quantity: number) {
|
||||||
const feedbackStore = useFeedbackStore()
|
const feedbackStore = useFeedbackStore()
|
||||||
feedbackStore.changeBanner(BannerStateEnum.BASKETPRODUCTADDED)
|
feedbackStore.changeBanner(BannerStateEnum.BASKETPRODUCTADDED)
|
||||||
|
|
||||||
// Product is already in the basket, increase number of items
|
// Product is already in the basket, increase number of items
|
||||||
if (this.itemsInBasket.find((basketItem: BasketItemModel) =>
|
if (this.itemsInBasket.find((basketItem: BasketItemModel) =>
|
||||||
basketItem.product.id == product.id))
|
basketItem.product.id == show.id))
|
||||||
{
|
{
|
||||||
this.itemsInBasket.find((basketItem: BasketItemModel) =>
|
this.itemsInBasket.find((basketItem: BasketItemModel) =>
|
||||||
basketItem.product.id == product.id).quantity += quantity
|
basketItem.product.id == show.id).quantity += quantity
|
||||||
} else {
|
} else {
|
||||||
this.itemsInBasket.push(new BasketItemModel(quantity, product))
|
this.itemsInBasket.push(new BasketItemModel(quantity, show))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -75,22 +74,23 @@ export const useBasketStore = defineStore('basketStore', {
|
|||||||
* Take an order to the server. Sends all articles in the basket and creates an order entry in the backend database
|
* Take an order to the server. Sends all articles in the basket and creates an order entry in the backend database
|
||||||
*/
|
*/
|
||||||
async takeOrder() {
|
async takeOrder() {
|
||||||
const accountStore = useAccountStore()
|
// todo
|
||||||
const productStore = useProductStore()
|
// const accountStore = useAccountStore()
|
||||||
const feedbackStore = useFeedbackStore()
|
// const productStore = useProductStore()
|
||||||
|
// const feedbackStore = useFeedbackStore()
|
||||||
|
|
||||||
await addOrder(accountStore.userAccount.id, this.itemsInBasket, this.usedPayment.id, this.usedAddress.id)
|
// await addOrder(accountStore.userAccount.id, this.itemsInBasket, this.usedPayment.id, this.usedAddress.id)
|
||||||
.then(async result => {
|
// .then(async result => {
|
||||||
if (result.status == 201) {
|
// if (result.status == 201) {
|
||||||
await accountStore.refreshOrders()
|
// await accountStore.refreshOrders()
|
||||||
await productStore.fetchAllProducts()
|
// await productStore.fetchAllProducts()
|
||||||
|
|
||||||
this.itemsInBasket = []
|
// this.itemsInBasket = []
|
||||||
feedbackStore.changeBanner(BannerStateEnum.ORDERPLACESUCCESSFUL)
|
// feedbackStore.changeBanner(BannerStateEnum.ORDERPLACESUCCESSFUL)
|
||||||
} else {
|
// } else {
|
||||||
feedbackStore.changeBanner(BannerStateEnum.ERROR)
|
// feedbackStore.changeBanner(BannerStateEnum.ERROR)
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
import { useLocalStorage } from "@vueuse/core";
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
import { getAllProducts } from "../api/productApi";
|
|
||||||
import { SortOrder } from "../enums/sortOrderEnum";
|
|
||||||
import { CategoryModel } from "../models/categoryModel";
|
|
||||||
import { ProductModel } from "../models/productModel";
|
|
||||||
import { BrandModel } from "../models/brandModel";
|
|
||||||
import { getAllCategories } from "../api/categoryApi";
|
|
||||||
import { getAllBrands } from "../api/brandApi";
|
|
||||||
|
|
||||||
|
|
||||||
export const useProductStore = defineStore("productStore", {
|
|
||||||
state: () => ({
|
|
||||||
products: useLocalStorage<Array<ProductModel>>("hackmycart/productStore/products", []),
|
|
||||||
filteredProducts: useLocalStorage<Array<ProductModel>>("hackmycart/productStore/filteredProducts", []),
|
|
||||||
sortOrder: useLocalStorage<SortOrder>("hackmycart/productStore/sortOrder", SortOrder.NAMEATOZ),
|
|
||||||
filteredCategory: useLocalStorage<CategoryModel>("hackmycart/productStore/filteredCategory", new CategoryModel()),
|
|
||||||
onlyDiscounts: useLocalStorage<Boolean>("hackmycart/productStore/onlyDiscounts", false),
|
|
||||||
brands: useLocalStorage<Array<BrandModel>>("hackmycart/productStore/brands", []),
|
|
||||||
categories: useLocalStorage<Array<CategoryModel>>("hackmycart/productStore/categories", [])
|
|
||||||
}),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
async fetchAllProducts() {
|
|
||||||
await getAllProducts()
|
|
||||||
.then(products => {
|
|
||||||
this.products = products.data
|
|
||||||
this.filteredProducts = products.data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchAllCategories() {
|
|
||||||
await getAllCategories()
|
|
||||||
.then(categories => {
|
|
||||||
this.categories = categories.data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchAllBrands() {
|
|
||||||
await getAllBrands()
|
|
||||||
.then(brands => {
|
|
||||||
this.brands = brands.data
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
async filterProducts() {
|
|
||||||
if (this.filteredCategory.id == -1 || this.filteredCategory.id == 0) {
|
|
||||||
this.filteredProducts = this.products
|
|
||||||
} else {
|
|
||||||
this.filteredProducts = this.products.filter((product: ProductModel) =>
|
|
||||||
product.category.id == this.filteredCategory.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.onlyDiscounts) {
|
|
||||||
this.filteredProducts = this.filteredProducts.filter((product: ProductModel) =>
|
|
||||||
product.discount > 0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
sortProducts() {
|
|
||||||
this.filteredProducts.sort((a: ProductModel, b: ProductModel) => {
|
|
||||||
switch (this.sortOrder)
|
|
||||||
{
|
|
||||||
case SortOrder.PRICELOWTOHIGH: {
|
|
||||||
return a.price - b.price
|
|
||||||
}
|
|
||||||
case SortOrder.PRICEHIGHTOLOW: {
|
|
||||||
return b.price - a.price
|
|
||||||
}
|
|
||||||
case SortOrder.NAMEATOZ: {
|
|
||||||
if (b.name > a.name) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case SortOrder.NAMEZTOA: {
|
|
||||||
if (b.name < a.name) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
21
software/src/data/stores/tourStore.ts
Normal file
21
software/src/data/stores/tourStore.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { useLocalStorage } from "@vueuse/core";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { TourModel } from "../models/tourModel";
|
||||||
|
import { getAllTours } from "../api/tourApi";
|
||||||
|
import { GenreModel } from "../models/genreModel";
|
||||||
|
|
||||||
|
export const useTourStore = defineStore("tourStore", {
|
||||||
|
state: () => ({
|
||||||
|
tours: useLocalStorage<Array<TourModel>>("hackmycart/tourStore/tours", []),
|
||||||
|
genres: useLocalStorage<Array<GenreModel>>("hackmycart/tourStore/genres", [])
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
async fetchAllTours() {
|
||||||
|
await getAllTours()
|
||||||
|
.then(result => {
|
||||||
|
this.tours = result.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,24 +1,32 @@
|
|||||||
{
|
{
|
||||||
"menu": {
|
"menu": {
|
||||||
"shopping": "Einkaufen",
|
"shopping": {
|
||||||
"products": "Produkte",
|
"shopping": "Einkaufen",
|
||||||
"basket": "Warenkorb",
|
"ticket": "Ticket | Tickets",
|
||||||
"login": "Login",
|
"basket": "Warenkorb"
|
||||||
"account": "Account",
|
},
|
||||||
"orders": "Bestellungen",
|
"account": {
|
||||||
"systemAndHelp": "System & Hilfe",
|
"accountManagement": "Kontoverwaltung",
|
||||||
"helpInstructions": "Hilfestellung",
|
"account": "Account",
|
||||||
"preferences": "Einstellungen",
|
"login": "Login",
|
||||||
"logout": "Ausloggen",
|
"order": "Bestellung | Bestellungen",
|
||||||
"scoreBoard": "Score Board",
|
"logout": "Ausloggen"
|
||||||
|
},
|
||||||
|
"systemAndHelp": {
|
||||||
|
"systemAndHelp": "System & Hilfe",
|
||||||
|
"helpInstructions": "Hilfestellung",
|
||||||
|
"preferences": "Einstellungen",
|
||||||
|
"scoreBoard": "Score Board"
|
||||||
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"admin": "Administration",
|
"admin": "Administration",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Dashboard"
|
||||||
"categories": "Kategorien",
|
|
||||||
"products": "Produkte",
|
|
||||||
"accounts": "Accounts"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tours": {
|
||||||
|
"concert": "Konzert | Konzerte"
|
||||||
|
},
|
||||||
|
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"pageSetup": "Seiteneinstellungen",
|
"pageSetup": "Seiteneinstellungen",
|
||||||
"selectedTheme": "Ausgewähltes Theme",
|
"selectedTheme": "Ausgewähltes Theme",
|
||||||
|
|||||||
@@ -1,24 +1,33 @@
|
|||||||
{
|
{
|
||||||
"menu": {
|
"menu": {
|
||||||
"shopping": "Shopping",
|
"shopping": {
|
||||||
"products": "Products",
|
"shopping": "Shopping",
|
||||||
"basket": "Basket",
|
"ticket": "Ticket | Tickets",
|
||||||
"login": "Login",
|
"basket": "Basket"
|
||||||
"account": "Account",
|
},
|
||||||
"orders": "Orders",
|
"account": {
|
||||||
"systemAndHelp": "System & Help",
|
"account": "Account Management",
|
||||||
"helpInstructions": "Help instructions",
|
"login": "Login",
|
||||||
"preferences": "Preferences",
|
"order": "Order | Orders",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"scoreBoard": "Score Board",
|
"accountManagement": "Account Management"
|
||||||
|
},
|
||||||
|
"systemAndHelp": {
|
||||||
|
"systemAndHelp": "System & Help",
|
||||||
|
"helpInstructions": "Help Instructions",
|
||||||
|
"preferences": "Preferences",
|
||||||
|
"scoreBoard": "Score Board"
|
||||||
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"admin": "Administration",
|
"admin": "Administration",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Dashboard"
|
||||||
"categories": "Categories",
|
|
||||||
"products": "Products",
|
|
||||||
"accounts": "Accounts"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tours": {
|
||||||
|
"concert": "Concert | Concerts"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"pageSetup": "Page setup",
|
"pageSetup": "Page setup",
|
||||||
"selectedTheme": "Selected theme",
|
"selectedTheme": "Selected theme",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
import { useProductStore } from '@/data/stores/productStore';
|
// import { useProductStore } from '@/data/stores/productStore';
|
||||||
|
|
||||||
const productStore = useProductStore()
|
// const productStore = useProductStore()
|
||||||
|
|
||||||
const headers = [
|
const headers = [
|
||||||
{ title: "Name", value: "name" },
|
{ title: "Name", value: "name" },
|
||||||
@@ -11,7 +11,7 @@ const headers = [
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="800">
|
<!-- <v-container max-width="800">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<card-view
|
<card-view
|
||||||
@@ -24,9 +24,8 @@ const headers = [
|
|||||||
:headers="headers"
|
:headers="headers"
|
||||||
>
|
>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
<!-- todo: Edit/Delete -->
|
|
||||||
</card-view>
|
</card-view>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container> -->
|
||||||
</template>
|
</template>
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
import { useProductStore } from '@/data/stores/productStore';
|
|
||||||
|
|
||||||
const productStore = useProductStore()
|
|
||||||
|
|
||||||
const headers = [
|
const headers = [
|
||||||
{ title: "Name", value: "name" },
|
{ title: "Name", value: "name" },
|
||||||
@@ -12,24 +9,5 @@ const headers = [
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="800">
|
|
||||||
<v-row>
|
|
||||||
<v-col>
|
|
||||||
<card-view
|
|
||||||
:title="$t('category', 2)"
|
|
||||||
icon="mdi-label"
|
|
||||||
:subtitle="productStore.categories.length + ' ' + $t('category', productStore.categories.length)"
|
|
||||||
>
|
|
||||||
<v-data-table
|
|
||||||
:items="productStore.categories"
|
|
||||||
:headers="headers"
|
|
||||||
>
|
|
||||||
<template v-slot:item.icon="{ item }">
|
|
||||||
<v-icon :icon="item.icon" />
|
|
||||||
</template>
|
|
||||||
</v-data-table>
|
|
||||||
</card-view>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</v-container>
|
|
||||||
</template>
|
</template>
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
import { ProductModel } from '@/data/models/productModel';
|
|
||||||
import { useProductStore } from '@/data/stores/productStore';
|
|
||||||
import productEditDialog from './productEditDialog.vue';
|
import productEditDialog from './productEditDialog.vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
const productStore = useProductStore()
|
// const productStore = useProductStore()
|
||||||
const editProduct = ref(new ProductModel())
|
// const editProduct = ref(new ProductModel())
|
||||||
const showEditProductDialog = ref(false)
|
const showEditProductDialog = ref(false)
|
||||||
|
|
||||||
const headers = [
|
const headers = [
|
||||||
@@ -20,16 +18,16 @@ const headers = [
|
|||||||
{ title: "Edit", value: "edit" },
|
{ title: "Edit", value: "edit" },
|
||||||
]
|
]
|
||||||
|
|
||||||
function openEditProductDialog(product: ProductModel) {
|
// function openEditProductDialog(product: ProductModel) {
|
||||||
editProduct.value = product
|
// editProduct.value = product
|
||||||
showEditProductDialog.value = true
|
// showEditProductDialog.value = true
|
||||||
}
|
// }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col>
|
<!-- <v-col>
|
||||||
<card-view
|
<card-view
|
||||||
:title="$t('product.product', 2)"
|
:title="$t('product.product', 2)"
|
||||||
:subtitle="productStore.products.length + ' ' + $t('product.product', productStore.products.length)"
|
:subtitle="productStore.products.length + ' ' + $t('product.product', productStore.products.length)"
|
||||||
@@ -88,11 +86,11 @@ function openEditProductDialog(product: ProductModel) {
|
|||||||
</template>
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
</card-view>
|
</card-view>
|
||||||
</v-col>
|
</v-col> -->
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<product-edit-dialog
|
<!-- <product-edit-dialog
|
||||||
v-model="showEditProductDialog"
|
v-model="showEditProductDialog"
|
||||||
:edit-product="editProduct" />
|
:edit-product="editProduct" /> -->
|
||||||
</template>
|
</template>
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import productCard from "./productCard.vue"
|
|
||||||
import productDetails from "./productDetailsDialog.vue"
|
|
||||||
import { ref, watch } from "vue";
|
|
||||||
import { useProductStore } from "@/data/stores/productStore";
|
|
||||||
import filterNavDrawer from "./filterNavDrawer.vue";
|
|
||||||
import { ProductModel } from '@/data/models/productModel';
|
|
||||||
|
|
||||||
const productStore = useProductStore()
|
|
||||||
|
|
||||||
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="1000">
|
|
||||||
<v-row dense>
|
|
||||||
<v-col
|
|
||||||
v-if="productStore.filteredProducts.length > 0"
|
|
||||||
v-for="product in productStore.filteredProducts"
|
|
||||||
cols="12"
|
|
||||||
>
|
|
||||||
<product-card
|
|
||||||
:product="product"
|
|
||||||
@click="showProductDialog(product)"
|
|
||||||
/>
|
|
||||||
</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>
|
|
||||||
6
software/src/pages/tourDetailPage/index.vue
Normal file
6
software/src/pages/tourDetailPage/index.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SortOrder } from '@/data/enums/sortOrderEnum';
|
import { SortOrder } from '@/data/enums/sortOrderEnum';
|
||||||
import { useProductStore } from '@/data/stores/productStore';
|
import { useTourStore } from '@/data/stores/tourStore';
|
||||||
|
|
||||||
const productStore = useProductStore()
|
const tourStore = useTourStore()
|
||||||
const sortOrderItems = Object.values(SortOrder)
|
const sortOrderItems = Object.values(SortOrder)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -11,15 +11,10 @@ const sortOrderItems = Object.values(SortOrder)
|
|||||||
<v-list>
|
<v-list>
|
||||||
<v-list-subheader>Filter</v-list-subheader>
|
<v-list-subheader>Filter</v-list-subheader>
|
||||||
|
|
||||||
<v-list-item>
|
<!-- <v-list-item>
|
||||||
<v-checkbox :label="$t('offers')" v-model="productStore.onlyDiscounts" />
|
|
||||||
</v-list-item>
|
|
||||||
|
|
||||||
<v-list-item>
|
|
||||||
<v-select
|
<v-select
|
||||||
:items="productStore.categories"
|
:items="tourStore.genres"
|
||||||
:label="$t('category', 2)"
|
:label="$t('category', 2)"
|
||||||
v-model="productStore.filteredCategory"
|
|
||||||
>
|
>
|
||||||
<template v-slot:item="{ props, item }">
|
<template v-slot:item="{ props, item }">
|
||||||
<v-list-item v-bind="props" :prepend-icon="item.raw.icon" :title="item.raw.name" />
|
<v-list-item v-bind="props" :prepend-icon="item.raw.icon" :title="item.raw.name" />
|
||||||
@@ -29,12 +24,12 @@ const sortOrderItems = Object.values(SortOrder)
|
|||||||
<v-list-item :prepend-icon="item.raw.icon" :title="item.raw.name" />
|
<v-list-item :prepend-icon="item.raw.icon" :title="item.raw.name" />
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</v-list-item>
|
</v-list-item> -->
|
||||||
|
|
||||||
<v-divider />
|
<v-divider />
|
||||||
<v-list-subheader>Sort</v-list-subheader>
|
<v-list-subheader>Sort</v-list-subheader>
|
||||||
|
|
||||||
<v-list-item>
|
<!-- <v-list-item>
|
||||||
<v-select :label="$t('sortBy')" :items="sortOrderItems" v-model="productStore.sortOrder" >
|
<v-select :label="$t('sortBy')" :items="sortOrderItems" v-model="productStore.sortOrder" >
|
||||||
<template v-slot:item="{ props, item }">
|
<template v-slot:item="{ props, item }">
|
||||||
<v-list-item v-bind="props" :title="item.title" />
|
<v-list-item v-bind="props" :title="item.title" />
|
||||||
@@ -44,7 +39,7 @@ const sortOrderItems = Object.values(SortOrder)
|
|||||||
<v-list-item :title="item.title" />
|
<v-list-item :title="item.title" />
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</v-list-item>
|
</v-list-item> -->
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
</template>
|
</template>
|
||||||
50
software/src/pages/toursPage/index.vue
Normal file
50
software/src/pages/toursPage/index.vue
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import tourCard from "./tourCard.vue"
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import filterNavDrawer from "./filterNavDrawer.vue";
|
||||||
|
import { useTourStore } from "@/data/stores/tourStore";
|
||||||
|
|
||||||
|
const tourStore = useTourStore()
|
||||||
|
|
||||||
|
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,35 +1,33 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ProductModel } from '@/data/models/productModel';
|
import { TourModel } from '@/data/models/tourModel';
|
||||||
import cardView from '@/components/cardView.vue';
|
import cardView from '@/components/cardView.vue';
|
||||||
|
import OutlinedButton from '@/components/outlinedButton.vue';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
product: {
|
tour: {
|
||||||
required: true,
|
required: true,
|
||||||
type: ProductModel
|
type: TourModel
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<card-view link>
|
<card-view
|
||||||
<template #withoutContainer>
|
:title="tour.band.name"
|
||||||
<v-row>
|
:subtitle="tour.name"
|
||||||
<v-col cols="3">
|
:prepend-image="'http://127.0.0.1:3000/static/bands/' + tour.band.images[0]"
|
||||||
<v-sheet color="white">
|
link
|
||||||
<v-img
|
>
|
||||||
:src="'http://127.0.0.1:3000/static/' + product.images[0]"
|
{{ tour.band.descriptionDe }}
|
||||||
height="200"
|
|
||||||
>
|
|
||||||
<template #placeholder>
|
|
||||||
<v-skeleton-loader type="image" />
|
|
||||||
</template>
|
|
||||||
</v-img>
|
|
||||||
</v-sheet>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col cols="7" class="pl-0 pt-5">
|
<template #actions>
|
||||||
<div class="text-h6">{{ product.name }}</div>
|
<OutlinedButton>
|
||||||
<div>
|
{{ tour.shows.length }} {{ $t('tours.concert', tour.shows.length) }}
|
||||||
|
</OutlinedButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- <template> -->
|
||||||
|
<!-- <div>
|
||||||
<v-rating
|
<v-rating
|
||||||
size="medium"
|
size="medium"
|
||||||
:model-value="product.rating"
|
:model-value="product.rating"
|
||||||
@@ -40,19 +38,19 @@ defineProps({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{{ product.rating }}/5
|
{{ product.rating }}/5
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<div>
|
<!-- <div>
|
||||||
<v-list class="pa-0">
|
<v-list class="pa-0">
|
||||||
<v-list-item v-for="i in 2" class="pa-0 ma-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-icon icon="mdi-circle-small" /> {{ product.specs[i - 1] }}
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</div>
|
</div> -->
|
||||||
</v-col>
|
<!-- </v-col> -->
|
||||||
|
|
||||||
<v-col cols="2" class="pt-5 pr-7">
|
<!-- <v-col cols="2" class="pt-5 pr-7"> -->
|
||||||
<div v-if="product.discount == 0" class="font-weight-bold text-h5 text-right">
|
<!-- <div v-if="product.discount == 0" class="font-weight-bold text-h5 text-right">
|
||||||
{{ product.price }} €
|
{{ product.price }} €
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -63,9 +61,9 @@ defineProps({
|
|||||||
<div>
|
<div>
|
||||||
<div class="text-decoration-line-through text-right">{{ product.price }} €</div>
|
<div class="text-decoration-line-through text-right">{{ product.price }} €</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<div style="position: absolute; bottom: 0; right: 0;" class="pr-2 pb-2">
|
<!-- <div style="position: absolute; bottom: 0; right: 0;" class="pr-2 pb-2">
|
||||||
<div v-if="product.inStock > 5" class="text-green-lighten-1">
|
<div v-if="product.inStock > 5" class="text-green-lighten-1">
|
||||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||||
</div>
|
</div>
|
||||||
@@ -75,10 +73,8 @@ defineProps({
|
|||||||
<div v-else class="text-red">
|
<div v-else class="text-red">
|
||||||
{{ $t("product.soldOut") }}
|
{{ $t("product.soldOut") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</v-col>
|
<!-- </template> -->
|
||||||
</v-row>
|
|
||||||
</template>
|
|
||||||
</card-view>
|
</card-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import AccountPage from "@/pages/accountPage/index.vue";
|
import AccountPage from "@/pages/accountPage/index.vue";
|
||||||
import OrdersPage from "@/pages/ordersPage/index.vue";
|
import OrdersPage from "@/pages/ordersPage/index.vue";
|
||||||
import PreferencesPage from "@/pages/preferencesPage/index.vue";
|
import PreferencesPage from "@/pages/preferencesPage/index.vue";
|
||||||
import ProductsPage from "@/pages/productsPage/index.vue";
|
import TourPage from "@/pages/toursPage/index.vue";
|
||||||
import LoginPage from "@/pages/loginPage/index.vue"
|
import LoginPage from "@/pages/loginPage/index.vue"
|
||||||
import BasketPage from "@/pages/basketPage/index.vue"
|
import BasketPage from "@/pages/basketPage/index.vue"
|
||||||
import HelpPage from "@/pages/helpPage/index.vue"
|
import HelpPage from "@/pages/helpPage/index.vue"
|
||||||
@@ -9,7 +9,7 @@ import ScoreBoardPage from "@/pages/scoreBoardPage/index.vue"
|
|||||||
import adminRoutes from "./admin.routes";
|
import adminRoutes from "./admin.routes";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{ path: '/', component: ProductsPage },
|
{ path: '/', component: TourPage },
|
||||||
{ path: '/account', component: AccountPage },
|
{ path: '/account', component: AccountPage },
|
||||||
{ path: '/orders', component: OrdersPage },
|
{ path: '/orders', component: OrdersPage },
|
||||||
{ path: '/preferences', component: PreferencesPage },
|
{ path: '/preferences', component: PreferencesPage },
|
||||||
|
|||||||
Reference in New Issue
Block a user