aboutsummaryrefslogtreecommitdiffstats
path: root/web/pages/conferences.vue
blob: 993bc664f317e2ecd4ceae00c9f7205c1bd0ed7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<script setup lang="ts">
import { MapPinPlus, MapPin } from 'lucide-vue-next';
import { expireAuth } from '~/composables/expire-auth';

definePageMeta({
  middleware: ['logged-in']
})

interface Conference {
  id: number,
  url: string,
  title: string,
  venue: string,
  city: string,
}

const setting = ref(false)
const conferences = ref([] as Conference[])

const conferenceStore = useConferenceStore();
const errorStore = useErrorStore();
const authStore = useAuthStore();
const config = useRuntimeConfig();

const status = ref('idle' as 'loading' | 'idle')

const fetchConferences = () => {
  status.value = 'loading'
  $api(config.public.baseURL + '/conference', {
    method: 'GET',
    onResponse: ({ response }) => {
      if (!response.ok) {
        if (response.status === 401) {
          expireAuth()
          return
        }
        errorStore.setError(response._data.message || 'An unknown error occurred');
      }
      status.value = 'idle'
      conferences.value = response._data.data
    },
  })
}

const deleteConference = (id: number) => {
  // todo make this better
  $api(config.public.baseURL + '/conference', {
    method: 'DELETE',
    body: {
      id: id
    },
    onResponse: ({ response }) => {
      if (!response.ok) {
        errorStore.setError(response._data.message || 'An unknown error occurred');
      }
    },
  })
}

const selectConference = async (c) => {
  setting.value = true
  conferenceStore.id = c.id
  try {
    await fetchSchedule()
    await fetchFavourites()
    navigateTo({ path: "/events" })
  } catch (e) {
    conferenceStore.clear()
    setting.value = false
  }
}

onMounted(fetchConferences)
</script>

<template>
  <template v-if="!setting">
    <Panel title="Conferences" :icon="MapPin">
      <span class="loading-text" v-if="status === 'loading'"><Spinner color="var(--color-text-muted)" />Fetching conferences...</span>
      <div class="conference-list" v-if="conferences.length > 0 && status !== 'loading'">
        <template v-for="conference of conferences">
          <span class="title">{{ conference.title }}</span>
          <span>{{ conference.city }}</span>
          <span>{{ conference.venue }}</span>
          <span class="actions">
            <Button v-if="authStore.admin" kind="secondary" @click="() => { deleteConference(conference.id) }">Delete</Button>
            <Button @click="() => { selectConference(conference) }">Select</Button>
          </span>
        </template>
      </div>
      <p v-if="conferences.length == 0 && status !== 'loading'">
        There are no conferences to display.
      </p>
    </Panel>
    
    <Panel v-if="authStore.admin" title="Add conference" :icon="MapPinPlus">
      <AddConference @update="fetchConferences" />
    </Panel>
  </template>
  <template v-else>
    <div class="loading">
      <span class="loading-text"><Spinner color="var(--color-text-muted)" />Setting conference...</span>
    </div>
  </template>
</template>

<style>
.conference-list {
  display: grid;
  grid-template-columns: 1fr 1fr 2fr 1fr;
  align-items: center;
  gap: 0.5rem;
}

.conference-list > .title {
  font-weight: bold;
}

.conference-list > .actions {
  display: flex;
  gap: 0.5rem;
  justify-self: flex-end;
}
</style>