Streamlined stores

This commit is contained in:
2024-10-22 18:47:27 +02:00
parent 780ab85a9e
commit 9140765772
45 changed files with 384 additions and 387 deletions

View File

@@ -2,9 +2,9 @@ import { useLocalStorage } from "@vueuse/core";
import { defineStore } from "pinia";
import { AccountModel } from "../data/models/user/accountModel";
import { OrderModel } from "../data/models/ordering/orderModel";
import { useFeedbackStore } from "./feedbackStore";
import { useFeedbackStore } from "./feedback.store";
import { loginAccount, registerAccount, updateAccount } from "../data/api/accountApi";
import { getUserOrders } from "../data/api/orderApi";
import { fetchUserOrders } from "../data/api/orderApi";
import { BannerStateEnum } from "../data/enums/bannerStateEnum";
import { AddressModel } from "../data/models/user/addressModel";
import { PaymentModel } from "../data/models/user/paymentModel";
@@ -17,27 +17,49 @@ export const useAccountStore = defineStore("accountStore", {
/** Useraccount which is currently logged in */
userAccount: useLocalStorage("hackmycart/accountStore/userAccount", new AccountApiModel()),
/** User input on login screen */
loginData: ref<{ username: String, password: String}>(
{ username: "duranduran", password: "H4nn0ver" }
),
/** */
registerData: ref<AccountModel>(new AccountModel()),
/** All orders of the user */
orders: ref<Array<OrderApiModel>>([])
orders: ref<Array<OrderApiModel>>([]),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
}),
actions: {
/**
* Start the login process
*
* @param username Account username
* @param password Account password
* @returns True on success
*/
async login(username: string, password: string) {
async login(): Promise<boolean> {
const feedbackStore = useFeedbackStore()
this.fetchInProgress = true
await loginAccount(username, password)
// Validate
if (this.loginData.username == null || this.loginData.username.length == 0 ||
this.loginData.password == null || this.loginData.password.length == 0
) {
feedbackStore.changeBanner(BannerStateEnum.ACCOUNTLOGINWRONGLOGIN)
this.fetchInProgress = false
return false
}
else
{
await loginAccount(this.loginData.username, this.loginData.password)
.then(async result => {
this.userAccount = result.data
feedbackStore.changeBanner(BannerStateEnum.ACCOUNTLOGINSUCCESSFUL)
this.refreshOrders()
this.fetchInProgress = false
return true
})
.catch(error => {
if (error.status == 400) {
@@ -45,22 +67,39 @@ export const useAccountStore = defineStore("accountStore", {
} else if (error.status == 401) {
feedbackStore.changeBanner(BannerStateEnum.ACCOUNTLOGINWRONGLOGIN)
}
this.fetchInProgress = false
return false
})
}
},
/**
* Register a new account to the database
* Log in on success
*
* @param userAccount New account dataset
* @returns True on success
*/
async registerAccount(userAccount: AccountModel) {
async registerAccount(): Promise<boolean> {
const feedbackStore = useFeedbackStore()
this.fetchInProgress = true
await registerAccount(userAccount)
.then(res => {
await registerAccount(this.registerData)
.then(async res => {
if (res.status == 201) {
feedbackStore.changeBanner(BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL)
}
this.loginData = {
username: this.registerData.username,
password: this.registerData.password
}
await this.login()
.then(result => {
this.fetchInProgress = false
return true
})
})
.catch((error) => {
if (error.status == 400) {
@@ -68,9 +107,17 @@ export const useAccountStore = defineStore("accountStore", {
} else if (error.status == 409) {
feedbackStore.changeBanner(BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE)
}
this.fetchInProgress = false
return false
})
return false
},
/**
* Update values of an existing account on server
*/
async updateAccount() {
const feedbackStore = useFeedbackStore()
@@ -82,6 +129,9 @@ export const useAccountStore = defineStore("accountStore", {
})
},
/**
* Logout user
*/
logout() {
const feedbackStore = useFeedbackStore()
@@ -95,9 +145,12 @@ export const useAccountStore = defineStore("accountStore", {
* Get all orders from current user
*/
async refreshOrders() {
await getUserOrders(this.userAccount.id)
this.fetchInProgress = true
await fetchUserOrders(this.userAccount.id)
.then(result => {
this.orders = result.data
this.fetchInProgress = false
})
},

View File

@@ -1,13 +1,18 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { BandApiModel } from "../data/models/acts/bandApiModel";
import { fetchAllBands, getBand } from "../data/api/bandApi";
import { fetchAllBands, fetchBandByName } from "../data/api/bandApi";
import { BandDetailsApiModel } from "../data/models/acts/bandDetailsApiModel";
export const useBandStore = defineStore("bandStore", {
state: () => ({
/** All available bands */
bands: ref<Array<BandApiModel>>([]),
/** All information about a single band */
band: ref<BandDetailsApiModel>(new BandDetailsApiModel()),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
}),
@@ -25,7 +30,7 @@ export const useBandStore = defineStore("bandStore", {
async getBand(name: string) {
this.fetchInProgress = true
getBand(name)
fetchBandByName(name)
.then(result => {
this.band = result.data
this.fetchInProgress = false

View File

@@ -1,7 +1,7 @@
import { defineStore } from "pinia";
import { useLocalStorage } from "@vueuse/core";
import { BasketItemModel } from "../data/models/ordering/basketItemModel";
import { useFeedbackStore } from "./feedbackStore";
import { useFeedbackStore } from "./feedback.store";
import { BannerStateEnum } from "../data/enums/bannerStateEnum";
import { AddressModel } from "../data/models/user/addressModel";
import { PaymentModel } from "../data/models/user/paymentModel";
@@ -15,9 +15,16 @@ import { createOrder } from "@/data/api/orderApi";
export const useBasketStore = defineStore('basketStore', {
state: () => ({
itemsInBasket: useLocalStorage<Array<BasketItemModel>>("hackmycart/basketStore/productsInBasket", []),
/** Items in customers basket */
itemsInBasket: useLocalStorage<Array<BasketItemModel>>("hackmycart/basketStore/itemsInBasket", []),
/** Address used in the order dialog */
usedAddress: useLocalStorage("hackmycart/basketStore/usedAddress", new AddressModel()),
/** Payment method used in the order dialog */
usedPayment: useLocalStorage("hackmycart/basketStore/usedPayment", new PaymentModel()),
/** Selected seats in the booking page */
selectedSeats: ref<Array<SelectedSeatModel>>([])
}),
@@ -53,9 +60,16 @@ export const useBasketStore = defineStore('basketStore', {
)
},
moveSeatSelectionsToBasket(concert: ConcertModel, band: BandModel) {
/**
* Move all selected seats from selectedSeats to itemsInBasket variable
*
* @param band Band of the concert
*/
moveSeatSelectionsToBasket(band: BandModel) {
for (let selectedSeat of this.selectedSeats) {
let itemInBasket: BasketItemModel = this.itemsInBasket.find((basketItem: BasketItemModel) => {
let itemInBasket: BasketItemModel =
this.itemsInBasket.find((basketItem: BasketItemModel) =>
{
return basketItem.concert.id == selectedSeat.concert.id
})
@@ -77,13 +91,19 @@ export const useBasketStore = defineStore('basketStore', {
},
/**
* Take an order to the server. Sends all articles in the basket and creates an order entry in the backend database
* Take an order to the server. Sends all articles in the basket and
* creates an order entry in the backend database
*/
async takeOrder() {
const accountStore = useAccountStore()
const feedbackStore = useFeedbackStore()
await createOrder(accountStore.userAccount.id, this.itemsInBasket, this.usedPayment.id, this.usedAddress.id)
await createOrder(
accountStore.userAccount.id,
this.itemsInBasket,
this.usedPayment.id,
this.usedAddress.id
)
.then(async result => {
if (result.status == 201) {
await accountStore.refreshOrders()

View File

@@ -1,14 +1,21 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { ConcertApiModel } from "../data/models/acts/concertApiModel";
import { fetchConcert, fetchConcerts, fetchUpcomingConcerts } from "../data/api/concertApi";
import { fetchConcertById, fetchAllConcerts, fetchUpcomingConcerts } from "../data/api/concertApi";
import { ConcertDetailsApiModel } from "../data/models/acts/concertDetailsApiModel";
export const useConcertStore = defineStore("concertStore", {
state: () => ({
/** All available concerts */
concerts: ref<Array<ConcertApiModel>>([]),
/** Next upcoming concerts */
upcomingConcerts: ref<Array<ConcertApiModel>>([]),
/** Enhanced data about a specific concert */
concert: ref<ConcertDetailsApiModel>(new ConcertDetailsApiModel()),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
}),
@@ -19,23 +26,31 @@ export const useConcertStore = defineStore("concertStore", {
async getConcerts() {
this.fetchInProgress = true
fetchConcerts()
fetchAllConcerts()
.then(result => {
this.concerts = result.data
this.fetchInProgress = false
})
},
/**
* Get all data about a specific concert
*
* @param id ID of the concert in the database
*/
async getConcert(id: number) {
this.fetchInProgress = true
fetchConcert(id)
fetchConcertById(id)
.then(result => {
this.concert = result.data
this.fetchInProgress = false
})
},
/**
* Download the next four upcoming concerts from server
*/
async getUpcomingConcerts() {
this.fetchInProgress = true

View File

@@ -3,13 +3,16 @@ import { ref } from "vue";
import { BannerStateEnum } from "../data/enums/bannerStateEnum";
import { Composer } from 'vue-i18n';
/**
* Logic of the bubble notifications
* Includes an i18n object for translation
*/
export const useFeedbackStore = defineStore("feedbackStore", {
state: () => ({
showBanner: ref(false),
title: ref(""),
color: ref(""),
icon: ref(""),
fetchDataFromServerInProgress: ref(false),
$i18n: {}
}),
@@ -50,21 +53,27 @@ export const useFeedbackStore = defineStore("feedbackStore", {
case BannerStateEnum.ACCOUNTLOGINSUCCESSFUL: {
this.title = this.i18n.t('bannerMessages.loginSuccessful'); break;
}
case BannerStateEnum.ACCOUNTLOGINWRONGLOGIN: {
this.title = this.i18n.t('bannerMessages.wrongLogin'); break;
}
case BannerStateEnum.ACCOUNTLOGINERROR: {
this.title = this.i18n.t('bannerMessages.error'); break;
}
case BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL: {
this.title = this.i18n.t("bannerMessages.registerSuccessful"); break;
}
case BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE: {
this.title = this.i18n.t("bannerMessages.usernameInUse"); break;
}
case BannerStateEnum.ACCOUNTUPDATESUCCESSFUL: {
this.title = this.i18n.t("bannerMessages.accountUpdated"); break;
}
case BannerStateEnum.ACCOUNTLOGOUTSUCCESSFUL: {
this.title = this.i18n.t('bannerMessages.logoutSuccessful'); break;
}
@@ -75,12 +84,15 @@ export const useFeedbackStore = defineStore("feedbackStore", {
case BannerStateEnum.CATEGORYCREATESUCCESSFUL: {
this.title = this.i18n.t('bannerMessages.categoryCreateSuccessful'); break;
}
case BannerStateEnum.CATEGORYDELETESUCESSFUL: {
this.title = this.i18n.t('bannerMessages.categoryDeleteSuccessful'); break;
}
case BannerStateEnum.CATEGORYCREATEERROR: {
this.title = this.i18n.t('bannerMessages.categoryCreateError'); break;
}
case BannerStateEnum.CATEGORYDELETEERROR: {
this.title = this.i18n.t('bannerMessages.categoryDeleteError'); break;
}
@@ -98,17 +110,21 @@ export const useFeedbackStore = defineStore("feedbackStore", {
case BannerStateEnum.PRODUCTCREATESUCCESSFUL: {
this.title = this.i18n.t('bannerMessages.productCreateSuccessful'); break;
}
case BannerStateEnum.PRODUCTCREATEERROR: {
this.title = this.i18n.t('bannerMessages.productCreateError'); break;
}
case BannerStateEnum.PRODUCTDELETESUCCESSFUL: {
this.title = this.i18n.t('bannerMessages.productDeleteSuccessful'); break;
}
case BannerStateEnum.PRODUCTDELETEERROR: {
this.title = this.i18n.t('bannerMessages.productDeleteError'); break;
}
}
// Banner color
switch (bannerState) {
@@ -201,9 +217,6 @@ export const useFeedbackStore = defineStore("feedbackStore", {
break;
}
this.showBanner = true
}
}

View File

@@ -1,15 +1,26 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { fetchAllLocations, fetchTopLocations } from "../data/api/locationApi";
import { fetchAllLocations, fetchLocationByName, fetchTopLocations } from "../data/api/locationApi";
import { LocationApiModel } from "../data/models/locations/locationApiModel";
import { CityModel } from "../data/models/locations/cityModel";
import { fetchAllCities } from "../data/api/cityApi";
import { LocationDetailsApiModel } from "@/data/models/locations/locationDetailsApiModel";
export const useLocationStore = defineStore("locationStore", {
state: () => ({
/** All available locations */
locations: ref<Array<LocationApiModel>>([]),
/** Locations with the most concerts */
topLocations: ref<Array<LocationApiModel>>([]),
/** Enhanced data about a specific location */
location: ref<LocationDetailsApiModel>(),
/** All available cities */
cities: ref<Array<CityModel>>([]),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
}),
@@ -32,6 +43,16 @@ export const useLocationStore = defineStore("locationStore", {
})
},
getLocationByName(name: string) {
this.fetchInProgress = true
fetchLocationByName(name)
.then(result => {
this.location = result.data
this.fetchInProgress = false
})
},
/**
* Get all locations in a specific city
*
@@ -46,6 +67,9 @@ export const useLocationStore = defineStore("locationStore", {
},
/**
* Fetch top 8 locations from server
*/
async getTopLocations() {
await fetchTopLocations(8)
.then(result => {

View File

@@ -2,10 +2,17 @@ import { defineStore } from "pinia";
import { useLocalStorage } from "@vueuse/core";
import { ThemeEnum } from "../data/enums/themeEnums";
import { LanguageEnum } from "../data/enums/languageEnum";
import { ref } from "vue";
export const usePreferencesStore = defineStore('preferencesStore', {
state: () => ({
/** Selected theme by user */
theme: useLocalStorage<ThemeEnum>("hackmycart/preferencesStore/theme", ThemeEnum.DARKBLUE),
language: useLocalStorage<LanguageEnum>("hackmycart/preferencesStore/language", LanguageEnum.GERMAN)
/** Selected language by user */
language: useLocalStorage<LanguageEnum>("hackmycart/preferencesStore/language", LanguageEnum.GERMAN),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
}),
})

View File

@@ -0,0 +1,55 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { fetchBandsBySearchTerm } from "../data/api/bandApi";
import { fetchLocationsBySearchTerm } from "../data/api/locationApi";
import { fetchConcertsBySearchTerm } from "../data/api/concertApi";
import { ConcertApiModel } from "@/data/models/acts/concertApiModel";
export const useSearchStore = defineStore("searchStore", {
state: () => ({
/** Search term */
searchTerm: ref(""),
/** Band results */
bands: ref(),
/** Location results */
locations: ref(),
/** Concert results */
concerts: ref<Array<ConcertApiModel>>([]),
/** One or more searches are already performed */
alreadySearched: ref(false),
/** Request to server sent, waiting for data response */
fetchInProgress: ref(false)
}),
actions: {
/**
* Search for the term in all bands, locations, events
*/
async startSearch() {
this.alreadySearched = true
this.fetchInProgress = true
await fetchBandsBySearchTerm(this.searchTerm)
.then(result => {
this.bands = result.data
})
await fetchLocationsBySearchTerm(this.searchTerm)
.then(result => {
this.locations = result.data
})
await fetchConcertsBySearchTerm(this.searchTerm)
.then(result => {
this.concerts = result.data
})
this.fetchInProgress = false
}
}
})

View File

@@ -1,43 +0,0 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { searchBand } from "../data/api/bandApi";
import { searchLocation } from "../data/api/locationApi";
import { searchConcert } from "../data/api/concertApi";
export const useSearchStore = defineStore("searchStore", {
state: () => ({
searchTerm: ref(""),
bands: ref(),
locations: ref(),
concerts: ref(),
alreadySearched: ref(false),
searchInProgress: ref(false)
}),
actions: {
/**
* Search for the termin in all bands, locations, events
*/
async startSearch() {
this.alreadySearched = true
this.searchInProgress = true
await searchBand(this.searchTerm)
.then(result => {
this.bands = result.data
})
await searchLocation(this.searchTerm)
.then(result => {
this.locations = result.data
})
await searchConcert(this.searchTerm)
.then(result => {
this.concerts = result.data
})
this.searchInProgress = false
}
}
})

View File

@@ -1,60 +0,0 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { ConcertApiModel } from "../data/models/acts/concertApiModel";
import { BandApiModel } from "../data/models/acts/bandApiModel";
import { CityApiModel } from "../data/models/locations/cityApiModel";
import { GenreApiModel } from "../data/models/acts/genreApiModel";
import { searchBand } from "../data/api/bandApi";
import { searchLocation } from "../data/api/locationApi";
import { fetchConcerts, searchConcert } from "../data/api/concertApi";
import { useFeedbackStore } from "./feedbackStore";
export const useShopStore = defineStore("shopStore", {
state: () => ({
concertsFiltered: ref<Array<ConcertApiModel>>([]),
bandsFiltered: ref<Array<BandApiModel>>([]),
cities: ref<Array<CityApiModel>>([]),
cityFilterName: ref<string>(),
genreFilterName: ref<string>(),
genres: ref<Array<GenreApiModel>>([]),
alreadySearched: ref(false),
searchInProgress: ref(false)
}),
actions: {
/**
* Search for the termin in all bands, locations, events
*/
async startSearch() {
this.alreadySearched = true
this.searchInProgress = true
await searchBand(this.searchTerm)
.then(result => {
this.bands = result.data
})
await searchLocation(this.searchTerm)
.then(result => {
this.locations = result.data
})
await searchConcert(this.searchTerm)
.then(result => {
this.concerts = result.data
})
this.searchInProgress = false
},
async getConcerts() {
const feedbackStore = useFeedbackStore()
feedbackStore.fetchDataFromServerInProgress = true
await fetchConcerts()
.then(result => {
this.concerts = result.data
})
}
}
})

View File

@@ -1,48 +0,0 @@
import { defineStore } from "pinia";
import { ref } from "vue";
import { fetchAllCities } from "../data/api/cityApi";
import { fetchAllGenres } from "../data/api/genreApi";
import { useFeedbackStore } from "./feedbackStore";
import { CityApiModel } from "../data/models/locations/cityApiModel";
import { GenreApiModel } from "../data/models/acts/genreApiModel";
/**
* @deprecated
*/
export const useShoppingStore = defineStore("shoppingStore", {
state: () => ({
cities: ref<Array<CityApiModel>>([]),
genres: ref<Array<GenreApiModel>>([]),
cityFilterName: ref<string>(),
genreFilterName: ref<string>()
}),
actions: {
async getEvents() {
const feedbackStore = useFeedbackStore()
feedbackStore.fetchDataFromServerInProgress = true
},
async getCities() {
const feedbackStore = useFeedbackStore()
feedbackStore.fetchDataFromServerInProgress = true
await fetchAllCities()
.then(result => {
this.cities = result.data
feedbackStore.fetchDataFromServerInProgress = false
})
},
async getGenres() {
const feedbackStore = useFeedbackStore()
feedbackStore.fetchDataFromServerInProgress = true
await fetchAllGenres()
.then(result => {
this.genres = result.data
feedbackStore.fetchDataFromServerInProgress = false
})
}
}
})