your personal website on atproto - mirror blento.app
at button 128 lines 3.8 kB view raw
1<script lang="ts"> 2 import { Alert, Button, Subheading } from '@foxui/core'; 3 import type { SettingsComponentProps } from '../types'; 4 import { parseVCard, generateVCard, parseVCardName, emptyVCardFields, type VCardFields } from '.'; 5 6 let { item = $bindable(), onclose }: SettingsComponentProps = $props(); 7 8 let mode: 'easy' | 'expert' = $state('easy'); 9 let fields: VCardFields = $state( 10 parseVCard(item.cardData.vcard || '') || { ...emptyVCardFields } 11 ); 12 13 function syncFromFields() { 14 item.cardData.vcard = generateVCard(fields); 15 item.cardData.displayName = parseVCardName(item.cardData.vcard); 16 } 17 18 function handleTextarea(e: Event) { 19 const text = (e.target as HTMLTextAreaElement).value; 20 item.cardData.vcard = text; 21 item.cardData.displayName = parseVCardName(text); 22 fields = parseVCard(text); 23 } 24</script> 25 26<div class="flex w-72 flex-col gap-3 p-2"> 27 <Subheading>Edit vCard</Subheading> 28 29 <Alert type="info" title="Privacy"> 30 <p class="text-xs">All data is public, be aware.</p> 31 </Alert> 32 33 <div class="flex items-center gap-2 text-xs"> 34 <button 35 class={[ 36 'rounded px-2 py-1', 37 mode === 'easy' ? 'bg-accent-500 text-white' : 'bg-base-200 dark:bg-base-700' 38 ]} 39 onclick={() => (mode = 'easy')} 40 > 41 Easy 42 </button> 43 <button 44 class={[ 45 'rounded px-2 py-1', 46 mode === 'expert' ? 'bg-accent-500 text-white' : 'bg-base-200 dark:bg-base-700' 47 ]} 48 onclick={() => (mode = 'expert')} 49 > 50 Expert 51 </button> 52 <a 53 href="https://wikipedia.org/wiki/VCard" 54 target="_blank" 55 class="text-accent-600 dark:text-accent-400 underline">Learn about the vCard format</a 56 > 57 </div> 58 59 {#if mode === 'easy'} 60 <div class="flex flex-col gap-1 text-xs"> 61 <div class="grid grid-cols-2 gap-1"> 62 <input 63 bind:value={fields.firstName} 64 oninput={syncFromFields} 65 placeholder="First name" 66 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 67 /> 68 <input 69 bind:value={fields.lastName} 70 oninput={syncFromFields} 71 placeholder="Last name" 72 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 73 /> 74 </div> 75 <input 76 bind:value={fields.org} 77 oninput={syncFromFields} 78 placeholder="Organization" 79 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 80 /> 81 <input 82 bind:value={fields.title} 83 oninput={syncFromFields} 84 placeholder="Job title" 85 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 86 /> 87 <input 88 bind:value={fields.email} 89 oninput={syncFromFields} 90 placeholder="Email" 91 type="email" 92 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 93 /> 94 <input 95 bind:value={fields.bday} 96 oninput={syncFromFields} 97 placeholder="Birthday" 98 type="date" 99 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 100 /> 101 <input 102 bind:value={fields.website} 103 oninput={syncFromFields} 104 placeholder="Website" 105 type="url" 106 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 107 /> 108 <input 109 bind:value={fields.address} 110 oninput={syncFromFields} 111 placeholder="Address" 112 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 rounded border px-2 py-1" 113 /> 114 </div> 115 {:else} 116 <textarea 117 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 h-40 w-full resize-none rounded border p-2 font-mono text-xs focus:outline-none" 118 value={item.cardData.vcard || ''} 119 oninput={handleTextarea} 120 placeholder="BEGIN:VCARD 121VERSION:4.0 122FN:John Doe 123END:VCARD" 124 ></textarea> 125 {/if} 126 127 <Button onclick={onclose} size="sm">Done</Button> 128</div>