Fix db relations, add sample data, show categories in frontend menu

This commit is contained in:
2024-09-05 16:19:23 +02:00
parent cfd1d29302
commit 8b1a396f68
23 changed files with 502 additions and 129 deletions

View File

@@ -1,11 +1,11 @@
import { Sequelize } from "sequelize-typescript" import { Sequelize } from "sequelize-typescript"
// Models // Models
import { Categories } from "./models/categories.model" import { Category } from "./models/category.model"
import { OrderedItem } from "./models/orderedItem.model" import { OrderedItem } from "./models/orderedItem.model"
import { Orders } from "./models/orders.model" import { Order } from "./models/order.model"
import { Products } from "./models/products.model" import { Product } from "./models/product.model"
import { Users } from "./models/users.model" import { Account } from "./models/account.model"
const dbName = "database" const dbName = "database"
const dbUser = "root" const dbUser = "root"
@@ -18,12 +18,12 @@ export const sequelize = new Sequelize({
username: dbUser, username: dbUser,
password: dbPassword, password: dbPassword,
storage: "database.sqlite", storage: "database.sqlite",
models: [ Categories, OrderedItem, Orders, Products, Users ] models: [ Category, Product, Account, Order, OrderedItem ]
}) })
export function startDatabase() { export function startDatabase() {
// Create database and tables // Create database and tables
sequelize.sync({ force: false }) sequelize.sync({ force: true })
.then(() => { .then(() => {
console.log(`Database & tables created!`) console.log(`Database & tables created!`)
}) })

View File

@@ -1,8 +1,8 @@
import { Table, Column, Model, HasMany } from 'sequelize-typescript'; import { Table, Column, Model, HasMany } from 'sequelize-typescript';
import { Orders } from './orders.model'; import { Order } from './order.model';
@Table @Table
export class Users extends Model { export class Account extends Model {
@Column @Column
username: string username: string
@@ -19,6 +19,6 @@ export class Users extends Model {
lastName: string lastName: string
// Relations // Relations
@HasMany(() => Orders) @HasMany(() => Order)
orders: Orders[] orders: Order[]
} }

View File

@@ -1,14 +0,0 @@
import { Table, Column, Model, BelongsTo, ForeignKey } from 'sequelize-typescript';
import { Products } from './products.model';
@Table
export class Categories extends Model {
@Column
name: string
@ForeignKey(() => Products)
productId: number
@BelongsTo(() => Products)
product: Products
}

View File

@@ -0,0 +1,14 @@
import { Table, Column, Model, BelongsTo, ForeignKey, HasMany } from 'sequelize-typescript';
import { Product } from './product.model';
@Table
export class Category extends Model {
@Column
name: string
@Column
icon: string
@HasMany(() => Product)
product: Product
}

View File

@@ -0,0 +1,21 @@
import { Table, Column, Model, BelongsTo, ForeignKey, HasMany, BelongsToMany } from 'sequelize-typescript';
import { Account } from './account.model';
import { OrderedItem } from './orderedItem.model';
import { Product } from './product.model';
@Table
export class Order extends Model {
@Column
@ForeignKey(() => Account)
accountId: number
@Column
totalPrice: number
// Relations
@BelongsTo(() => Account)
user: Account
@BelongsToMany(() => Product, () => OrderedItem)
orderedItems: OrderedItem
}

View File

@@ -1,15 +1,15 @@
import { Table, Column, Model, BelongsTo, ForeignKey, HasMany } from 'sequelize-typescript'; import { Table, Column, Model, BelongsTo, ForeignKey, HasMany } from 'sequelize-typescript';
import { Orders } from './orders.model'; import { Order } from './order.model';
import { Products } from './products.model'; import { Product } from './product.model';
@Table @Table
export class OrderedItem extends Model { export class OrderedItem extends Model {
@Column @Column
@ForeignKey(() => Orders) @ForeignKey(() => Order)
orderId: number orderId: number
@Column @Column
@ForeignKey(() => Products) @ForeignKey(() => Product)
productId: number productId: number
@Column @Column
@@ -17,11 +17,4 @@ export class OrderedItem extends Model {
@Column @Column
totalPrice: number totalPrice: number
// Relations
@BelongsTo(() => Orders)
order: Orders
@HasMany(() => Products)
products: Products[]
} }

View File

@@ -1,20 +0,0 @@
import { Table, Column, Model, BelongsTo, ForeignKey, HasMany } from 'sequelize-typescript';
import { Users } from './users.model';
import { OrderedItem } from './orderedItem.model';
@Table
export class Orders extends Model {
@Column
@ForeignKey(() => Users)
userNameId: number
@Column
totalPrice: number
// Relations
@BelongsTo(() => Users)
user: Users
@HasMany(() => OrderedItem)
orderedItems: OrderedItem
}

View File

@@ -0,0 +1,30 @@
import { Table, Column, Model, ForeignKey, BelongsTo, BelongsToMany } from 'sequelize-typescript';
import { Category } from './category.model';
import { OrderedItem } from './orderedItem.model';
import { Order } from './order.model';
@Table
export class Product extends Model {
@Column
brand: string
@Column
name: string
@Column
@ForeignKey(() => Category)
categoryId: number
@Column
price: number
@Column
discount: number
// Relations
@BelongsTo(() => Category)
category: Category
@BelongsToMany(() => Order,() => OrderedItem)
orderedItem: OrderedItem
}

View File

@@ -1,30 +0,0 @@
import { Table, Column, Model, ForeignKey, BelongsTo, HasOne } from 'sequelize-typescript';
import { Categories } from './categories.model';
import { OrderedItem } from './orderedItem.model';
@Table
export class Products extends Model {
@Column
name: string
@Column
@ForeignKey(() => Categories)
categoryId: number
@Column
@ForeignKey(() => OrderedItem)
orderedItemId: number
@Column
price: number
@Column
discount: number
// Relations
@BelongsTo(() => OrderedItem)
orderedItem: OrderedItem
@HasOne(() => Categories)
category: Categories
}

View File

@@ -0,0 +1,12 @@
import { Router, Request, Response, NextFunction } from "express";
import { Account } from "../models/account.model";
export const account = Router()
account.get("/", (req: Request, res: Response, next: NextFunction)=> {
Account.findAll()
.then(accounts => {
res.json(accounts)
})
.catch(next)
})

View File

@@ -1,7 +1,80 @@
import { Request, Response, NextFunction, Router } from 'express' import { Request, Response, NextFunction, Router } from 'express'
import { Category } from '../models/category.model'
import { OrderedItem } from '../models/orderedItem.model'
import { Order } from '../models/order.model'
import { Product } from '../models/product.model'
import { Account } from '../models/account.model'
export const api = Router() export const api = Router()
api.get("/", (req: Request, res: Response, next: NextFunction) => { api.get("/", (req: Request, res: Response, next: NextFunction) => {
res.send("Hello World!") res.send("Hello World!")
})
api.post("/resetdatabase", (req: Request, res: Response, next: NextFunction) => {
// Step 1: Delete all data tables
Category.destroy({ truncate: true })
OrderedItem.destroy({ truncate: true })
Order.destroy({ truncate: true })
Product.destroy({ truncate: true })
Account.destroy({ truncate: true })
// Step 2: Prepopulate with default values
Category.bulkCreate(
[
{ id: 0, icon: "mdi-chip", name: "Electronic" },
{ id: 1, icon: "mdi-soccer", name: "Sports" },
{ id: 2, icon: "mdi-tshirt-crew", name: "Clothes" },
{ id: 3, icon: "mdi-bookshelf", name: "Books" }
]
)
Product.bulkCreate(
[
{ id: 0, brand: "Tuxedo", name: "Hypherion Ultra Max", price: 999.99, categoryId: 0, discount: 0 },
{ id: 1, brand: "Puma", name: "Men's Shirt", price: 14.99, categoryId: 2, discount: 0 },
{ id: 2, brand: "Puma", name: "Woman's Shirt", price: 14.99, categoryId: 2, discount: 0 },
{ id: 3, brand: "George Orwell", name: "1984", price: 9.99, categoryId: 3, discount: 0 },
{ id: 4, brand: "Johann W. Goethe", name: "Faust", price: 4.99, categoryId: 3, discount: 0 },
{ id: 5, brand: "Theodor Sturm", name: "Der Schimmelreiter", price: 4.99, categoryId: 3, discount: 0 },
{ id: 6, brand: "Aldous Huxley", name: "Brave New World", price: 7.99, categoryId: 3, discount: 0 },
]
)
Account.bulkCreate(
[
{ id: 0, username: "hagemeister93", password: "Xjt3qb5t", address: "Laportestraße 22, 30449 Hannover", firstName: "Laurin", lastName: "Hagemeister" },
{ id: 1, username: "katjaStoiber", password: "target123", address: "Gustav-Adolf-Straße 30, 30167 Hannover", firstName: "Katja", lastName: "Stoiber" },
{ id: 2, username: "oetkerohnek", password: "iloveyou", address: "Eckermannstraße 1, 30625 Hannover", firstName: "Luna", lastName: "Oeter" },
{ id: 3, username: "duranduran", password: "H4nn0ver", address: "Schlägerstraße 36, 30171 Hannover", firstName: "Jürgen", lastName: "Durand" },
{ id: 4, username: "guitarhero", password: "gwerty123", address: "Steinmetzstraße 12, 30163 Hannover", firstName: "Frederik", lastName: "Furtwängler" },
{ id: 5, username: "herbstMareike", password: "qhsrbpgrs", address: "Allerweg 33, 30851 Langenhagen", firstName: "Mareike", lastName: "Herbst" },
{ id: 6, username: "seibertmitb", password: "{jkz+WvQe", address: "Marktstraße 26, 30880 Laatzen", firstName: "Janna", lastName: "Seibert" },
]
)
Order.bulkCreate(
[
{ id: 0, accountId: 0, totalPrice: 0 },
{ id: 1, accountId: 1, totalPrice: 0 },
{ id: 2, accountId: 1, totalPrice: 0 },
{ id: 3, accountId: 2, totalPrice: 0 },
{ id: 4, accountId: 2, totalPrice: 0 },
{ id: 5, accountId: 3, totalPrice: 0 },
{ id: 6, accountId: 3, totalPrice: 0 },
{ id: 7, accountId: 3, totalPrice: 0 },
{ id: 8, accountId: 4, totalPrice: 0 },
{ id: 9, accountId: 5, totalPrice: 0 },
{ id: 10, accountId: 6, totalPrice: 0 },
{ id: 11, accountId: 6, totalPrice: 0 },
]
)
OrderedItem.bulkCreate(
[
{ orderId: 0, productId: 4, quantity: 2, totalPrice: 0 }
]
)
res.send("Success")
}) })

View File

@@ -1,20 +0,0 @@
import { Router, Request, Response, NextFunction } from "express";
import { Categories } from "../models/categories.model";
export const categories = Router()
categories.get("/", (req: Request, res: Response, next: NextFunction) => {
Categories.findAll()
.then(categories => res.json(categories))
.catch(next)
})
categories.post("/", (req: Request, res: Response, next: NextFunction) => {
try {
console.log(req.body)
const category = Categories.create(req.body)
res.status(201).json(category)
} catch (e) {
next(e)
}
})

View File

@@ -0,0 +1,22 @@
import { Router, Request, Response, NextFunction } from "express";
import { Category } from "../models/category.model";
export const category = Router()
category.get("/", (req: Request, res: Response, next: NextFunction) => {
Category.findAll()
.then(categories => {
res.json(categories)
})
.catch(next)
})
category.post("/", (req: Request, res: Response, next: NextFunction) => {
try {
console.log(req.body)
const category = Category.create(req.body)
res.status(201).json(category)
} catch (e) {
next(e)
}
})

View File

@@ -0,0 +1,12 @@
import { Router, Request, Response, NextFunction } from "express";
import { Order } from "../models/order.model";
export const order = Router()
order.get("/", (req: Request, res: Response, next: NextFunction) => {
Order.findAll()
.then(orders => {
res.json(orders)
})
.catch(next)
})

View File

@@ -0,0 +1,12 @@
import { Router, Request, Response, NextFunction } from "express";
import { OrderedItem } from "../models/orderedItem.model";
export const orderedItem = Router()
orderedItem.get("/", (req: Request, res: Response, next: NextFunction) => {
OrderedItem.findAll()
.then(orderedItems => {
res.json(orderedItems)
})
.catch(next)
})

View File

@@ -0,0 +1,12 @@
import { Router, Request, Response, NextFunction } from "express";
import { Product } from "../models/product.model";
export const product = Router()
product.get("/", (req: Request, res: Response, next: NextFunction)=> {
Product.findAll()
.then(products => {
res.json(products)
})
.catch(next)
})

View File

@@ -2,8 +2,12 @@ import express from 'express'
import cors from 'cors' import cors from 'cors'
import bodyParser from 'body-parser' import bodyParser from 'body-parser'
import { api } from './routes/api.routes' import { api } from './routes/api.routes'
import { categories } from './routes/categories.routes'
import { startDatabase } from './database' import { startDatabase } from './database'
import { category } from './routes/category.routes'
import { product } from './routes/product.routes'
import { order } from './routes/order.routes'
import { orderedItem } from './routes/orderedItem.routes'
import { account } from './routes/account.routes'
const app = express() const app = express()
const port = 3000 const port = 3000
@@ -19,7 +23,11 @@ startDatabase()
// Routes // Routes
app.use("/api", api) app.use("/api", api)
app.use("/categories", categories) app.use("/categories", category)
app.use("/products", product)
app.use("/orders", order)
app.use("/ordereditems", orderedItem)
app.use("/accounts", account)
// Start server // Start server
app.listen(port, () => { app.listen(port, () => {

58
software/db.svg Normal file
View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: undefined Pages: 1 -->
<svg width="378pt" height="252pt"
viewBox="0.00 0.00 377.60 251.60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(28.8 201.8)">
<title>undefined</title>
<polygon fill="white" stroke="transparent" points="-28.8,49.8 -28.8,-201.8 348.8,-201.8 348.8,49.8 -28.8,49.8"/>
<text text-anchor="start" x="116.5" y="12.6" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">database.sqlite</text>
<!-- Categories -->
<g id="node1" class="node">
<title>Categories</title>
<path fill="none" stroke="black" d="M12.24,-60.53C12.24,-60.53 132.24,-60.53 132.24,-60.53 138.24,-60.53 144.24,-66.53 144.24,-72.53 144.24,-72.53 144.24,-152.53 144.24,-152.53 144.24,-158.53 138.24,-164.53 132.24,-164.53 132.24,-164.53 12.24,-164.53 12.24,-164.53 6.24,-164.53 0.24,-158.53 0.24,-152.53 0.24,-152.53 0.24,-72.53 0.24,-72.53 0.24,-66.53 6.24,-60.53 12.24,-60.53"/>
<text text-anchor="start" x="37.24" y="-144.13" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="13.00">Categories</text>
<polyline fill="none" stroke="black" points="0.24,-134.53 144.24,-134.53 "/>
<text text-anchor="start" x="7.24" y="-120.93" font-family="Helvetica,sans-Serif" font-size="12.00">id* </text>
<text text-anchor="start" x="25.24" y="-120.93" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">integer</text>
<text text-anchor="start" x="7.24" y="-103.93" font-family="Helvetica,sans-Serif" font-size="12.00">name </text>
<text text-anchor="start" x="41.24" y="-103.93" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">varchar(255)</text>
<text text-anchor="start" x="7.24" y="-86.93" font-family="Helvetica,sans-Serif" font-size="12.00">createdAt </text>
<text text-anchor="start" x="62.24" y="-86.93" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">datetime</text>
<text text-anchor="start" x="7.24" y="-69.93" font-family="Helvetica,sans-Serif" font-size="12.00">updatedAt </text>
<text text-anchor="start" x="65.24" y="-69.93" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">datetime</text>
</g>
<!-- Products -->
<g id="node2" class="node">
<title>Products</title>
<path fill="none" stroke="black" d="M188.26,-0.23C188.26,-0.23 308.26,-0.23 308.26,-0.23 314.26,-0.23 320.26,-6.23 320.26,-12.23 320.26,-12.23 320.26,-160.23 320.26,-160.23 320.26,-166.23 314.26,-172.23 308.26,-172.23 308.26,-172.23 188.26,-172.23 188.26,-172.23 182.26,-172.23 176.26,-166.23 176.26,-160.23 176.26,-160.23 176.26,-12.23 176.26,-12.23 176.26,-6.23 182.26,-0.23 188.26,-0.23"/>
<text text-anchor="start" x="219.26" y="-151.83" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="13.00">Products</text>
<polyline fill="none" stroke="black" points="176.26,-142.23 320.26,-142.23 "/>
<text text-anchor="start" x="183.26" y="-128.63" font-family="Helvetica,sans-Serif" font-size="12.00">id* </text>
<text text-anchor="start" x="201.26" y="-128.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">integer</text>
<text text-anchor="start" x="183.26" y="-111.63" font-family="Helvetica,sans-Serif" font-size="12.00">brand </text>
<text text-anchor="start" x="217.26" y="-111.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">varchar(255)</text>
<text text-anchor="start" x="183.26" y="-94.63" font-family="Helvetica,sans-Serif" font-size="12.00">name </text>
<text text-anchor="start" x="217.26" y="-94.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">varchar(255)</text>
<text text-anchor="start" x="183.26" y="-77.63" font-family="Helvetica,sans-Serif" font-size="12.00">categoryId </text>
<text text-anchor="start" x="242.26" y="-77.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">integer</text>
<text text-anchor="start" x="183.26" y="-60.63" font-family="Helvetica,sans-Serif" font-size="12.00">price </text>
<text text-anchor="start" x="213.26" y="-60.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">integer</text>
<text text-anchor="start" x="183.26" y="-43.63" font-family="Helvetica,sans-Serif" font-size="12.00">discount </text>
<text text-anchor="start" x="232.26" y="-43.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">integer</text>
<text text-anchor="start" x="183.26" y="-26.63" font-family="Helvetica,sans-Serif" font-size="12.00">createdAt </text>
<text text-anchor="start" x="238.26" y="-26.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">datetime</text>
<text text-anchor="start" x="183.26" y="-9.63" font-family="Helvetica,sans-Serif" font-size="12.00">updatedAt </text>
<text text-anchor="start" x="241.26" y="-9.63" font-family="Helvetica,sans-Serif" font-weight="bold" font-size="12.00">datetime</text>
</g>
<!-- Products&#45;&gt;Categories -->
<g id="edge1" class="edge">
<title>Products&#45;&gt;Categories</title>
<path fill="none" stroke="black" stroke-width="0.9" d="M176.16,-97C168.49,-98.15 160.65,-99.32 152.89,-100.48"/>
<polygon fill="black" stroke="black" stroke-width="0.9" points="152.02,-97.78 144.52,-101.73 152.84,-103.32 152.02,-97.78"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -18,6 +18,7 @@
"sequelize": "^6.37.3", "sequelize": "^6.37.3",
"sequelize-typescript": "^2.1.6", "sequelize-typescript": "^2.1.6",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"ts-node": "^10.9.2",
"vue": "^3.4.29", "vue": "^3.4.29",
"vuetify": "^3.7.1", "vuetify": "^3.7.1",
"wait-on": "^8.0.0" "wait-on": "^8.0.0"
@@ -90,6 +91,18 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5", "version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
@@ -503,12 +516,31 @@
"@hapi/hoek": "^9.0.0" "@hapi/hoek": "^9.0.0"
} }
}, },
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@mdi/font": { "node_modules/@mdi/font": {
"version": "7.4.47", "version": "7.4.47",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz",
@@ -796,6 +828,30 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"license": "MIT"
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"license": "MIT"
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"license": "MIT"
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"license": "MIT"
},
"node_modules/@types/body-parser": { "node_modules/@types/body-parser": {
"version": "1.19.5", "version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -1075,6 +1131,30 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/acorn": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-walk": {
"version": "8.3.3",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz",
"integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==",
"license": "MIT",
"dependencies": {
"acorn": "^8.11.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -1200,6 +1280,12 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0" "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
} }
}, },
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"license": "MIT"
},
"node_modules/array-flatten": { "node_modules/array-flatten": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
@@ -1626,6 +1712,12 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"license": "MIT"
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
@@ -1742,6 +1834,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dottie": { "node_modules/dottie": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz",
@@ -2631,6 +2732,12 @@
"@jridgewell/sourcemap-codec": "^1.5.0" "@jridgewell/sourcemap-codec": "^1.5.0"
} }
}, },
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"license": "ISC"
},
"node_modules/make-fetch-happen": { "node_modules/make-fetch-happen": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
@@ -4129,6 +4236,49 @@
"tree-kill": "cli.js" "tree-kill": "cli.js"
} }
}, },
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"license": "MIT",
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
@@ -4165,7 +4315,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
"integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
"license": "Apache-2.0", "license": "Apache-2.0",
"optional": true,
"peer": true, "peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@@ -4241,6 +4390,12 @@
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }
}, },
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"license": "MIT"
},
"node_modules/validator": { "node_modules/validator": {
"version": "13.12.0", "version": "13.12.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz",
@@ -4488,6 +4643,15 @@
"engines": { "engines": {
"node": ">=12" "node": ">=12"
} }
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"license": "MIT",
"engines": {
"node": ">=6"
}
} }
} }
} }

