From 76a98b8a16cd59f91a0bb93bd3925ac9873a7ec8 Mon Sep 17 00:00:00 2001 From: TobiZog Date: Sat, 26 Oct 2024 14:35:33 +0200 Subject: [PATCH] Creating Band edit page --- software/backend/routes/account.routes.ts | 11 ++- software/backend/routes/band.routes.ts | 22 +++++ software/backend/server.ts | 6 +- software/src/components/basics/cardView.vue | 2 +- .../navigation/navigationAppendItems.vue | 8 ++ software/src/data/api/bandApi.ts | 10 ++ software/src/data/enums/bannerStateEnum.ts | 14 +-- software/src/data/models/acts/bandModel.ts | 2 +- software/src/locales/de.json | 16 ++- software/src/locales/en.json | 16 ++- .../pages/account/loginPage/registerForm.vue | 2 +- .../admin/bandsAdminPage/bandEditDialog.vue | 87 ++++++++++++++++ .../src/pages/admin/bandsAdminPage/index.vue | 98 ++++++++++++++++++- software/src/stores/account.store.ts | 6 +- software/src/stores/band.store.ts | 74 +++++++++++++- software/src/stores/feedback.store.ts | 44 ++++++--- 16 files changed, 377 insertions(+), 41 deletions(-) create mode 100644 software/src/pages/admin/bandsAdminPage/bandEditDialog.vue diff --git a/software/backend/routes/account.routes.ts b/software/backend/routes/account.routes.ts index 0bac911..b3342a4 100644 --- a/software/backend/routes/account.routes.ts +++ b/software/backend/routes/account.routes.ts @@ -43,7 +43,7 @@ account.post("/login", (req: Request, res: Response) => { }) // Creating a new user -account.post("/", (req: Request, res: Response) => { +account.post("/", async (req: Request, res: Response) => { // Check if username is valid if (!validateString(req.body.username, 4)) { @@ -65,6 +65,15 @@ account.post("/", (req: Request, res: Response) => { } // Create account + await AccountRole.findOne({ + where: { + name: "User" + } + }) + .then(role => { + req.body["accountRoleId"] = role.id + }) + Account.create(req.body) .then(account => { // Status: 201 Created diff --git a/software/backend/routes/band.routes.ts b/software/backend/routes/band.routes.ts index bc4a9f5..4267a19 100644 --- a/software/backend/routes/band.routes.ts +++ b/software/backend/routes/band.routes.ts @@ -133,4 +133,26 @@ band.get("/search", (req: Request, res: Response) => { .then(bands => { res.status(200).json(bands) }) +}) + + +// Edit band +band.patch("/", (req: Request, res: Response) => { + Band.update(req.body, { + where: { + id: req.body.id + } + }) + .then(result => { + res.status(200).json(result) + }) +}) + + +// New band +band.post("/", (req: Request, res: Response) => { + Band.create(req.body) + .then(result => { + res.status(200).json(result) + }) }) \ No newline at end of file diff --git a/software/backend/server.ts b/software/backend/server.ts index dc8f10f..2c653ad 100644 --- a/software/backend/server.ts +++ b/software/backend/server.ts @@ -29,9 +29,9 @@ const path = require('path') app.use('/static', express.static(path.join(__dirname, 'images'))) // Add delay for more realistic response times -// app.use((req, res, next) => { -// setTimeout(next, Math.floor((Math.random () * 2000) + 100)) -// }) +app.use((req, res, next) => { + setTimeout(next, Math.floor((Math.random () * 2000) + 100)) +}) // Routes app.use("/api", api) diff --git a/software/src/components/basics/cardView.vue b/software/src/components/basics/cardView.vue index 3e17994..2181c4e 100644 --- a/software/src/components/basics/cardView.vue +++ b/software/src/components/basics/cardView.vue @@ -44,7 +44,7 @@ defineProps({ - + diff --git a/software/src/components/navigation/navigationAppendItems.vue b/software/src/components/navigation/navigationAppendItems.vue index 56ace27..477376b 100644 --- a/software/src/components/navigation/navigationAppendItems.vue +++ b/software/src/components/navigation/navigationAppendItems.vue @@ -22,6 +22,14 @@ const basketStore = useBasketStore() + + \ No newline at end of file diff --git a/software/src/data/api/bandApi.ts b/software/src/data/api/bandApi.ts index 79aeddd..23212cf 100644 --- a/software/src/data/api/bandApi.ts +++ b/software/src/data/api/bandApi.ts @@ -1,4 +1,6 @@ import axios from "axios" +import { BandDetailsApiModel } from "../models/acts/bandDetailsApiModel" +import { BandModel } from "../models/acts/bandModel" let BASE_URL = "http://localhost:3000/bands" @@ -12,4 +14,12 @@ export async function fetchBandByName(bandName: string) { export async function fetchBandsBySearchTerm(searchTerm: string) { return await axios.get(BASE_URL + '/search?value=' + searchTerm) +} + +export async function postBand(band: BandModel) { + return await axios.post(BASE_URL, band) +} + +export async function patchBand(band: BandModel) { + return await axios.patch(BASE_URL, band) } \ No newline at end of file diff --git a/software/src/data/enums/bannerStateEnum.ts b/software/src/data/enums/bannerStateEnum.ts index 13d803d..45de686 100644 --- a/software/src/data/enums/bannerStateEnum.ts +++ b/software/src/data/enums/bannerStateEnum.ts @@ -76,17 +76,13 @@ export enum BannerStateEnum { ORDERPLACESUCCESSFUL, - ////////// API Endpoint /products ////////// + ////////// API Endpoint /bands ////////// - // Status: 201 Created - PRODUCTCREATESUCCESSFUL, + BANDSAVEDSUCCESSFUL, - // Status: 400 Bad request - PRODUCTCREATEERROR, + BANDSAVEDERROR, - // Status: 200 OK - PRODUCTDELETESUCCESSFUL, + BANDDELETESUCCESSFUL, - // Status: 400 Bad request - PRODUCTDELETEERROR + BANDDELETEERROR } \ No newline at end of file diff --git a/software/src/data/models/acts/bandModel.ts b/software/src/data/models/acts/bandModel.ts index ea470d5..c713402 100644 --- a/software/src/data/models/acts/bandModel.ts +++ b/software/src/data/models/acts/bandModel.ts @@ -1,5 +1,5 @@ export class BandModel { - id: number = -1 + id: number name: string = "" foundingYear: number = 1900 descriptionEn: string = "" diff --git a/software/src/locales/de.json b/software/src/locales/de.json index e302536..b3ae09a 100644 --- a/software/src/locales/de.json +++ b/software/src/locales/de.json @@ -32,7 +32,15 @@ "rating": "Bewertung | Bewertungen", "bandMember": "Band Mitglieder", "image": "Foto | Fotos", - "genre": "Genre | Genres" + "genre": "Genre | Genres", + "name": "Bandname", + "editBand": "Band bearbeiten", + "foundingYear": "Gründungsjahr", + "descriptionDe": "Beschreibung Deutsch", + "descriptionEn": "Beschreibung Englisch", + "addNewBand": "Neue Band hinzufügen", + "logo": "Band Logo", + "imageMember": "Bilder Mitglieder" }, "ticket": { "tickets": "Ticket | Tickets" @@ -136,7 +144,11 @@ "orderPlaceSuccessfull": "Bestellung erfolgreich aufgegeben", "basketTicketAdded": "Ticket zum Warenkorb hinzugefügt", "basketTicketRemoved": "Ticket aus Warenkorb entfernt", - "exerciseSolvedNr": "Aufgabe {0}.{1} gelöst!" + "exerciseSolvedNr": "Aufgabe {0}.{1} gelöst!", + "bandDeleteError": "Fehler beim Löschen der Band", + "bandDeleteSuccessful": "Band erfolgreich gelöscht", + "bandSavedError": "Fehler beim Speichern der Band", + "bandSavedSuccessful": "Band erfolgreich gespeichert" }, "misc": { "sortBy": "Sortieren nach", diff --git a/software/src/locales/en.json b/software/src/locales/en.json index 11fdced..c82e4f8 100644 --- a/software/src/locales/en.json +++ b/software/src/locales/en.json @@ -32,7 +32,15 @@ "rating": "Rating | Ratings", "bandMember": "Band Member", "image": "Photo | Photos", - "genre": "Genre | Genres" + "genre": "Genre | Genres", + "name": "Name of band", + "editBand": "Edit band", + "foundingYear": "Founding Year", + "descriptionDe": "Description German", + "descriptionEn": "Description English", + "addNewBand": "Add new Band", + "logo": "Band logo", + "imageMember": "Images Members" }, "ticket": { "tickets": "Ticket | Tickets" @@ -136,7 +144,11 @@ "orderPlaceSuccessfull": "Order successfully placed", "basketTicketAdded": "Added ticket to basket", "basketTicketRemoved": "Removed ticket from basket", - "exerciseSolvedNr": "Exercise {0}.{1} solved!" + "exerciseSolvedNr": "Exercise {0}.{1} solved!", + "bandDeleteError": "Error on deleting band", + "bandDeleteSuccessful": "Band successfully deleted", + "bandSavedError": "Error on saving band", + "bandSavedSuccessful": "Band successfully saved" }, "misc": { "sortBy": "Sort by", diff --git a/software/src/pages/account/loginPage/registerForm.vue b/software/src/pages/account/loginPage/registerForm.vue index 6a6b46c..af55230 100644 --- a/software/src/pages/account/loginPage/registerForm.vue +++ b/software/src/pages/account/loginPage/registerForm.vue @@ -13,7 +13,7 @@ async function registerAccount() { accountStore.registerAccount() .then(result => { if (result) { - router.push("/account/home") + showRegisterCard.value = false } }) } diff --git a/software/src/pages/admin/bandsAdminPage/bandEditDialog.vue b/software/src/pages/admin/bandsAdminPage/bandEditDialog.vue new file mode 100644 index 0000000..f5fa188 --- /dev/null +++ b/software/src/pages/admin/bandsAdminPage/bandEditDialog.vue @@ -0,0 +1,87 @@ + + + \ No newline at end of file diff --git a/software/src/pages/admin/bandsAdminPage/index.vue b/software/src/pages/admin/bandsAdminPage/index.vue index d1fce7e..1e49df7 100644 --- a/software/src/pages/admin/bandsAdminPage/index.vue +++ b/software/src/pages/admin/bandsAdminPage/index.vue @@ -1,6 +1,102 @@ \ No newline at end of file diff --git a/software/src/stores/account.store.ts b/software/src/stores/account.store.ts index 6e943c0..d3f45b8 100644 --- a/software/src/stores/account.store.ts +++ b/software/src/stores/account.store.ts @@ -95,11 +95,7 @@ export const useAccountStore = defineStore("accountStore", { password: this.registerData.password } - await this.login() - .then(result => { - this.fetchInProgress = false - return true - }) + this.fetchInProgress = false }) .catch((error) => { if (error.status == 400) { diff --git a/software/src/stores/band.store.ts b/software/src/stores/band.store.ts index e87f53a..c595a13 100644 --- a/software/src/stores/band.store.ts +++ b/software/src/stores/band.store.ts @@ -1,10 +1,12 @@ import { defineStore } from "pinia"; import { ref } from "vue"; import { BandApiModel } from "../data/models/acts/bandApiModel"; -import { fetchAllBands, fetchBandByName } from "../data/api/bandApi"; +import { fetchAllBands, fetchBandByName, patchBand, postBand } from "../data/api/bandApi"; import { BandDetailsApiModel } from "../data/models/acts/bandDetailsApiModel"; import { GenreModel } from "@/data/models/acts/genreModel"; import { fetchAllGenres } from "@/data/api/genreApi"; +import { useFeedbackStore } from "./feedback.store"; +import { BannerStateEnum } from "@/data/enums/bannerStateEnum"; export const useBandStore = defineStore("bandStore", { state: () => ({ @@ -21,7 +23,10 @@ export const useBandStore = defineStore("bandStore", { availableGenres: ref>([]), /** Request to server sent, waiting for data response */ - fetchInProgress: ref(false) + fetchInProgress: ref(false), + + /** Show or hide the edit dialog for edit a band */ + showBandEditDialog: ref(false) }), actions: { @@ -66,11 +71,74 @@ export const useBandStore = defineStore("bandStore", { async getBand(name: string) { this.fetchInProgress = true - fetchBandByName(name) + await fetchBandByName(name) .then(result => { this.band = result.data this.fetchInProgress = false }) + }, + + /** + * Prepare edit dialog for new band, opens it + */ + newBand() { + this.band = new BandDetailsApiModel() + + this.showBandEditDialog = true + }, + + /** + * Edit a band. Fetch all information about the band, opens the edit dialog + * + * @param name Name of band to edit + */ + async editBand(name: string) { + await this.getBand(name) + + this.showBandEditDialog = true + }, + + /** + * Save band in this store to the database + */ + saveBand() { + const feedbackStore = useFeedbackStore() + this.fetchInProgress = true + + if (this.band.id == undefined) { + postBand(this.band) + .then(result => { + if (result.status == 200) { + feedbackStore.changeBanner(BannerStateEnum.BANDSAVEDSUCCESSFUL) + + this.getBands() + this.showBandEditDialog = false + } else { + feedbackStore.changeBanner(BannerStateEnum.BANDSAVEDERROR) + } + }) + } else { + patchBand(this.band) + .then(result => { + if (result.status == 200) { + feedbackStore.changeBanner(BannerStateEnum.BANDSAVEDSUCCESSFUL) + + this.getBands() + this.showBandEditDialog = false + } else { + feedbackStore.changeBanner(BannerStateEnum.BANDSAVEDERROR) + } + }) + } + }, + + /** + * Delete a band by it's identifier + * + * @param id Id of the band in the database + */ + deleteBand(id: number) { + // todo } } }) \ No newline at end of file diff --git a/software/src/stores/feedback.store.ts b/software/src/stores/feedback.store.ts index 2797ab5..3202404 100644 --- a/software/src/stores/feedback.store.ts +++ b/software/src/stores/feedback.store.ts @@ -131,6 +131,25 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.ORDERPLACESUCCESSFUL: { this.title = this.i18n.t('bannerMessages.orderPlaceSuccessfull'); break; } + + + ////////// API Endpoint /bands ////////// + + case BannerStateEnum.BANDDELETEERROR: { + this.title = this.i18n.t('bannerMessages.bandDeleteError'); break; + } + + case BannerStateEnum.BANDDELETESUCCESSFUL: { + this.title = this.i18n.t('bannerMessages.bandDeleteSuccessful'); break; + } + + case BannerStateEnum.BANDSAVEDERROR: { + this.title = this.i18n.t('bannerMessages.bandSavedError'); break; + } + + case BannerStateEnum.BANDSAVEDSUCCESSFUL: { + this.title = this.i18n.t('bannerMessages.bandSavedSuccessful'); break; + } } @@ -142,8 +161,8 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.ACCOUNTLOGINWRONGLOGIN: case BannerStateEnum.ACCOUNTREGISTERERROR: case BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE: - case BannerStateEnum.PRODUCTDELETESUCCESSFUL: - case BannerStateEnum.PRODUCTDELETEERROR: + case BannerStateEnum.BANDDELETEERROR: + case BannerStateEnum.BANDSAVEDERROR: this.color = "red" break; @@ -154,8 +173,9 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.ACCOUNTUPDATESUCCESSFUL: case BannerStateEnum.ACCOUNTLOGOUTSUCCESSFUL: case BannerStateEnum.ORDERPLACESUCCESSFUL: - case BannerStateEnum.PRODUCTCREATESUCCESSFUL: - case BannerStateEnum.PRODUCTCREATEERROR: + case BannerStateEnum.BANDDELETESUCCESSFUL: + case BannerStateEnum.BANDSAVEDSUCCESSFUL: + case BannerStateEnum.EXERCISEPROGRESSRESETSUCCESSFUL: this.color = "green" break; @@ -192,14 +212,6 @@ export const useFeedbackStore = defineStore("feedbackStore", { this.icon = "mdi-account" break; - - case BannerStateEnum.PRODUCTDELETESUCCESSFUL: - case BannerStateEnum.PRODUCTDELETEERROR: - case BannerStateEnum.PRODUCTCREATESUCCESSFUL: - case BannerStateEnum.PRODUCTCREATEERROR: - this.icon = "mdi-store" - break; - case BannerStateEnum.EXERCISESOLVED01: case BannerStateEnum.EXERCISESOLVED02: case BannerStateEnum.EXERCISESOLVED11: @@ -214,6 +226,7 @@ export const useFeedbackStore = defineStore("feedbackStore", { this.icon = "mdi-check-circle-outline" break; + case BannerStateEnum.DATABASERESETSUCCESSFUL: this.icon = "mdi-database-refresh" break; @@ -242,6 +255,13 @@ export const useFeedbackStore = defineStore("feedbackStore", { case BannerStateEnum.ACCOUNTUPDATESUCCESSFUL: this.icon = "mdi-account-reactivate" break; + + case BannerStateEnum.BANDDELETEERROR: + case BannerStateEnum.BANDDELETESUCCESSFUL: + case BannerStateEnum.BANDSAVEDERROR: + case BannerStateEnum.BANDSAVEDSUCCESSFUL: + this.icon = "mdi-guitar-electric" + break; } this.showBanner = true