Working on product detail dialog

This commit is contained in:
2024-09-08 20:35:10 +02:00
parent f82f6ce9af
commit 20e8ce1024
5 changed files with 85 additions and 9 deletions

View File

@@ -26,6 +26,9 @@ export class Product extends Model {
@Column @Column
imageUrl: string imageUrl: string
@Column
description: string
// Relations // Relations
@BelongsTo(() => Category) @BelongsTo(() => Category)

View File

@@ -31,14 +31,24 @@ api.get("/resetdatabase", (req: Request, res: Response, next: NextFunction) => {
Product.bulkCreate( Product.bulkCreate(
[ [
{ id: 0, brand: "Lenovo", name: "Thinkpad T14", price: 799.99, categoryId: 0, discount: 10, rating: 4.6, imageUrl: "https://f.media-amazon.com/images/I/51OHlMuJ5pL._AC_SL1280_.jpg" }, { id: 0, brand: "Lenovo", name: "Thinkpad T14", price: 799.99, categoryId: 0, discount: 10,
{ id: 1, brand: "Puma", name: "Men's Shirt", price: 14.99, categoryId: 2, discount: 0, rating: 3.8, imageUrl: "https://images.unsplash.com/photo-1496346236646-50e985b31ea4?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NHx8dCUyMHNoaXJ0JTIwbWVufGVufDB8fDB8fHww" }, rating: 4.6, description: "Die stabile Arbeitsmaschine. Mit AMD Ryzen 7 89029U, 128 GB RAM und 8 TB M.2 SSD!", imageUrl: "https://f.media-amazon.com/images/I/51OHlMuJ5pL._AC_SL1280_.jpg" },
{ id: 2, brand: "Puma", name: "Woman's Shirt", price: 14.99, categoryId: 2, discount: 0, rating: 4.0, imageUrl: "https://images.unsplash.com/photo-1485218126466-34e6392ec754?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8N3x8dCUyMHNoaXJ0JTIwd29tYW58ZW58MHx8MHx8fDA%3D" }, { id: 1, brand: "Puma", name: "Men's Shirt", price: 14.99, categoryId: 2, discount: 0,
{ id: 3, brand: "George Orwell", name: "1984", price: 9.99, categoryId: 3, discount: 0, rating: 4.9, imageUrl: "https://f.media-amazon.com/images/I/81BExVLr8sL._SL1500_.jpg" }, rating: 3.8, description: "", imageUrl: "https://images.unsplash.com/photo-1496346236646-50e985b31ea4?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NHx8dCUyMHNoaXJ0JTIwbWVufGVufDB8fDB8fHww" },
{ id: 4, brand: "Johann W. Goethe", name: "Faust", price: 4.99, categoryId: 3, discount: 0, rating: 4.2, imageUrl: "https://f.media-amazon.com/images/I/71p1k4JwDqL._SL1500_.jpg" }, { id: 2, brand: "Puma", name: "Woman's Shirt", price: 14.99, categoryId: 2, discount: 0,
{ id: 5, brand: "Theodor Sturm", name: "Der Schimmelreiter", price: 4.99, categoryId: 3, discount: 0, rating: 3.5, imageUrl: "https://f.media-amazon.com/images/I/81uUWtGmKtL._SL1500_.jpg" }, rating: 4.0, description: "", imageUrl: "https://images.unsplash.com/photo-1485218126466-34e6392ec754?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8N3x8dCUyMHNoaXJ0JTIwd29tYW58ZW58MHx8MHx8fDA%3D" },
{ id: 6, brand: "Aldous Huxley", name: "Brave New World", price: 7.99, categoryId: 3, discount: 0, rating: 4.4, imageUrl: "https://f.media-amazon.com/images/I/917t3Joq2WL._SL1500_.jpg" }, { id: 3, brand: "George Orwell", name: "1984", price: 9.99, categoryId: 3, discount: 0,
{ id: 7, brand: "Ankermann", name: "Gaming Work V3", price: 1299.99, categoryId: 0, discount: 0, rating: 4.7, imageUrl: "https://f.media-amazon.com/images/I/81gpDyNWhzL._AC_SL1500_.jpg" } rating: 4.9, imageUrl: "https://f.media-amazon.com/images/I/81BExVLr8sL._SL1500_.jpg",
description: "BIG BROTHER IS WATCHING YOU! George Orwells 1984 ist längst zu einer scheinbar nicht mehr erklärungsbedürftigen Metapher für totalitäre Verhältnisse geworden. Mit atemberaubender Unerbittlichkeit zeichnet der Autor das erschreckende Bild einer durch und..." },
{ id: 4, brand: "Johann W. Goethe", name: "Faust", price: 4.99, categoryId: 3, discount: 0,
rating: 4.2, description: "", imageUrl: "https://f.media-amazon.com/images/I/71p1k4JwDqL._SL1500_.jpg" },
{ id: 5, brand: "Theodor Sturm", name: "Der Schimmelreiter", price: 4.99, categoryId: 3, discount: 0,
rating: 3.5, description: "", imageUrl: "https://f.media-amazon.com/images/I/81uUWtGmKtL._SL1500_.jpg" },
{ id: 6, brand: "Aldous Huxley", name: "Brave New World", price: 7.99, categoryId: 3, discount: 0,
rating: 4.4, imageUrl: "https://f.media-amazon.com/images/I/917t3Joq2WL._SL1500_.jpg",
description: "Brave New World beschreibt eine genormte Gesellschaft, in der Föten genetisch manipuliert und Menschen konditioniert werden. Ziel des Staates ist Zufriedenheit und Stabilität, und dies wird durch Gleichheit, Drogen und Propaganda erreicht. Gott und Religion..." },
{ id: 7, brand: "Ankermann", name: "Gaming Work V3", price: 1299.99, categoryId: 0, discount: 0,
rating: 4.7, description: "", imageUrl: "https://f.media-amazon.com/images/I/81gpDyNWhzL._AC_SL1500_.jpg" }
] ]
) )

View File

@@ -2,6 +2,7 @@ export class ProductModel {
id: number = -1 id: number = -1
brand: string = "" brand: string = ""
name: string = "" name: string = ""
description: string = ""
categoryId: number = 0 categoryId: number = 0
price: number = 0 price: number = 0
discount: number = 0 discount: number = 0

View File

@@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import productCard from "./productCard.vue" import productCard from "./productCard.vue"
import productDetails from "./productDetails.vue"
import filterBar from "./filterBar.vue" import filterBar from "./filterBar.vue"
import axios from "axios"; import axios from "axios";
import { Ref, ref, watch } from "vue"; import { Ref, ref, watch } from "vue";
@@ -13,6 +14,8 @@ const categories: Ref<Array<CategoryModel>> = ref<Array<CategoryModel>>([new Cat
const selectedCategory: Ref<CategoryModel> = ref<CategoryModel>(new CategoryModel()) const selectedCategory: Ref<CategoryModel> = ref<CategoryModel>(new CategoryModel())
const sortedBy: Ref<FilterModel> = ref<FilterModel>() const sortedBy: Ref<FilterModel> = ref<FilterModel>()
const onlyDiscounts: Ref<boolean> = ref(false) const onlyDiscounts: Ref<boolean> = ref(false)
const showProductDetails = ref(false)
const dialogProduct = ref(new ProductModel())
const sortBy: Array<FilterModel> = [ const sortBy: Array<FilterModel> = [
{ icon: "mdi-sort-ascending", name: "Price: Low to high" }, { icon: "mdi-sort-ascending", name: "Price: Low to high" },
@@ -100,6 +103,11 @@ function filterProducts() {
} }
} }
function showProductDialog(product: ProductModel) {
dialogProduct.value = product
showProductDetails.value = true
}
watch(() => selectedCategory.value, () => { filterProducts() }) watch(() => selectedCategory.value, () => { filterProducts() })
watch(() => sortedBy.value, () => { sortProducts() }) watch(() => sortedBy.value, () => { sortProducts() })
watch(() => onlyDiscounts.value, () => { filterProducts() }) watch(() => onlyDiscounts.value, () => { filterProducts() })
@@ -123,6 +131,7 @@ watch(() => onlyDiscounts.value, () => { filterProducts() })
<product-card <product-card
:product="product" :product="product"
:category="getCategoryById(product.categoryId)" :category="getCategoryById(product.categoryId)"
@click="showProductDialog(product)"
/> />
</v-col> </v-col>
@@ -133,4 +142,6 @@ watch(() => onlyDiscounts.value, () => { filterProducts() })
/> />
</v-col> </v-col>
</v-row> </v-row>
<product-details v-model="showProductDetails" :product="dialogProduct" :productCategory="getCategoryById(dialogProduct.categoryId)" />
</template> </template>

View File

@@ -1,6 +1,57 @@
<script setup lang="ts"> <script setup lang="ts">
import { VNumberInput } from 'vuetify/labs/VNumberInput'
import { ProductModel } from '@/data/models/productModel';
import { CategoryModel } from '@/data/models/categoryModel';
import { ref } from 'vue';
const showDialog = defineModel("showDialog", { type: Boolean })
const nrOfArticles = ref(1)
defineProps({
product: ProductModel,
productCategory: CategoryModel
})
</script> </script>
<template> <template>
<v-dialog max-width="800" v-model="showDialog">
<v-card :title="product.name" :subtitle="product.brand" >
<v-img :src="product.imageUrl" max-height="300" />
<v-card-text>
<v-row>
<v-col>
<v-icon :icon="productCategory.icon" />
{{ productCategory.name }}
</v-col>
</v-row>
<v-row>
<v-col>
{{ product.description }}
</v-col>
</v-row>
<v-row>
<v-col>
<v-number-input
:reverse="false"
controlVariant="default"
label="Anzahl"
:hideInput="false"
:inset="false"
v-model="nrOfArticles"
/>
</v-col>
<v-col>
{{ nrOfArticles * product.price }}
</v-col>
</v-row>
</v-card-text>
<v-card-actions>
<v-btn prepend-icon="mdi-cart-plus" >Zum Einkaufswagen hinzufügen</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template> </template>