@getmicdrop/svelte-components 2.0.13 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__LIB_STORES__.js +30 -2
- package/dist/components/AboutShow/AboutShow.svelte +278 -0
- package/dist/components/AboutShow/AboutShow.svelte.d.ts +43 -0
- package/dist/components/AboutShow/AboutShow.svelte.d.ts.map +1 -0
- package/dist/components/Calendar/MiniMonthCalendar.svelte +1446 -0
- package/dist/components/Calendar/{Calendar.svelte.d.ts → MiniMonthCalendar.svelte.d.ts} +20 -21
- package/dist/components/Calendar/MiniMonthCalendar.svelte.d.ts.map +1 -0
- package/dist/components/DarkModeToggle.svelte +3 -1
- package/dist/components/DarkModeToggle.svelte.d.ts.map +1 -1
- package/dist/components/FAQs/FAQs.svelte +49 -0
- package/dist/components/{Calendar/QuarterView.svelte.d.ts → FAQs/FAQs.svelte.d.ts} +10 -10
- package/dist/components/FAQs/FAQs.svelte.d.ts.map +1 -0
- package/dist/components/Input/Input.svelte +100 -12
- package/dist/components/Input/Input.svelte.d.ts +12 -0
- package/dist/components/Input/Input.svelte.d.ts.map +1 -1
- package/dist/components/Input/OTPInput.svelte +1 -1
- package/dist/components/MonthSwitcher/MonthSwitcher.svelte +206 -0
- package/dist/components/MonthSwitcher/MonthSwitcher.svelte.d.ts +37 -0
- package/dist/components/MonthSwitcher/MonthSwitcher.svelte.d.ts.map +1 -0
- package/dist/components/OrderSummary/OrderSummary.svelte +553 -0
- package/dist/components/OrderSummary/OrderSummary.svelte.d.ts +65 -0
- package/dist/components/OrderSummary/OrderSummary.svelte.d.ts.map +1 -0
- package/dist/components/PublicCard/PublicCard.svelte +267 -0
- package/dist/components/{pages/performers/AvailabilityCalendarModal.svelte.d.ts → PublicCard/PublicCard.svelte.d.ts} +12 -14
- package/dist/components/PublicCard/PublicCard.svelte.d.ts.map +1 -0
- package/dist/components/ShowCard/ShowCard.svelte +240 -0
- package/dist/components/ShowCard/ShowCard.svelte.d.ts +39 -0
- package/dist/components/ShowCard/ShowCard.svelte.d.ts.map +1 -0
- package/dist/components/ShowTimeCard/ShowTimeCard.svelte +92 -0
- package/dist/components/{Calendar/QuarterView.stories.svelte.d.ts → ShowTimeCard/ShowTimeCard.svelte.d.ts} +17 -21
- package/dist/components/ShowTimeCard/ShowTimeCard.svelte.d.ts.map +1 -0
- package/dist/components/Spinner/Spinner.svelte +73 -17
- package/dist/components/Spinner/Spinner.svelte.d.ts +5 -3
- package/dist/components/Spinner/Spinner.svelte.d.ts.map +1 -1
- package/dist/components/pages/performers/ShowDetails.svelte.d.ts +2 -2
- package/dist/components/pages/performers/ShowItemCard.svelte.d.ts +6 -6
- package/dist/components/pages/performers/VenueItemCard.svelte.d.ts +2 -2
- package/dist/components/pages/shows/TabNavigation.svelte +7 -8
- package/dist/index.d.ts +8 -3
- package/dist/index.js +12 -3
- package/dist/services/EventService.js +75 -75
- package/dist/services/EventService.spec.js +217 -217
- package/dist/services/ShowService.spec.js +342 -342
- package/package.json +160 -160
- package/dist/components/Calendar/Calendar.spec.d.ts +0 -2
- package/dist/components/Calendar/Calendar.spec.d.ts.map +0 -1
- package/dist/components/Calendar/Calendar.spec.js +0 -131
- package/dist/components/Calendar/Calendar.svelte +0 -1115
- package/dist/components/Calendar/Calendar.svelte.d.ts.map +0 -1
- package/dist/components/Calendar/QuarterView.spec.d.ts +0 -2
- package/dist/components/Calendar/QuarterView.spec.d.ts.map +0 -1
- package/dist/components/Calendar/QuarterView.spec.js +0 -394
- package/dist/components/Calendar/QuarterView.stories.svelte +0 -134
- package/dist/components/Calendar/QuarterView.stories.svelte.d.ts.map +0 -1
- package/dist/components/Calendar/QuarterView.svelte +0 -736
- package/dist/components/Calendar/QuarterView.svelte.d.ts.map +0 -1
- package/dist/components/pages/performers/AvailabilityCalendarModal.svelte +0 -632
- package/dist/components/pages/performers/AvailabilityCalendarModal.svelte.d.ts.map +0 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher, onMount, onDestroy } from "svelte";
|
|
3
|
+
|
|
4
|
+
export let events = [];
|
|
5
|
+
export let view = "row"; // 'row' for list view, 'col' for gallery view
|
|
6
|
+
export let placeholderImage = null; // Allow custom placeholder
|
|
7
|
+
|
|
8
|
+
const dispatch = createEventDispatcher();
|
|
9
|
+
let isSmallScreen = false;
|
|
10
|
+
|
|
11
|
+
// Default placeholder image for events without images
|
|
12
|
+
const DEFAULT_PLACEHOLDER = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%23e5e7eb' width='100' height='100'/%3E%3Cpath d='M50 25c-8.3 0-15 6.7-15 15v5c0 8.3 6.7 15 15 15s15-6.7 15-15v-5c0-8.3-6.7-15-15-15zm0 45c-13.8 0-25 5.6-25 12.5V90h50v-7.5c0-6.9-11.2-12.5-25-12.5z' fill='%239ca3af'/%3E%3C/svg%3E";
|
|
13
|
+
|
|
14
|
+
$: placeholder = placeholderImage || DEFAULT_PLACEHOLDER;
|
|
15
|
+
|
|
16
|
+
let options = {
|
|
17
|
+
weekday: "short",
|
|
18
|
+
month: "short",
|
|
19
|
+
day: "numeric",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
onMount(() => {
|
|
23
|
+
isSmallScreen = window.innerWidth < 768;
|
|
24
|
+
window.addEventListener("resize", handleResize);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
onDestroy(() => {
|
|
28
|
+
if (typeof window !== 'undefined') {
|
|
29
|
+
window.removeEventListener("resize", handleResize);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function handleResize() {
|
|
34
|
+
isSmallScreen = window.innerWidth < 768;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function handleEventClick(event) {
|
|
38
|
+
dispatch("eventClick", event);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function handleKeydown(e, event) {
|
|
42
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
handleEventClick(event);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getStatusBadgeClass(status) {
|
|
49
|
+
switch (status) {
|
|
50
|
+
case 'Sold out':
|
|
51
|
+
return 'badge-sold-out';
|
|
52
|
+
case 'Selling fast':
|
|
53
|
+
return 'badge-selling-fast';
|
|
54
|
+
case 'Almost sold out':
|
|
55
|
+
return 'badge-almost-sold-out';
|
|
56
|
+
default:
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Only show badges for urgency statuses (not "On Sale" which is the default state)
|
|
62
|
+
function shouldShowBadge(status) {
|
|
63
|
+
return status === 'Sold out' || status === 'Selling fast' || status === 'Almost sold out';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function formatEventDate(dateStr) {
|
|
67
|
+
if (!dateStr) return '';
|
|
68
|
+
// Parse as local date (not UTC)
|
|
69
|
+
const [year, month, day] = dateStr.split('-').map(Number);
|
|
70
|
+
const date = new Date(year, month - 1, day);
|
|
71
|
+
return date.toLocaleDateString("en-US", options);
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
{#each events as event}
|
|
76
|
+
<article
|
|
77
|
+
class={`event-card rounded-lg cursor-pointer overflow-hidden bg-bg-primary border border-stroke-secondary transition-all duration-200 hover:shadow-lg hover:border-stroke-primary focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 relative ${
|
|
78
|
+
view === "col"
|
|
79
|
+
? "flex flex-col"
|
|
80
|
+
: "grid grid-cols-[100px_1fr] sm:grid-cols-[160px_1fr] gap-3 sm:gap-4 p-3 sm:p-4"
|
|
81
|
+
}`}
|
|
82
|
+
on:click={() => handleEventClick(event)}
|
|
83
|
+
on:keydown={(e) => handleKeydown(e, event)}
|
|
84
|
+
tabindex="0"
|
|
85
|
+
role="button"
|
|
86
|
+
aria-label={`${event.name}, ${event.status || 'On Sale'}, ${formatEventDate(event.date)}. Press Enter to view details.`}
|
|
87
|
+
>
|
|
88
|
+
<!-- Event Image -->
|
|
89
|
+
<div
|
|
90
|
+
class={`bg-bg-secondary flex items-center justify-center overflow-hidden ${
|
|
91
|
+
view === "col"
|
|
92
|
+
? "w-full aspect-[4/3] rounded-t-lg"
|
|
93
|
+
: "w-[100px] h-[100px] sm:w-[160px] sm:h-[120px] rounded-lg flex-shrink-0"
|
|
94
|
+
}`}
|
|
95
|
+
>
|
|
96
|
+
<img
|
|
97
|
+
src={event.image || placeholder}
|
|
98
|
+
alt={event.name}
|
|
99
|
+
class="object-contain w-full h-full"
|
|
100
|
+
loading="lazy"
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<!-- Event Details -->
|
|
105
|
+
<div
|
|
106
|
+
class={`flex flex-col ${
|
|
107
|
+
view === "col" ? "p-3 gap-1" : "gap-1.5 sm:gap-2 justify-center"
|
|
108
|
+
}`}
|
|
109
|
+
>
|
|
110
|
+
<!-- Status Badge for gallery view - positioned over image -->
|
|
111
|
+
{#if view === "col" && event.status && shouldShowBadge(event.status)}
|
|
112
|
+
<span
|
|
113
|
+
class={`status-badge ${getStatusBadgeClass(event.status)} absolute top-2 left-2`}
|
|
114
|
+
>
|
|
115
|
+
{event.status}
|
|
116
|
+
</span>
|
|
117
|
+
{/if}
|
|
118
|
+
|
|
119
|
+
<!-- Status Badge for list view - inline -->
|
|
120
|
+
{#if view === "row" && event.status && shouldShowBadge(event.status)}
|
|
121
|
+
<span
|
|
122
|
+
class={`status-badge ${getStatusBadgeClass(event.status)}`}
|
|
123
|
+
>
|
|
124
|
+
{event.status}
|
|
125
|
+
</span>
|
|
126
|
+
{/if}
|
|
127
|
+
|
|
128
|
+
<!-- Event Name -->
|
|
129
|
+
<h3
|
|
130
|
+
class={`font-semibold text-text-primary leading-tight ${
|
|
131
|
+
view === "col"
|
|
132
|
+
? "text-sm sm:text-base line-clamp-2"
|
|
133
|
+
: "text-sm sm:text-lg line-clamp-2"
|
|
134
|
+
}`}
|
|
135
|
+
>
|
|
136
|
+
{event.name}
|
|
137
|
+
</h3>
|
|
138
|
+
|
|
139
|
+
<!-- Date & Time -->
|
|
140
|
+
<div
|
|
141
|
+
class={`text-text-secondary ${
|
|
142
|
+
view === "col" ? "text-xs" : "text-xs sm:text-sm"
|
|
143
|
+
}`}
|
|
144
|
+
>
|
|
145
|
+
<span class="font-medium">
|
|
146
|
+
{formatEventDate(event.date)}
|
|
147
|
+
{#if event.timeline}
|
|
148
|
+
<span class="text-text-tertiary">•</span>
|
|
149
|
+
{event.timeline.split("-")[0].trim()}
|
|
150
|
+
{/if}
|
|
151
|
+
</span>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<!-- Description (list view only) -->
|
|
155
|
+
{#if view === "row" && event.description}
|
|
156
|
+
<p class="text-text-tertiary text-xs sm:text-sm line-clamp-2 mt-1">
|
|
157
|
+
{event.description}
|
|
158
|
+
</p>
|
|
159
|
+
{/if}
|
|
160
|
+
|
|
161
|
+
<!-- Doors time (if available) -->
|
|
162
|
+
{#if event.doorsTimeline && view === "row"}
|
|
163
|
+
<div class="text-[10px] sm:text-xs text-text-tertiary">
|
|
164
|
+
{event.doorsTimeline}
|
|
165
|
+
</div>
|
|
166
|
+
{/if}
|
|
167
|
+
</div>
|
|
168
|
+
</article>
|
|
169
|
+
{/each}
|
|
170
|
+
|
|
171
|
+
<style>
|
|
172
|
+
/* Event card base styles */
|
|
173
|
+
.event-card {
|
|
174
|
+
background-color: hsl(var(--BG-Primary));
|
|
175
|
+
border-color: hsl(var(--Stroke-Secondary));
|
|
176
|
+
transition: all 0.2s ease-in-out;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.event-card:hover {
|
|
180
|
+
transform: translateY(-2px);
|
|
181
|
+
border-color: hsl(var(--Stroke-Primary));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.event-card:active {
|
|
185
|
+
transform: translateY(0);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/* Text colors using CSS variables */
|
|
189
|
+
.text-text-primary {
|
|
190
|
+
color: hsl(var(--Text-Primary));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.text-text-secondary {
|
|
194
|
+
color: hsl(var(--Text-Secondary));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.text-text-tertiary {
|
|
198
|
+
color: hsl(var(--Text-Tartiary));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.bg-bg-secondary {
|
|
202
|
+
background-color: hsl(var(--BG-Secondary));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Status badge base styles - compact inline pill */
|
|
206
|
+
.status-badge {
|
|
207
|
+
display: inline-flex;
|
|
208
|
+
align-items: center;
|
|
209
|
+
width: -moz-fit-content;
|
|
210
|
+
width: fit-content;
|
|
211
|
+
padding: 2px 8px;
|
|
212
|
+
font-size: 11px;
|
|
213
|
+
font-weight: 600;
|
|
214
|
+
line-height: 1.4;
|
|
215
|
+
border-radius: 4px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@media (min-width: 640px) {
|
|
219
|
+
.status-badge {
|
|
220
|
+
font-size: 12px;
|
|
221
|
+
padding: 3px 10px;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* Status badge variants using CSS variables */
|
|
226
|
+
.badge-selling-fast {
|
|
227
|
+
background-color: hsl(var(--Status-SellingFast) / 0.15);
|
|
228
|
+
color: hsl(var(--Status-SellingFast));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.badge-sold-out {
|
|
232
|
+
background-color: hsl(var(--Status-SoldOut) / 0.15);
|
|
233
|
+
color: hsl(var(--Status-SoldOut));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.badge-almost-sold-out {
|
|
237
|
+
background-color: hsl(var(--Status-SoldOut) / 0.15);
|
|
238
|
+
color: hsl(var(--Status-SoldOut));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Line clamping for text truncation */
|
|
242
|
+
.line-clamp-2 {
|
|
243
|
+
display: -webkit-box;
|
|
244
|
+
-webkit-line-clamp: 2;
|
|
245
|
+
line-clamp: 2;
|
|
246
|
+
-webkit-box-orient: vertical;
|
|
247
|
+
overflow: hidden;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Reduced motion support */
|
|
251
|
+
@media (prefers-reduced-motion: reduce) {
|
|
252
|
+
.event-card {
|
|
253
|
+
transition: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.event-card:hover {
|
|
257
|
+
transform: none;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* Mobile optimizations */
|
|
262
|
+
@media (max-width: 640px) {
|
|
263
|
+
.event-card {
|
|
264
|
+
-webkit-tap-highlight-color: transparent;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
</style>
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
export default
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
onUpdate?: ((updatedTimestamp: any) => void) | undefined;
|
|
1
|
+
export default PublicCard;
|
|
2
|
+
type PublicCard = SvelteComponent<{
|
|
3
|
+
view?: string | undefined;
|
|
4
|
+
events?: any[] | undefined;
|
|
5
|
+
placeholderImage?: null | undefined;
|
|
7
6
|
}, {
|
|
8
|
-
|
|
7
|
+
eventClick: CustomEvent<any>;
|
|
9
8
|
} & {
|
|
10
9
|
[evt: string]: CustomEvent<any>;
|
|
11
10
|
}, {}> & {
|
|
12
11
|
$$bindings?: string | undefined;
|
|
13
12
|
};
|
|
14
|
-
declare const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
onUpdate?: ((updatedTimestamp: any) => void) | undefined;
|
|
13
|
+
declare const PublicCard: $$__sveltets_2_IsomorphicComponent<{
|
|
14
|
+
view?: string | undefined;
|
|
15
|
+
events?: any[] | undefined;
|
|
16
|
+
placeholderImage?: null | undefined;
|
|
19
17
|
}, {
|
|
20
|
-
|
|
18
|
+
eventClick: CustomEvent<any>;
|
|
21
19
|
} & {
|
|
22
20
|
[evt: string]: CustomEvent<any>;
|
|
23
21
|
}, {}, {}, string>;
|
|
@@ -34,4 +32,4 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
34
32
|
};
|
|
35
33
|
z_$$bindings?: Bindings;
|
|
36
34
|
}
|
|
37
|
-
//# sourceMappingURL=
|
|
35
|
+
//# sourceMappingURL=PublicCard.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PublicCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/PublicCard/PublicCard.svelte.js"],"names":[],"mappings":";;;;;;;;;;;;AAoKA;;;;;;;;mBAA4J;6CAT/G,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,OAAO,OAAO,QAAQ;IAC3L,cAAc,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,WAAW,OAAO,SAAS,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
import Share from 'carbon-icons-svelte/lib/Share.svelte';
|
|
4
|
+
import Checkmark from 'carbon-icons-svelte/lib/Checkmark.svelte';
|
|
5
|
+
import ShowTimeCard from '../ShowTimeCard/ShowTimeCard.svelte';
|
|
6
|
+
|
|
7
|
+
export let event = {};
|
|
8
|
+
export let showtimes = [];
|
|
9
|
+
export let showTitle = true;
|
|
10
|
+
|
|
11
|
+
// Formatting functions - can be overridden via props
|
|
12
|
+
export let formatDateTime = (dateStr) => {
|
|
13
|
+
if (!dateStr) return '';
|
|
14
|
+
const date = new Date(dateStr);
|
|
15
|
+
if (isNaN(date.getTime())) return dateStr;
|
|
16
|
+
return date.toLocaleDateString('en-US', {
|
|
17
|
+
weekday: 'long',
|
|
18
|
+
year: 'numeric',
|
|
19
|
+
month: 'long',
|
|
20
|
+
day: 'numeric',
|
|
21
|
+
hour: 'numeric',
|
|
22
|
+
minute: '2-digit'
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export let formatTimeline = (timeStr) => {
|
|
27
|
+
if (!timeStr) return '';
|
|
28
|
+
// Handle ISO datetime or time string
|
|
29
|
+
const date = new Date(timeStr);
|
|
30
|
+
if (!isNaN(date.getTime())) {
|
|
31
|
+
return date.toLocaleTimeString('en-US', {
|
|
32
|
+
hour: 'numeric',
|
|
33
|
+
minute: '2-digit',
|
|
34
|
+
hour12: true
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return timeStr;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const dispatch = createEventDispatcher();
|
|
41
|
+
|
|
42
|
+
let selectedDate = null;
|
|
43
|
+
let shareSuccess = false;
|
|
44
|
+
|
|
45
|
+
function handleSelect(e) {
|
|
46
|
+
selectedDate = e.detail.date;
|
|
47
|
+
dispatch('showtimeSelect', e.detail);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function handleShare() {
|
|
51
|
+
const shareData = {
|
|
52
|
+
title: event.name,
|
|
53
|
+
text: `Check out ${event.name} at ${event.venue?.name || 'this venue'}!`,
|
|
54
|
+
url: typeof window !== 'undefined' ? window.location.href : ''
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
// Use Web Share API if available (mobile devices, some desktop browsers)
|
|
59
|
+
if (typeof navigator !== 'undefined' && navigator.share && navigator.canShare && navigator.canShare(shareData)) {
|
|
60
|
+
await navigator.share(shareData);
|
|
61
|
+
} else if (typeof navigator !== 'undefined' && navigator.clipboard) {
|
|
62
|
+
// Fallback: copy URL to clipboard
|
|
63
|
+
await navigator.clipboard.writeText(shareData.url);
|
|
64
|
+
shareSuccess = true;
|
|
65
|
+
setTimeout(() => {
|
|
66
|
+
shareSuccess = false;
|
|
67
|
+
}, 2000);
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
// User cancelled share or error occurred - try clipboard as last resort
|
|
71
|
+
if (err.name !== 'AbortError' && typeof navigator !== 'undefined' && navigator.clipboard) {
|
|
72
|
+
try {
|
|
73
|
+
await navigator.clipboard.writeText(shareData.url);
|
|
74
|
+
shareSuccess = true;
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
shareSuccess = false;
|
|
77
|
+
}, 2000);
|
|
78
|
+
} catch {
|
|
79
|
+
console.error('Share failed:', err);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<div class="show-card h-fit rounded-[8px] sm:px-5 py-4 md:border">
|
|
87
|
+
<!-- Event Title -->
|
|
88
|
+
{#if showTitle}
|
|
89
|
+
<div class="flex justify-between items-start gap-2 mb-4">
|
|
90
|
+
<h1 class="event-title flex-1 text-left font-semibold text-[22px] leading-tight">
|
|
91
|
+
{event.name || ''}
|
|
92
|
+
</h1>
|
|
93
|
+
<button
|
|
94
|
+
class="share-btn flex-shrink-0 p-2 rounded-lg transition-colors relative"
|
|
95
|
+
aria-label="Share event"
|
|
96
|
+
on:click={handleShare}
|
|
97
|
+
>
|
|
98
|
+
{#if shareSuccess}
|
|
99
|
+
<Checkmark size={20} class="success-icon" />
|
|
100
|
+
{:else}
|
|
101
|
+
<Share size={20} class="share-icon cursor-pointer" />
|
|
102
|
+
{/if}
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
{/if}
|
|
106
|
+
|
|
107
|
+
<!-- Date & Time -->
|
|
108
|
+
<div class="space-y-1 text-[15px]">
|
|
109
|
+
<p class="date-primary font-medium">{formatDateTime(event.startDateTime)}</p>
|
|
110
|
+
{#if event.displayStartTime && event.doorsOpenTime}
|
|
111
|
+
<p class="date-secondary">Doors open {formatTimeline(event.doorsOpenTime)}</p>
|
|
112
|
+
{/if}
|
|
113
|
+
{#if event.displayEndTime && event.endDateTime}
|
|
114
|
+
<p class="date-secondary">Ends {formatTimeline(event.endDateTime)}</p>
|
|
115
|
+
{/if}
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{#if showtimes && showtimes.length > 1}
|
|
119
|
+
<div class="showtimes-section mt-4 pt-4">
|
|
120
|
+
<p class="showtimes-label text-sm mb-2">More showtimes</p>
|
|
121
|
+
<div class="flex flex-wrap gap-2">
|
|
122
|
+
{#each showtimes as showtime}
|
|
123
|
+
<div class="w-[91px]">
|
|
124
|
+
<ShowTimeCard
|
|
125
|
+
day={showtime.day}
|
|
126
|
+
date={showtime.date}
|
|
127
|
+
time={showtime.time}
|
|
128
|
+
isSelected={selectedDate === showtime.date}
|
|
129
|
+
on:select={handleSelect}
|
|
130
|
+
/>
|
|
131
|
+
</div>
|
|
132
|
+
{/each}
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
{/if}
|
|
136
|
+
|
|
137
|
+
<!-- Location -->
|
|
138
|
+
{#if event.venue}
|
|
139
|
+
<div class="location-section mt-4 pt-4">
|
|
140
|
+
<a
|
|
141
|
+
href="https://www.google.com/maps/search/?api=1&query={encodeURIComponent(event.venue.googleLocationNameCache || event.venue.address || event.venue.name)}"
|
|
142
|
+
target="_blank"
|
|
143
|
+
rel="noopener noreferrer"
|
|
144
|
+
class="group block"
|
|
145
|
+
>
|
|
146
|
+
<p class="venue-name text-[15px] font-medium transition-colors">
|
|
147
|
+
{event.venue.name}
|
|
148
|
+
</p>
|
|
149
|
+
<p class="venue-address text-[14px] transition-colors">
|
|
150
|
+
{event.venue.address || ''}
|
|
151
|
+
</p>
|
|
152
|
+
</a>
|
|
153
|
+
|
|
154
|
+
{#if event.hasAgeRestriction || event.ageRequirement || event.minimumAge}
|
|
155
|
+
<p class="age-text text-[14px] mt-2">
|
|
156
|
+
{#if event.ageRequirement != null}
|
|
157
|
+
{event.ageRequirement <= 1 ? 'All ages' : `${event.ageRequirement}+`}
|
|
158
|
+
{:else if event.minimumAge != null}
|
|
159
|
+
{event.minimumAge <= 1 ? 'All ages' : `${event.minimumAge}+`}
|
|
160
|
+
{:else if event.ageRestriction != null}
|
|
161
|
+
{event.ageRestriction <= 1 ? 'All ages' : `${event.ageRestriction}+`}
|
|
162
|
+
{/if}
|
|
163
|
+
</p>
|
|
164
|
+
{/if}
|
|
165
|
+
</div>
|
|
166
|
+
{/if}
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<style>
|
|
170
|
+
/* Theme-responsive colors using CSS variables */
|
|
171
|
+
.show-card {
|
|
172
|
+
background-color: hsl(var(--BG-Primary));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@media (min-width: 768px) {
|
|
176
|
+
.show-card {
|
|
177
|
+
border-color: hsl(var(--Stroke-Secondary));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.event-title {
|
|
182
|
+
color: hsl(var(--Text-Primary));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.share-btn:hover {
|
|
186
|
+
background-color: hsl(var(--BG-Secondary));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
:global(.share-icon) {
|
|
190
|
+
color: hsl(var(--Text-Tartiary));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
:global(.share-icon:hover) {
|
|
194
|
+
color: hsl(var(--Text-Secondary));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
:global(.success-icon) {
|
|
198
|
+
color: hsl(var(--Status-OnSale));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.date-primary {
|
|
202
|
+
color: hsl(var(--Text-Primary));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.date-secondary {
|
|
206
|
+
color: hsl(var(--Text-Secondary));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.showtimes-section {
|
|
210
|
+
border-top: 1px solid hsl(var(--Stroke-Secondary));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.showtimes-label {
|
|
214
|
+
color: hsl(var(--Text-Tartiary));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.location-section {
|
|
218
|
+
border-top: 1px solid hsl(var(--Stroke-Secondary));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.venue-name {
|
|
222
|
+
color: hsl(var(--Text-Primary));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.group:hover .venue-name {
|
|
226
|
+
color: hsl(var(--Brand-Primary));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.venue-address {
|
|
230
|
+
color: hsl(var(--Text-Tartiary));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.group:hover .venue-address {
|
|
234
|
+
color: hsl(var(--Brand-Primary));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.age-text {
|
|
238
|
+
color: hsl(var(--Text-Tartiary));
|
|
239
|
+
}
|
|
240
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export default ShowCard;
|
|
2
|
+
type ShowCard = SvelteComponent<{
|
|
3
|
+
event?: {} | undefined;
|
|
4
|
+
showtimes?: any[] | undefined;
|
|
5
|
+
showTitle?: boolean | undefined;
|
|
6
|
+
formatDateTime?: ((dateStr: any) => any) | undefined;
|
|
7
|
+
formatTimeline?: ((timeStr: any) => any) | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
showtimeSelect: CustomEvent<any>;
|
|
10
|
+
} & {
|
|
11
|
+
[evt: string]: CustomEvent<any>;
|
|
12
|
+
}, {}> & {
|
|
13
|
+
$$bindings?: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
declare const ShowCard: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
event?: {} | undefined;
|
|
17
|
+
showtimes?: any[] | undefined;
|
|
18
|
+
showTitle?: boolean | undefined;
|
|
19
|
+
formatDateTime?: ((dateStr: any) => any) | undefined;
|
|
20
|
+
formatTimeline?: ((timeStr: any) => any) | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
showtimeSelect: CustomEvent<any>;
|
|
23
|
+
} & {
|
|
24
|
+
[evt: string]: CustomEvent<any>;
|
|
25
|
+
}, {}, {}, string>;
|
|
26
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
27
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
28
|
+
$$bindings?: Bindings;
|
|
29
|
+
} & Exports;
|
|
30
|
+
(internal: unknown, props: Props & {
|
|
31
|
+
$$events?: Events;
|
|
32
|
+
$$slots?: Slots;
|
|
33
|
+
}): Exports & {
|
|
34
|
+
$set?: any;
|
|
35
|
+
$on?: any;
|
|
36
|
+
};
|
|
37
|
+
z_$$bindings?: Bindings;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=ShowCard.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShowCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ShowCard/ShowCard.svelte.js"],"names":[],"mappings":";;;;;;;;;;;;;;AA8KA;;;;;;;;;;mBAAyL;6CAT5I,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,OAAO,OAAO,QAAQ;IAC3L,cAAc,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,WAAW,OAAO,SAAS,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export let day = '';
|
|
5
|
+
export let date = '';
|
|
6
|
+
export let time = '';
|
|
7
|
+
export let isSelected = false;
|
|
8
|
+
|
|
9
|
+
const dispatch = createEventDispatcher();
|
|
10
|
+
|
|
11
|
+
function handleCardClick() {
|
|
12
|
+
dispatch('select', { date });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function handleKeydown(e) {
|
|
16
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
handleCardClick();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function formatHour(timeStr) {
|
|
23
|
+
if (!timeStr) return '';
|
|
24
|
+
// Handle various time formats
|
|
25
|
+
const date = new Date(`1970-01-01T${timeStr}`);
|
|
26
|
+
if (isNaN(date.getTime())) return timeStr;
|
|
27
|
+
return date.toLocaleTimeString('en-US', {
|
|
28
|
+
hour: 'numeric',
|
|
29
|
+
minute: '2-digit',
|
|
30
|
+
hour12: true
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function formatDate(dateStr) {
|
|
35
|
+
if (!dateStr) return '';
|
|
36
|
+
const d = new Date(dateStr);
|
|
37
|
+
if (isNaN(d.getTime())) return dateStr;
|
|
38
|
+
return d.toLocaleDateString('en-US', {
|
|
39
|
+
month: 'short',
|
|
40
|
+
day: 'numeric',
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<div
|
|
46
|
+
class="showtime-card w-full h-[106px] rounded-lg flex flex-col justify-center items-center gap-1.5 cursor-pointer border-2 px-1 transition-colors"
|
|
47
|
+
class:selected={isSelected}
|
|
48
|
+
on:click={handleCardClick}
|
|
49
|
+
on:keydown={handleKeydown}
|
|
50
|
+
tabindex="0"
|
|
51
|
+
role="button"
|
|
52
|
+
aria-label={`${day} ${formatDate(date)} at ${formatHour(time)}${isSelected ? ', selected' : ''}`}
|
|
53
|
+
aria-pressed={isSelected}
|
|
54
|
+
>
|
|
55
|
+
<span class="day-text font-medium text-sm">{day}</span>
|
|
56
|
+
<span class="date-text font-medium text-[16px]" class:selected-text={isSelected}>
|
|
57
|
+
{formatDate(date)}
|
|
58
|
+
</span>
|
|
59
|
+
<span class="time-text font-medium text-sm">{formatHour(time)}</span>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<style>
|
|
63
|
+
/* Theme-responsive colors using CSS variables */
|
|
64
|
+
.showtime-card {
|
|
65
|
+
background-color: hsl(var(--BG-Primary));
|
|
66
|
+
border-color: hsl(var(--Stroke-Secondary));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.showtime-card:hover {
|
|
70
|
+
border-color: hsl(var(--Brand-Primary));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.showtime-card.selected {
|
|
74
|
+
border-color: hsl(var(--Brand-Primary));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.day-text {
|
|
78
|
+
color: hsl(var(--Text-Tartiary));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.date-text {
|
|
82
|
+
color: hsl(var(--Text-Primary));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.date-text.selected-text {
|
|
86
|
+
color: hsl(var(--Brand-Primary));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.time-text {
|
|
90
|
+
color: hsl(var(--Text-Tartiary));
|
|
91
|
+
}
|
|
92
|
+
</style>
|