Files
Montech_Landing/apps/landing/components/SiteFooter.vue
T
MahdiandCursor 55e3b6a0e9 Wire landing footer contact info to site settings.
Admin phone/email/address/socials now drive the public footer instead of stale section JSON.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-30 21:36:43 +03:30

114 lines
4.0 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.
<template>
<footer id="contact" class="relative overflow-hidden border-t border-white/[0.07]">
<div class="border-b border-white/[0.07] py-8 md:py-10">
<SiteMarquee
:items="data.marquee || []"
:duration="20"
class-name="font-display text-xl font-bold md:text-3xl"
/>
</div>
<div class="mx-auto max-w-[1500px] px-6 py-20 md:px-10 md:py-28">
<SectionTag index="۰۶" :title="data.tag || 'تماس'" right="پاسخ تا ۲۴ ساعت" />
<div class="mt-14 grid gap-12 lg:grid-cols-[1.4fr_1fr]">
<div>
<h2 class="font-display text-[clamp(2.2rem,6vw,4.5rem)] font-extrabold leading-[1.15] tracking-[-0.02em]">
{{ data.cta || "شروع همکاری" }}
</h2>
<a
v-if="email"
:href="`mailto:${email}`"
class="mt-8 inline-flex items-center gap-3 border border-volt bg-volt px-6 py-3 text-sm text-ink transition hover:bg-transparent hover:text-volt"
dir="ltr"
>
{{ email }} ↗
</a>
</div>
<div class="grid gap-8 sm:grid-cols-3 lg:grid-cols-1">
<div>
<p class="text-xs text-ash">کسب‌وکار جدید</p>
<p v-if="email" class="mt-2 text-sm" dir="ltr">{{ email }}</p>
<p v-if="phone" class="text-sm text-ash" dir="ltr">{{ phone }}</p>
</div>
<div>
<p class="text-xs text-ash">استودیو</p>
<p v-for="line in addressLines" :key="line" class="mt-1 text-sm text-ash">{{ line }}</p>
</div>
<div>
<p class="text-xs text-ash">شبکه‌های اجتماعی</p>
<template v-if="socialLinks.length">
<a
v-for="s in socialLinks"
:key="s.label + s.url"
:href="s.url || undefined"
class="mt-1 block text-sm text-ash hover:text-volt"
:target="s.url ? '_blank' : undefined"
rel="noopener"
>{{ s.label }}</a>
</template>
<p v-else-if="legacySocials.length" v-for="s in legacySocials" :key="s" class="mt-1 text-sm text-ash">{{ s }}</p>
</div>
</div>
</div>
<div class="mt-20 flex flex-wrap items-center justify-between gap-4 border-t border-white/[0.07] pt-6 text-xs text-ash">
<span>© {{ year }} گروه نرم‌افزاری {{ brand || "منتک" }}</span>
<span>{{ brand || "منتک" }}®</span>
</div>
</div>
</footer>
</template>
<script setup lang="ts">
const props = defineProps<{
brand?: string;
email?: string;
phone?: string;
address?: string;
socials?: Array<{ label: string; url: string }>;
data: {
tag?: string;
marquee?: string[];
cta?: string;
email?: string;
phone?: string;
address?: string[] | string;
socials?: string[] | Array<{ label: string; url: string }>;
};
}>();
const year = new Date().getFullYear();
const email = computed(() => props.email || props.data.email || "");
const phone = computed(() => props.phone || props.data.phone || "");
const addressLines = computed(() => {
if (props.address) {
return props.address
.split(/\n|,/)
.map((s) => s.trim())
.filter(Boolean);
}
const a = props.data.address;
if (Array.isArray(a)) return a;
if (typeof a === "string") return a.split(/\n|,/).map((s) => s.trim()).filter(Boolean);
return [];
});
const socialLinks = computed(() => {
if (props.socials?.length) return props.socials.filter((s) => s.label);
const raw = props.data.socials;
if (!Array.isArray(raw) || !raw.length) return [];
if (typeof raw[0] === "object" && raw[0] !== null) {
return (raw as Array<{ label: string; url: string }>).filter((s) => s.label);
}
return [];
});
const legacySocials = computed(() => {
const raw = props.data.socials;
if (!Array.isArray(raw) || !raw.length) return [] as string[];
if (typeof raw[0] === "string") return raw as string[];
return [];
});
</script>