[READ-ONLY] Mirror of https://github.com/danielroe/roe.dev. This is the code and content for my personal website, built in Nuxt. roe.dev
0

Configure Feed

Select the types of activity you want to include in your feed.

roe.dev / app / components / admin / UsesCategoryForm.vue
2.6 kB 102 lines
1<script setup lang="ts"> 2import type { DevRoeUsesCategory } from '#shared/lex' 3import type { Strict } from '#shared/cms/strict' 4 5type UsesCategoryValue = Omit<Strict<DevRoeUsesCategory.Record>, '$type'> 6 7const props = defineProps<{ 8 initial?: Partial<UsesCategoryValue> 9 submitLabel?: string 10}>() 11 12const emit = defineEmits<{ 13 (e: 'submit', value: UsesCategoryValue): void 14}>() 15 16const form = reactive({ 17 title: props.initial?.title ?? '', 18 order: props.initial?.order ?? 100, 19 displayAsGrid: props.initial?.displayAsGrid ?? false, 20}) 21 22const submitting = ref(false) 23const error = ref<string | null>(null) 24 25async function onSubmit () { 26 error.value = null 27 submitting.value = true 28 try { 29 const value: UsesCategoryValue = { 30 title: form.title, 31 order: form.order, 32 displayAsGrid: form.displayAsGrid, 33 ...(props.initial?.createdAt ? { createdAt: props.initial.createdAt } : { createdAt: new Date().toISOString() }), 34 } 35 emit('submit', value) 36 } 37 catch (err) { 38 error.value = err instanceof Error ? err.message : String(err) 39 } 40 finally { 41 submitting.value = false 42 } 43} 44</script> 45 46<template> 47 <form 48 class="flex flex-col gap-4 max-w-lg" 49 @submit.prevent="onSubmit" 50 > 51 <p 52 v-if="error" 53 class="text-sm text-red-500" 54 > 55 {{ error }} 56 </p> 57 58 <label class="flex flex-col gap-1 text-sm"> 59 <span class="text-muted">Title <span class="text-red-500">*</span></span> 60 <input 61 v-model="form.title" 62 required 63 type="text" 64 class="bg-accent px-3 py-2" 65 > 66 </label> 67 68 <label class="flex flex-col gap-1 text-sm"> 69 <span class="text-muted">Order</span> 70 <input 71 v-model.number="form.order" 72 type="number" 73 class="bg-accent px-3 py-2" 74 > 75 <span class="text-xs text-muted">Lower numbers render first. Defaults to 100.</span> 76 </label> 77 78 <label class="flex items-center gap-2 text-sm"> 79 <input 80 v-model="form.displayAsGrid" 81 type="checkbox" 82 > 83 <span>Display items as a grid (with images) rather than a list</span> 84 </label> 85 86 <div class="flex gap-3"> 87 <button 88 type="submit" 89 :disabled="submitting" 90 class="bg-primary text-background px-4 py-2 hover:bg-primary/90 transition-colors disabled:opacity-60" 91 > 92 {{ submitting ? 'Saving…' : (submitLabel ?? 'Save') }} 93 </button> 94 <NuxtLink 95 to="/admin/uses" 96 class="text-muted hover:text-primary self-center text-sm" 97 > 98 Cancel 99 </NuxtLink> 100 </div> 101 </form> 102</template>