your personal website on atproto - mirror blento.app
at fix-cards-loading 99 lines 3.0 kB view raw
1<script lang="ts"> 2 import { Alert, Button, Input, Subheading } from '@foxui/core'; 3 import Modal from '$lib/components/modal/Modal.svelte'; 4 import type { CreationModalComponentProps } from '../../types'; 5 6 const EVENT_COLLECTION = 'community.lexicon.calendar.event'; 7 8 let { item = $bindable(), oncreate, oncancel }: CreationModalComponentProps = $props(); 9 10 let isValidating = $state(false); 11 let errorMessage = $state(''); 12 let eventUrl = $state(''); 13 14 function parseEventUrl(url: string): { did: string; rkey: string } | null { 15 // Match smokesignal.events URLs: https://smokesignal.events/{did}/{rkey} 16 const smokesignalMatch = url.match(/^https?:\/\/smokesignal\.events\/(did:[^/]+)\/([^/?#]+)/); 17 if (smokesignalMatch) { 18 return { did: smokesignalMatch[1], rkey: smokesignalMatch[2] }; 19 } 20 21 // Match AT URIs: at://{did}/community.lexicon.calendar.event/{rkey} 22 const atUriMatch = url.match(/^at:\/\/(did:[^/]+)\/([^/]+)\/([^/?#]+)/); 23 if (atUriMatch && atUriMatch[2] === EVENT_COLLECTION) { 24 return { did: atUriMatch[1], rkey: atUriMatch[3] }; 25 } 26 27 return null; 28 } 29 30 async function validateAndCreate() { 31 errorMessage = ''; 32 isValidating = true; 33 34 try { 35 const parsed = parseEventUrl(eventUrl.trim()); 36 37 if (!parsed) { 38 throw new Error('Invalid URL format'); 39 } 40 41 // Validate the event exists by fetching it 42 const response = await fetch( 43 `https://smokesignal.events/xrpc/community.lexicon.calendar.GetEvent?repository=${encodeURIComponent(parsed.did)}&record_key=${encodeURIComponent(parsed.rkey)}` 44 ); 45 46 if (!response.ok) { 47 throw new Error('Event not found'); 48 } 49 50 // Store as AT URI 51 item.cardData.uri = `at://${parsed.did}/${EVENT_COLLECTION}/${parsed.rkey}`; 52 53 return true; 54 } catch (err) { 55 errorMessage = 56 err instanceof Error && err.message === 'Event not found' 57 ? "Couldn't find that event. Please check the URL and try again." 58 : 'Invalid URL. Please enter a valid smokesignal.events URL or AT URI.'; 59 return false; 60 } finally { 61 isValidating = false; 62 } 63 } 64</script> 65 66<Modal open={true} closeButton={false}> 67 <form 68 onsubmit={async () => { 69 if (await validateAndCreate()) oncreate(); 70 }} 71 class="flex flex-col gap-2" 72 > 73 <Subheading>Enter a Smoke Signal event URL</Subheading> 74 <Input 75 bind:value={eventUrl} 76 placeholder="https://smokesignal.events/did:.../..." 77 class="mt-4" 78 /> 79 80 {#if errorMessage} 81 <Alert type="error" title="Failed to create event card"><span>{errorMessage}</span></Alert> 82 {/if} 83 84 <p class="text-base-500 dark:text-base-400 mt-2 text-xs"> 85 Paste a URL from <a 86 href="https://smokesignal.events" 87 class="text-accent-800 dark:text-accent-300" 88 target="_blank">smokesignal.events</a 89 > or an AT URI for a calendar event. 90 </p> 91 92 <div class="mt-4 flex justify-end gap-2"> 93 <Button onclick={oncancel} variant="ghost">Cancel</Button> 94 <Button type="submit" disabled={isValidating || !eventUrl.trim()} 95 >{isValidating ? 'Creating...' : 'Create'}</Button 96 > 97 </div> 98 </form> 99</Modal>