Finish GenresAdminPanel

This commit is contained in:
2024-11-06 17:55:18 +01:00
parent 80dd2a0ae8
commit 9ec8e382cf
17 changed files with 181 additions and 21 deletions

View File

@@ -14,4 +14,54 @@ genre.get("/", (req: Request, res: Response) => {
.then(genres => { .then(genres => {
res.status(200).json(genres) res.status(200).json(genres)
}) })
.catch(error => {
res.status(500).send()
})
})
/**
* Update a Genre entry
*/
genre.patch("/", (req: Request, res: Response) => {
Genre.update(req.body, {
where: {
id: req.body.id
}
})
.then(result => {
res.status(200).json(result)
})
.catch(error => {
res.status(500).send()
})
})
/**
* Create a new Genre entry
*/
genre.post("/", (req: Request, res: Response) => {
Genre.create(req.body)
.then(result => {
res.status(200).json(result)
})
.catch(error => {
res.status(500).send()
})
})
/**
* Delete a Genre entry
*/
genre.delete("/", (req: Request, res: Response) => {
Genre.destroy({
where: {
id: req.body.id
}
})
.then(result => {
res.status(200).json(result)
})
.catch(error => {
res.status(500).send()
})
}) })

View File

@@ -88,6 +88,8 @@ export async function prepopulateDatabase() {
{ {
location["cityId"] = cityDataset.id location["cityId"] = cityDataset.id
location["urlName"] = location.name.replaceAll(" ", "-").toLowerCase() location["urlName"] = location.name.replaceAll(" ", "-").toLowerCase()
location["imageIndoor"] = "http://localhost:3000/static/" + location["imageIndoor"]
location["imageOutdoor"] = "http://localhost:3000/static/" + location["imageOutdoor"]
await Location.create(location) await Location.create(location)
.then(async locationDataset => { .then(async locationDataset => {
@@ -193,14 +195,14 @@ export async function prepopulateDatabase() {
}) })
} }
for (let payment of account.payments) { for (let payment of account.payments) {
await Payment.create({ await Payment.create({
accountId: dataset.dataValues.id, accountId: dataset.dataValues.id,
bankName: payment.bankName, bankName: payment.bankName,
iban: payment.iban iban: payment.iban
}) })
} }
}) })
} }
@@ -208,6 +210,10 @@ export async function prepopulateDatabase() {
////////// Band and Concert Tables ////////// ////////// Band and Concert Tables //////////
for(let band of bandsConcerts.bands) { for(let band of bandsConcerts.bands) {
band.imageMembers = "http://localhost:3000/static/" + band.imageMembers
band.images = band.images.map(image => "http://localhost:3000/static/" + image)
band.logo = "http://localhost:3000/static/" + band.logo
// Create a band dataset // Create a band dataset
await Band.create(band) await Band.create(band)
.then(async dataset => { .then(async dataset => {
@@ -245,6 +251,8 @@ export async function prepopulateDatabase() {
} }
for (let member of band.members) { for (let member of band.members) {
member.image = "http://localhost:3000/static/" + member.image
await Member.create({ await Member.create({
name: member.name, name: member.name,
image: member.image, image: member.image,

View File

@@ -29,7 +29,7 @@ defineProps({
height="150" height="150"
> >
<v-img <v-img
:src="'http://localhost:3000/static/' + image" :src="image"
aspect-ratio="1" aspect-ratio="1"
max-height="200" max-height="200"
cover cover

View File

@@ -34,7 +34,7 @@ defineProps({
<card-view-horizontal <card-view-horizontal
v-if="!loading" v-if="!loading"
:title="band.name" :title="band.name"
:image="'http://localhost:3000/static/' + band.logo" :image="band.logo"
@click="router.push('/bands/details/' + band.name.replaceAll(' ', '-').toLowerCase())" @click="router.push('/bands/details/' + band.name.replaceAll(' ', '-').toLowerCase())"
> >
<template #content> <template #content>

View File

@@ -22,7 +22,7 @@ defineProps({
<template> <template>
<v-img <v-img
:src="!loading ? 'http://localhost:3000/static/' + image : ''" :src="!loading ? image : ''"
height="600" height="600"
gradient="to top, rgba(0, 0, 0, .9), rgba(255, 255, 255, 0.1)" gradient="to top, rgba(0, 0, 0, .9), rgba(255, 255, 255, 0.1)"
cover cover
@@ -40,7 +40,7 @@ defineProps({
<v-card> <v-card>
<v-img <v-img
v-if="logo" v-if="logo"
:src="'http://localhost:3000/static/' + logo" :src="logo"
width="200" width="200"
aspect-ratio="1" aspect-ratio="1"
cover cover

View File

@@ -41,7 +41,7 @@ defineProps({
<template> <template>
<card-with-left-image <card-with-left-image
:image="'http://localhost:3000/static/' + image" :image="image"
:link="false" :link="false"
color-header="primary" color-header="primary"
:title="band.name + ' - ' + concert.name" :title="band.name + ' - ' + concert.name"

View File

@@ -1,7 +1,22 @@
import axios from "axios" import axios from "axios"
import { GenreModel } from "../models/acts/genreModel"
let BASE_URL = "http://localhost:3000/genres" let BASE_URL = "http://localhost:3000/genres"
export async function fetchAllGenres() { export async function fetchAllGenres() {
return await axios.get(BASE_URL) return await axios.get(BASE_URL)
}
export async function postGenre(genre: GenreModel) {
return await axios.post(BASE_URL, genre)
}
export async function patchGenre(genre: GenreModel) {
return await axios.patch(BASE_URL, genre)
}
export async function deleteGenre(genre: GenreModel) {
return await axios.delete(BASE_URL, {
data: genre
})
} }

View File

@@ -84,5 +84,15 @@ export enum BannerStateEnum {
BANDDELETESUCCESSFUL, BANDDELETESUCCESSFUL,
BANDDELETEERROR BANDDELETEERROR,
////////// API Endpoint /genres //////////
GENRESAVEDSUCCESSFUL,
GENRESAVEDERROR,
GENREDELETESUCCESSFUL,
GENREDELETEERROR
} }

View File

@@ -1,4 +1,4 @@
export class GenreModel { export class GenreModel {
id: number = -1 id: number
name: string = "" name: string = ""
} }

View File

@@ -74,6 +74,21 @@ function itemProps(item: GenreModel) {
/> />
</v-col> </v-col>
</v-row> </v-row>
<v-row>
<v-col>
<v-img
:src="bandStore.band.logo"
/>
</v-col>
<v-col>
<v-img
max-width="300"
:src="bandStore.band.imageMembers"
placeholder=""
/>
</v-col>
</v-row>
</v-container> </v-container>
<template #actions> <template #actions>

View File

@@ -11,6 +11,7 @@ const genreStore = useGenreStore()
v-model="genreStore.showEditDialog" v-model="genreStore.showEditDialog"
:title="$t('band.editGenre')" :title="$t('band.editGenre')"
icon="mdi-pencil" icon="mdi-pencil"
max-width="500"
> >
<v-container> <v-container>
<v-row> <v-row>

View File

@@ -24,6 +24,7 @@ genreStore.getGenres()
:loading="genreStore.fetchInProgress" :loading="genreStore.fetchInProgress"
:items="genreStore.genres" :items="genreStore.genres"
:headers="headers" :headers="headers"
:items-per-page="100"
> >
<template #item.bands="{ item }"> <template #item.bands="{ item }">
<v-chip v-for="band of item.bands" class="mx-1"> <v-chip v-for="band of item.bands" class="mx-1">

View File

@@ -44,7 +44,7 @@ defineProps({
<v-carousel-item <v-carousel-item
v-for="image in band.images" v-for="image in band.images"
:src="'http://localhost:3000/static/' + image" :src="image"
cover cover
/> />
</v-carousel> </v-carousel>

View File

@@ -22,7 +22,6 @@ watch(() => router.currentRoute.value.params.name, () => {
</script> </script>
<template> <template>
{{ router.currentRoute.value.params.name }}
<hero-image <hero-image
:image="bandStore.band.imageMembers" :image="bandStore.band.imageMembers"
:logo="bandStore.band.logo" :logo="bandStore.band.logo"

View File

@@ -29,7 +29,7 @@ bandStore.getBands()
> >
<v-img <v-img
class="d-flex align-center text-center" class="d-flex align-center text-center"
:src="'http://localhost:3000/static/' + band.imageMembers" :src="band.imageMembers"
height="250px" height="250px"
width="350" width="350"
cover cover

View File

@@ -4,6 +4,7 @@ import { useRouter } from 'vue-router';
import cardViewTopImage from '@/components/basics/cardViewTopImage.vue'; import cardViewTopImage from '@/components/basics/cardViewTopImage.vue';
import outlinedButton from '@/components/basics/outlinedButton.vue'; import outlinedButton from '@/components/basics/outlinedButton.vue';
import sectionDivider from '@/components/basics/sectionDivider.vue'; import sectionDivider from '@/components/basics/sectionDivider.vue';
import moment from 'moment';
const concertStore = useConcertStore() const concertStore = useConcertStore()
const router = useRouter() const router = useRouter()
@@ -29,6 +30,7 @@ const router = useRouter()
@click="router.push('/bands/details/' + concert.band.name.replaceAll(' ', '-').toLowerCase())" @click="router.push('/bands/details/' + concert.band.name.replaceAll(' ', '-').toLowerCase())"
:loading="concertStore.fetchInProgress" :loading="concertStore.fetchInProgress"
> >
{{ moment(concert.date).format("DD.MM.YYYY") }},
{{ $t("misc.from") }} {{ (concert.price).toPrecision(4) }} {{ $t("misc.from") }} {{ (concert.price).toPrecision(4) }}
</card-view-top-image> </card-view-top-image>
</v-col> </v-col>

View File

@@ -1,7 +1,9 @@
import { fetchAllGenres } from "@/data/api/genreApi"; import { deleteGenre, fetchAllGenres, patchGenre, postGenre } from "@/data/api/genreApi";
import { GenreApiModel } from "@/data/models/acts/genreApiModel"; import { GenreApiModel } from "@/data/models/acts/genreApiModel";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue"; import { ref } from "vue";
import { useFeedbackStore } from "./feedback.store";
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
export const useGenreStore = defineStore("genreStore", { export const useGenreStore = defineStore("genreStore", {
state: () => ({ state: () => ({
@@ -14,11 +16,17 @@ export const useGenreStore = defineStore("genreStore", {
/** Genres to filter bands for */ /** Genres to filter bands for */
filteredGenres: ref<Array<GenreApiModel>>([]), filteredGenres: ref<Array<GenreApiModel>>([]),
/** Show or hide edit dialog for Genre object */
showEditDialog: ref(false), showEditDialog: ref(false),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false) fetchInProgress: ref(false)
}), }),
actions: { actions: {
/**
* Get all genres from the database
*/
getGenres() { getGenres() {
this.fetchInProgress = true this.fetchInProgress = true
@@ -37,17 +45,68 @@ export const useGenreStore = defineStore("genreStore", {
this.showEditDialog = true this.showEditDialog = true
}, },
/**
* Edit a Genre object, move parameter to this.genre, opens dialog
*
* @param genre Selected Genre object
*/
editGenre(genre: GenreApiModel) { editGenre(genre: GenreApiModel) {
this.genre = genre this.genre = genre
this.showEditDialog = true this.showEditDialog = true
}, },
/**
* Save edited genre to the backend server
*/
saveGenre() { saveGenre() {
// todo const feedbackStore = useFeedbackStore()
this.fetchInProgress = true
if (this.genre.id == undefined) {
// Creating new Genre
postGenre(this.genre)
.then(response => {
if (response.status == 200) {
feedbackStore.changeBanner(BannerStateEnum.GENRESAVEDSUCCESSFUL)
this.getGenres()
this.showEditDialog = false
} else {
feedbackStore.changeBanner(BannerStateEnum.GENRESAVEDERROR)
}
})
} else {
// Update existing Genre
patchGenre(this.genre)
.then(response => {
if (response.status == 200) {
feedbackStore.changeBanner(BannerStateEnum.GENRESAVEDSUCCESSFUL)
this.getGenres()
this.showEditDialog = false
} else {
feedbackStore.changeBanner(BannerStateEnum.GENRESAVEDERROR)
}
})
}
}, },
/**
* Delete a Genre object
*
* @param genre Genre to delete
*/
deleteGenre(genre: GenreApiModel) { deleteGenre(genre: GenreApiModel) {
// todo const feedbackStore = useFeedbackStore()
this.fetchInProgress = true
deleteGenre(genre)
.then(response => {
if (response.status == 200) {
feedbackStore.changeBanner(BannerStateEnum.GENREDELETESUCCESSFUL)
this.getGenres()
} else {
feedbackStore.changeBanner(BannerStateEnum.GENREDELETEERROR)
}
})
} }
} }
}) })