Files
imen_pishghaman/app/components/sections/Testimonials.vue
T
s.esmaeiliandClaude Opus 4.6 bb7f1e3378 feat: update Dockerfile, add category pages, fonts and product images
Rebuild Docker setup with simplified nginx-only Dockerfile (build runs
on host). Add category detail pages, IRANSans font files, product
images, and update all landing sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-10-07 00:45:51 +03:30

95 lines
3.5 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 setup lang="ts">
import { AnimatePresence, motion } from "motion-v";
import { Quote } from "lucide-vue-next";
import SectionHead from "~/components/ui/SectionHead.vue";
const QUOTES = [
{
text: "ایمن پیشگامان فقط تأمین‌کننده نیست؛ شریک ایمنی ماست. بازرسی‌های دوره‌ای و آموزش‌های میدانی‌شان نرخ حوادث سایت را به کمترین رقم تاریخ مجموعه رساند.",
name: "مهندس رضا کاظمی",
role: "مدیر HSE — مجتمع پتروشیمی خلیج فارس",
},
{
text: "کیفیت تجهیزات و سرعت پاسخ‌گویی در سطحی بود که قرارداد سالانه را بدون هیچ تردیدی تمدید کردیم؛ از خط تولید تا دفتر مرکزی.",
name: "سارا محمدی",
role: "سرپرست تدارکات — هلدینگ ساختمانی آرکان",
},
{
text: "۱۴۰ کیلومتر دورتر از سایت، در عرض ۲۴ ساعت تجهیزات حیاتی را تحویل گرفتیم. به این می‌گویند شریک واقعی کاری.",
name: "امیرحسین راد",
role: "مدیر پروژه — صنایع معدنی کاوه",
},
];
const idx = ref(0);
const q = computed(() => QUOTES[idx.value]!);
let t: ReturnType<typeof setInterval> | undefined;
onMounted(() => {
t = setInterval(() => (idx.value = (idx.value + 1) % QUOTES.length), 7000);
});
onBeforeUnmount(() => clearInterval(t));
</script>
<template>
<section
aria-labelledby="testimonials-title"
class="relative overflow-hidden border-t border-line py-24 md:py-32"
>
<div class="absolute inset-0 bg-grid opacity-40" />
<div
class="pointer-events-none absolute -top-10 -end-10 select-none font-mono text-[18vw] font-bold leading-none text-outline opacity-50"
>
"
</div>
<div class="relative mx-auto max-w-4xl px-5 text-center md:px-8">
<SectionHead
heading-id="testimonials-title"
center
tag="۰۶ — اعتماد"
title="آنچه مشتریان ما می‌گویند"
/>
<div class="mt-14 flex min-h-[320px] flex-col items-center md:min-h-[280px]">
<span
class="flex size-16 items-center justify-center rounded-full border border-accent/30 bg-accent/10"
>
<Quote class="size-7 text-accent" />
</span>
<AnimatePresence mode="wait">
<motion.blockquote
:key="idx"
:initial="{ opacity: 0, y: 26 }"
:animate="{ opacity: 1, y: 0 }"
:exit="{ opacity: 0, y: -26 }"
:transition="{ duration: 0.55, ease: EASE }"
class="mt-8"
>
<p class="text-xl font-bold leading-[2.1] text-ink/90 md:text-2xl md:leading-[2]">
«{{ q.text }}»
</p>
<footer class="mt-8">
<div class="text-lg font-black">{{ q.name }}</div>
<div class="mt-2 font-mono text-xs text-muted">{{ q.role }}</div>
</footer>
</motion.blockquote>
</AnimatePresence>
</div>
<div class="mt-12 flex items-center justify-center gap-3">
<button
v-for="(_, i) in QUOTES"
:key="i"
:aria-label="`نظر شماره ${faNum(i + 1)}`"
:class="`h-1.5 rounded-full transition-all duration-500 ${
i === idx ? 'w-12 bg-accent' : 'w-4 bg-line hover:bg-muted'
}`"
@click="idx = i"
/>
</div>
</div>
</section>
</template>