2019-09-18 17:32:37 +02:00
< template >
2020-12-09 19:09:31 +01:00
< div class = "section container" >
2020-02-18 08:57:00 +01:00
< h1 class = "title" >
{ { $t ( "My events" ) } }
< / h1 >
2020-12-09 19:09:31 +01:00
< p >
{ {
$t (
2021-11-22 09:39:50 +01:00
"You will find here all the events you have created or of which you are a participant, as well as events organized by groups you follow or are a member of."
2020-12-09 19:09:31 +01:00
)
} }
< / p >
2021-10-06 18:00:50 +02:00
< div class = "buttons" v-if ="!hideCreateEventButton" >
2020-12-09 19:09:31 +01:00
< router -link
class = "button is-primary"
: to = "{ name: RouteName.CREATE_EVENT }"
> { { $t ( "Create event" ) } } < / r o u t e r - l i n k
>
< / div >
2020-02-18 08:57:00 +01:00
< b -loading :active.sync ="$apollo.loading" > < / b - l o a d i n g >
2021-11-02 19:47:54 +01:00
< div class = "wrapper" >
< div class = "event-filter" >
< b -field grouped group -multiline >
< b -field >
< b -switch v-model ="showUpcoming" > {{
showUpcoming ? $t ( "Upcoming events" ) : $t ( "Past events" )
} } < / b - s w i t c h >
< / b - f i e l d >
< b -field v-if ="showUpcoming" >
< b -checkbox v-model ="showDrafts" > {{ $ t ( " Drafts " ) }} < / b -checkbox >
< / b - f i e l d >
< b -field v-if ="showUpcoming" >
< b -checkbox v-model ="showAttending" > {{
$t ( "Attending" )
} } < / b - c h e c k b o x >
< / b - f i e l d >
< b -field v-if ="showUpcoming" >
< b -checkbox v-model ="showMyGroups" > {{
$t ( "From my groups" )
} } < / b - c h e c k b o x >
< / b - f i e l d >
< p v-if ="!showUpcoming" >
{ {
$tc (
"You have attended {count} events in the past." ,
pastParticipations . total ,
{
count : pastParticipations . total ,
}
)
} }
< / p >
< b -field
class = "date-filter"
expanded
: label = "
showUpcoming
? $t ( 'Showing events starting on' )
: $t ( 'Showing events before' )
"
>
< b -datepicker v -model = " dateFilter " / >
< b -button
@ click = "dateFilter = new Date()"
class = "reset-area"
icon - left = "close"
: title = "$t('Clear date filter field')"
/ >
< / b - f i e l d >
< / b - f i e l d >
< / div >
< div class = "my-events" >
< section
class = "py-4"
v - if = "showUpcoming && showDrafts && drafts.length > 0"
>
< multi -event -minimalist -card :events ="drafts" :showOrganizer ="true" / >
< / section >
< section
class = "py-4"
2020-11-30 10:24:11 +01:00
v - if = "
2021-11-02 19:47:54 +01:00
showUpcoming && monthlyFutureEvents && monthlyFutureEvents . size > 0
2020-11-30 10:24:11 +01:00
"
2020-02-18 08:57:00 +01:00
>
2021-11-02 19:47:54 +01:00
< transition -group name = "list" tag = "p" >
< div
class = "mb-5"
v - for = "month in monthlyFutureEvents"
: key = "month[0]"
>
< span class = "upcoming-month" > { { month [ 0 ] } } < / span >
< div v-for ="element in month[1]" :key="element.id" >
< event -participation -card
v - if = "'role' in element"
: participation = "element"
: options = "{ hideDate: false }"
@ event - deleted = "eventDeleted"
class = "participation"
/ >
< event -minimalist -card
v - else - if = "
! monthParticipationsIds ( month [ 1 ] ) . includes ( element . id )
"
: event = "element"
class = "participation"
/ >
< / div >
< / div >
< / t r a n s i t i o n - g r o u p >
< div class = "columns is-centered" >
< b -button
class = "column is-narrow"
v - if = "
hasMoreFutureParticipations &&
futureParticipations &&
futureParticipations . length === limit
"
@ click = "loadMoreFutureParticipations"
size = "is-large"
type = "is-primary"
> { { $t ( "Load more" ) } } < / b - b u t t o n
>
< / div >
< / section >
< section
class = "has-text-centered not-found"
2020-11-30 10:24:11 +01:00
v - if = "
2021-11-02 19:47:54 +01:00
showUpcoming &&
monthlyFutureEvents &&
monthlyFutureEvents . size === 0 &&
! $apollo . loading
2020-11-30 10:24:11 +01:00
"
2020-02-18 08:57:00 +01:00
>
2020-12-11 15:27:04 +01:00
< div class = "img-container" : class = "{ webp: supportsWebPFormat }" / >
2020-12-09 19:09:31 +01:00
< div class = "content has-text-centered" >
< p >
2021-11-02 19:47:54 +01:00
{ {
$t (
"You don't have any upcoming events. Maybe try another filter?"
)
} }
2020-12-09 19:09:31 +01:00
< / p >
2021-11-02 19:47:54 +01:00
< i18n
path = "Do you wish to {create_event} or {explore_events}?"
tag = "p"
>
< router -link
: to = "{ name: RouteName.CREATE_EVENT }"
slot = "create_event"
> { { $t ( "create an event" ) } } < / r o u t e r - l i n k
>
< router -link
: to = "{ name: RouteName.SEARCH }"
slot = "explore_events"
> { { $t ( "explore the events" ) } } < / r o u t e r - l i n k
>
< / i18n >
2020-12-09 19:09:31 +01:00
< / div >
2021-11-02 19:47:54 +01:00
< / section >
< section v-if ="!showUpcoming && pastParticipations.elements.length > 0" >
< transition -group name = "list" tag = "p" >
< div v-for ="month in monthlyPastParticipations" :key="month[0]" >
< span class = "past-month" > { { month [ 0 ] } } < / span >
< event -participation -card
v - for = "participation in month[1]"
: key = "participation.id"
: participation = "participation"
: options = "{ hideDate: false }"
@ event - deleted = "eventDeleted"
class = "participation"
/ >
< / div >
< / t r a n s i t i o n - g r o u p >
< div class = "columns is-centered" >
< b -button
class = "column is-narrow"
v - if = "
hasMorePastParticipations &&
pastParticipations . elements . length === limit
"
@ click = "loadMorePastParticipations"
size = "is-large"
type = "is-primary"
> { { $t ( "Load more" ) } } < / b - b u t t o n
>
< / div >
< / section >
2020-12-08 10:39:59 +01:00
< / div >
2021-11-02 19:47:54 +01:00
< / div >
2020-12-09 19:09:31 +01:00
< / div >
2019-09-18 17:32:37 +02:00
< / template >
< script lang = "ts" >
2021-10-06 18:00:50 +02:00
import { CONFIG } from "../../graphql/config" ;
import { IConfig } from "../../types/config.model" ;
2020-02-18 08:57:00 +01:00
import { Component , Vue } from "vue-property-decorator" ;
2020-11-27 19:27:44 +01:00
import { ParticipantRole } from "@/types/enums" ;
2020-12-09 19:09:31 +01:00
import RouteName from "@/router/name" ;
2020-12-11 15:27:04 +01:00
import { supportsWebPFormat } from "@/utils/support" ;
2020-11-27 19:27:44 +01:00
import { IParticipant , Participant } from "../../types/participant.model" ;
2021-11-02 19:47:54 +01:00
import { LOGGED _USER _DRAFTS } from "../../graphql/actor" ;
2020-11-06 11:34:32 +01:00
import { EventModel , IEvent } from "../../types/event.model" ;
2021-11-02 19:47:54 +01:00
import EventParticipationCard from "../../components/Event/EventParticipationCard.vue" ;
import MultiEventMinimalistCard from "../../components/Event/MultiEventMinimalistCard.vue" ;
import EventMinimalistCard from "../../components/Event/EventMinimalistCard.vue" ;
2020-02-18 08:57:00 +01:00
import Subtitle from "../../components/Utils/Subtitle.vue" ;
2021-11-02 19:47:54 +01:00
import {
LOGGED _USER _PARTICIPATIONS ,
LOGGED _USER _UPCOMING _EVENTS ,
} from "@/graphql/participant" ;
import { Paginate } from "@/types/paginate" ;
type Eventable = IParticipant | IEvent ;
2019-09-18 17:32:37 +02:00
@ Component ( {
components : {
2020-02-18 08:47:41 +01:00
Subtitle ,
2021-11-02 19:47:54 +01:00
MultiEventMinimalistCard ,
EventParticipationCard ,
EventMinimalistCard ,
2019-09-18 17:32:37 +02:00
} ,
apollo : {
2021-10-06 18:00:50 +02:00
config : CONFIG ,
2021-11-02 19:47:54 +01:00
userUpcomingEvents : {
query : LOGGED _USER _UPCOMING _EVENTS ,
2020-10-21 12:14:53 +02:00
fetchPolicy : "cache-and-network" ,
2021-11-02 19:47:54 +01:00
variables ( ) {
return {
page : 1 ,
limit : 10 ,
afterDateTime : this . dateFilter ,
} ;
2019-09-18 17:32:37 +02:00
} ,
2021-11-02 19:47:54 +01:00
update ( data ) {
this . futureParticipations = data . loggedUser . participations . elements . map (
2020-02-18 08:57:00 +01:00
( participation : IParticipant ) => new Participant ( participation )
2021-11-02 19:47:54 +01:00
) ;
this . groupEvents = data . loggedUser . followedGroupEvents . elements . map (
( { event } : { event : IEvent } ) => event
) ;
} ,
2019-09-18 17:32:37 +02:00
} ,
2019-10-02 17:59:07 +02:00
drafts : {
query : LOGGED _USER _DRAFTS ,
2020-10-21 12:14:53 +02:00
fetchPolicy : "cache-and-network" ,
2019-10-02 17:59:07 +02:00
variables : {
page : 1 ,
limit : 10 ,
} ,
2020-11-30 10:24:11 +01:00
update : ( data ) =>
data . loggedUser . drafts . map ( ( event : IEvent ) => new EventModel ( event ) ) ,
2019-10-02 17:59:07 +02:00
} ,
2019-09-18 17:32:37 +02:00
pastParticipations : {
query : LOGGED _USER _PARTICIPATIONS ,
2020-10-21 12:14:53 +02:00
fetchPolicy : "cache-and-network" ,
2021-11-02 19:47:54 +01:00
variables ( ) {
return {
page : 1 ,
limit : 10 ,
beforeDateTime : this . dateFilter ,
} ;
2019-09-18 17:32:37 +02:00
} ,
2021-11-02 19:47:54 +01:00
update : ( data ) => data . loggedUser . participations ,
2019-09-18 17:32:37 +02:00
} ,
} ,
2019-10-10 16:47:38 +02:00
metaInfo ( ) {
return {
2020-02-18 08:57:00 +01:00
title : this . $t ( "My events" ) as string ,
2019-10-10 16:47:38 +02:00
} ;
} ,
2019-09-18 17:32:37 +02:00
} )
export default class MyEvents extends Vue {
2020-02-18 08:57:00 +01:00
futurePage = 1 ;
pastPage = 1 ;
limit = 10 ;
2019-09-18 17:32:37 +02:00
2021-11-02 19:47:54 +01:00
get showUpcoming ( ) : boolean {
return ( ( this . $route . query . showUpcoming as string ) || "true" ) === "true" ;
}
set showUpcoming ( showUpcoming : boolean ) {
this . $router . push ( {
name : RouteName . MY _EVENTS ,
query : { ... this . $route . query , showUpcoming : showUpcoming . toString ( ) } ,
} ) ;
}
get showDrafts ( ) : boolean {
return ( ( this . $route . query . showDrafts as string ) || "true" ) === "true" ;
}
set showDrafts ( showDrafts : boolean ) {
this . $router . push ( {
name : RouteName . MY _EVENTS ,
query : { ... this . $route . query , showDrafts : showDrafts . toString ( ) } ,
} ) ;
}
get showAttending ( ) : boolean {
return ( ( this . $route . query . showAttending as string ) || "true" ) === "true" ;
}
set showAttending ( showAttending : boolean ) {
this . $router . push ( {
name : RouteName . MY _EVENTS ,
query : { ... this . $route . query , showAttending : showAttending . toString ( ) } ,
} ) ;
}
get showMyGroups ( ) : boolean {
return ( ( this . $route . query . showMyGroups as string ) || "false" ) === "true" ;
}
set showMyGroups ( showMyGroups : boolean ) {
this . $router . push ( {
name : RouteName . MY _EVENTS ,
query : { ... this . $route . query , showMyGroups : showMyGroups . toString ( ) } ,
} ) ;
}
get dateFilter ( ) : Date {
const query = this . $route . query . dateFilter as string ;
if ( query && /(\d{4}-\d{2}-\d{2})/ . test ( query ) ) {
return new Date ( ` ${ query } T00:00:00Z ` ) ;
}
return new Date ( ) ;
}
set dateFilter ( date : Date ) {
const pad = ( number : number ) => {
if ( number < 10 ) {
return "0" + number ;
}
return number ;
} ;
const stringifiedDate = ` ${ date . getFullYear ( ) } - ${ pad (
date . getMonth ( ) + 1
) } - $ { pad ( date . getDate ( ) ) } ` ;
if ( this . $route . query . dateFilter !== stringifiedDate ) {
this . $router . push ( {
name : RouteName . MY _EVENTS ,
query : {
... this . $route . query ,
dateFilter : stringifiedDate ,
} ,
} ) ;
}
}
2021-10-06 18:00:50 +02:00
config ! : IConfig ;
2019-09-18 17:32:37 +02:00
futureParticipations : IParticipant [ ] = [ ] ;
2020-02-18 08:57:00 +01:00
2021-11-02 19:47:54 +01:00
groupEvents : IEvent [ ] = [ ] ;
2020-02-18 08:57:00 +01:00
hasMoreFutureParticipations = true ;
2019-09-18 17:32:37 +02:00
2021-11-02 19:47:54 +01:00
pastParticipations : Paginate < IParticipant > = { elements : [ ] , total : 0 } ;
2020-02-18 08:57:00 +01:00
hasMorePastParticipations = true ;
2019-09-18 17:32:37 +02:00
2019-10-02 17:59:07 +02:00
drafts : IEvent [ ] = [ ] ;
2020-12-09 19:09:31 +01:00
RouteName = RouteName ;
2020-12-11 15:27:04 +01:00
supportsWebPFormat = supportsWebPFormat ;
2021-11-02 19:47:54 +01:00
static monthlyEvents (
elements : Eventable [ ] ,
2020-07-09 17:24:28 +02:00
revertSort = false
2021-11-02 19:47:54 +01:00
) : Map < string , Eventable [ ] > {
const res = elements . filter ( ( element : Eventable ) => {
if ( "role" in element ) {
return (
element . event . beginsOn != null &&
element . role !== ParticipantRole . REJECTED
) ;
}
return element . beginsOn != null ;
} ) ;
2020-07-06 17:35:03 +02:00
if ( revertSort ) {
2021-11-02 19:47:54 +01:00
res . sort ( ( a : Eventable , b : Eventable ) => {
const aTime = "role" in a ? a . event . beginsOn : a . beginsOn ;
const bTime = "role" in b ? b . event . beginsOn : b . beginsOn ;
return new Date ( bTime ) . getTime ( ) - new Date ( aTime ) . getTime ( ) ;
} ) ;
2020-07-06 17:35:03 +02:00
} else {
2021-11-02 19:47:54 +01:00
res . sort ( ( a : Eventable , b : Eventable ) => {
const aTime = "role" in a ? a . event . beginsOn : a . beginsOn ;
const bTime = "role" in b ? b . event . beginsOn : b . beginsOn ;
return new Date ( aTime ) . getTime ( ) - new Date ( bTime ) . getTime ( ) ;
} ) ;
2020-07-06 17:35:03 +02:00
}
2021-11-02 19:47:54 +01:00
return res . reduce ( ( acc : Map < string , Eventable [ ] > , element : Eventable ) => {
const month = new Date (
"role" in element ? element . event . beginsOn : element . beginsOn
) . toLocaleDateString ( undefined , {
year : "numeric" ,
month : "long" ,
} ) ;
const filteredElements : Eventable [ ] = acc . get ( month ) || [ ] ;
filteredElements . push ( element ) ;
acc . set ( month , filteredElements ) ;
return acc ;
} , new Map ( ) ) ;
2019-09-18 17:32:37 +02:00
}
2021-11-02 19:47:54 +01:00
get monthlyFutureEvents ( ) : Map < string , Eventable [ ] > {
let eventable = [ ] as Eventable [ ] ;
if ( this . showAttending ) {
eventable = [ ... eventable , ... this . futureParticipations ] ;
}
if ( this . showMyGroups ) {
eventable = [ ... eventable , ... this . groupEvents ] ;
}
return MyEvents . monthlyEvents ( eventable ) ;
2019-09-18 17:32:37 +02:00
}
2021-11-02 19:47:54 +01:00
get monthlyPastParticipations ( ) : Map < string , Eventable [ ] > {
return MyEvents . monthlyEvents ( this . pastParticipations . elements , true ) ;
}
monthParticipationsIds ( elements : Eventable [ ] ) : string [ ] {
let res = elements . filter ( ( element : Eventable ) => {
return "role" in element ;
} ) as IParticipant [ ] ;
return res . map ( ( { event } : { event : IEvent } ) => {
return event . id as string ;
} ) ;
2019-09-18 17:32:37 +02:00
}
2020-11-06 11:34:32 +01:00
loadMoreFutureParticipations ( ) : void {
2019-09-18 17:32:37 +02:00
this . futurePage += 1 ;
this . $apollo . queries . futureParticipations . fetchMore ( {
// New variables
variables : {
page : this . futurePage ,
limit : this . limit ,
} ,
} ) ;
}
2020-11-06 11:34:32 +01:00
loadMorePastParticipations ( ) : void {
2019-09-18 17:32:37 +02:00
this . pastPage += 1 ;
this . $apollo . queries . pastParticipations . fetchMore ( {
2020-02-18 08:57:00 +01:00
// New variables
2019-09-18 17:32:37 +02:00
variables : {
page : this . pastPage ,
limit : this . limit ,
} ,
} ) ;
}
2020-11-06 11:34:32 +01:00
eventDeleted ( eventid : string ) : void {
2020-02-18 08:57:00 +01:00
this . futureParticipations = this . futureParticipations . filter (
( participation ) => participation . event . id !== eventid
) ;
2021-11-02 19:47:54 +01:00
this . pastParticipations = {
elements : this . pastParticipations . elements . filter (
( participation ) => participation . event . id !== eventid
) ,
total : this . pastParticipations . total - 1 ,
} ;
2019-09-18 17:32:37 +02:00
}
2021-10-06 18:00:50 +02:00
get hideCreateEventButton ( ) : boolean {
return ! ! this . config ? . restrictions ? . onlyGroupsCanCreateEvents ;
}
2019-09-18 17:32:37 +02:00
}
< / script >
<!-- Add "scoped" attribute to limit CSS to this component only -- >
< style lang = "scss" scoped >
2021-11-02 19:47:54 +01:00
@ import "~bulma/sass/utilities/mixins.sass" ;
2020-02-18 08:57:00 +01:00
main > . container {
background : $white ;
2020-12-09 19:09:31 +01:00
& > h1 {
margin : 10 px auto 5 px ;
}
2020-02-18 08:57:00 +01:00
}
2019-12-20 13:04:34 +01:00
2020-02-18 08:57:00 +01:00
. participation {
margin : 1 rem auto ;
}
2019-09-18 17:32:37 +02:00
2020-02-18 08:57:00 +01:00
section {
2021-06-11 18:31:24 +02:00
. upcoming - month ,
. past - month {
2020-02-18 08:57:00 +01:00
text - transform : capitalize ;
2021-06-11 18:31:24 +02:00
display : inline - block ;
position : relative ;
font - size : 1.3 rem ;
& : : after {
background : $orange - 3 ;
position : absolute ;
left : 0 ;
right : 0 ;
top : 100 % ;
content : "" ;
width : calc ( 100 % + 30 px ) ;
height : 3 px ;
max - width : 150 px ;
}
2020-02-18 08:57:00 +01:00
}
}
2020-12-09 19:09:31 +01:00
. not - found {
2021-11-02 19:47:54 +01:00
margin - top : 2 rem ;
2020-12-09 19:09:31 +01:00
. img - container {
2021-05-06 17:20:54 +02:00
background - image : url ( "../../../public/img/pics/event_creation-480w.jpg" ) ;
2020-12-11 15:27:04 +01:00
@ media ( min - resolution : 2 dppx ) {
& {
2021-05-06 17:20:54 +02:00
background - image : url ( "../../../public/img/pics/event_creation-1024w.jpg" ) ;
2020-12-11 15:27:04 +01:00
}
}
& . webp {
2021-05-06 17:20:54 +02:00
background - image : url ( "../../../public/img/pics/event_creation-480w.webp" ) ;
2020-12-11 15:27:04 +01:00
@ media ( min - resolution : 2 dppx ) {
& {
2021-05-06 17:20:54 +02:00
background - image : url ( "../../../public/img/pics/event_creation-1024w.webp" ) ;
2020-12-11 15:27:04 +01:00
}
}
}
2020-12-09 19:09:31 +01:00
max - width : 450 px ;
height : 300 px ;
box - shadow : 0 0 8 px 8 px white inset ;
background - size : cover ;
border - radius : 10 px ;
margin : auto auto 1 rem ;
}
}
2021-11-02 19:47:54 +01:00
. wrapper {
display : grid ;
grid - template - areas : "filter" "events" ;
align - items : start ;
@ include desktop {
gap : 2 rem ;
grid - template - columns : 1 fr 3 fr ;
grid - template - areas : "filter events" ;
}
. event - filter {
grid - area : filter ;
background : lightgray ;
border - radius : 5 px ;
padding : 0.75 rem 1.25 rem 0.25 rem ;
@ include desktop {
padding : 2 rem 1.25 rem ;
: : v - deep . field . is - grouped {
display : block ;
}
}
: : v - deep . field > . field {
margin : 0 auto 1.25 rem ! important ;
}
. date - filter : : v - deep . field - body {
display : block ;
}
}
. my - events {
grid - area : events ;
}
}
2019-09-18 17:32:37 +02:00
< / style >