View File

@@ -6,13 +6,14 @@
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"dev-server": "concurrently \"nodemon\" \"wait-on http://localhost:3000/api/ && vite\"" "server": "nodemon",
"serve": "concurrently \"nodemon\" \"wait-on http://localhost:3000/api/ && vite\""
}, },
"nodemonConfig": { "nodemonConfig": {
"watch": [ "watch": [
"backend" "backend"
], ],
"exec": "tsc && node ./build/dist/server.js", "exec": "ts-node --project ./tsconfig.server.json --files ./backend/server.ts && node ./build/dist/server.js",
"ext": "ts, js, json" "ext": "ts, js, json"
}, },
"dependencies": { "dependencies": {

View File

@@ -1,16 +1,16 @@
<script setup> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import axios from 'axios'; import axios from 'axios';
const showDrawer = ref(true) const showDrawer = ref(true)
const apiCategories = ref([]) const categories = ref([])
const newCategory = ref("") const newCategory = ref("")
function requestAllCategories() { function requestAllCategories() {
axios.get('http://127.0.0.1:3000/categories') axios.get('http://127.0.0.1:3000/categories')
.then(function (response) { .then(function (response) {
console.log(response) console.log(response)
apiCategories.value = response.data categories.value = response.data
}) })
} }
@@ -21,19 +21,34 @@ function addCategory() {
.then(requestAllCategories) .then(requestAllCategories)
} }
function resetDb() {
axios.post("http://127.0.0.1:3000/api/resetdatabase")
requestAllCategories()
}
requestAllCategories() requestAllCategories()
</script> </script>
<template> <template>
<v-app> <v-app>
<v-app-bar> <v-app-bar>
<v-app-bar-nav-icon @click="showDrawer = !showDrawer"/> <v-app-bar-nav-icon />
<v-app-bar-title>HackMyCart</v-app-bar-title> <v-app-bar-title>HackMyCart</v-app-bar-title>
</v-app-bar> </v-app-bar>
<v-navigation-drawer v-model="showDrawer"> <v-navigation-drawer>
<!-- todo --> <v-list>
<v-list-subheader>Shop Kategorien</v-list-subheader>
<v-list-item v-for="category in categories" link :prepend-icon="category.icon">
{{ category.name }}
</v-list-item>
<v-list-subheader>Account & Hilfe</v-list-subheader>
<v-list-item title="Account" link prepend-icon="mdi-account" />
<v-list-item title="Bestellungen" link prepend-icon="mdi-cart-check" />
<v-list-item title="Einstellungen" link prepend-icon="mdi-cog" />
</v-list>
</v-navigation-drawer> </v-navigation-drawer>
<v-main> <v-main>
@@ -42,17 +57,12 @@ requestAllCategories()
<v-col> <v-col>
<v-text-field label="Category name" v-model="newCategory" /> <v-text-field label="Category name" v-model="newCategory" />
</v-col> </v-col>
<v-col> <v-col cols="2">
<v-btn @click="addCategory" >Hinzufügen</v-btn> <v-btn @click="addCategory" >Hinzufügen</v-btn>
</v-col> </v-col>
</v-row> <v-col cols="2">
<v-btn @click="resetDb">Datenbank zurücksetzen</v-btn>
<v-row> </v-col>
<v-list>
<v-list-item v-for="category in apiCategories">
{{ category.name }}
</v-list-item>
</v-list>
</v-row> </v-row>
</v-container> </v-container>
<!-- todo --> <!-- todo -->

View File

@@ -8,12 +8,10 @@
"esModuleInterop": true, "esModuleInterop": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"baseUrl": ".",
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
} }
}, },
"exclude": ["node_modules", "dist"], "exclude": ["node_modules", "dist"]
"include": [
"backend/**/*.ts",
]
} }

View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"moduleResolution": "node",
"isolatedModules": false,
"outDir": "build/dist",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"baseUrl": "."
},
"exclude": ["node_modules", "dist"],
"include": [
"backend/**/*.ts"
]
}