2 Commits

Author SHA1 Message Date
409fa835a3 Bugfix genre store 2025-09-01 15:08:13 +02:00
9506156070 Limit nr of top genres on homepage 2025-09-01 14:49:02 +02:00
6 changed files with 95 additions and 61 deletions

View File

@@ -1,4 +1,4 @@
# v.0.4.0 (2025-08-30)
# v.0.4.0 MuC-Edition (2025-09-01)
## 🚀 Features
@@ -12,7 +12,13 @@
- Icons on exercise groups on help page
- Welcome dialog: New page for look and feel, merge database and exercise creation in one step
- Add links to GitHub and project page on settings
- New section on homepage for popular genres
## 🐛 Bugfixes
- Filter on band page changes visible bands on homepage
- No startup after packaging
- Infinity loading on concert booking page is user comes from band page
# v.0.3.0 (2025-02-28)
## 🚀 Features

View File

@@ -297,7 +297,8 @@
},
"genre": {
"withoutBand": "ohne Band",
"popular": "Beliebte Genres"
"popular": "Beliebte Genres",
"allGenres": "Alle Genres"
},
"admin": {
"adminpanel": "Admin Panel"

View File

@@ -297,7 +297,8 @@
},
"genre": {
"withoutBand": "without Band",
"popular": "Popular Genres"
"popular": "Popular Genres",
"allGenres": "All Genres"
},
"admin": {
"adminpanel": "Admin Panel"

View File

@@ -7,7 +7,7 @@ import TopLocationsSection from "./topLocationsSection.vue";
import { usePreferencesStore } from "@/stores/preferences.store";
import welcomeDialog from "./welcomeDialog/dialog.vue";
import { ref } from "vue";
import genresSection from "./genresSection.vue";
import genresSection from "./topGenresSection.vue";
const concertStore = useConcertStore();
const locationStore = useLocationStore();

View File

@@ -6,6 +6,7 @@ import { GenreApiModel } from "@/data/models/acts/genreApiModel";
import { useGenreStore } from "@/stores/genre.store";
import { ref, watch } from "vue";
import { useRouter } from "vue-router";
import outlinedButton from "@/components/basics/outlinedButton.vue";
const genreStore = useGenreStore();
const genresByNumberOfBands = ref<Array<GenreApiModel>>([]);
@@ -37,7 +38,7 @@ watch(
<v-skeleton-loader :loading="true" type="card" />
</v-col>
<v-col v-else v-for="genre in genresByNumberOfBands" cols="6" md="3">
<v-col v-else v-for="genre in genreStore.topGenres" cols="6" md="3">
<card-view
@click="router.push({ path: '/bands', query: { genreName: genre.name }})"
:title="genre.name"
@@ -45,4 +46,17 @@ watch(
/>
</v-col>
</v-row>
<!-- todo?
<v-row>
<v-col>
<outlined-button
append-icon="mdi-chevron-right"
@click="router.push('/')"
block
>
{{ $t('genre.allGenres') }}
</outlined-button>
</v-col>
</v-row> -->
</template>

View File

@@ -1,4 +1,9 @@
import { deleteGenre, fetchAllGenres, patchGenre, postGenre } from "@/data/api/genreApi";
import {
deleteGenre,
fetchAllGenres,
patchGenre,
postGenre,
} from "@/data/api/genreApi";
import { GenreApiModel } from "@/data/models/acts/genreApiModel";
import { defineStore } from "pinia";
import { ref } from "vue";
@@ -10,6 +15,8 @@ export const useGenreStore = defineStore("genreStore", {
/** All available genres from server */
genres: ref<Array<GenreApiModel>>([]),
topGenres: ref<Array<GenreApiModel>>([]),
/** Currently selected genre */
genre: ref<GenreApiModel>(null),
@@ -17,7 +24,7 @@ export const useGenreStore = defineStore("genreStore", {
showEditDialog: ref(false),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
fetchInProgress: ref(false),
}),
actions: {
@@ -25,21 +32,29 @@ export const useGenreStore = defineStore("genreStore", {
* Get all genres from the database
*/
getGenres() {
this.fetchInProgress = true
this.fetchInProgress = true;
fetchAllGenres()
.then(response => {
this.genres = response.data
this.fetchInProgress = false
})
fetchAllGenres().then((response) => {
this.genres = response.data;
let genresByNumberOfBands = this.genres.slice();
genresByNumberOfBands.sort((a, b) => {
return b.bands.length - a.bands.length;
});
this.topGenres = genresByNumberOfBands.splice(0, 8)
this.fetchInProgress = false;
});
},
/**
* Prepare edit dialog for new genre, opens it
*/
newGenre() {
this.genre = new GenreApiModel()
this.showEditDialog = true
this.genre = new GenreApiModel();
this.showEditDialog = true;
},
/**
@@ -48,41 +63,39 @@ export const useGenreStore = defineStore("genreStore", {
* @param genre Selected Genre object
*/
editGenre(genre: GenreApiModel) {
this.genre = genre
this.showEditDialog = true
this.genre = genre;
this.showEditDialog = true;
},
/**
* Save edited genre to the backend server
*/
saveGenre() {
const feedbackStore = useFeedbackStore()
this.fetchInProgress = true
const feedbackStore = useFeedbackStore();
this.fetchInProgress = true;
if (this.genre.id == undefined) {
// Creating new Genre
postGenre(this.genre)
.then(response => {
if (response.status == 200) {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDSUCCESSFUL)
this.getGenres()
this.showEditDialog = false
} else {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDERROR)
}
})
postGenre(this.genre).then((response) => {
if (response.status == 200) {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDSUCCESSFUL);
this.getGenres();
this.showEditDialog = false;
} else {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDERROR);
}
});
} else {
// Update existing Genre
patchGenre(this.genre)
.then(response => {
if (response.status == 200) {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDSUCCESSFUL)
this.getGenres()
this.showEditDialog = false
} else {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDERROR)
}
})
patchGenre(this.genre).then((response) => {
if (response.status == 200) {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDSUCCESSFUL);
this.getGenres();
this.showEditDialog = false;
} else {
feedbackStore.addSnackbar(BannerStateEnum.GENRESAVEDERROR);
}
});
}
},
@@ -92,31 +105,30 @@ export const useGenreStore = defineStore("genreStore", {
* @param genre Genre to delete
*/
deleteGenre(genre: GenreApiModel) {
const feedbackStore = useFeedbackStore()
this.fetchInProgress = true
const feedbackStore = useFeedbackStore();
this.fetchInProgress = true;
deleteGenre(genre)
.then(response => {
if (response.status == 200) {
feedbackStore.addSnackbar(BannerStateEnum.GENREDELETESUCCESSFUL)
this.getGenres()
} else {
feedbackStore.addSnackbar(BannerStateEnum.GENREDELETEERROR)
}
})
deleteGenre(genre).then((response) => {
if (response.status == 200) {
feedbackStore.addSnackbar(BannerStateEnum.GENREDELETESUCCESSFUL);
this.getGenres();
} else {
feedbackStore.addSnackbar(BannerStateEnum.GENREDELETEERROR);
}
});
},
setGenreByName(name: string) {
this.genre = null
name = name.replace("+", " ")
this.genre = null;
name = name.replace("+", " ");
let newGenre = this.genres.find(genre => {
return genre.name == name
})
let newGenre = this.genres.find((genre) => {
return genre.name == name;
});
if (newGenre != undefined) {
this.genre = newGenre
this.genre = newGenre;
}
}
}
})
},
},
});