| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- <script setup lang="ts">
- import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
- } from '@/components/ui/dialog'
- import { Button } from '@/components/ui/button'
- import { Input } from '@/components/ui/input'
- import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
- import { useForm } from 'vee-validate'
- import { toTypedSchema } from '@vee-validate/zod'
- import * as z from 'zod'
- import { toast } from 'vue-sonner'
- import { api } from '@/api/client'
- import type { Zone } from '@/api/types'
- import { ref, watch } from 'vue'
- import SpinnerLoader from '@/components/SpinnerLoader.vue'
- const props = defineProps<{
- open: boolean
- zone?: Zone | null
- }>()
- const emit = defineEmits<{
- (e: 'update:open', value: boolean): void
- (e: 'saved'): void
- }>()
- const submitting = ref(false)
- const isEdit = () => !!props.zone
- const schema = toTypedSchema(
- z.object({
- zone_id: z.string().min(1, 'Zone ID is required'),
- name: z.string().min(1, 'Name is required'),
- api_key: z.string().min(1, 'API key is required'),
- }),
- )
- const { handleSubmit, resetForm, setValues } = useForm({
- validationSchema: schema,
- })
- watch(
- () => props.open,
- (open) => {
- if (open && props.zone) {
- setValues({
- zone_id: props.zone.zone_id,
- name: props.zone.name,
- api_key: props.zone.api_key,
- })
- } else if (open) {
- resetForm()
- }
- },
- )
- const onSubmit = handleSubmit(async (values) => {
- submitting.value = true
- try {
- if (isEdit() && props.zone) {
- await api.put(`/api/zones/${props.zone.id}`, values)
- toast.success('Zone updated')
- } else {
- await api.post('/api/zones', values)
- toast.success('Zone created')
- }
- emit('update:open', false)
- emit('saved')
- } catch (err) {
- toast.error(err instanceof Error ? err.message : 'Failed to save zone')
- } finally {
- submitting.value = false
- }
- })
- </script>
- <template>
- <Dialog :open="open" @update:open="emit('update:open', $event)">
- <DialogContent class="sm:max-w-md">
- <DialogHeader>
- <DialogTitle>{{ isEdit() ? 'Edit Zone' : 'Add Zone' }}</DialogTitle>
- <DialogDescription>
- {{ isEdit() ? 'Update the Cloudflare zone details.' : 'Add a new Cloudflare zone to manage.' }}
- </DialogDescription>
- </DialogHeader>
- <form @submit="onSubmit" class="space-y-4">
- <FormField name="zone_id" v-slot="{ field }">
- <FormItem>
- <FormLabel>Zone ID</FormLabel>
- <FormControl>
- <Input v-bind="field" placeholder="Cloudflare Zone ID" :disabled="isEdit()" />
- </FormControl>
- <FormMessage />
- </FormItem>
- </FormField>
- <FormField name="name" v-slot="{ field }">
- <FormItem>
- <FormLabel>Name</FormLabel>
- <FormControl>
- <Input v-bind="field" placeholder="example.com" />
- </FormControl>
- <FormMessage />
- </FormItem>
- </FormField>
- <FormField name="api_key" v-slot="{ field }">
- <FormItem>
- <FormLabel>API Key</FormLabel>
- <FormControl>
- <Input v-bind="field" type="password" placeholder="Cloudflare API token" />
- </FormControl>
- <FormMessage />
- </FormItem>
- </FormField>
- <DialogFooter>
- <Button type="button" variant="outline" @click="emit('update:open', false)">
- Cancel
- </Button>
- <Button type="submit" class="bg-orange-500 hover:bg-orange-500/90 text-white">
- <SpinnerLoader v-if="submitting" customClass="w-4 h-4 fill-gray-200 text-orange-500" />
- <template v-else>{{ isEdit() ? 'Update' : 'Create' }}</template>
- </Button>
- </DialogFooter>
- </form>
- </DialogContent>
- </Dialog>
- </template>
|