Finish GenresAdminPanel
This commit is contained in:
@@ -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()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
})
|
||||||
}
|
}
|
||||||
@@ -84,5 +84,15 @@ export enum BannerStateEnum {
|
|||||||
|
|
||||||
BANDDELETESUCCESSFUL,
|
BANDDELETESUCCESSFUL,
|
||||||
|
|
||||||
BANDDELETEERROR
|
BANDDELETEERROR,
|
||||||
|
|
||||||
|
////////// API Endpoint /genres //////////
|
||||||
|
|
||||||
|
GENRESAVEDSUCCESSFUL,
|
||||||
|
|
||||||
|
GENRESAVEDERROR,
|
||||||
|
|
||||||
|
GENREDELETESUCCESSFUL,
|
||||||
|
|
||||||
|
GENREDELETEERROR
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export class GenreModel {
|
export class GenreModel {
|
||||||
id: number = -1
|
id: number
|
||||||
name: string = ""
|
name: string = ""
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user