forbidden.vue 1.82 KB
<script setup lang="ts">
definePageMeta({
  layout: false
})

const route = useRoute()
const router = useRouter()
const { t } = useAppI18n()

const from = computed(() => {
  const raw = route.query.from

  if (typeof raw !== 'string' || !raw.startsWith('/')) {
    return '/'
  }

  return raw
})
</script>

<template>
  <main class="min-h-screen bg-gradient-to-br from-default via-elevated/20 to-warning/10">
    <div class="mx-auto flex min-h-screen max-w-3xl items-center justify-center px-4 py-10">
      <UCard class="w-full max-w-xl shadow-sm ring-1 ring-default">
        <template #header>
          <div class="space-y-2">
            <UBadge color="warning" variant="soft" class="rounded-full">
              {{ t('permission.forbidden.badge') }}
            </UBadge>
            <h1 class="text-2xl font-semibold text-highlighted">
              {{ t('permission.forbidden.title') }}
            </h1>
            <p class="text-sm text-toned">
              {{ t('permission.forbidden.description') }}
            </p>
          </div>
        </template>

        <div class="space-y-4">
          <UAlert
            color="warning"
            variant="soft"
            icon="i-lucide-shield-alert"
            :title="t('permission.forbidden.fromTitle')"
            :description="from"
          />

          <div class="flex flex-wrap gap-2">
            <UButton
              color="primary"
              icon="i-lucide-house"
              :label="t('permission.forbidden.backLogin')"
              to="/login"
            />
            <UButton
              color="neutral"
              variant="outline"
              icon="i-lucide-arrow-left"
              :label="t('permission.forbidden.goBack')"
              @click="router.back()"
            />
          </div>
        </div>
      </UCard>
    </div>
  </main>
</template>