Files
ghatreh_user/src/views/base/404.vue
T
2026-07-22 12:20:39 +03:30

206 lines
5.2 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts" setup>
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { getConfigApp } from '@/utils/config'
const router = useRouter()
const brandName = computed(
() => String(getConfigApp('name_fa') || getConfigApp('name') || 'خانه')
)
const logo = computed(() => String(getConfigApp('avatar') || ''))
function goHome() {
router.push({ name: 'home' })
}
function goBack() {
if (window.history.length > 1) {
router.back()
return
}
goHome()
}
</script>
<template>
<div class="not-found" dir="rtl">
<div class="not-found__glow not-found__glow--a" aria-hidden="true" />
<div class="not-found__glow not-found__glow--b" aria-hidden="true" />
<div class="not-found__grid" aria-hidden="true" />
<div class="not-found__panel">
<div v-if="logo" class="not-found__brand">
<img :src="logo" :alt="brandName" class="not-found__logo">
<span class="not-found__brand-name">{{ brandName }}</span>
</div>
<p v-else class="not-found__brand-name not-found__brand-name--solo">
{{ brandName }}
</p>
<p class="not-found__code" aria-hidden="true">۴۰۴</p>
<h1 class="not-found__title">
صفحه مورد نظر یافت نشد
</h1>
<p class="not-found__subtitle">
این مسیر وجود ندارد یا جابه‌جا شده است. می‌توانید به صفحه اصلی برگردید
و از آنجا ادامه دهید.
</p>
<div class="not-found__actions">
<a-button type="primary" size="large" class="not-found__cta" @click="goHome">
بازگشت به صفحه اصلی
</a-button>
<a-button size="large" class="not-found__secondary" @click="goBack">
صفحه قبل
</a-button>
</div>
</div>
</div>
</template>
<style scoped>
.not-found {
@apply relative min-h-screen w-full overflow-hidden flex items-center justify-center px-4 py-10;
background:
radial-gradient(120% 80% at 50% -10%, color-mix(in srgb, var(--App-primary, #7f1d1d) 18%, transparent), transparent 55%),
linear-gradient(165deg, #f7f4f0 0%, #efe8e0 45%, #f8f6f3 100%);
color: #1c1917;
}
.not-found__glow {
@apply pointer-events-none absolute rounded-full;
filter: blur(48px);
opacity: 0.45;
animation: not-found-float 9s ease-in-out infinite;
}
.not-found__glow--a {
width: min(48vw, 22rem);
height: min(48vw, 22rem);
top: 8%;
left: 6%;
background: color-mix(in srgb, var(--App-primary, #7f1d1d) 35%, #c4a574);
}
.not-found__glow--b {
width: min(42vw, 18rem);
height: min(42vw, 18rem);
right: 4%;
bottom: 12%;
background: color-mix(in srgb, var(--App-primary, #7f1d1d) 22%, #d6c3a3);
animation-delay: -3.5s;
}
.not-found__grid {
@apply pointer-events-none absolute inset-0 opacity-40;
background-image:
linear-gradient(rgba(28, 25, 23, 0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(28, 25, 23, 0.04) 1px, transparent 1px);
background-size: 48px 48px;
mask-image: radial-gradient(ellipse at center, black 20%, transparent 75%);
}
.not-found__panel {
@apply relative z-1 w-full max-w-lg flex flex-col items-center text-center;
animation: not-found-rise 0.7s ease-out both;
}
.not-found__brand {
@apply flex items-center justify-center gap-2.5 mb-6;
}
.not-found__logo {
@apply w-11 h-11 rounded-full object-cover;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9), 0 8px 24px rgba(28, 25, 23, 0.12);
}
.not-found__brand-name {
@apply text-base font-bold tracking-wide text-primary m-0;
}
.not-found__brand-name--solo {
@apply mb-6;
}
.not-found__code {
@apply m-0 font-black leading-none select-none;
font-size: clamp(5.5rem, 22vw, 9rem);
letter-spacing: -0.06em;
background: linear-gradient(
135deg,
var(--App-primary, #7f1d1d) 0%,
#b45309 48%,
var(--App-primary, #7f1d1d) 100%
);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
filter: drop-shadow(0 12px 28px rgba(127, 29, 29, 0.18));
animation: not-found-pulse 5.5s ease-in-out infinite;
}
.not-found__title {
@apply m-0 mt-2 text-xl md:text-2xl font-bold text-stone-900;
}
.not-found__subtitle {
@apply m-0 mt-3 text-sm md:text-base leading-7 text-stone-500 max-w-md;
}
.not-found__actions {
@apply mt-8 flex flex-wrap items-center justify-center gap-3 w-full;
}
.not-found__cta {
@apply min-w-44 font-bold;
box-shadow: 0 10px 28px color-mix(in srgb, var(--App-primary, #7f1d1d) 28%, transparent);
}
.not-found__secondary {
@apply min-w-28;
}
@keyframes not-found-rise {
from {
opacity: 0;
transform: translateY(18px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes not-found-float {
0%,
100% {
transform: translate3d(0, 0, 0) scale(1);
}
50% {
transform: translate3d(12px, -16px, 0) scale(1.05);
}
}
@keyframes not-found-pulse {
0%,
100% {
transform: translateY(0);
filter: drop-shadow(0 12px 28px rgba(127, 29, 29, 0.18));
}
50% {
transform: translateY(-6px);
filter: drop-shadow(0 18px 36px rgba(127, 29, 29, 0.26));
}
}
@media (prefers-reduced-motion: reduce) {
.not-found__glow,
.not-found__code,
.not-found__panel {
animation: none;
}
}
</style>