|
8 | 8 | import { Modal } from '$lib/components/Modal/index.js'; |
9 | 9 | import { IsWithinViewport } from '$lib/helpers/index.js'; |
10 | 10 |
|
| 11 | + export interface Topic { |
| 12 | + id: string; |
| 13 | + title: string; |
| 14 | + description: string; |
| 15 | + /** |
| 16 | + * The associated tag code (e.g. `AI`, `BOB`), used to select the topic |
| 17 | + * icon. Null when the collection has no tag. |
| 18 | + */ |
| 19 | + code: string | null; |
| 20 | + } |
| 21 | +
|
11 | 22 | export interface Props { |
12 | 23 | /** |
13 | 24 | * Indicates whether the view is open. |
|
17 | 28 | * A callback invoked when the view is closed. |
18 | 29 | */ |
19 | 30 | onclose: () => void; |
| 31 | + /** |
| 32 | + * The selectable topic collections, sourced from the database. |
| 33 | + */ |
| 34 | + topics: Topic[]; |
20 | 35 | } |
21 | 36 |
|
22 | | - const { isopen, onclose }: Props = $props(); |
| 37 | + const { isopen, onclose, topics }: Props = $props(); |
| 38 | +
|
| 39 | + /** |
| 40 | + * Tag codes that have a topic icon. Keep in sync with the `enhanced:img` |
| 41 | + * mapping in the topic-selection markup below; a topic whose code is not |
| 42 | + * here has no icon and is not shown. |
| 43 | + */ |
| 44 | + const TOPIC_ICON_CODES = new Set([ |
| 45 | + 'AI', |
| 46 | + 'CAREER', |
| 47 | + 'EDU_VOICES', |
| 48 | + 'EMP_ENGAGEMENT', |
| 49 | + 'NEWS', |
| 50 | + 'INFRA', |
| 51 | + 'INNOV', |
| 52 | + 'BOB', |
| 53 | + 'PROD', |
| 54 | + 'STU_DEV', |
| 55 | + 'STU_WELL', |
| 56 | + 'WELLBEING', |
| 57 | + ]); |
| 58 | +
|
| 59 | + const displayedTopics = $derived( |
| 60 | + topics.filter((topic) => topic.code !== null && TOPIC_ICON_CODES.has(topic.code)), |
| 61 | + ); |
23 | 62 |
|
24 | 63 | let target = $state<HTMLElement | null>(null); |
25 | 64 | let isStartPage = $state(true); |
|
64 | 103 |
|
65 | 104 | const handleConfirm = async () => { |
66 | 105 | const payload = { |
67 | | - topics: selectedTopics, |
| 106 | + collectionIds: selectedTopics, |
68 | 107 | frequency: selectedFrequency, |
69 | 108 | csrfToken: page.data.csrfToken, |
70 | 109 | }; |
|
127 | 166 | await handleClose(); |
128 | 167 | }; |
129 | 168 |
|
130 | | - const handleTopicChange = (title: string, checked: boolean) => { |
| 169 | + const handleTopicChange = (id: string, checked: boolean) => { |
131 | 170 | if (checked) { |
132 | | - selectedTopics = [...selectedTopics, title]; |
| 171 | + selectedTopics = [...selectedTopics, id]; |
133 | 172 | } else { |
134 | | - selectedTopics = selectedTopics.filter((topic) => topic !== title); |
| 173 | + selectedTopics = selectedTopics.filter((topic) => topic !== id); |
135 | 174 | } |
136 | 175 | }; |
137 | | -
|
138 | | - const collectionsList = { |
139 | | - 'artificial-intelligence': { |
140 | | - title: 'Artificial Intelligence', |
141 | | - description: 'AI news, use cases and tools to master the changing landscape.', |
142 | | - }, |
143 | | - 'career-growth': { |
144 | | - title: 'Career Growth', |
145 | | - description: 'Tips to help you set career goals and transform potential into performance.', |
146 | | - }, |
147 | | - 'educator-voices': { |
148 | | - title: 'Educator Voices', |
149 | | - description: 'Inspiring stories from fellow educators.', |
150 | | - }, |
151 | | - 'employee-engagement': { |
152 | | - title: 'Employee Engagement', |
153 | | - description: |
154 | | - 'Analyze EES results and get practical tips to maintain workplace staff engagement.', |
155 | | - }, |
156 | | - 'in-the-news': { |
157 | | - title: 'In the News', |
158 | | - description: 'Education news and survey highlights for ground insights.', |
159 | | - }, |
160 | | - infrastructure: { |
161 | | - title: 'Infrastructure', |
162 | | - description: 'Learn about device setups, connectivity, and digital tools for efficient work.', |
163 | | - }, |
164 | | - innovation: { |
165 | | - title: 'Innovation', |
166 | | - description: 'Strategies to empower new ideas, innovation, and creative thinking.', |
167 | | - }, |
168 | | - 'learn-with-bob': { |
169 | | - title: 'Learn with Bob', |
170 | | - description: 'SPACES framework for purposeful work and a sustainable pace.', |
171 | | - }, |
172 | | - productivity: { |
173 | | - title: 'Productivity', |
174 | | - description: |
175 | | - 'Master time management and workflows to minimize distractions and reach goals faster.', |
176 | | - }, |
177 | | - 'student-development': { |
178 | | - title: 'Student Development', |
179 | | - description: |
180 | | - "Learn ways to develop students' cognitive, affective, physical and aesthetic abilities.", |
181 | | - }, |
182 | | - 'student-wellbeing': { |
183 | | - title: 'Student Wellbeing', |
184 | | - description: 'Learn ways to support students emotional and physical health.', |
185 | | - }, |
186 | | - wellbeing: { |
187 | | - title: 'Wellbeing', |
188 | | - description: |
189 | | - 'Identify workplace stress, monitor peer distress, conduct check-ins, and provide support resources.', |
190 | | - }, |
191 | | - }; |
192 | 176 | </script> |
193 | 177 |
|
194 | 178 | <!-- Modal --> |
|
277 | 261 |
|
278 | 262 | <div class="overflow-y-auto pt-6"> |
279 | 263 | <div class="flex w-full flex-col gap-y-2" role="group" aria-labelledby="topic"> |
280 | | - {#each Object.entries(collectionsList) as [key, { title, description }] (key)} |
| 264 | + {#each displayedTopics as { id, title, description, code } (id)} |
281 | 265 | <label |
282 | 266 | class={[ |
283 | 267 | 'group flex cursor-pointer items-center rounded-3xl border border-slate-200 bg-white', |
|
291 | 275 | <input |
292 | 276 | type="checkbox" |
293 | 277 | name="topics" |
294 | | - value={title} |
| 278 | + value={id} |
295 | 279 | class="sr-only" |
296 | | - onchange={(e) => handleTopicChange(title, e.currentTarget.checked)} |
| 280 | + onchange={(e) => handleTopicChange(id, e.currentTarget.checked)} |
297 | 281 | /> |
298 | 282 |
|
299 | 283 | <div class="flex h-24 w-20 shrink-0 items-center justify-center"> |
300 | | - {#if key === 'artificial-intelligence'} |
| 284 | + {#if code === 'AI'} |
301 | 285 | <enhanced:img |
302 | 286 | src="$lib/assets/collections/artificial-intelligence.png" |
303 | 287 | alt={title} |
304 | 288 | class="max-h-full max-w-full object-contain" |
305 | 289 | /> |
306 | | - {:else if key === 'career-growth'} |
| 290 | + {:else if code === 'CAREER'} |
307 | 291 | <enhanced:img |
308 | 292 | src="$lib/assets/collections/career-growth.png" |
309 | 293 | alt={title} |
310 | 294 | class="max-h-full max-w-full object-contain" |
311 | 295 | /> |
312 | | - {:else if key === 'educator-voices'} |
| 296 | + {:else if code === 'EDU_VOICES'} |
313 | 297 | <enhanced:img |
314 | 298 | src="$lib/assets/collections/educator-voices.png" |
315 | 299 | alt={title} |
316 | 300 | class="max-h-full max-w-full object-contain" |
317 | 301 | /> |
318 | | - {:else if key === 'employee-engagement'} |
| 302 | + {:else if code === 'EMP_ENGAGEMENT'} |
319 | 303 | <enhanced:img |
320 | 304 | src="$lib/assets/collections/employee-engagement.png" |
321 | 305 | alt={title} |
322 | 306 | class="max-h-full max-w-full object-contain" |
323 | 307 | /> |
324 | | - {:else if key === 'in-the-news'} |
| 308 | + {:else if code === 'NEWS'} |
325 | 309 | <enhanced:img |
326 | 310 | src="$lib/assets/collections/in-the-news.png" |
327 | 311 | alt={title} |
328 | 312 | class="max-h-full max-w-full object-contain" |
329 | 313 | /> |
330 | | - {:else if key === 'infrastructure'} |
| 314 | + {:else if code === 'INFRA'} |
331 | 315 | <enhanced:img |
332 | 316 | src="$lib/assets/collections/infrastructure.png" |
333 | 317 | alt={title} |
334 | 318 | class="max-h-full max-w-full object-contain" |
335 | 319 | /> |
336 | | - {:else if key === 'innovation'} |
| 320 | + {:else if code === 'INNOV'} |
337 | 321 | <enhanced:img |
338 | 322 | src="$lib/assets/collections/innovation.png" |
339 | 323 | alt={title} |
340 | 324 | class="max-h-full max-w-full object-contain" |
341 | 325 | /> |
342 | | - {:else if key === 'learn-with-bob'} |
| 326 | + {:else if code === 'BOB'} |
343 | 327 | <enhanced:img |
344 | 328 | src="$lib/assets/collections/learn-with-bob.png" |
345 | 329 | alt={title} |
346 | 330 | class="max-h-full max-w-full object-contain" |
347 | 331 | /> |
348 | | - {:else if key === 'productivity'} |
| 332 | + {:else if code === 'PROD'} |
349 | 333 | <enhanced:img |
350 | 334 | src="$lib/assets/collections/productivity.png" |
351 | 335 | alt={title} |
352 | 336 | class="max-h-full max-w-full object-contain" |
353 | 337 | /> |
354 | | - {:else if key === 'student-development'} |
| 338 | + {:else if code === 'STU_DEV'} |
355 | 339 | <enhanced:img |
356 | 340 | src="$lib/assets/collections/student-development.png" |
357 | 341 | alt={title} |
358 | 342 | class="max-h-full max-w-full object-contain" |
359 | 343 | /> |
360 | | - {:else if key === 'student-wellbeing'} |
| 344 | + {:else if code === 'STU_WELL'} |
361 | 345 | <enhanced:img |
362 | 346 | src="$lib/assets/collections/student-wellbeing.png" |
363 | 347 | alt={title} |
364 | 348 | class="max-h-full max-w-full object-contain" |
365 | 349 | /> |
366 | | - {:else if key === 'wellbeing'} |
| 350 | + {:else if code === 'WELLBEING'} |
367 | 351 | <enhanced:img |
368 | 352 | src="$lib/assets/collections/wellbeing.png" |
369 | 353 | alt={title} |
|
0 commit comments