202 lines
7.1 KiB
Vue
202 lines
7.1 KiB
Vue
|
<template>
|
||
|
<main class="container">
|
||
|
<h1 class="title">
|
||
|
{{ $t('My events') }}
|
||
|
</h1>
|
||
|
<b-loading :active.sync="$apollo.loading"></b-loading>
|
||
|
<section v-if="futureParticipations.length > 0">
|
||
|
<h2 class="subtitle">
|
||
|
{{ $t('Upcoming') }}
|
||
|
</h2>
|
||
|
<transition-group name="list" tag="p">
|
||
|
<div v-for="month in monthlyFutureParticipations" :key="month[0]">
|
||
|
<h3>{{ month[0] }}</h3>
|
||
|
<EventListCard
|
||
|
v-for="participation in month[1]"
|
||
|
:key="`${participation.event.uuid}${participation.actor.id}`"
|
||
|
:participation="participation"
|
||
|
:options="{ hideDate: false }"
|
||
|
@eventDeleted="eventDeleted"
|
||
|
class="participation"
|
||
|
/>
|
||
|
</div>
|
||
|
</transition-group>
|
||
|
<div class="columns is-centered">
|
||
|
<b-button class="column is-narrow"
|
||
|
v-if="hasMoreFutureParticipations && (futureParticipations.length === limit)" @click="loadMoreFutureParticipations" size="is-large" type="is-primary">{{ $t('Load more') }}</b-button>
|
||
|
</div>
|
||
|
</section>
|
||
|
<section v-if="pastParticipations.length > 0">
|
||
|
<h2 class="subtitle">
|
||
|
{{ $t('Past events') }}
|
||
|
</h2>
|
||
|
<transition-group name="list" tag="p">
|
||
|
<div v-for="month in monthlyPastParticipations" :key="month[0]">
|
||
|
<h3>{{ month[0] }}</h3>
|
||
|
<EventListCard
|
||
|
v-for="participation in month[1]"
|
||
|
:key="`${participation.event.uuid}${participation.actor.id}`"
|
||
|
:participation="participation"
|
||
|
:options="{ hideDate: false }"
|
||
|
@eventDeleted="eventDeleted"
|
||
|
class="participation"
|
||
|
/>
|
||
|
</div>
|
||
|
</transition-group>
|
||
|
<div class="columns is-centered">
|
||
|
<b-button class="column is-narrow"
|
||
|
v-if="hasMorePastParticipations && (pastParticipations.length === limit)" @click="loadMorePastParticipations" size="is-large" type="is-primary">{{ $t('Load more') }}</b-button>
|
||
|
</div>
|
||
|
</section>
|
||
|
<b-message v-if="futureParticipations.length === 0 && pastParticipations.length === 0 && $apollo.loading === false" type="is-danger">
|
||
|
{{ $t('No events found') }}
|
||
|
</b-message>
|
||
|
</main>
|
||
|
</template>
|
||
|
|
||
|
<script lang="ts">
|
||
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||
|
import { LOGGED_USER_PARTICIPATIONS } from '@/graphql/actor';
|
||
|
import { IParticipant, Participant } from '@/types/event.model';
|
||
|
import EventListCard from '@/components/Event/EventListCard.vue';
|
||
|
|
||
|
|
||
|
@Component({
|
||
|
components: {
|
||
|
EventListCard,
|
||
|
},
|
||
|
apollo: {
|
||
|
futureParticipations: {
|
||
|
query: LOGGED_USER_PARTICIPATIONS,
|
||
|
variables: {
|
||
|
page: 1,
|
||
|
limit: 10,
|
||
|
afterDateTime: (new Date()).toISOString(),
|
||
|
},
|
||
|
update: data => data.loggedUser.participations.map(participation => new Participant(participation)),
|
||
|
},
|
||
|
pastParticipations: {
|
||
|
query: LOGGED_USER_PARTICIPATIONS,
|
||
|
variables: {
|
||
|
page: 1,
|
||
|
limit: 10,
|
||
|
beforeDateTime: (new Date()).toISOString(),
|
||
|
},
|
||
|
update: data => data.loggedUser.participations.map(participation => new Participant(participation)),
|
||
|
},
|
||
|
},
|
||
|
})
|
||
|
export default class MyEvents extends Vue {
|
||
|
@Prop(String) location!: string;
|
||
|
|
||
|
futurePage: number = 1;
|
||
|
pastPage: number = 1;
|
||
|
limit: number = 10;
|
||
|
|
||
|
futureParticipations: IParticipant[] = [];
|
||
|
hasMoreFutureParticipations: boolean = true;
|
||
|
|
||
|
pastParticipations: IParticipant[] = [];
|
||
|
hasMorePastParticipations: boolean = true;
|
||
|
|
||
|
private monthlyParticipations(participations: IParticipant[]): Map<string, Participant[]> {
|
||
|
const res = participations.filter(({ event }) => event.beginsOn != null);
|
||
|
res.sort(
|
||
|
(a: IParticipant, b: IParticipant) => a.event.beginsOn.getTime() - b.event.beginsOn.getTime(),
|
||
|
);
|
||
|
return res.reduce((acc: Map<string, IParticipant[]>, participation: IParticipant) => {
|
||
|
const month = (new Date(participation.event.beginsOn)).toLocaleDateString(undefined, { year: 'numeric', month: 'long' });
|
||
|
const participations: IParticipant[] = acc.get(month) || [];
|
||
|
participations.push(participation);
|
||
|
acc.set(month, participations);
|
||
|
return acc;
|
||
|
}, new Map());
|
||
|
}
|
||
|
|
||
|
get monthlyFutureParticipations(): Map<string, Participant[]> {
|
||
|
return this.monthlyParticipations(this.futureParticipations);
|
||
|
}
|
||
|
|
||
|
get monthlyPastParticipations(): Map<string, Participant[]> {
|
||
|
return this.monthlyParticipations(this.pastParticipations);
|
||
|
}
|
||
|
|
||
|
loadMoreFutureParticipations() {
|
||
|
this.futurePage += 1;
|
||
|
this.$apollo.queries.futureParticipations.fetchMore({
|
||
|
// New variables
|
||
|
variables: {
|
||
|
page: this.futurePage,
|
||
|
limit: this.limit,
|
||
|
},
|
||
|
// Transform the previous result with new data
|
||
|
updateQuery: (previousResult, { fetchMoreResult }) => {
|
||
|
const newParticipations = fetchMoreResult.loggedUser.participations;
|
||
|
this.hasMoreFutureParticipations = newParticipations.length === this.limit;
|
||
|
|
||
|
return {
|
||
|
loggedUser: {
|
||
|
__typename: previousResult.loggedUser.__typename,
|
||
|
participations: [...previousResult.loggedUser.participations, ...newParticipations],
|
||
|
},
|
||
|
};
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
|
||
|
loadMorePastParticipations() {
|
||
|
this.pastPage += 1;
|
||
|
this.$apollo.queries.pastParticipations.fetchMore({
|
||
|
// New variables
|
||
|
variables: {
|
||
|
page: this.pastPage,
|
||
|
limit: this.limit,
|
||
|
},
|
||
|
// Transform the previous result with new data
|
||
|
updateQuery: (previousResult, { fetchMoreResult }) => {
|
||
|
const newParticipations = fetchMoreResult.loggedUser.participations;
|
||
|
this.hasMorePastParticipations = newParticipations.length === this.limit;
|
||
|
|
||
|
return {
|
||
|
loggedUser: {
|
||
|
__typename: previousResult.loggedUser.__typename,
|
||
|
participations: [...previousResult.loggedUser.participations, ...newParticipations],
|
||
|
},
|
||
|
};
|
||
|
},
|
||
|
});
|
||
|
}
|
||
|
|
||
|
eventDeleted(eventid) {
|
||
|
this.futureParticipations = this.futureParticipations.filter(participation => participation.event.id !== eventid);
|
||
|
this.pastParticipations = this.pastParticipations.filter(participation => participation.event.id !== eventid);
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||
|
<style lang="scss" scoped>
|
||
|
@import "../../variables";
|
||
|
|
||
|
.participation {
|
||
|
margin: 1rem auto;
|
||
|
}
|
||
|
|
||
|
section {
|
||
|
margin: 3rem auto;
|
||
|
|
||
|
& > h2 {
|
||
|
display: block;
|
||
|
color: $primary;
|
||
|
font-size: 3rem;
|
||
|
text-decoration: underline;
|
||
|
text-decoration-color: $secondary;
|
||
|
}
|
||
|
|
||
|
h3 {
|
||
|
margin-top: 2rem;
|
||
|
font-weight: bold;
|
||
|
}
|
||
|
}
|
||
|
</style>
|