Move software files one directory up, Readme
This commit is contained in:
236
src/stores/account.store.ts
Normal file
236
src/stores/account.store.ts
Normal file
@@ -0,0 +1,236 @@
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
import { AccountModel } from "../data/models/user/accountModel";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
import { deleteAccount, fetchAllAccounts, getAccount, login, registerAccount, updateAccount } from "../data/api/accountApi";
|
||||
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";
|
||||
import { AccountApiModel } from "../data/models/user/accountApiModel";
|
||||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
import { useExerciseStore } from "./exercise.store";
|
||||
|
||||
export const useAccountStore = defineStore("accountStore", {
|
||||
state: () => ({
|
||||
/** All accounts */
|
||||
accounts: ref<Array<AccountApiModel>>([]),
|
||||
|
||||
/** Useraccount which is currently logged in */
|
||||
userAccountToken: useLocalStorage("hackmycart/accountStore/userAccountToken", ""),
|
||||
|
||||
userAccount: useLocalStorage("hackmycart/accountStore/userAccount", new AccountApiModel()),
|
||||
|
||||
/** User input on login screen */
|
||||
loginData: ref<{ username: String, password: String}>(
|
||||
{ username: "", password: "" }
|
||||
),
|
||||
|
||||
/** Buffer for register data */
|
||||
registerData: ref<AccountModel>(new AccountModel()),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
adminPanelVisible: ref(false),
|
||||
|
||||
privilegeBuy: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async getAllAccounts() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchAllAccounts()
|
||||
.then(response => {
|
||||
this.accounts = response.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Start the login process
|
||||
*
|
||||
* @returns True on success
|
||||
*/
|
||||
async login(): Promise<boolean> {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
const exerciseStore = useExerciseStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
// Validate
|
||||
if (this.loginData.username == null || this.loginData.username.length == 0 ||
|
||||
this.loginData.password == null || this.loginData.password.length == 0
|
||||
) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTLOGINWRONGLOGIN)
|
||||
this.fetchInProgress = false
|
||||
return false
|
||||
}
|
||||
else
|
||||
{
|
||||
await login(this.loginData.username, this.loginData.password)
|
||||
.then(async result => {
|
||||
this.userAccountToken = result.data.token
|
||||
|
||||
getAccount(this.userAccountToken)
|
||||
.then(response => {
|
||||
this.userAccount = response.data
|
||||
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTLOGINSUCCESSFUL)
|
||||
this.fetchInProgress = false
|
||||
|
||||
this.privilegeBuy = true
|
||||
this.adminPanelVisible = response.data.accountRole.privilegeAdminPanel
|
||||
|
||||
if (response.data.accountRoleId == 3) {
|
||||
exerciseStore.solveExercise(2, 4)
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.status == 400) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTLOGINERROR)
|
||||
} else if (error.status == 401) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTLOGINWRONGLOGIN)
|
||||
}
|
||||
|
||||
this.fetchInProgress = false
|
||||
return false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Register a new account to the database
|
||||
* Log in on success
|
||||
*
|
||||
* @returns True on success
|
||||
*/
|
||||
async registerAccount(): Promise<boolean> {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
const exerciseStore = useExerciseStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
await registerAccount(this.registerData)
|
||||
.then(async res => {
|
||||
if (res.status == 201) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL)
|
||||
exerciseStore.solveExercise(0, 1)
|
||||
}
|
||||
|
||||
this.loginData = {
|
||||
username: this.registerData.username,
|
||||
password: this.registerData.password
|
||||
}
|
||||
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.status == 400) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTREGISTERERROR)
|
||||
} else if (error.status == 409) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE)
|
||||
}
|
||||
|
||||
this.fetchInProgress = false
|
||||
return false
|
||||
})
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
/**
|
||||
* Update values of an existing account on server
|
||||
*/
|
||||
async updateAccount() {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
const exerciseStore = useExerciseStore()
|
||||
|
||||
// Check for exercise 0.2 completion
|
||||
let accountComplete = this.userAccount.firstName != "" && this.userAccount.lastName != "" &&
|
||||
this.userAccount.addresses.length != 0 && this.userAccount.payments.length != 0
|
||||
|
||||
if (accountComplete) {
|
||||
exerciseStore.solveExercise(0, 2)
|
||||
}
|
||||
|
||||
// Update in backend
|
||||
await updateAccount(this.userAccount, this.userAccountToken)
|
||||
.then(res => {
|
||||
|
||||
if (res.status == 200) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTUPDATESUCCESSFUL)
|
||||
|
||||
this.userAccount = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Logout user
|
||||
*/
|
||||
logout() {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
|
||||
this.userAccount = new AccountModel()
|
||||
this.userAccountId = -1
|
||||
this.loggedIn = false
|
||||
this.privilegeBuy = false
|
||||
this.adminPanelVisible = false
|
||||
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ACCOUNTLOGOUTSUCCESSFUL)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all orders from current user
|
||||
*/
|
||||
async refreshOrders() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
await fetchUserOrders(this.userAccount.id)
|
||||
.then(result => {
|
||||
this.orders = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
async getAdresses() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an address from the user model
|
||||
*
|
||||
* @param address Address dataset to remove
|
||||
*/
|
||||
removeAddress(address: AddressModel) {
|
||||
this.userAccount.addresses = this.userAccount.addresses.filter((addr: AddressModel) =>
|
||||
addr != address
|
||||
)
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove an payment from the user model
|
||||
*
|
||||
* @param address Payment dataset to remove
|
||||
*/
|
||||
removePayment(payment: PaymentModel) {
|
||||
this.userAccount.payments = this.userAccount.payments.filter((paym: PaymentModel) =>
|
||||
paym != payment
|
||||
)
|
||||
},
|
||||
|
||||
editAccount(item: AccountModel) {
|
||||
// todo
|
||||
},
|
||||
|
||||
async deleteAccount(account: AccountModel) {
|
||||
this.fetchInProgress = true
|
||||
|
||||
deleteAccount(account)
|
||||
.then(response => {
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
137
src/stores/band.store.ts
Normal file
137
src/stores/band.store.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { BandApiModel } from "../data/models/acts/bandApiModel";
|
||||
import { fetchAllBands, fetchBandByName, patchBand, postBand } from "../data/api/bandApi";
|
||||
import { BandDetailsApiModel } from "../data/models/acts/bandDetailsApiModel";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
|
||||
import { useGenreStore } from "./genre.store";
|
||||
|
||||
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),
|
||||
|
||||
/** Show or hide the edit dialog for edit a band */
|
||||
showEditDialog: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Get all bands from server
|
||||
*/
|
||||
async getBands() {
|
||||
const genreStore = useGenreStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
await fetchAllBands()
|
||||
.then(result => {
|
||||
this.bands = result.data.filter((band: BandApiModel) => {
|
||||
if (genreStore.filteredGenres.length == 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
for (let bandGenre of band.genres) {
|
||||
for (let filteredGenres of genreStore.filteredGenres) {
|
||||
if (bandGenre.name == filteredGenres.name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
this.fetchInProgress = false
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all available data about a specific band
|
||||
*
|
||||
* @param name Name of band
|
||||
*/
|
||||
async getBand(name: string) {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
await fetchBandByName(name)
|
||||
.then(result => {
|
||||
this.band = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
.catch(res => {
|
||||
feedbackStore.notFound = true
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare edit dialog for new band, opens it
|
||||
*/
|
||||
newBand() {
|
||||
this.band = new BandDetailsApiModel()
|
||||
this.showEditDialog = 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.showEditDialog = 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.addSnackbar(BannerStateEnum.BANDSAVEDSUCCESSFUL)
|
||||
|
||||
this.getBands()
|
||||
this.showEditDialog = false
|
||||
} else {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.BANDSAVEDERROR)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
patchBand(this.band)
|
||||
.then(result => {
|
||||
if (result.status == 200) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.BANDSAVEDSUCCESSFUL)
|
||||
|
||||
this.getBands()
|
||||
this.showEditDialog = false
|
||||
} else {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.BANDSAVEDERROR)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a band by it's identifier
|
||||
*
|
||||
* @param id Id of the band in the database
|
||||
*/
|
||||
deleteBand(id: number) {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
})
|
||||
133
src/stores/basket.store.ts
Normal file
133
src/stores/basket.store.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
import { BasketItemModel } from "../data/models/ordering/basketItemModel";
|
||||
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";
|
||||
import { ref } from "vue";
|
||||
import { SelectedSeatModel } from "../data/models/ordering/selectedSeatModel";
|
||||
import { calcPrice } from "@/scripts/concertScripts";
|
||||
import { BandModel } from "../data/models/acts/bandModel";
|
||||
import { useAccountStore } from "./account.store";
|
||||
import { createOrder } from "@/data/api/orderApi";
|
||||
import { useExerciseStore } from "./exercise.store";
|
||||
|
||||
export const useBasketStore = defineStore('basketStore', {
|
||||
state: () => ({
|
||||
/** Items in customers basket */
|
||||
itemsInBasket: useLocalStorage<Array<BasketItemModel>>("hackmycart/basketStore/itemsInBasket", []),
|
||||
|
||||
/** Address used in the order dialog */
|
||||
usedAddress: ref(new AddressModel()),
|
||||
|
||||
/** Payment method used in the order dialog */
|
||||
usedPayment: ref(new PaymentModel()),
|
||||
|
||||
/** Selected seats in the booking page */
|
||||
selectedSeats: ref<Array<SelectedSeatModel>>([])
|
||||
}),
|
||||
|
||||
getters: {
|
||||
/**
|
||||
* Calculate price of all items in the basket with discount
|
||||
*
|
||||
* @returns Total price of basket
|
||||
*/
|
||||
getTotalPrice() {
|
||||
let result = 0
|
||||
|
||||
for (let item of this.itemsInBasket) {
|
||||
result += calcPrice(item.price, item.seats.length)
|
||||
}
|
||||
|
||||
return Math.round(result * 100) / 100
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Remove an item from the basket
|
||||
*
|
||||
* @param item Item to remove
|
||||
*/
|
||||
removeItemFromBasket(item: BasketItemModel) {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
feedbackStore.addSnackbar(BannerStateEnum.BASKETPRODUCTREMOVED)
|
||||
|
||||
this.itemsInBasket = this.itemsInBasket.filter((basketItemModel: BasketItemModel) =>
|
||||
basketItemModel.concert.id != item.concert.id
|
||||
)
|
||||
},
|
||||
|
||||
/**
|
||||
* 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) =>
|
||||
{
|
||||
return basketItem.concert.id == selectedSeat.concert.id
|
||||
})
|
||||
|
||||
if (itemInBasket != undefined) {
|
||||
itemInBasket.seats.push(selectedSeat.seat)
|
||||
} else {
|
||||
this.itemsInBasket.push(
|
||||
new BasketItemModel(
|
||||
selectedSeat.concert,
|
||||
band,
|
||||
selectedSeat.seat,
|
||||
selectedSeat.concert.price
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
this.selectedSeats = []
|
||||
},
|
||||
|
||||
/**
|
||||
* 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()
|
||||
const exerciseStore = useExerciseStore()
|
||||
|
||||
await createOrder(
|
||||
accountStore.userAccount.id,
|
||||
this.itemsInBasket,
|
||||
this.usedPayment.id,
|
||||
this.usedAddress.id
|
||||
)
|
||||
.then(async result => {
|
||||
if (result.status == 201) {
|
||||
await accountStore.refreshOrders()
|
||||
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ORDERPLACESUCCESSFUL)
|
||||
|
||||
// Exercise 0.3 is solved
|
||||
exerciseStore.solveExercise(0, 3)
|
||||
|
||||
console.log(this.itemsInBasket)
|
||||
|
||||
for (let item of this.itemsInBasket) {
|
||||
if (!item.concert.offered) {
|
||||
exerciseStore.solveExercise(1, 2)
|
||||
feedbackStore.addSnackbar(BannerStateEnum.EXERCISESOLVED12)
|
||||
}
|
||||
}
|
||||
|
||||
this.itemsInBasket = []
|
||||
} else {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.ERROR)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
107
src/stores/concert.store.ts
Normal file
107
src/stores/concert.store.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { ConcertApiModel } from "../data/models/acts/concertApiModel";
|
||||
import { fetchConcertById, fetchAllConcerts, fetchUpcomingConcerts } from "../data/api/concertApi";
|
||||
import { ConcertDetailsApiModel } from "../data/models/acts/concertDetailsApiModel";
|
||||
import { CityModel } from "@/data/models/locations/cityModel";
|
||||
import { ConcertModel } from "@/data/models/acts/concertModel";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
|
||||
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()),
|
||||
|
||||
/** Array of cities for which the concerts should be filtered */
|
||||
filteredCities: ref<Array<CityModel>>([]),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
/** Show or hide the edit dialog for edit a concert */
|
||||
showEditDialog: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Download all concerts from server
|
||||
*/
|
||||
async getConcerts() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchAllConcerts()
|
||||
.then(result => {
|
||||
this.concerts = result.data.filter((concert: ConcertApiModel) => {
|
||||
if (this.filteredCities.length == 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
for (let city of this.filteredCities) {
|
||||
if (city.name == concert.location.city.name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all data about a specific concert
|
||||
*
|
||||
* @param id ID of the concert in the database
|
||||
*/
|
||||
async getConcert(location: string, date: string) {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
let id = this.concerts.find((concert: ConcertApiModel) => {
|
||||
return (concert.location.urlName == location && concert.date == date)
|
||||
}).id
|
||||
|
||||
fetchConcertById(id)
|
||||
.then(result => {
|
||||
this.concert = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
.catch(res => {
|
||||
feedbackStore.notFound = true
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Download the next four upcoming concerts from server
|
||||
*/
|
||||
async getUpcomingConcerts() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchUpcomingConcerts(4)
|
||||
.then(result => {
|
||||
this.upcomingConcerts = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
newConcert() {
|
||||
this.concert = new ConcertDetailsApiModel()
|
||||
this.showEditDialog = true
|
||||
},
|
||||
|
||||
editConcert(concert: ConcertModel) {
|
||||
// todo
|
||||
},
|
||||
|
||||
async deleteConcert(item: ConcertModel) {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
})
|
||||
117
src/stores/exercise.store.ts
Normal file
117
src/stores/exercise.store.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { fetchAllExerciseGroups, updateExercise } from "@/data/api/exerciseApi";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
|
||||
import { ExerciseModel } from "@/data/models/exercises/exerciseModel";
|
||||
|
||||
export const useExerciseStore = defineStore("exerciseStore", {
|
||||
state: () => ({
|
||||
/** All exercise groups with sub-exercises */
|
||||
exercises: ref<Array<ExerciseModel>>([]),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
helpPageVisible: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Get all exercises and exercise groups from server
|
||||
*/
|
||||
async getAllExercises() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
await fetchAllExerciseGroups()
|
||||
.then(result => {
|
||||
this.exercises = result.data
|
||||
|
||||
this.helpPageVisible = this.getExercise(1, 1).solved
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a exercise by group and exercise number
|
||||
*
|
||||
* @param exerciseGroupNr Number of group of exercise
|
||||
* @param exerciseNr Number of exercise in group
|
||||
*
|
||||
* @returns ExerciseModel
|
||||
*/
|
||||
getExercise(exerciseGroupNr: number, exerciseNr: number): ExerciseModel {
|
||||
return this.exercises.find((exercise: ExerciseModel) => {
|
||||
return exercise.exerciseNr == exerciseNr && exercise.exerciseGroup.groupNr == exerciseGroupNr
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Mark an exercise as solved
|
||||
*
|
||||
* @param exerciseGroupNr Exercise group number (0-3)
|
||||
* @param exerciseNr Exercise number (1-3)
|
||||
*/
|
||||
async solveExercise(exerciseGroupNr: number, exerciseNr: number) {
|
||||
// Request all exercises from server
|
||||
await this.getAllExercises()
|
||||
|
||||
const feedbackStore = useFeedbackStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
// Change only if the exercise is not solved
|
||||
updateExercise(exerciseGroupNr, exerciseNr, true)
|
||||
.then(result => {
|
||||
if (result.data.changed) {
|
||||
|
||||
let bannerState = BannerStateEnum.ERROR
|
||||
|
||||
switch(exerciseGroupNr) {
|
||||
case 0: {
|
||||
switch(exerciseNr) {
|
||||
case 1: bannerState = BannerStateEnum.EXERCISESOLVED01; break;
|
||||
case 2: bannerState = BannerStateEnum.EXERCISESOLVED02; break;
|
||||
case 3: bannerState = BannerStateEnum.EXERCISESOLVED03; break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
switch(exerciseNr) {
|
||||
case 1: bannerState = BannerStateEnum.EXERCISESOLVED11; break;
|
||||
case 2: bannerState = BannerStateEnum.EXERCISESOLVED12; break;
|
||||
case 3: bannerState = BannerStateEnum.EXERCISESOLVED13; break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
switch(exerciseNr) {
|
||||
case 1: bannerState = BannerStateEnum.EXERCISESOLVED21; break;
|
||||
case 2: bannerState = BannerStateEnum.EXERCISESOLVED22; break;
|
||||
case 3: bannerState = BannerStateEnum.EXERCISESOLVED23; break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
switch(exerciseNr) {
|
||||
case 1: bannerState = BannerStateEnum.EXERCISESOLVED31; break;
|
||||
case 2: bannerState = BannerStateEnum.EXERCISESOLVED32; break;
|
||||
case 3: bannerState = BannerStateEnum.EXERCISESOLVED33; break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
feedbackStore.addSnackbar(bannerState)
|
||||
this.getAllExercises()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
288
src/stores/feedback.store.ts
Normal file
288
src/stores/feedback.store.ts
Normal file
@@ -0,0 +1,288 @@
|
||||
import { defineStore } from "pinia";
|
||||
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
|
||||
* Includes a variable for redirecting to 404 page
|
||||
*/
|
||||
export const useFeedbackStore = defineStore("feedbackStore", {
|
||||
state: () => ({
|
||||
snackbars: ref<Array<{text: string, color: string, icon: string }>>([]),
|
||||
|
||||
/** Show notification banner in top right corner */
|
||||
showSnackbar: ref(false),
|
||||
|
||||
/** Programmatically access to language translation module */
|
||||
$i18n: {},
|
||||
|
||||
/** Band, Location or concert on URL does not exist, redirect to 404 page */
|
||||
notFound: ref(false)
|
||||
}),
|
||||
|
||||
getters: {
|
||||
i18n(): Composer {
|
||||
return this.$i18n.global as Composer
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
addSnackbar(bannerState: BannerStateEnum) {
|
||||
this.snackbars.push({
|
||||
text: this.getSnackbarText(bannerState),
|
||||
color: this.getSnackbarColor(bannerState),
|
||||
icon: this.getSnackbarIcon(bannerState)
|
||||
})
|
||||
|
||||
this.showSnackbar = true
|
||||
},
|
||||
|
||||
getSnackbarText(bannerState: BannerStateEnum) {
|
||||
switch (bannerState) {
|
||||
////////// System feedback //////////
|
||||
|
||||
case BannerStateEnum.ERROR:
|
||||
return this.i18n.t('bannerMessages.error')
|
||||
|
||||
case BannerStateEnum.BASKETPRODUCTADDED:
|
||||
return this.i18n.t('bannerMessages.basketTicketAdded')
|
||||
|
||||
case BannerStateEnum.BASKETPRODUCTREMOVED:
|
||||
return this.i18n.t("bannerMessages.basketTicketRemoved")
|
||||
|
||||
|
||||
////////// Exercise feedback //////////
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED01:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [0, 1])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED02:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [0, 2])
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED03:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [0, 3])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED11:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [1, 1])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED12:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [1, 2])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED13:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [1, 3])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED21:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [2, 1])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED22:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [2, 2])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED23:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [2, 3])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED31:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [3, 1])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED32:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [3, 2])
|
||||
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED33:
|
||||
return this.i18n.t("bannerMessages.exerciseSolvedNr", [3, 3])
|
||||
|
||||
|
||||
|
||||
////////// API Endpoint /api //////////
|
||||
|
||||
case BannerStateEnum.DATABASERESETSUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.databaseResetSuccessful')
|
||||
|
||||
case BannerStateEnum.EXERCISEPROGRESSRESETSUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.exerciseProgressResetSuccessful')
|
||||
|
||||
|
||||
////////// API Endpoint /accounts //////////
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGINSUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.loginSuccessful')
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGINWRONGLOGIN:
|
||||
return this.i18n.t('bannerMessages.wrongLogin')
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGINERROR:
|
||||
return this.i18n.t('bannerMessages.error')
|
||||
|
||||
case BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL:
|
||||
return this.i18n.t("bannerMessages.registerSuccessful")
|
||||
|
||||
case BannerStateEnum.ACCOUNTREGISTERERROR:
|
||||
return this.i18n.t("bannerMessages.registerSuccessful")
|
||||
|
||||
case BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE:
|
||||
return this.i18n.t("bannerMessages.usernameInUse")
|
||||
|
||||
case BannerStateEnum.ACCOUNTUPDATESUCCESSFUL:
|
||||
return this.i18n.t("bannerMessages.accountUpdated")
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGOUTSUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.logoutSuccessful')
|
||||
|
||||
|
||||
////////// API Endpoint /orders //////////
|
||||
|
||||
case BannerStateEnum.ORDERPLACESUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.orderPlaceSuccessfull')
|
||||
|
||||
|
||||
////////// API Endpoint /bands //////////
|
||||
|
||||
case BannerStateEnum.BANDDELETEERROR:
|
||||
return this.i18n.t('bannerMessages.bandDeleteError')
|
||||
|
||||
case BannerStateEnum.BANDDELETESUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.bandDeleteSuccessful')
|
||||
|
||||
case BannerStateEnum.BANDSAVEDERROR:
|
||||
return this.i18n.t('bannerMessages.bandSavedError')
|
||||
|
||||
case BannerStateEnum.BANDSAVEDSUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.bandSavedSuccessful')
|
||||
|
||||
|
||||
////////// API Endpoint /genres //////////
|
||||
|
||||
case BannerStateEnum.GENREDELETEERROR:
|
||||
return this.i18n.t('bannerMessages.genreDeleteError')
|
||||
|
||||
case BannerStateEnum.GENREDELETESUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.genreDeleteSuccessful')
|
||||
|
||||
case BannerStateEnum.GENRESAVEDERROR:
|
||||
return this.i18n.t('bannerMessages.genreSavedError')
|
||||
|
||||
case BannerStateEnum.GENRESAVEDSUCCESSFUL:
|
||||
return this.i18n.t('bannerMessages.genreSavedSuccessful')
|
||||
}
|
||||
},
|
||||
|
||||
getSnackbarColor(bannerState: BannerStateEnum) {
|
||||
switch (bannerState) {
|
||||
case BannerStateEnum.ERROR:
|
||||
case BannerStateEnum.ACCOUNTLOGINERROR:
|
||||
case BannerStateEnum.ACCOUNTLOGINWRONGLOGIN:
|
||||
case BannerStateEnum.ACCOUNTREGISTERERROR:
|
||||
case BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE:
|
||||
case BannerStateEnum.BANDDELETEERROR:
|
||||
case BannerStateEnum.BANDSAVEDERROR:
|
||||
case BannerStateEnum.GENREDELETEERROR:
|
||||
case BannerStateEnum.GENRESAVEDERROR:
|
||||
return "red"
|
||||
|
||||
case BannerStateEnum.BASKETPRODUCTADDED:
|
||||
case BannerStateEnum.DATABASERESETSUCCESSFUL:
|
||||
case BannerStateEnum.ACCOUNTLOGINSUCCESSFUL:
|
||||
case BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL:
|
||||
case BannerStateEnum.ACCOUNTUPDATESUCCESSFUL:
|
||||
case BannerStateEnum.ACCOUNTLOGOUTSUCCESSFUL:
|
||||
case BannerStateEnum.ORDERPLACESUCCESSFUL:
|
||||
case BannerStateEnum.BANDDELETESUCCESSFUL:
|
||||
case BannerStateEnum.BANDSAVEDSUCCESSFUL:
|
||||
case BannerStateEnum.EXERCISEPROGRESSRESETSUCCESSFUL:
|
||||
case BannerStateEnum.GENREDELETESUCCESSFUL:
|
||||
case BannerStateEnum.GENRESAVEDSUCCESSFUL:
|
||||
return "green"
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED01:
|
||||
case BannerStateEnum.EXERCISESOLVED02:
|
||||
case BannerStateEnum.EXERCISESOLVED03:
|
||||
case BannerStateEnum.EXERCISESOLVED11:
|
||||
case BannerStateEnum.EXERCISESOLVED12:
|
||||
case BannerStateEnum.EXERCISESOLVED13:
|
||||
case BannerStateEnum.EXERCISESOLVED21:
|
||||
case BannerStateEnum.EXERCISESOLVED22:
|
||||
case BannerStateEnum.EXERCISESOLVED23:
|
||||
case BannerStateEnum.EXERCISESOLVED31:
|
||||
case BannerStateEnum.EXERCISESOLVED32:
|
||||
case BannerStateEnum.EXERCISESOLVED33:
|
||||
return "purple"
|
||||
|
||||
case BannerStateEnum.BASKETPRODUCTREMOVED:
|
||||
return "blue"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getSnackbarIcon(bannerState: BannerStateEnum) {
|
||||
switch (bannerState) {
|
||||
case BannerStateEnum.ERROR:
|
||||
return "mdi-alert-circle"
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGINERROR:
|
||||
case BannerStateEnum.ACCOUNTLOGINWRONGLOGIN:
|
||||
case BannerStateEnum.ACCOUNTREGISTERERROR:
|
||||
case BannerStateEnum.ACCOUNTREGISTERUSERNAMEINUSE:
|
||||
return "mdi-account"
|
||||
|
||||
case BannerStateEnum.EXERCISESOLVED01:
|
||||
case BannerStateEnum.EXERCISESOLVED02:
|
||||
case BannerStateEnum.EXERCISESOLVED03:
|
||||
case BannerStateEnum.EXERCISESOLVED11:
|
||||
case BannerStateEnum.EXERCISESOLVED12:
|
||||
case BannerStateEnum.EXERCISESOLVED13:
|
||||
case BannerStateEnum.EXERCISESOLVED21:
|
||||
case BannerStateEnum.EXERCISESOLVED22:
|
||||
case BannerStateEnum.EXERCISESOLVED23:
|
||||
case BannerStateEnum.EXERCISESOLVED31:
|
||||
case BannerStateEnum.EXERCISESOLVED32:
|
||||
case BannerStateEnum.EXERCISESOLVED33:
|
||||
return "mdi-check-circle-outline"
|
||||
|
||||
case BannerStateEnum.DATABASERESETSUCCESSFUL:
|
||||
case BannerStateEnum.EXERCISEPROGRESSRESETSUCCESSFUL:
|
||||
return "mdi-database-refresh"
|
||||
|
||||
case BannerStateEnum.BASKETPRODUCTADDED:
|
||||
case BannerStateEnum.BASKETPRODUCTREMOVED:
|
||||
return "mdi-basket"
|
||||
|
||||
case BannerStateEnum.ORDERPLACESUCCESSFUL:
|
||||
return "mdi-basket-check"
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGOUTSUCCESSFUL:
|
||||
return "mdi-logout"
|
||||
|
||||
case BannerStateEnum.ACCOUNTLOGINSUCCESSFUL:
|
||||
return "mdi-login"
|
||||
|
||||
case BannerStateEnum.ACCOUNTREGISTERSUCCESSFUL:
|
||||
return "mdi-account-plus"
|
||||
|
||||
case BannerStateEnum.ACCOUNTUPDATESUCCESSFUL:
|
||||
return "mdi-account-reactivate"
|
||||
|
||||
case BannerStateEnum.BANDDELETEERROR:
|
||||
case BannerStateEnum.BANDDELETESUCCESSFUL:
|
||||
case BannerStateEnum.BANDSAVEDERROR:
|
||||
case BannerStateEnum.BANDSAVEDSUCCESSFUL:
|
||||
return "mdi-guitar-electric"
|
||||
|
||||
case BannerStateEnum.GENREDELETEERROR:
|
||||
case BannerStateEnum.GENREDELETESUCCESSFUL:
|
||||
case BannerStateEnum.GENRESAVEDERROR:
|
||||
case BannerStateEnum.GENRESAVEDSUCCESSFUL:
|
||||
return "mdi-music-clef-treble"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
61
src/stores/files.store.ts
Normal file
61
src/stores/files.store.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { fetchFileNames, fetchFolderNames, postFile } from "@/data/api/files.api";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
|
||||
export const useFilesStore = defineStore('filesStore', {
|
||||
state: () => ({
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
staticFolders: ref<Array<{name: string, nrOfItems: number}>>([]),
|
||||
|
||||
selectedFolder: ref<{name: string, nrOfItems: number}>(),
|
||||
|
||||
/** List of files on the server */
|
||||
staticFiles: ref<Array<{name: string, size: number, url: string}>>([]),
|
||||
|
||||
selectedFile: ref<{name: string, size: number, url: string}>(),
|
||||
|
||||
showFileUploadDialog: ref(false),
|
||||
|
||||
fileUpload: ref(),
|
||||
|
||||
fileUploadDir: ref(""),
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async getStaticFolders() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchFolderNames()
|
||||
.then(res => {
|
||||
this.staticFolders = res.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Request all available static files on server
|
||||
*/
|
||||
async getStaticFiles() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchFileNames(this.selectedFolder.name)
|
||||
.then(res => {
|
||||
this.staticFiles = res.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
async uploadFile() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
postFile(this.uploadFile, this.fileUploadDir)
|
||||
.then(response => {
|
||||
console.log(response)
|
||||
this.showFileUploadDialog = false
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
112
src/stores/genre.store.ts
Normal file
112
src/stores/genre.store.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { deleteGenre, fetchAllGenres, patchGenre, postGenre } from "@/data/api/genreApi";
|
||||
import { GenreApiModel } from "@/data/models/acts/genreApiModel";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
|
||||
|
||||
export const useGenreStore = defineStore("genreStore", {
|
||||
state: () => ({
|
||||
/** All available genres from server */
|
||||
genres: ref<Array<GenreApiModel>>([]),
|
||||
|
||||
/** Currently edited genre */
|
||||
genre: ref<GenreApiModel>(new GenreApiModel()),
|
||||
|
||||
/** Genres to filter bands for */
|
||||
filteredGenres: ref<Array<GenreApiModel>>([]),
|
||||
|
||||
/** Show or hide edit dialog for Genre object */
|
||||
showEditDialog: ref(false),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Get all genres from the database
|
||||
*/
|
||||
getGenres() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchAllGenres()
|
||||
.then(response => {
|
||||
this.genres = response.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare edit dialog for new genre, opens it
|
||||
*/
|
||||
newGenre() {
|
||||
this.genre = new GenreApiModel()
|
||||
this.showEditDialog = true
|
||||
},
|
||||
|
||||
/**
|
||||
* Edit a Genre object, move parameter to this.genre, opens dialog
|
||||
*
|
||||
* @param genre Selected Genre object
|
||||
*/
|
||||
editGenre(genre: GenreApiModel) {
|
||||
this.genre = genre
|
||||
this.showEditDialog = true
|
||||
},
|
||||
|
||||
/**
|
||||
* Save edited genre to the backend server
|
||||
*/
|
||||
saveGenre() {
|
||||
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)
|
||||
}
|
||||
})
|
||||
} 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a Genre object
|
||||
*
|
||||
* @param genre Genre to delete
|
||||
*/
|
||||
deleteGenre(genre: GenreApiModel) {
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
105
src/stores/location.store.ts
Normal file
105
src/stores/location.store.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
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";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
|
||||
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>(new LocationDetailsApiModel()),
|
||||
|
||||
/** All available cities */
|
||||
cities: ref<Array<CityModel>>([]),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
showEditLocation: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Download all cities/locations from server
|
||||
*/
|
||||
async getLocations() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
await fetchAllLocations()
|
||||
.then(result => {
|
||||
this.locations = result.data
|
||||
})
|
||||
|
||||
await fetchAllCities()
|
||||
.then(result => {
|
||||
this.cities = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
getLocationByName(name: string) {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchLocationByName(name)
|
||||
.then(result => {
|
||||
this.location = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
.catch(res => {
|
||||
feedbackStore.notFound = true
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all locations in a specific city
|
||||
*
|
||||
* @param city City to filter for
|
||||
*
|
||||
* @returns Array of cities which are in the target city
|
||||
*/
|
||||
getLocationsByCity(city: string): Array<LocationApiModel> {
|
||||
return this.locations.filter((location: LocationApiModel) => {
|
||||
return location.city.name == city
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Fetch top 8 locations from server
|
||||
*/
|
||||
async getTopLocations() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
await fetchTopLocations(8)
|
||||
.then(result => {
|
||||
this.topLocations = result.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
newLocation() {
|
||||
this.location = new LocationDetailsApiModel()
|
||||
this.showEditLocation = true
|
||||
},
|
||||
|
||||
editLocation(item: LocationApiModel) {
|
||||
this.location = item
|
||||
this.showEditLocation = true
|
||||
},
|
||||
|
||||
async deleteLocation(item: LocationApiModel) {
|
||||
// todo
|
||||
}
|
||||
},
|
||||
})
|
||||
58
src/stores/order.store.ts
Normal file
58
src/stores/order.store.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { fetchAllOrders, fetchUserOrders } from "@/data/api/orderApi";
|
||||
import { OrderApiModel } from "@/data/models/apiEndpoints/orderApiModel";
|
||||
import { AccountModel } from "@/data/models/user/accountModel";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
|
||||
export const useOrderStore = defineStore("orderStore", {
|
||||
state: () => ({
|
||||
/** All orders of one/all users */
|
||||
orders: ref<Array<OrderApiModel>>([]),
|
||||
|
||||
order: ref<OrderApiModel>(new OrderApiModel),
|
||||
|
||||
showDetailDialog: ref<boolean>(false),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false)
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Get all orders from all accounts from server
|
||||
*/
|
||||
async getAllOrders() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchAllOrders()
|
||||
.then(res => {
|
||||
this.orders = res.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all orders from one account from server
|
||||
*
|
||||
* @param user User to request orders from
|
||||
*/
|
||||
async getOrdersOfAccount(user: AccountModel) {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchUserOrders(user.id)
|
||||
.then(res => {
|
||||
this.orders = res.data
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
openDetails(order: OrderApiModel) {
|
||||
this.order = order
|
||||
this.showDetailDialog = true
|
||||
},
|
||||
|
||||
async deleteOrder(order: OrderApiModel) {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
})
|
||||
136
src/stores/preferences.store.ts
Normal file
136
src/stores/preferences.store.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
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";
|
||||
import { fetchServerState,resetDatabase, resetExerciseProgress } from "@/data/api/mainApi";
|
||||
import { ServerStateEnum } from "@/data/enums/serverStateEnum";
|
||||
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
|
||||
import { useFeedbackStore } from "./feedback.store";
|
||||
import { useBasketStore } from "./basket.store";
|
||||
import { useExerciseStore } from "./exercise.store";
|
||||
import { useAccountStore } from "./account.store";
|
||||
import { AccountApiModel } from "@/data/models/user/accountApiModel";
|
||||
|
||||
export const usePreferencesStore = defineStore('preferencesStore', {
|
||||
state: () => ({
|
||||
/** Selected theme by user */
|
||||
theme: useLocalStorage<ThemeEnum>("hackmycart/preferencesStore/theme", ThemeEnum.DARK),
|
||||
|
||||
/** Selected language by user */
|
||||
language: useLocalStorage<LanguageEnum>("hackmycart/preferencesStore/language", LanguageEnum.GERMAN),
|
||||
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
/** State of the server */
|
||||
serverState: ref<ServerStateEnum>(ServerStateEnum.PENDING),
|
||||
|
||||
/** Show the "Delete DB?" confirm dialog */
|
||||
showDeleteDbDialog: ref(false),
|
||||
|
||||
/** Show the "Delete Exercise progress?" confirm dialog */
|
||||
showDeleteExerciseDialog: ref(false),
|
||||
|
||||
/** Show the "Factory reset" confirm dialog */
|
||||
showFactoryResetDialog: ref(false),
|
||||
|
||||
/** Marks the first run of the app */
|
||||
firstStartup: useLocalStorage<Boolean>("hackmycart/preferencesStore/firstStartup", true),
|
||||
|
||||
/** Full name of student */
|
||||
studentName: useLocalStorage<string>("hackmycart/preferencesStore/studentName", ""),
|
||||
|
||||
/** Matrikel number */
|
||||
registrationNumber: useLocalStorage<string>("hackmycart/preferencesStore/registrationNumber", "")
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Request the state of the backend server
|
||||
*/
|
||||
async getServerState() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
fetchServerState()
|
||||
.then(result => {
|
||||
if (result.status == 200) {
|
||||
this.serverState = ServerStateEnum.ONLINE
|
||||
} else {
|
||||
this.serverState = ServerStateEnum.OFFLINE
|
||||
}
|
||||
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
.catch(error => {
|
||||
this.serverState = ServerStateEnum.OFFLINE
|
||||
this.fetchInProgress = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the database (without exercise tables)
|
||||
*/
|
||||
async resetDb() {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
this.serverState = ServerStateEnum.PENDING
|
||||
this.fetchInProgress = true
|
||||
|
||||
await resetDatabase()
|
||||
.then(result => {
|
||||
if (result.status == 200) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.DATABASERESETSUCCESSFUL)
|
||||
this.serverState = ServerStateEnum.ONLINE
|
||||
}
|
||||
|
||||
this.fetchInProgress = false
|
||||
this.showDeleteDbDialog = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the exercise progress
|
||||
*/
|
||||
async resetExerciseProg() {
|
||||
const feedbackStore = useFeedbackStore()
|
||||
const exerciseStore = useExerciseStore()
|
||||
|
||||
this.serverState = ServerStateEnum.PENDING
|
||||
this.fetchInProgress = true
|
||||
|
||||
await resetExerciseProgress()
|
||||
.then(result => {
|
||||
if (result.status == 200) {
|
||||
feedbackStore.addSnackbar(BannerStateEnum.EXERCISEPROGRESSRESETSUCCESSFUL)
|
||||
this.serverState = ServerStateEnum.ONLINE
|
||||
|
||||
exerciseStore.getAllExercises()
|
||||
}
|
||||
|
||||
this.fetchInProgress = false
|
||||
this.showDeleteExerciseDialog = false
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset all store values to factory state
|
||||
*/
|
||||
resetToFactorySettings() {
|
||||
const basketStore = useBasketStore()
|
||||
const accountStore = useAccountStore()
|
||||
|
||||
this.firstStartup = true
|
||||
this.studentName = ""
|
||||
this.registrationNumber = ""
|
||||
this.theme = "dark"
|
||||
this.language = LanguageEnum.GERMAN
|
||||
basketStore.itemsInBasket = []
|
||||
accountStore.userAccountToken = ""
|
||||
accountStore.userAccount = new AccountApiModel()
|
||||
|
||||
|
||||
|
||||
this.showFactoryResetDialog = false
|
||||
}
|
||||
}
|
||||
})
|
||||
67
src/stores/search.store.ts
Normal file
67
src/stores/search.store.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
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";
|
||||
import { useExerciseStore } from "./exercise.store";
|
||||
|
||||
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() {
|
||||
const exerciseStore = useExerciseStore()
|
||||
|
||||
this.alreadySearched = true
|
||||
this.fetchInProgress = true
|
||||
|
||||
// Exercise solutions
|
||||
if (this.searchTerm.endsWith("'); SELECT * FROM Accounts; --")) {
|
||||
exerciseStore.solveExercise(2, 1)
|
||||
} else if (this.searchTerm.endsWith("'); SELECT * FROM AccountRoles; --")) {
|
||||
exerciseStore.solveExercise(2, 2)
|
||||
} else if (this.searchTerm.includes("'); UPDATE Accounts SET accountRoleId = 2 WHERE username = ")) {
|
||||
exerciseStore.solveExercise(2, 3)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user