@@ -70,19 +70,64 @@ n-modal(v-model:show='modalShown')
7070 span.badge {{eventDetails.locationShort}}
7171 span {{eventDetails.locationName}}
7272 span {{eventDetails.room}}
73- .detail-text ( v-if ='eventDetails.materialsUrl' )
74- iframe(
75- :src ='eventDetails.materialsUrl'
73+ nav.detail-nav.nav.nav-pills.nav-justified.mt-3
74+ a.nav-link (
75+ :class ='{ active: state.tab === `agenda` }'
76+ @click ='state.tab = `agenda`'
77+ )
78+ i.bi.bi-list-columns-reverse.me-2
79+ span Agenda
80+ a.nav-link (
81+ :class ='{ active: state.tab === `slides` }'
82+ @click ='state.tab = `slides`'
83+ )
84+ i.bi.bi-easel.me-2
85+ span Slides
86+ a.nav-link (
87+ :class ='{ active: state.tab === `minutes` }'
88+ @click ='state.tab = `minutes`'
7689 )
90+ i.bi.bi-journal-text.me-2
91+ span Minutes
92+ .detail-text ( v-if ='eventDetails.materialsUrl' )
93+ template( v-if ='state.tab === `agenda`' )
94+ iframe(
95+ :src ='eventDetails.materialsUrl'
96+ )
97+ template( v-else-if ='state.tab === `slides`' )
98+ .text-center ( v-if ='state.isLoading' )
99+ n-spin( description ='Loading slides...' )
100+ .text-center.p-3 ( v-else-if ='!state.materials || !state.materials.slides || state.materials.slides.length < 1' )
101+ span No slides submitted for this session.
102+ .list-group ( v-else )
103+ a.list-group-item (
104+ v-for ='slide of state.materials.slides'
105+ :key ='slide.id'
106+ :href ='slide.url'
107+ target ='_blank'
108+ )
109+ i.bi.me-2 ( :class ='`bi-filetype-` + slide.ext' )
110+ span {{slide.title}}
111+ template( v-else )
112+ .text-center ( v-if ='state.isLoading' )
113+ n-spin( description ='Loading minutes...' )
114+ .text-center.p-3 ( v-else-if ='!state.materials || !state.materials.minutes' )
115+ span No minutes submitted for this session.
116+ iframe(
117+ v-else
118+ :src ='state.materials.minutes.url'
119+ )
77120</template >
78121
79122<script setup>
80- import { computed } from ' vue'
123+ import { computed , reactive , watch } from ' vue'
81124import {
82125 NButton ,
83126 NCard ,
84127 NModal ,
85- NPopover
128+ NPopover ,
129+ NSpin ,
130+ useMessage
86131} from ' naive-ui'
87132
88133import { useAgendaStore } from ' ./store'
@@ -101,6 +146,10 @@ const props = defineProps({
101146 }
102147})
103148
149+ // MESSAGE PROVIDER
150+
151+ const message = useMessage ()
152+
104153// STORES
105154
106155const agendaStore = useAgendaStore ()
@@ -109,6 +158,14 @@ const agendaStore = useAgendaStore()
109158
110159const emit = defineEmits ([' update:shown' ])
111160
161+ // STATE
162+
163+ const state = reactive ({
164+ tab: ' agenda' ,
165+ isLoading: false ,
166+ materials: {}
167+ })
168+
112169// COMPUTED
113170
114171const eventDetails = computed (() => {
@@ -142,6 +199,38 @@ const modalShown = computed({
142199 }
143200})
144201
202+ // WATCHERS
203+
204+ watch (() => props .shown , (newValue ) => {
205+ if (newValue) {
206+ state .materials = {}
207+ state .tab = ' agenda'
208+ if (props .event .flags .showAgenda ) {
209+ fetchSessionMaterials ()
210+ }
211+ }
212+ })
213+
214+ // METHODS
215+
216+ async function fetchSessionMaterials () {
217+ if (! props .event ) { return null }
218+
219+ state .isLoading = true
220+
221+ try {
222+ const resp = await fetch (` /api/meeting/session/${ props .event .sessionId } /materials` , { credentials: ' omit' })
223+ if (! resp .ok ) {
224+ throw new Error (resp .statusText )
225+ }
226+ state .materials = await resp .json ()
227+ } catch (err) {
228+ console .warn (err)
229+ message .error (' Failed to fetch session materials.' )
230+ }
231+ state .isLoading = false
232+ }
233+
145234< / script>
146235
147236< style lang= " scss" >
@@ -209,6 +298,27 @@ const modalShown = computed({
209298 }
210299 }
211300
301+ nav .detail - nav {
302+ padding: 5px ;
303+ background- color: #FFF ;
304+ border: 1px solid $gray- 300 ;
305+ border- radius: 5px ;
306+ font- weight: 500 ;
307+
308+ a {
309+ cursor: pointer;
310+
311+ .bi {
312+ font- size: inherit;
313+ color: inherit;
314+ }
315+
316+ & : not (.active ): hover {
317+ background- color: rgba ($blue- 100 , .25 );
318+ }
319+ }
320+ }
321+
212322 .detail - text {
213323 padding: 12px ;
214324 background- color: #FAFAFA ;
@@ -217,6 +327,10 @@ const modalShown = computed({
217327 margin- top: 12px ;
218328 border- radius: 5px ;
219329
330+ .bi {
331+ color: $blue;
332+ }
333+
220334 > iframe {
221335 width: 100 % ;
222336 height: 50vh ;
0 commit comments