Full 1:1 migration preserving all visuals, animations and behavior: - Nuxt 4 + Vue 3 (script setup, TypeScript strict) with SSG output - Tailwind CSS v4 with @tailwindcss/vite - Ant Design Vue 4 (dark theme, RTL, Persian locale) for design system - Pinia for state management (ui + contact stores) - motion-v (framer-motion port) for all animations - lucide-vue-next for icons - SEO improvements: og:image, canonical fix, real 404 page, JSON-LD services - JS bundle reduced from 302KB to 239KB gzip - Docker/nginx deployment preserved (out/ -> nginx) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
79 lines
2.2 KiB
Vue
79 lines
2.2 KiB
Vue
<script setup lang="ts">
|
|
import { motion } from "motion-v";
|
|
import { ShieldCheck } from "lucide-vue-next";
|
|
|
|
const STEPS = [
|
|
"بررسی سیستمهای ایمنی",
|
|
"تأیید استانداردهای بینالمللی",
|
|
"بارگذاری تجهیزات حفاظت فردی",
|
|
"محیط کاری آماده است",
|
|
];
|
|
|
|
const emit = defineEmits<{ complete: [] }>();
|
|
|
|
const progress = ref(0);
|
|
let done = false;
|
|
let t: ReturnType<typeof setInterval> | undefined;
|
|
|
|
onMounted(() => {
|
|
let v = 0;
|
|
t = setInterval(() => {
|
|
v += Math.floor(Math.random() * 11) + 7;
|
|
if (v >= 100) {
|
|
v = 100;
|
|
clearInterval(t);
|
|
if (!done) {
|
|
done = true;
|
|
setTimeout(() => emit("complete"), 450);
|
|
}
|
|
}
|
|
progress.value = v;
|
|
}, 140);
|
|
});
|
|
onBeforeUnmount(() => clearInterval(t));
|
|
|
|
const step = computed(
|
|
() =>
|
|
STEPS[
|
|
Math.min(STEPS.length - 1, Math.floor((progress.value / 100) * STEPS.length))
|
|
],
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<motion.div
|
|
:exit="{ y: '-100%' }"
|
|
:transition="{ duration: 0.85, ease: [0.76, 0, 0.24, 1] }"
|
|
class="fixed inset-0 z-[200] flex flex-col items-center justify-center bg-bg"
|
|
>
|
|
<div class="hazard absolute inset-x-0 top-0 h-3" />
|
|
<div class="hazard absolute inset-x-0 bottom-0 h-3" />
|
|
|
|
<div class="flex items-center gap-4">
|
|
<span class="flex size-12 items-center justify-center rounded-xl bg-accent text-bg">
|
|
<ShieldCheck class="size-7" />
|
|
</span>
|
|
<span class="font-mono text-xs tracking-[0.35em] text-muted">
|
|
ARIA IMEN CO.
|
|
</span>
|
|
</div>
|
|
|
|
<div class="mt-12 font-mono text-7xl font-semibold tabular-nums md:text-8xl">
|
|
{{ progress.toLocaleString("fa-IR") }}<span class="text-accent">٪</span>
|
|
</div>
|
|
|
|
<div class="mt-8 h-[3px] w-64 overflow-hidden rounded-full bg-line md:w-80">
|
|
<div
|
|
class="h-full bg-accent transition-all duration-200"
|
|
:style="{ width: `${progress}%` }"
|
|
/>
|
|
</div>
|
|
|
|
<div class="mt-6 flex items-center gap-3 text-xs text-muted">
|
|
<span class="size-1.5 animate-pulse rounded-full bg-accent" />
|
|
{{ step }}
|
|
<span class="animate-blink text-accent">▍</span>
|
|
</div>
|
|
</motion.div>
|
|
</template>
|