AddModal.vue 2.78 KB
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
import type { ButtonPermissionKey } from '~/utils/permission'

const props = withDefaults(defineProps<{
  pagePath?: string
  buttonKey?: ButtonPermissionKey
}>(), {
  pagePath: '/customers',
  buttonKey: 'customers.create'
})

const { t } = useAppI18n()
const { can, getDeniedReason } = usePermission()

const buildSchema = () => z.object({
  name: z.string().min(2, t('settings.profile.validation.tooShort')),
  email: z.string().email(t('settings.profile.validation.invalidEmail'))
})

const schema = computed(buildSchema)
const open = ref(false)

type Schema = z.output<ReturnType<typeof buildSchema>>

const state = reactive<Partial<Schema>>({
  name: '',
  email: ''
})

const toast = useToast()
const canCreate = computed(() => can(props.pagePath, props.buttonKey))

function showNoPermissionToast() {
  toast.add({
    title: t('permission.toast.title'),
    description: t(getDeniedReason(props.pagePath, props.buttonKey)),
    icon: 'i-lucide-shield-alert',
    color: 'warning'
  })
}

function onOpenClick() {
  if (!canCreate.value) {
    showNoPermissionToast()
    return
  }

  open.value = true
}

async function onSubmit(event: FormSubmitEvent<Schema>) {
  if (!canCreate.value) {
    showNoPermissionToast()
    return
  }

  toast.add({
    title: t('customers.addModal.successTitle'),
    description: t('customers.addModal.successDescription', { name: event.data.name }),
    color: 'success'
  })
  open.value = false
}
</script>

<template>
  <UModal v-model:open="open" :title="t('customers.addModal.title')" :description="t('customers.addModal.description')">
    <UButton
      :label="t('common.newCustomer')"
      icon="i-lucide-plus"
      :disabled="!canCreate"
      @click="onOpenClick"
    />

    <template #body>
      <UForm
        :schema="schema"
        :state="state"
        class="space-y-4"
        @submit="onSubmit"
      >
        <UFormField :label="t('customers.addModal.name')" :placeholder="t('customers.addModal.namePlaceholder')" name="name">
          <UInput v-model="state.name" class="w-full" />
        </UFormField>
        <UFormField :label="t('customers.addModal.email')" :placeholder="t('customers.addModal.emailPlaceholder')" name="email">
          <UInput v-model="state.email" class="w-full" />
        </UFormField>
        <div class="flex justify-end gap-2">
          <UButton
            :label="t('common.cancel')"
            color="neutral"
            variant="subtle"
            @click="open = false"
          />
          <UButton
            :label="t('common.create')"
            color="primary"
            variant="solid"
            type="submit"
            :disabled="!canCreate"
          />
        </div>
      </UForm>
    </template>
  </UModal>
</template>