More skelton loader, add optional parameters to /locations and /events
This commit is contained in:
1 parent
e2f6fb9c52
commit
bfffd72a4a
16 files changed
+106
-48
No files matched your search
@@ -53,7 +53,7 @@ The application host it's data in a SQLite database. The access is managed by an
|
|||||||
#### Listing existing
|
#### Listing existing
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><code><span style="color:#70AFFD"><b>GET</b></span></code> <code><b>/events?city=cityName&genre=genreName</b></code> <code> (Get all events, filtered by city and genre)</code>
|
<summary><code><span style="color:#70AFFD"><b>GET</b></span></code> <code><b>/events?city=cityName&genre=genreName&count=nrOfItems&sort=sortDirection</b></code> <code> (Get all events, filtered by city and genre)</code>
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
##### Parameters
|
##### Parameters
|
||||||
@@ -61,16 +61,31 @@ The application host it's data in a SQLite database. The access is managed by an
|
|||||||
> | :---: | --- | --- | --- |
|
> | :---: | --- | --- | --- |
|
||||||
> | `cityName` | optional | string | Name of the city to filter for |
|
> | `cityName` | optional | string | Name of the city to filter for |
|
||||||
> | `genreName` | optional | string | Name of the genre to filter for |
|
> | `genreName` | optional | string | Name of the genre to filter for |
|
||||||
|
> | `nrOfItems` | optional | number | Limits number of results |
|
||||||
|
> | `sortDirection` | optional | string | Sort by number of concerts, 'asc' or 'desc' |
|
||||||
|
|
||||||
##### Responses
|
##### Responses
|
||||||
> | http code | content-type | response |
|
> | http code | content-type | response |
|
||||||
> | :---: | --- | --- |
|
> | :---: | --- | --- |
|
||||||
> | `200` | `application/json` | `Event` + `Array<Concert + Location>` + `Array<Band>` |
|
> | `200` | `application/json` | `Array<Event + Array<Concert + Location + City> + Band & Genre>` |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><code><span style="color:#70AFFD"><b>GET</b></span></code> <code><b>/locations?count=nrOfItems&sort=sortDirection</b></code> <code> (Get all locations)</code>
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
##### Parameters
|
||||||
|
> | name | type | data type | description |
|
||||||
|
> | :---: | --- | --- | --- |
|
||||||
|
> | `nrOfItems` | optional | number | Limits number of results |
|
||||||
|
> | `sortDirection` | optional | string | Sort by number of concerts, 'asc' or 'desc' |
|
||||||
|
|
||||||
|
##### Responses
|
||||||
|
> | http code | content-type | response |
|
||||||
|
> | :---: | --- | --- |
|
||||||
|
> | `200` | `application/json` | `Array<Location + City + Array<Concert + Event>>` |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
Down here: todo!
|
Down here: todo!
|
||||||
@@ -156,18 +171,7 @@ Down here: todo!
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><code><span style="color:#70AFFD"><b>GET</b></span></code> <code><b>/locations</b></code> <code> (Get all locations)</code>
|
|
||||||
</summary>
|
|
||||||
|
|
||||||
##### Parameters
|
|
||||||
> None
|
|
||||||
|
|
||||||
##### Responses
|
|
||||||
> | http code | content-type | response |
|
|
||||||
> | :---: | --- | --- |
|
|
||||||
> | `200` | `application/json` | `Array<Location>` + `City` |
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"name": "Unlimited Love",
|
"name": "Unlimited Love",
|
||||||
"bandId": 0,
|
"bandId": 0,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "unlimited-love-tour.jpg",
|
"image": "events/unlimited-love-tour.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
"name": "The Bends",
|
"name": "The Bends",
|
||||||
"bandId": 1,
|
"bandId": 1,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "the-bends-tour.jpg",
|
"image": "events/the-bends-tour.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 5,
|
"id": 5,
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"name": "European Tour",
|
"name": "European Tour",
|
||||||
"bandId": 2,
|
"bandId": 2,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "european-tour-arctic-monkeys.jpg",
|
"image": "events/european-tour-arctic-monkeys.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 8,
|
"id": 8,
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
"name": "Music of the Spheres",
|
"name": "Music of the Spheres",
|
||||||
"bandId": 3,
|
"bandId": 3,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "music-of-the-spheres.png",
|
"image": "events/music-of-the-spheres.png",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 10,
|
"id": 10,
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
"name": "But Here We Are Tour",
|
"name": "But Here We Are Tour",
|
||||||
"bandId": 4,
|
"bandId": 4,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "but-here-we-are.jpg",
|
"image": "events/but-here-we-are.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 13,
|
"id": 13,
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
"name": "Crisis of Faith",
|
"name": "Crisis of Faith",
|
||||||
"bandId": 5,
|
"bandId": 5,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "crisis-of-faith-tour.jpg",
|
"image": "events/crisis-of-faith-tour.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 14,
|
"id": 14,
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
"name": "Back to the Water Below",
|
"name": "Back to the Water Below",
|
||||||
"bandId": 6,
|
"bandId": 6,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "back-to-the-water-below.jpg",
|
"image": "events/back-to-the-water-below.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 16,
|
"id": 16,
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
"name": "Will of the People Tour",
|
"name": "Will of the People Tour",
|
||||||
"bandId": 7,
|
"bandId": 7,
|
||||||
"offered": true,
|
"offered": true,
|
||||||
"image": "will-of-the-people-tour.jpg",
|
"image": "events/will-of-the-people-tour.jpg",
|
||||||
"concerts": [
|
"concerts": [
|
||||||
{
|
{
|
||||||
"id": 18,
|
"id": 18,
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -11,6 +11,8 @@ export const events = Router()
|
|||||||
events.get("/", async (req: Request, res: Response) => {
|
events.get("/", async (req: Request, res: Response) => {
|
||||||
let cityName = req.query.city
|
let cityName = req.query.city
|
||||||
let genreName = req.query.genre
|
let genreName = req.query.genre
|
||||||
|
let sort = req.query.sort
|
||||||
|
let count = req.query.count
|
||||||
let cityFilter = {}
|
let cityFilter = {}
|
||||||
let genreFilter = {}
|
let genreFilter = {}
|
||||||
|
|
||||||
@@ -44,14 +46,16 @@ events.get("/", async (req: Request, res: Response) => {
|
|||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Location,
|
model: Location,
|
||||||
|
required: true,
|
||||||
include: [
|
include: [
|
||||||
cityFilter
|
cityFilter
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: Band,
|
model: Band,
|
||||||
|
required: true,
|
||||||
include: [
|
include: [
|
||||||
genreFilter
|
genreFilter
|
||||||
]
|
]
|
||||||
@@ -59,21 +63,21 @@ events.get("/", async (req: Request, res: Response) => {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
.then(events => {
|
.then(events => {
|
||||||
let resultArray = []
|
if (sort != undefined) {
|
||||||
|
events.sort((event1, event2) => {
|
||||||
// Remove datasets which not fulfill the optional parameter
|
if (sort == "desc") {
|
||||||
for (let event of events) {
|
return event2.dataValues.concerts.length - event1.dataValues.concerts.length
|
||||||
if (event.dataValues.band != null) {
|
} else if (sort == "asc") {
|
||||||
for (let concert of event.dataValues.concerts) {
|
return event1.dataValues.concerts.length - event2.dataValues.concerts.length
|
||||||
if (concert.dataValues.location != null) {
|
|
||||||
resultArray.push(event)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(200).json(resultArray)
|
if (count != undefined) {
|
||||||
|
events.splice(Number(count))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json(events)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -12,6 +12,9 @@ import { Op } from "sequelize";
|
|||||||
export const location = Router()
|
export const location = Router()
|
||||||
|
|
||||||
location.get("/", (req: Request, res: Response) => {
|
location.get("/", (req: Request, res: Response) => {
|
||||||
|
let sort = req.query.sort
|
||||||
|
let count = req.query.count
|
||||||
|
|
||||||
Location.findAll({
|
Location.findAll({
|
||||||
include: [
|
include: [
|
||||||
City,
|
City,
|
||||||
@@ -49,13 +52,25 @@ location.get("/", (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sort != undefined) {
|
||||||
|
locations.sort((location1, location2) => {
|
||||||
|
if (sort == "desc") {
|
||||||
|
return location2.dataValues.concerts.length - location1.dataValues.concerts.length
|
||||||
|
} else if (sort == "asc") {
|
||||||
|
return location1.dataValues.concerts.length - location2.dataValues.concerts.length
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count != undefined) {
|
||||||
|
locations.splice(Number(count))
|
||||||
|
}
|
||||||
|
|
||||||
res.status(200).json(locations)
|
res.status(200).json(locations)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
location.get("/:name", (req: Request, res: Response) => {
|
location.get("/:name", (req: Request, res: Response) => {
|
||||||
console.log(req.params.name)
|
|
||||||
|
|
||||||
Location.findOne({
|
Location.findOne({
|
||||||
where: { name: { [Op.like]: req.params.name } },
|
where: { name: { [Op.like]: req.params.name } },
|
||||||
include: [
|
include: [
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ defineProps({
|
|||||||
<v-col>
|
<v-col>
|
||||||
<card-with-left-image
|
<card-with-left-image
|
||||||
:title="title"
|
:title="title"
|
||||||
:image="'http://localhost:3000/static/tours/' + image"
|
:image="'http://localhost:3000/static/' + image"
|
||||||
>
|
>
|
||||||
<div class="text-body-1 font-weight-bold">
|
<div class="text-body-1 font-weight-bold">
|
||||||
<div v-if="!$slots.description">
|
<div v-if="!$slots.description">
|
||||||
|
|||||||
@@ -7,5 +7,11 @@ export async function fetchEvents(city: string = "", genre: string = "") {
|
|||||||
url += (city.length > 0) ? "city=" + city + "&" : ""
|
url += (city.length > 0) ? "city=" + city + "&" : ""
|
||||||
url += (genre.length > 0) ? "genre=" + genre : ""
|
url += (genre.length > 0) ? "genre=" + genre : ""
|
||||||
|
|
||||||
|
return await axios.get(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTopEvents(nrOfEvents) {
|
||||||
|
let url = BASE_URL + "?sort=desc&count=" + nrOfEvents
|
||||||
|
|
||||||
return await axios.get(url)
|
return await axios.get(url)
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
|
|
||||||
let BASE_URL = "http://localhost:3000/locations"
|
const BASE_URL = "http://localhost:3000/locations"
|
||||||
|
|
||||||
export async function getAllLocations() {
|
export async function getAllLocations() {
|
||||||
return await axios.get(BASE_URL)
|
return await axios.get(BASE_URL)
|
||||||
@@ -8,4 +8,10 @@ export async function getAllLocations() {
|
|||||||
|
|
||||||
export async function getLocation(locationName: string) {
|
export async function getLocation(locationName: string) {
|
||||||
return await axios.get(BASE_URL + "/" + locationName)
|
return await axios.get(BASE_URL + "/" + locationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTopLocations(nrOfLocations: number) {
|
||||||
|
let url = BASE_URL + "?sort=desc&count=" + nrOfLocations
|
||||||
|
|
||||||
|
return await axios.get(url)
|
||||||
}
|
}
|
||||||
@@ -3,12 +3,33 @@ import { useConcertStore } from '@/data/stores/concertStore';
|
|||||||
import highlightCarousel from './highlightCarousel.vue';
|
import highlightCarousel from './highlightCarousel.vue';
|
||||||
import sectionDivider from '@/components/sectionDivider.vue';
|
import sectionDivider from '@/components/sectionDivider.vue';
|
||||||
import cardWithTopImage from '@/components/cardWithTopImage.vue';
|
import cardWithTopImage from '@/components/cardWithTopImage.vue';
|
||||||
import { calcRating, lowestTicketPrice } from '@/scripts/concertScripts';
|
import { lowestTicketPrice } from '@/scripts/concertScripts';
|
||||||
import OutlinedButton from '@/components/outlinedButton.vue';
|
import OutlinedButton from '@/components/outlinedButton.vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useFeedbackStore } from '@/data/stores/feedbackStore';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { EventModel } from '@/data/models/acts/eventModel';
|
||||||
|
import { getTopEvents } from '@/data/api/eventApi';
|
||||||
|
import { LocationModel } from '@/data/models/locations/locationModel';
|
||||||
|
import { getTopLocations } from '@/data/api/locationApi';
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const concertStore = useConcertStore()
|
const feedbackStore = useFeedbackStore()
|
||||||
|
const topEvents = ref<Array<EventModel>>(Array.from({length: 4}, () => new EventModel()))
|
||||||
|
const topLocations = ref<Array<LocationModel>>(Array.from({length: 8}, () => new LocationModel()))
|
||||||
|
|
||||||
|
feedbackStore.fetchDataFromServerInProgress = true
|
||||||
|
|
||||||
|
getTopEvents(4)
|
||||||
|
.then(events => {
|
||||||
|
topEvents.value = events.data
|
||||||
|
|
||||||
|
getTopLocations(8)
|
||||||
|
.then(locations => {
|
||||||
|
topLocations.value = locations.data
|
||||||
|
feedbackStore.fetchDataFromServerInProgress = false
|
||||||
|
})
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -28,12 +49,13 @@ const concertStore = useConcertStore()
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-col v-for="i in 4" cols="3">
|
<v-col v-for="i in 4" cols="3">
|
||||||
<card-with-top-image
|
<card-with-top-image
|
||||||
:image="'tours/' + concertStore.tours[i - 1].image"
|
:image="topEvents[i - 1].image"
|
||||||
:title="concertStore.tours[i - 1].band.name"
|
:title="topEvents[i - 1].band.name"
|
||||||
smaller-title
|
smaller-title
|
||||||
@click="router.push('/bands/' + concertStore.tours[i - 1].band.name.replaceAll(' ', '-').toLowerCase())"
|
@click="router.push('/bands/' + topEvents[i - 1].band.name.replaceAll(' ', '-').toLowerCase())"
|
||||||
|
:loading="feedbackStore.fetchDataFromServerInProgress"
|
||||||
>
|
>
|
||||||
ab {{ lowestTicketPrice(concertStore.tours[i - 1]) }} €
|
ab {{ lowestTicketPrice(topEvents[i - 1]) }} €
|
||||||
</card-with-top-image>
|
</card-with-top-image>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -59,12 +81,13 @@ const concertStore = useConcertStore()
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-col v-for="i in 8" cols="3">
|
<v-col v-for="i in 8" cols="3">
|
||||||
<card-with-top-image
|
<card-with-top-image
|
||||||
:image="'locations/' + concertStore.locations[i + 2].image"
|
:image="topLocations[i - 1].image"
|
||||||
:title="concertStore.locations[i + 2].name"
|
:title="topLocations[i - 1].name"
|
||||||
smaller-title
|
smaller-title
|
||||||
@click="router.push('/locations/' + concertStore.locations[i + 2].name.replaceAll(' ', '-').toLowerCase())"
|
@click="router.push('/locations/' + topLocations[i - 1].name.replaceAll(' ', '-').toLowerCase())"
|
||||||
|
:loading="feedbackStore.fetchDataFromServerInProgress"
|
||||||
>
|
>
|
||||||
{{ concertStore.locations[i + 2].city.name }}, {{ concertStore.locations[i + 2].city.country }}
|
{{ topLocations[i - 1].city.name }}, {{ topLocations[i - 1].city.country }}
|
||||||
</card-with-top-image>
|
</card-with-top-image>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
Reference in new issue
Block a user