your personal website on atproto - mirror
blento.app
1<script lang="ts">
2 import type { Item } from '$lib/types';
3 import { Button, Input, Label } from '@foxui/core';
4 import type { TimerCardData, TimerMode } from './index';
5 import { onMount } from 'svelte';
6
7 let { item }: { item: Item; onclose: () => void } = $props();
8
9 let cardData = $derived(item.cardData as TimerCardData);
10
11 const modeOptions = [
12 { value: 'clock', label: 'Clock', desc: 'Show current time' },
13 { value: 'event', label: 'Event', desc: 'Countdown to date' }
14 ];
15
16 // All 24 timezones with representative cities
17 const timezoneOptions = [
18 { value: 'Pacific/Midway', label: 'UTC-11 (Midway)' },
19 { value: 'Pacific/Honolulu', label: 'UTC-10 (Honolulu)' },
20 { value: 'America/Anchorage', label: 'UTC-9 (Anchorage)' },
21 { value: 'America/Los_Angeles', label: 'UTC-8 (Los Angeles)' },
22 { value: 'America/Denver', label: 'UTC-7 (Denver)' },
23 { value: 'America/Chicago', label: 'UTC-6 (Chicago)' },
24 { value: 'America/New_York', label: 'UTC-5 (New York)' },
25 { value: 'America/Halifax', label: 'UTC-4 (Halifax)' },
26 { value: 'America/Sao_Paulo', label: 'UTC-3 (São Paulo)' },
27 { value: 'Atlantic/South_Georgia', label: 'UTC-2 (South Georgia)' },
28 { value: 'Atlantic/Azores', label: 'UTC-1 (Azores)' },
29 { value: 'UTC', label: 'UTC+0 (London)' },
30 { value: 'Europe/Paris', label: 'UTC+1 (Paris)' },
31 { value: 'Europe/Helsinki', label: 'UTC+2 (Helsinki)' },
32 { value: 'Europe/Moscow', label: 'UTC+3 (Moscow)' },
33 { value: 'Asia/Dubai', label: 'UTC+4 (Dubai)' },
34 { value: 'Asia/Karachi', label: 'UTC+5 (Karachi)' },
35 { value: 'Asia/Kolkata', label: 'UTC+5:30 (Mumbai)' },
36 { value: 'Asia/Dhaka', label: 'UTC+6 (Dhaka)' },
37 { value: 'Asia/Bangkok', label: 'UTC+7 (Bangkok)' },
38 { value: 'Asia/Shanghai', label: 'UTC+8 (Shanghai)' },
39 { value: 'Asia/Tokyo', label: 'UTC+9 (Tokyo)' },
40 { value: 'Australia/Sydney', label: 'UTC+10 (Sydney)' },
41 { value: 'Pacific/Noumea', label: 'UTC+11 (Noumea)' },
42 { value: 'Pacific/Auckland', label: 'UTC+12 (Auckland)' }
43 ];
44
45 // Auto-detect timezone on mount if not set
46 onMount(() => {
47 if (!cardData.timezone) {
48 try {
49 item.cardData.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
50 } catch {
51 item.cardData.timezone = 'UTC';
52 }
53 }
54 });
55
56 function useLocalTimezone() {
57 try {
58 item.cardData.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
59 } catch {
60 item.cardData.timezone = 'UTC';
61 }
62 }
63
64 // Parse target date for inputs
65 let targetDateValue = $derived.by(() => {
66 if (!cardData.targetDate) return '';
67 return new Date(cardData.targetDate).toISOString().split('T')[0];
68 });
69
70 let targetTimeValue = $derived.by(() => {
71 if (!cardData.targetDate) return '12:00';
72 return new Date(cardData.targetDate).toTimeString().slice(0, 5);
73 });
74
75 function updateTargetDate(dateStr: string, timeStr: string) {
76 if (!dateStr) return;
77 item.cardData.targetDate = new Date(`${dateStr}T${timeStr}`).toISOString();
78 }
79</script>
80
81<div class="flex flex-col gap-4">
82 <!-- Mode Selection -->
83 <div class="flex flex-col gap-2">
84 <Label>Mode</Label>
85 <div class="grid grid-cols-2 gap-2">
86 {#each modeOptions as opt (opt.value)}
87 <button
88 type="button"
89 onclick={() => (item.cardData.mode = opt.value as TimerMode)}
90 class={[
91 'rounded-xl border px-3 py-2 text-left transition-colors',
92 cardData.mode === opt.value
93 ? 'border-accent-500 bg-accent-500/10 text-accent-700 dark:text-accent-300'
94 : 'border-base-300 dark:border-base-700 hover:bg-base-100 dark:hover:bg-base-800'
95 ]}
96 >
97 <div class="text-sm font-medium">{opt.label}</div>
98 <div class="text-base-500 text-xs">{opt.desc}</div>
99 </button>
100 {/each}
101 </div>
102 </div>
103
104 <!-- Clock Settings -->
105 {#if cardData.mode === 'clock'}
106 <div class="flex flex-col gap-2">
107 <Label for="timezone">Timezone</Label>
108 <div class="flex gap-2">
109 <select
110 id="timezone"
111 value={cardData.timezone || 'UTC'}
112 onchange={(e) => (item.cardData.timezone = e.currentTarget.value)}
113 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 text-base-900 dark:text-base-100 flex-1 rounded-xl border px-3 py-2"
114 >
115 {#each timezoneOptions as tz (tz.value)}
116 <option value={tz.value}>{tz.label}</option>
117 {/each}
118 </select>
119 <Button size="sm" variant="ghost" onclick={useLocalTimezone}>Local</Button>
120 </div>
121 </div>
122 {/if}
123
124 <!-- Event Settings -->
125 {#if cardData.mode === 'event'}
126 <div class="flex flex-col gap-2">
127 <Label>Target Date & Time</Label>
128 <div class="flex gap-2">
129 <Input
130 type="date"
131 value={targetDateValue}
132 onchange={(e) => updateTargetDate(e.currentTarget.value, targetTimeValue)}
133 class="flex-1"
134 />
135 <Input
136 type="time"
137 value={targetTimeValue}
138 onchange={(e) => updateTargetDate(targetDateValue, e.currentTarget.value)}
139 class="w-28"
140 />
141 </div>
142 </div>
143 {/if}
144</div>