Matching UI with improved API
This commit is contained in:
@@ -2,12 +2,18 @@
|
||||
"data": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Unregistered",
|
||||
"privilegeBuy": false,
|
||||
"privilegeAdminPanel": false
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "User",
|
||||
"privilegeBuy": true,
|
||||
"privilegeAdminPanel": false
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"id": 2,
|
||||
"name": "Admin",
|
||||
"privilegeBuy": true,
|
||||
"privilegeAdminPanel": true
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"iban": "DE92500105175721645777"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 1
|
||||
"accountRoleId": 2
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
@@ -46,7 +46,7 @@
|
||||
"iban": "DE12500105179557939114"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 0
|
||||
"accountRoleId": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
@@ -77,7 +77,7 @@
|
||||
"iban": "DE31500105175417833272"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 0
|
||||
"accountRoleId": 1
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
@@ -101,7 +101,7 @@
|
||||
"iban": "DE41500105172184936679"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 0
|
||||
"accountRoleId": 1
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
@@ -125,7 +125,7 @@
|
||||
"iban": "DE85500105172283979774"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 0
|
||||
"accountRoleId": 1
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
@@ -149,7 +149,7 @@
|
||||
"iban": "DE45500105178862417577"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 0
|
||||
"accountRoleId": 1
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
@@ -180,7 +180,7 @@
|
||||
"iban": "DE51500105177526222196"
|
||||
}
|
||||
],
|
||||
"accountRoleId": 0
|
||||
"accountRoleId": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,20 +22,20 @@ account.post("/login", (req: Request, res: Response) => {
|
||||
if (account != null) {
|
||||
if (account.dataValues.password == req.body.password) {
|
||||
// Status: 200 OK
|
||||
res.status(200).json(account).send()
|
||||
res.status(200).json(account)
|
||||
} else {
|
||||
// Status: 401 Unauthorized
|
||||
res.status(401).json({
|
||||
code: 401,
|
||||
message: "Unauthorized"
|
||||
}).send()
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Status: 400 Bad request
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: "Bad Request"
|
||||
}).send()
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -50,7 +50,7 @@ account.post("/", (req: Request, res: Response) => {
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: "Username too short!"
|
||||
}).send()
|
||||
})
|
||||
}
|
||||
|
||||
// Check if password is valid
|
||||
@@ -60,20 +60,20 @@ account.post("/", (req: Request, res: Response) => {
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: "Password too short!"
|
||||
}).send()
|
||||
})
|
||||
}
|
||||
|
||||
// Create account
|
||||
Account.create(req.body)
|
||||
.then(account => {
|
||||
// Status: 201 Created
|
||||
res.status(201).json(account).send()
|
||||
res.status(201).json(account)
|
||||
}).catch(reason => {
|
||||
// Status: 409 Conflict
|
||||
res.status(409).json({
|
||||
code: 409,
|
||||
message: "Username already in use"
|
||||
}).send()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -84,13 +84,13 @@ account.patch("/", (req: Request, res: Response) => {
|
||||
})
|
||||
.then(account => {
|
||||
// Status: 200 OK
|
||||
res.status(200).json(account).send()
|
||||
res.status(200).json(account)
|
||||
})
|
||||
.catch(error => {
|
||||
// Status: 400 Bad request
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: error
|
||||
}).send()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,7 +7,7 @@ export const category = Router()
|
||||
category.get("/", (req: Request, res: Response, next: NextFunction) => {
|
||||
Category.findAll()
|
||||
.then(categories => {
|
||||
res.status(200).json(categories).send()
|
||||
res.status(200).json(categories)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -15,13 +15,13 @@ category.get("/", (req: Request, res: Response, next: NextFunction) => {
|
||||
category.post("/", (req: Request, res: Response, next: NextFunction) => {
|
||||
Category.create(req.body)
|
||||
.then(category => {
|
||||
res.status(201).json(category).send()
|
||||
res.status(201).json(category)
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: error
|
||||
}).send()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -31,12 +31,12 @@ category.delete("/:id", (req: Request, res: Response, next: NextFunction) => {
|
||||
where: { id: req.params.id }
|
||||
})
|
||||
.then(category => {
|
||||
res.status(200).json(category).send()
|
||||
res.status(200).json(category)
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: error
|
||||
}).send()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -2,6 +2,8 @@ import { Router, Request, Response } from "express";
|
||||
import { Order } from "../models/order.model";
|
||||
import { Product } from "../models/product.model";
|
||||
import { OrderItem } from "../models/orderItem.model";
|
||||
import { Brand } from "../models/brand.model";
|
||||
import { Category } from "../models/category.model";
|
||||
|
||||
export const order = Router()
|
||||
|
||||
@@ -10,7 +12,21 @@ order.get("/:id", (req: Request, res: Response) => {
|
||||
Order.findAll({
|
||||
where: { accountId: req.params.id },
|
||||
include: [
|
||||
{ model: OrderItem, include: [ Product ] }
|
||||
{
|
||||
model: OrderItem,
|
||||
include: [
|
||||
{
|
||||
model: Product,
|
||||
include: [ Brand, Category ],
|
||||
attributes: {
|
||||
exclude: [
|
||||
"categoryId",
|
||||
"brandId"
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
.then(orders => {
|
||||
@@ -42,6 +58,6 @@ order.post("/", (req: Request, res: Response) => {
|
||||
}
|
||||
|
||||
// Created
|
||||
res.status(201).json(order).send()
|
||||
res.status(201).json(order)
|
||||
})
|
||||
})
|
||||
@@ -36,7 +36,7 @@ product.get("/:productId", (req: Request, res: Response) => {
|
||||
}
|
||||
)
|
||||
.then(product => {
|
||||
res.status(200).json(product).send()
|
||||
res.status(200).json(product)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -44,13 +44,13 @@ product.get("/:productId", (req: Request, res: Response) => {
|
||||
product.post("/", (req: Request, res: Response) => {
|
||||
Product.create(req.body)
|
||||
.then(product => {
|
||||
res.status(201).json(product).send()
|
||||
res.status(201).json(product)
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: error
|
||||
}).send()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -60,12 +60,12 @@ product.delete("/:id", (req: Request, res: Response) => {
|
||||
where: { id: req.params.id }
|
||||
})
|
||||
.then(product => {
|
||||
res.status(200).json(product).send()
|
||||
res.status(200).json(product)
|
||||
})
|
||||
.catch(error => {
|
||||
res.status(400).json({
|
||||
code: 400,
|
||||
message: error
|
||||
}).send()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,27 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
import { useTheme } from 'vuetify/lib/framework.mjs';
|
||||
import { useUserStore } from './data/stores/userStore';
|
||||
import { i18n } from './plugins/i18n';
|
||||
import { ref, watch } from 'vue';
|
||||
import vuetify from './plugins/vuetify';
|
||||
import navigationItems from './components/navigationItems.vue';
|
||||
import { useProductStore } from './data/stores/productStore';
|
||||
import { useCategoryStore } from './data/stores/categoryStore';
|
||||
import { usePreferencesStore } from './data/stores/preferencesStore';
|
||||
|
||||
const userStore = useUserStore()
|
||||
const preferencesStore = usePreferencesStore()
|
||||
const productStore = useProductStore()
|
||||
const categoryStore = useCategoryStore()
|
||||
const theme = useTheme()
|
||||
const navRail = ref(vuetify.display.mobile)
|
||||
|
||||
theme.global.name.value = userStore.theme
|
||||
theme.global.name.value = preferencesStore.theme
|
||||
|
||||
productStore.fetchAllProducts()
|
||||
categoryStore.fetchAllCategories()
|
||||
|
||||
// Global watcher
|
||||
watch(() => userStore.language, () => {
|
||||
i18n.global.locale = userStore.language
|
||||
watch(() => preferencesStore.language, () => {
|
||||
i18n.global.locale = preferencesStore.language
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import { useBasketStore } from '@/data/stores/basketStore';
|
||||
import { useAccountStore } from '@/data/stores/accountStore';
|
||||
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
const basketStore = useBasketStore()
|
||||
const navRail = defineModel("navRail", { type: Boolean })
|
||||
</script>
|
||||
@@ -36,16 +36,16 @@ const navRail = defineModel("navRail", { type: Boolean })
|
||||
</v-list-subheader>
|
||||
|
||||
<v-expand-transition>
|
||||
<div v-if="!userStore.loggedIn">
|
||||
<v-list-item v-if="!userStore.loggedIn" :title="$t('menu.login')" prepend-icon="mdi-login" to="/login" link />
|
||||
<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 />
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
|
||||
<v-expand-transition>
|
||||
<div v-if="userStore.loggedIn">
|
||||
<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.orders')" prepend-icon="mdi-cart-check" to="/orders" link />
|
||||
<v-list-item :title="$t('menu.logout')" prepend-icon="mdi-logout" @click="userStore.logout" link />
|
||||
<v-list-item :title="$t('menu.logout')" prepend-icon="mdi-logout" @click="accountStore.logout" link />
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { AccountRole } from "./accountRole"
|
||||
import { AddressModel } from "./addressModel"
|
||||
import { PaymentModel } from "./paymentModel"
|
||||
|
||||
export class AccountModel {
|
||||
id: number
|
||||
username: string = ""
|
||||
password: string = ""
|
||||
street: string = ""
|
||||
houseNumber: number = 0
|
||||
postalCode: number = 0
|
||||
city: string = ""
|
||||
firstName: string = ""
|
||||
lastName: string = ""
|
||||
createdAt: string = ""
|
||||
updatedAt: string = ""
|
||||
bankName: string = ""
|
||||
iban: string = ""
|
||||
addresses: Array<AddressModel> = [ new AddressModel() ]
|
||||
payments: Array<PaymentModel> = [ new PaymentModel() ]
|
||||
accountRole: AccountRole = new AccountRole()
|
||||
}
|
||||
5
software/src/data/models/accountRole.ts
Normal file
5
software/src/data/models/accountRole.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export class AccountRole {
|
||||
name: string = ""
|
||||
privilegeBuy: boolean = false
|
||||
privilegeAdminPanel: boolean = false
|
||||
}
|
||||
6
software/src/data/models/addressModel.ts
Normal file
6
software/src/data/models/addressModel.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export class AddressModel {
|
||||
street: string = ""
|
||||
houseNumber: number = 0
|
||||
postalCode: number = 0
|
||||
city: string = ""
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
import { ProductModel } from "./productModel"
|
||||
|
||||
export class BasketItemModel {
|
||||
id: number = -1
|
||||
brand: string = ""
|
||||
name: string = ""
|
||||
categoryName: string = ""
|
||||
categoryIcon: string = ""
|
||||
price: number = 0
|
||||
discount: number = 0
|
||||
quantity: number = 1
|
||||
product: ProductModel = new ProductModel()
|
||||
}
|
||||
4
software/src/data/models/brandModel.ts
Normal file
4
software/src/data/models/brandModel.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export class BrandModel {
|
||||
id: number = 0
|
||||
name: string = ""
|
||||
}
|
||||
@@ -2,6 +2,4 @@ export class CategoryModel {
|
||||
id: number = -1
|
||||
name: string
|
||||
icon: string
|
||||
createdAt: string = ""
|
||||
updatedAt: string = ""
|
||||
}
|
||||
@@ -2,8 +2,7 @@ import { OrderedItemModel } from "./orderedItemModel"
|
||||
|
||||
export class OrderModel {
|
||||
accountId: number
|
||||
totalPrice: number
|
||||
shippingProgress: number
|
||||
orderItem: Array<OrderedItemModel>
|
||||
createdAt: string
|
||||
orderItems: Array<OrderedItemModel>
|
||||
orderedAt: string
|
||||
}
|
||||
4
software/src/data/models/paymentModel.ts
Normal file
4
software/src/data/models/paymentModel.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export class PaymentModel {
|
||||
bankName: string = ""
|
||||
iban: string = ""
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
import { BrandModel } from "./brandModel"
|
||||
import { CategoryModel } from "./categoryModel"
|
||||
|
||||
export class ProductModel {
|
||||
id: number = -1
|
||||
brand: string
|
||||
name: string
|
||||
id: number = 0
|
||||
category: CategoryModel = new CategoryModel()
|
||||
brand: BrandModel = new BrandModel()
|
||||
name: string = ""
|
||||
description: string = ""
|
||||
specs: Array<string> = []
|
||||
categoryId: number
|
||||
price: number = 0
|
||||
discount: number = 0
|
||||
rating: number = 1
|
||||
inStock: number
|
||||
specs: Array<string> = []
|
||||
images: Array<string> = [""]
|
||||
storedItems: number
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { CategoryModel } from "./categoryModel"
|
||||
|
||||
export class ProductWithCategoryModel {
|
||||
id: number = -1
|
||||
brand: string
|
||||
name: string
|
||||
description: string = ""
|
||||
specs: Array<string> = []
|
||||
category: CategoryModel = new CategoryModel()
|
||||
price: number = 0
|
||||
discount: number = 0
|
||||
rating: number = 1
|
||||
images: Array<string> = [""]
|
||||
storedItems: number
|
||||
}
|
||||
@@ -1,21 +1,16 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
import { ThemeEnum } from "../enums/themeEnums";
|
||||
import { LanguageEnum } from "../enums/languageEnum";
|
||||
import { defineStore } from "pinia";
|
||||
import { AccountModel } from "../models/accountModel";
|
||||
import { loginAccount, registerAccount, updateAccount } from "../api/accountApi";
|
||||
import { useFeedbackStore } from "./feedbackStore";
|
||||
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
||||
import { OrderModel } from "../models/orderModel";
|
||||
import { useFeedbackStore } from "./feedbackStore";
|
||||
import { loginAccount, registerAccount, updateAccount } from "../api/accountApi";
|
||||
import { getUserOrders } from "../api/orderApi";
|
||||
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
||||
|
||||
export const useUserStore = defineStore('userStore', {
|
||||
export const useAccountStore = defineStore("accountStore", {
|
||||
state: () => ({
|
||||
theme: useLocalStorage<ThemeEnum>("hackmycart/userStore/theme", ThemeEnum.DARKRED),
|
||||
language: useLocalStorage<LanguageEnum>("hackmycart/userStore/language", LanguageEnum.GERMAN),
|
||||
userAccount: useLocalStorage<AccountModel>("hackmycart/userStore/userAccount", new AccountModel()),
|
||||
loggedIn: useLocalStorage<Boolean>("hackmycart/userStore/loggedIn", false),
|
||||
orders: useLocalStorage<Array<OrderModel>>("hackmycart/userStore/orders", [])
|
||||
userAccount: useLocalStorage("hackmycart/accountStore/userAccount", new AccountModel()),
|
||||
orders: useLocalStorage<Array<OrderModel>>("hackmycart/accountStore/orders", [ new OrderModel() ])
|
||||
}),
|
||||
|
||||
actions: {
|
||||
@@ -4,11 +4,10 @@ import { calcProductPrice } from "@/scripts/productScripts";
|
||||
import { BasketItemModel } from "../models/basketItemModel";
|
||||
import { useFeedbackStore } from "./feedbackStore";
|
||||
import { BannerStateEnum } from "../enums/bannerStateEnum";
|
||||
import { OrderModel } from "../models/orderModel";
|
||||
import { useUserStore } from "./userStore";
|
||||
import { addOrder } from "../api/orderApi";
|
||||
import { useAccountStore } from "./accountStore";
|
||||
|
||||
export const useBasketStore = defineStore('basket', {
|
||||
export const useBasketStore = defineStore('basketStore', {
|
||||
state: () => ({
|
||||
itemsInBasket: useLocalStorage<Array<BasketItemModel>>("hackmycart/basketStore/productsInBasket", [])
|
||||
}),
|
||||
@@ -31,7 +30,7 @@ export const useBasketStore = defineStore('basket', {
|
||||
feedbackStore.changeBanner(BannerStateEnum.BASKETPRODUCTREMOVED)
|
||||
|
||||
this.itemsInBasket = this.itemsInBasket.filter((basketItemModel: BasketItemModel) =>
|
||||
basketItemModel.productId != item.productId
|
||||
basketItemModel.product.id != item.product.id
|
||||
)
|
||||
},
|
||||
|
||||
@@ -40,15 +39,16 @@ export const useBasketStore = defineStore('basket', {
|
||||
feedbackStore.changeBanner(BannerStateEnum.BASKETPRODUCTADDED)
|
||||
|
||||
// Product is already in the basket, increase number of items
|
||||
if (this.itemsInBasket.find((basketItem) => basketItem.productId == item.productId)) {
|
||||
this.itemsInBasket.find((basketItem) => basketItem.productId == item.productId).quantity += item.quantity
|
||||
if (this.itemsInBasket.find((basketItem) => basketItem.productId == item.product.id)) {
|
||||
this.itemsInBasket.find((basketItem) =>
|
||||
basketItem.productId == item.product.id).quantity += item.quantity
|
||||
} else {
|
||||
this.itemsInBasket.push(item)
|
||||
}
|
||||
},
|
||||
|
||||
takeOrder() {
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
//
|
||||
// const order = new OrderModel()
|
||||
// order.accountId = userStore.userAccount.id
|
||||
@@ -56,7 +56,7 @@ export const useBasketStore = defineStore('basket', {
|
||||
//
|
||||
// console.log(order)
|
||||
|
||||
addOrder(userStore.userAccount.id, this.itemsInBasket)
|
||||
addOrder(accountStore.userAccount.id, this.itemsInBasket)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
11
software/src/data/stores/preferencesStore.ts
Normal file
11
software/src/data/stores/preferencesStore.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
import { ThemeEnum } from "../enums/themeEnums";
|
||||
import { LanguageEnum } from "../enums/languageEnum";
|
||||
|
||||
export const usePreferencesStore = defineStore('preferencesStore', {
|
||||
state: () => ({
|
||||
theme: useLocalStorage<ThemeEnum>("hackmycart/preferencesStore/theme", ThemeEnum.DARKRED),
|
||||
language: useLocalStorage<LanguageEnum>("hackmycart/preferencesStore/language", LanguageEnum.GERMAN)
|
||||
}),
|
||||
})
|
||||
@@ -3,13 +3,13 @@ import { defineStore } from "pinia";
|
||||
import { getAllProducts } from "../api/productApi";
|
||||
import { SortOrder } from "../enums/sortOrderEnum";
|
||||
import { CategoryModel } from "../models/categoryModel";
|
||||
import { ProductWithCategoryModel } from "../models/productWithCategoryModel";
|
||||
import { ProductModel } from "../models/productModel";
|
||||
|
||||
|
||||
export const useProductStore = defineStore("productStore", {
|
||||
state: () => ({
|
||||
products: useLocalStorage<Array<ProductWithCategoryModel>>("hackmycart/productStore/products", []),
|
||||
filteredProducts: useLocalStorage<Array<ProductWithCategoryModel>>("hackmycart/productStore/filteredProducts", []),
|
||||
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)
|
||||
@@ -28,20 +28,20 @@ export const useProductStore = defineStore("productStore", {
|
||||
if (this.filteredCategory.id == -1 || this.filteredCategory.id == 0) {
|
||||
this.filteredProducts = this.products
|
||||
} else {
|
||||
this.filteredProducts = this.products.filter((product: ProductWithCategoryModel) =>
|
||||
this.filteredProducts = this.products.filter((product: ProductModel) =>
|
||||
product.category.id == this.filteredCategory.id
|
||||
)
|
||||
}
|
||||
|
||||
if (this.onlyDiscounts) {
|
||||
this.filteredProducts = this.filteredProducts.filter((product: ProductWithCategoryModel) =>
|
||||
this.filteredProducts = this.filteredProducts.filter((product: ProductModel) =>
|
||||
product.discount > 0
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
sortProducts() {
|
||||
this.filteredProducts.sort((a: ProductWithCategoryModel, b: ProductWithCategoryModel) => {
|
||||
this.filteredProducts.sort((a: ProductModel, b: ProductModel) => {
|
||||
switch (this.sortOrder)
|
||||
{
|
||||
case SortOrder.PRICELOWTOHIGH: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import cardView from '@/components/cardView.vue';
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
import { useAccountStore } from '@/data/stores/accountStore';
|
||||
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -13,14 +13,14 @@ const userStore = useUserStore()
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('account.username')"
|
||||
v-model="userStore.userAccount.username"
|
||||
v-model="accountStore.userAccount.username"
|
||||
disabled
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('account.password')"
|
||||
v-model="userStore.userAccount.password"
|
||||
v-model="accountStore.userAccount.password"
|
||||
type="password"
|
||||
/>
|
||||
</v-col>
|
||||
@@ -30,13 +30,13 @@ const userStore = useUserStore()
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.firstName')"
|
||||
v-model="userStore.userAccount.firstName"
|
||||
v-model="accountStore.userAccount.firstName"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.lastName')"
|
||||
v-model="userStore.userAccount.lastName"
|
||||
v-model="accountStore.userAccount.lastName"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@@ -45,13 +45,13 @@ const userStore = useUserStore()
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.street')"
|
||||
v-model="userStore.userAccount.street"
|
||||
v-model="accountStore.userAccount.addresses[0].street"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.houseNumber')"
|
||||
v-model="userStore.userAccount.houseNumber"
|
||||
v-model="accountStore.userAccount.addresses[0].houseNumber"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@@ -60,13 +60,13 @@ const userStore = useUserStore()
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.postalCode')"
|
||||
v-model="userStore.userAccount.postalCode"
|
||||
v-model="accountStore.userAccount.addresses[0].postalCode"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.city')"
|
||||
v-model="userStore.userAccount.city"
|
||||
v-model="accountStore.userAccount.addresses[0].city"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@@ -75,13 +75,13 @@ const userStore = useUserStore()
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.bankName')"
|
||||
v-model="userStore.userAccount.bankName"
|
||||
v-model="accountStore.userAccount.payments[0].bankName"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
:label="$t('userInfo.iban')"
|
||||
v-model="userStore.userAccount.iban"
|
||||
v-model="accountStore.userAccount.payments[0].iban"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@@ -89,7 +89,7 @@ const userStore = useUserStore()
|
||||
|
||||
<template #actions>
|
||||
<outlined-button
|
||||
@click="userStore.updateAccount()"
|
||||
@click="accountStore.updateAccount()"
|
||||
prepend-icon="mdi-content-save"
|
||||
color="green"
|
||||
>
|
||||
|
||||
@@ -3,13 +3,13 @@ import { useBasketStore } from '@/data/stores/basketStore';
|
||||
import productsTable from './productsTable.vue';
|
||||
import alertBanner from '@/components/alertBanner.vue';
|
||||
import cardView from '@/components/cardView.vue';
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import orderingDialog from './orderingDialog.vue';
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
import { ref } from 'vue';
|
||||
import { useAccountStore } from '@/data/stores/accountStore';
|
||||
|
||||
const basketStore = useBasketStore()
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
const showOrderingDialog = ref()
|
||||
</script>
|
||||
|
||||
@@ -47,7 +47,7 @@ const showOrderingDialog = ref()
|
||||
<template #actions>
|
||||
<outlined-button
|
||||
prepend-icon="mdi-basket-check"
|
||||
:disabled="basketStore.itemsInBasket.length == 0 || userStore.userAccount.id == null"
|
||||
:disabled="basketStore.itemsInBasket.length == 0 || accountStore.userAccount.id == null"
|
||||
variant="outlined"
|
||||
color="green"
|
||||
@click="showOrderingDialog = true"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import { ref } from 'vue';
|
||||
import cardView from '@/components/cardView.vue';
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
import { useAccountStore } from '@/data/stores/accountStore';
|
||||
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, default: false })
|
||||
const username = ref("duranduran")
|
||||
const password = ref("H4nn0ver")
|
||||
|
||||
function startLogin() {
|
||||
userStore.login(username.value, password.value)
|
||||
accountStore.login(username.value, password.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { AccountModel } from '@/data/models/accountModel';
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import { ref } from 'vue';
|
||||
import cardView from '@/components/cardView.vue';
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
import { useAccountStore } from '@/data/stores/accountStore';
|
||||
|
||||
const newUser = ref(new AccountModel())
|
||||
const showRegisterCard = defineModel("showRegisterCard", { type: Boolean, default: false })
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -54,12 +54,12 @@ const userStore = useUserStore()
|
||||
<v-text-field
|
||||
:label="$t('userInfo.street')"
|
||||
prepend-icon="mdi-numeric"
|
||||
v-model="newUser.street"
|
||||
v-model="newUser.addresses[0].street"
|
||||
clearable
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="4">
|
||||
<v-text-field :label="$t('userInfo.houseNumber')" v-model="newUser.houseNumber" clearable />
|
||||
<v-text-field :label="$t('userInfo.houseNumber')" v-model="newUser.addresses[0].houseNumber" clearable />
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
@@ -68,12 +68,12 @@ const userStore = useUserStore()
|
||||
<v-text-field
|
||||
:label="$t('userInfo.postalCode')"
|
||||
prepend-icon="mdi-city"
|
||||
v-model="newUser.postalCode"
|
||||
v-model="newUser.addresses[0].postalCode"
|
||||
clearable
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field :label="$t('userInfo.city')" v-model="newUser.city" clearable />
|
||||
<v-text-field :label="$t('userInfo.city')" v-model="newUser.addresses[0].city" clearable />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
@@ -88,7 +88,7 @@ const userStore = useUserStore()
|
||||
|
||||
<outlined-button
|
||||
prepend-icon="mdi-account-plus"
|
||||
@click="userStore.registerAccount(newUser)"
|
||||
@click="accountStore.registerAccount(newUser)"
|
||||
>
|
||||
{{ $t('account.register') }}
|
||||
</outlined-button>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import { useAccountStore } from '@/data/stores/accountStore';
|
||||
import ordersCard from './ordersCard.vue';
|
||||
|
||||
const userStore = useUserStore()
|
||||
const accountStore = useAccountStore()
|
||||
|
||||
function getDotColor(order, step: number) {
|
||||
if (order.shippingProgress == step)
|
||||
@@ -27,7 +27,7 @@ function formatDateTimeString(string: string) {
|
||||
|
||||
<template>
|
||||
<v-container max-width="1000">
|
||||
<v-row v-for="order in userStore.orders">
|
||||
<v-row v-for="order in accountStore.orders">
|
||||
<v-col>
|
||||
<orders-card :order="order" />
|
||||
</v-col>
|
||||
|
||||
@@ -29,8 +29,8 @@ function formatDateTimeString(string: string) {
|
||||
|
||||
<template>
|
||||
<card-view
|
||||
:title="$t('orders.orderFrom') + ' ' + formatDateTimeString(order.createdAt) + ' ' + $t('oclock')"
|
||||
:subtitle="$t('totalPrice') + ': ' + order.totalPrice + ' €'"
|
||||
:title="$t('orders.orderFrom') + ' ' + formatDateTimeString(order.orderedAt) + ' ' + $t('oclock')"
|
||||
:subtitle="$t('totalPrice') + ': ' + 0 + ' €'"
|
||||
>
|
||||
<v-timeline direction="horizontal" side="start" size="x-large">
|
||||
<v-timeline-item :dot-color="getDotColor(order, 1)" icon="mdi-basket-check">
|
||||
@@ -64,9 +64,9 @@ function formatDateTimeString(string: string) {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="orderItem in order.orderItem">
|
||||
<tr v-for="orderItem in order.orderItems">
|
||||
<td>{{ orderItem.quantity }}x</td>
|
||||
<td>{{ orderItem.product.brand }}</td>
|
||||
<td>{{ orderItem.product.brand.name }}</td>
|
||||
<td>{{ orderItem.product.name }}</td>
|
||||
<td>{{ orderItem.product.price }} €</td>
|
||||
</tr>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { ThemeEnum } from '@/data/enums/themeEnums';
|
||||
import { useTheme } from 'vuetify/lib/framework.mjs';
|
||||
import { useUserStore } from '@/data/stores/userStore';
|
||||
import { i18n } from '@/plugins/i18n';
|
||||
import cardView from '@/components/cardView.vue';
|
||||
import { usePreferencesStore } from '@/data/stores/preferencesStore';
|
||||
|
||||
const userStore = useUserStore()
|
||||
const preferencesStore = usePreferencesStore()
|
||||
const theme = useTheme()
|
||||
const themeEnums = Object.values(ThemeEnum)
|
||||
|
||||
function changeTheme() {
|
||||
theme.global.name.value = userStore.theme
|
||||
theme.global.name.value = preferencesStore.theme
|
||||
}
|
||||
|
||||
function changeLanguage() {
|
||||
i18n.global.locale = userStore.language
|
||||
i18n.global.locale = preferencesStore.language
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -24,7 +24,7 @@ function changeLanguage() {
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-select
|
||||
v-model="userStore.theme"
|
||||
v-model="preferencesStore.theme"
|
||||
:items="themeEnums"
|
||||
:label="$t('preferences.selectedTheme')"
|
||||
@update:model-value="changeTheme"
|
||||
@@ -34,7 +34,7 @@ function changeLanguage() {
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-select v-model="userStore.language" :items="$i18n.availableLocales" :label="$t('preferences.language')"
|
||||
<v-select v-model="preferencesStore.language" :items="$i18n.availableLocales" :label="$t('preferences.language')"
|
||||
@update:model-value="changeLanguage"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
@@ -3,16 +3,16 @@ import productCard from "./productCard.vue"
|
||||
import productDetails from "./productDetailsDialog.vue"
|
||||
import { ref, watch } from "vue";
|
||||
import { useProductStore } from "@/data/stores/productStore";
|
||||
import { ProductWithCategoryModel } from "@/data/models/productWithCategoryModel";
|
||||
import alertBanner from "@/components/alertBanner.vue";
|
||||
import filterNavDrawer from "./filterNavDrawer.vue";
|
||||
import { ProductModel } from '@/data/models/productModel';
|
||||
|
||||
const productStore = useProductStore()
|
||||
|
||||
const showProductDetails = ref(false)
|
||||
const dialogProduct = ref(new ProductWithCategoryModel())
|
||||
const dialogProduct = ref(new ProductModel())
|
||||
|
||||
function showProductDialog(product: ProductWithCategoryModel) {
|
||||
function showProductDialog(product: ProductModel) {
|
||||
dialogProduct.value = product
|
||||
showProductDetails.value = true
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ProductWithCategoryModel } from '@/data/models/productWithCategoryModel';
|
||||
import { ProductModel } from '@/data/models/productModel';
|
||||
import cardView from '@/components/cardView.vue';
|
||||
|
||||
defineProps({
|
||||
product: {
|
||||
required: true,
|
||||
type: ProductWithCategoryModel
|
||||
type: ProductModel
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -65,11 +65,11 @@ defineProps({
|
||||
</div>
|
||||
|
||||
<div style="position: absolute; bottom: 0; right: 0;" class="pr-2 pb-2">
|
||||
<div v-if="product.storedItems > 5" class="text-green-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.storedItems]) }}
|
||||
<div v-if="product.inStock > 5" class="text-green-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||
</div>
|
||||
<div v-else-if="product.storedItems > 0" class="text-orange-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.storedItems]) }}
|
||||
<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") }}
|
||||
|
||||
@@ -4,13 +4,13 @@ import { ModelRef, ref, watch } from 'vue';
|
||||
import { useBasketStore } from '@/data/stores/basketStore';
|
||||
import { calcProductPrice, productToBasketItem } from '@/scripts/productScripts';
|
||||
import ActionDialog from '@/components/actionDialog.vue'
|
||||
import { ProductWithCategoryModel } from '@/data/models/productWithCategoryModel';
|
||||
import { ProductModel } from '@/data/models/productModel';
|
||||
import outlinedButton from '@/components/outlinedButton.vue';
|
||||
|
||||
const props = defineProps({
|
||||
product: {
|
||||
type: ProductWithCategoryModel,
|
||||
default: new ProductWithCategoryModel()
|
||||
type: ProductModel,
|
||||
default: new ProductModel()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -32,7 +32,7 @@ watch(() => props.product.images, () => {
|
||||
|
||||
<template>
|
||||
<action-dialog
|
||||
:title="product.brand + ': ' + product.name"
|
||||
:title="product.brand.name + ': ' + product.name"
|
||||
:icon="product.category.icon"
|
||||
:subtitle="product.category.name"
|
||||
v-model="showDialog"
|
||||
@@ -107,11 +107,11 @@ watch(() => props.product.images, () => {
|
||||
<v-row>
|
||||
<v-col cols="3">
|
||||
<div class="pt-3">
|
||||
<div v-if="product.storedItems > 5" class="text-green-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.storedItems]) }}
|
||||
<div v-if="product.inStock > 5" class="text-green-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.inStock]) }}
|
||||
</div>
|
||||
<div v-else-if="product.storedItems > 0" class="text-orange-lighten-1">
|
||||
{{ $t("product.storedItemsAvailable", [product.storedItems]) }}
|
||||
<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") }}
|
||||
@@ -147,14 +147,14 @@ watch(() => props.product.images, () => {
|
||||
:max="10"
|
||||
density="comfortable"
|
||||
:hide-details="true"
|
||||
:disabled="product.storedItems == 0"
|
||||
:disabled="product.inStock == 0"
|
||||
/>
|
||||
|
||||
<outlined-button
|
||||
prepend-icon="mdi-cart-plus"
|
||||
@click="addProductToBasket"
|
||||
height="50"
|
||||
:disabled="product.storedItems == 0"
|
||||
:disabled="product.inStock == 0"
|
||||
>
|
||||
{{ $t('addToBasket') }}
|
||||
</outlined-button>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { BasketItemModel } from "@/data/models/basketItemModel";
|
||||
import { CategoryModel } from "@/data/models/categoryModel";
|
||||
import { ProductModel } from "@/data/models/productModel";
|
||||
import { ProductWithCategoryModel } from "@/data/models/productWithCategoryModel";
|
||||
|
||||
export function calcProductPrice(product: ProductWithCategoryModel, quantity: number = 1): number {
|
||||
export function calcProductPrice(product: ProductModel, quantity: number = 1): number {
|
||||
return calcPrice(product.price, product.discount, quantity)
|
||||
}
|
||||
|
||||
@@ -29,7 +28,7 @@ export function calcPrice(price: number, discount: number = 0, quantity: number
|
||||
*
|
||||
* @returns BasketItemModel
|
||||
*/
|
||||
export function productToBasketItem(product: ProductWithCategoryModel, quantity: number): BasketItemModel {
|
||||
export function productToBasketItem(product: ProductModel, quantity: number): BasketItemModel {
|
||||
let result = new BasketItemModel()
|
||||
|
||||
result.productId = product.id
|
||||
|
||||
Reference in New Issue
Block a user