Skip to content

Commit b817413

Browse files
Mattclaude
andcommitted
Add API integration for schedule, sponsors, and speakers
- Integrate with Copia Events API for dynamic content - Add Vite proxy to handle CORS for API requests - Schedule page now fetches tracks, sessions, and speaker data from API - Talk titles and abstracts pulled from speaker.talk_title/talk_abstract - Sponsors page fetches sponsor data with tier grouping from API - Speakers page fetches speaker profiles from API - Force light mode by removing all dark mode CSS - Improve sponsor toast UX with "Tap for details" indicator - Add migration guide for applying changes to other projects Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 6d89bfc commit b817413

13 files changed

Lines changed: 956 additions & 129 deletions

File tree

MIGRATION_GUIDE.md

Lines changed: 465 additions & 0 deletions
Large diffs are not rendered by default.

helsing-ad/~$ wording.docx

-162 Bytes
Binary file not shown.

src/lib/components/Header.svelte

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,6 @@
9191
color: var(--color-primary);
9292
}
9393
94-
@media (prefers-color-scheme: dark) {
95-
.nav-link.active {
96-
color: var(--color-text-light);
97-
}
98-
}
99-
10094
@media (min-width: 768px) {
10195
.header {
10296
padding: var(--space-md) var(--space-xl);

src/lib/components/SpeakerCard.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
}
88
99
interface Speaker {
10-
id: number;
10+
id: string | number;
1111
name: string;
1212
photo?: string;
1313
title?: string;
@@ -102,7 +102,7 @@
102102
{/if}
103103
{#if speaker.social?.linkedin}
104104
<a
105-
href="https://linkedin.com/in/{speaker.social.linkedin}"
105+
href={speaker.social.linkedin.startsWith('http') ? speaker.social.linkedin : `https://linkedin.com/in/${speaker.social.linkedin}`}
106106
target="_blank"
107107
rel="noopener noreferrer"
108108
aria-label="{speaker.name} on LinkedIn"

src/lib/components/SponsorCard.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
interface Sponsor {
3-
id: number;
3+
id: string | number;
44
name: string;
55
tier: string;
66
logo: string;

src/lib/components/SponsorToast.svelte

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { base } from '$app/paths';
44
55
interface SponsorAd {
6-
id: number;
6+
id: string | number;
77
name: string;
88
tier: string;
99
logo: string;
@@ -28,7 +28,6 @@
2828
let expanded = $state(false);
2929
let progress = $state(0);
3030
let dismissed = $state(false);
31-
let isDarkMode = $state(false);
3231
3332
let progressInterval: ReturnType<typeof setInterval>;
3433
let hideTimeout: ReturnType<typeof setTimeout>;
@@ -104,15 +103,6 @@
104103
}
105104
106105
onMount(() => {
107-
// Detect dark mode
108-
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)');
109-
isDarkMode = darkModeQuery.matches;
110-
111-
const handleColorSchemeChange = (e: MediaQueryListEvent) => {
112-
isDarkMode = e.matches;
113-
};
114-
darkModeQuery.addEventListener('change', handleColorSchemeChange);
115-
116106
// Show first ad after a short delay
117107
const initialDelay = setTimeout(() => {
118108
showAd();
@@ -123,7 +113,6 @@
123113
clearInterval(progressInterval);
124114
clearTimeout(hideTimeout);
125115
clearTimeout(nextAdTimeout);
126-
darkModeQuery.removeEventListener('change', handleColorSchemeChange);
127116
};
128117
});
129118
@@ -137,11 +126,8 @@
137126
return path;
138127
}
139128
140-
// Get the correct logo based on dark/light mode
129+
// Get the logo (always light mode)
141130
function getLogo(ad: SponsorAd): string {
142-
if (isDarkMode && ad.logoDark) {
143-
return resolveAsset(ad.logoDark);
144-
}
145131
return resolveAsset(ad.logo);
146132
}
147133
</script>
@@ -171,6 +157,12 @@
171157
<span class="sponsor-message">{currentAd.message}</span>
172158
<span class="sponsor-name">{currentAd.name}</span>
173159
<span class="sponsor-tier">{currentAd.tier} sponsor</span>
160+
<span class="tap-hint">
161+
Tap for details
162+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
163+
<polyline points="9 18 15 12 9 6"/>
164+
</svg>
165+
</span>
174166
</div>
175167

176168
<button
@@ -307,14 +299,19 @@
307299
width: 100%;
308300
text-align: left;
309301
cursor: pointer;
302+
transition: transform var(--transition-fast), box-shadow var(--transition-fast);
310303
}
311304
312-
@media (prefers-color-scheme: dark) {
313-
.toast {
314-
border-color: var(--color-yellow);
315-
}
305+
.toast:hover {
306+
transform: translateY(-2px);
307+
box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.2);
316308
}
317309
310+
.toast:active {
311+
transform: translateY(0);
312+
}
313+
314+
318315
.progress-bar {
319316
position: absolute;
320317
top: 0;
@@ -374,6 +371,29 @@
374371
text-overflow: ellipsis;
375372
}
376373
374+
.tap-hint {
375+
display: inline-flex;
376+
align-items: center;
377+
gap: 4px;
378+
font-size: var(--text-xs);
379+
font-weight: 600;
380+
color: var(--color-primary);
381+
margin-top: 2px;
382+
}
383+
384+
.tap-hint svg {
385+
animation: bounce-right 1s ease-in-out infinite;
386+
}
387+
388+
@keyframes bounce-right {
389+
0%, 100% {
390+
transform: translateX(0);
391+
}
392+
50% {
393+
transform: translateX(3px);
394+
}
395+
}
396+
377397
.close-btn {
378398
display: flex;
379399
align-items: center;

src/lib/components/TalkCard.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
}
99
1010
interface Talk {
11-
id: number;
12-
track: number;
11+
id: string | number;
12+
track: string | number;
1313
time: string;
1414
duration: number;
1515
title: string;

src/lib/components/TrackSelector.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import { onMount } from 'svelte';
33
44
interface Track {
5-
id: number;
5+
id: string | number;
66
name: string;
77
}
88
99
interface Props {
1010
tracks: Track[];
11-
selectedTrack: number;
12-
onSelect: (trackId: number) => void;
11+
selectedTrack: string | number;
12+
onSelect: (trackId: string | number) => void;
1313
}
1414
1515
let { tracks, selectedTrack, onSelect }: Props = $props();

src/lib/styles/theme.css

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,3 @@ a {
137137
border: 0;
138138
}
139139

140-
/* Dark Mode */
141-
@media (prefers-color-scheme: dark) {
142-
:root {
143-
--color-white: #1C1C1E;
144-
--color-black: #F5F5F7;
145-
--color-surface: #1C1C1E;
146-
--color-text: #F5F5F7;
147-
--color-text-muted: #98989D;
148-
--color-gray-100: #000000;
149-
--color-gray-200: #2C2C2E;
150-
--color-gray-300: #3A3A3C;
151-
--color-gray-600: #98989D;
152-
--color-gray-800: #D1D1D6;
153-
--color-primary: #B366F9; /* Lighter purple for dark mode contrast */
154-
--color-primary-dark: #9A3EF0;
155-
--color-primary-light: #C88FFF;
156-
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
157-
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
158-
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
159-
}
160-
}

0 commit comments

Comments
 (0)