Files

127 lines
9.5 KiB
Vue
Raw Permalink 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.
<!-- Product-specific miniature interfaces, built from type and line, no screenshots to download. -->
<script setup lang="ts">
const props = defineProps<{ product: { fa: string; en: string; kind: string }; compact?: boolean }>();
const k = computed(() => props.product.kind);
const ledger = [["فروش آنلاین", "۱۲٬۴۰۰٬۰۰۰"], ["کارمزد درگاه", "۱۸۶٬۰۰۰"], ["مالیات بر ارزش افزوده", "۱٬۱۱۶٬۰۰۰"], ["حمل و ارسال", "۹۴۰٬۰۰۰"]];
const payroll = [["مریم احمدی", "۴۲٬۸۰۰٬۰۰۰"], ["علی رضایی", "۳۸٬۲۰۰٬۰۰۰"], ["سارا کریمی", "۳۶٬۵۰۰٬۰۰۰"], ["رضا موسوی", "۳۱٬۹۰۰٬۰۰۰"]];
const bars = [30, 42, 38, 55, 48, 62, 58, 70, 66, 80, 76, 92];
const store = [["کوزهٔ لعابی", "۸۲۰", "#2341B8"], ["گلیم ۲×۳", "۴٬۹۰۰", "#C2330F"], ["قوری مسی", "۱٬۲۵۰", "#14213A"]];
const services = [["auth", true], ["checkout", true], ["search", false], ["media", true]] as const;
const results = ["پیش‌نویس قرارداد اجاره — واحد حقوقی", "صورت‌جلسهٔ تمدید اجاره — شعبهٔ شیراز", "پیوست مالی قرارداد — ۱۴۰۲/۰۶"];
const wave = Array.from({ length: 48 }, (_, i) => Math.min(100, 18 + Math.abs(Math.sin(i * 1.7) * 60) + (i % 5) * 4));
const apps = [["دفتر", true], ["پیام", true], ["سنجه", false], ["بندر", true]] as const;
const buckets = [["media-prod", "۷۸%", "78%"], ["backups", "۵۲%", "52%"], ["logs-archive", "۳۱%", "31%"]];
const days = ["ش", "ی", "د", "س", "چ", "پ"];
const booked = new Set([1, 2, 7, 9, 10, 14, 15, 16, 20, 22]);
</script>
<template>
<figure class="flex flex-col overflow-hidden rounded-[12px] border border-ink/10 bg-surface text-ink" :class="compact ? 'h-[min(176px,22svh)]' : 'h-[min(270px,32vh)]'">
<figcaption class="flex items-center justify-between border-b border-ink/[0.07] px-4 py-[9px] text-[14px] text-mute">
<span>{{ product.fa }}</span>
<bdi dir="ltr" class="font-mono text-[13px] tracking-wide">{{ product.en.toLowerCase() }}.rasad.ir</bdi>
</figcaption>
<div class="min-h-0 flex-1 overflow-hidden" :class="compact ? 'p-3' : 'p-5'">
<div v-if="k === 'pay'" class="flex h-full flex-col justify-between">
<div>
<p class="text-[14px] text-mute">تسویهٔ امروز</p>
<p class="mt-1 text-[clamp(1.6rem,3vw,2.4rem)] font-extrabold leading-none">۲٬۴۸۰٬۰۰۰<span class="ms-2 text-[14px] font-normal text-mute">تومان</span></p>
</div>
<div class="flex h-16 items-end gap-[5px]">
<span v-for="(h, i) in bars" :key="i" class="flex-1 rounded-t-[2px]" :class="i === 11 ? 'bg-verm' : 'bg-lapis/25'" :style="{ height: h + '%' }" />
</div>
</div>
<div v-else-if="k === 'ledger' || k === 'payroll'" class="flex h-full flex-col justify-center gap-[10px] text-[14px]">
<div v-for="([a, b], i) in (k === 'ledger' ? ledger : payroll)" :key="i" class="flex items-center justify-between gap-3" :class="i < 3 ? 'border-b border-ink/[0.07] pb-[9px]' : ''">
<span>{{ a }}</span><span class="font-medium tabular-nums">{{ b }}</span>
</div>
</div>
<div v-else-if="k === 'store'" class="grid h-full grid-cols-3 gap-3">
<div v-for="[n, p, c] in store" :key="n" class="flex flex-col gap-2">
<div class="flex-1 rounded-[6px]" :style="{ background: `repeating-linear-gradient(135deg, ${c}22 0 6px, ${c}0d 6px 12px)` }" />
<p class="truncate text-[14px]">{{ n }}</p><p class="text-[14px] text-mute">{{ p }} هزار</p>
</div>
</div>
<div v-else-if="k === 'chart'" class="flex h-full flex-col gap-2">
<p class="text-[14px] text-mute">«فروش هفتگی تهران در برابر اصفهان»</p>
<svg viewBox="0 0 300 110" class="w-full flex-1" preserveAspectRatio="none" aria-hidden="true">
<line v-for="y in [20, 50, 80]" :key="y" x1="0" x2="300" :y1="y" :y2="y" stroke="#14213A" stroke-opacity=".08" />
<polyline fill="none" stroke="#2341B8" stroke-width="2" points="300,80 260,70 220,74 180,52 140,58 100,36 60,40 20,18" />
<polyline fill="none" stroke="#14213A" stroke-opacity=".35" stroke-width="1.5" stroke-dasharray="4 4" points="300,92 260,88 220,84 180,80 140,70 100,72 60,62 20,58" />
<circle cx="100" cy="36" r="4" fill="#C2330F" />
</svg>
</div>
<div v-else-if="k === 'monitor'" class="grid h-full grid-cols-2 gap-x-5 gap-y-3 text-[14px]">
<div v-for="[n, ok] in services" :key="n" class="flex flex-col justify-center gap-1">
<div class="flex items-center justify-between"><bdi dir="ltr" class="font-mono">{{ n }}</bdi><span :class="ok ? 'text-lapis' : 'text-verm'">{{ ok ? 'سالم' : 'کُند' }}</span></div>
<svg viewBox="0 0 100 24" class="h-6 w-full" preserveAspectRatio="none" aria-hidden="true">
<polyline fill="none" :stroke="ok ? '#2341B8' : '#C2330F'" stroke-width="1.5" :points="ok ? '0,16 15,14 30,17 45,12 60,15 75,13 100,14' : '0,18 20,16 40,15 55,6 70,9 85,4 100,7'" />
</svg>
</div>
</div>
<div v-else-if="k === 'search'" class="flex h-full flex-col gap-3 text-[14px]">
<div class="rounded-[6px] border border-ink/15 px-3 py-2">قرارداد اجارهٔ دفتر <span class="text-mute">۱۴۰۲</span></div>
<p v-for="t in results" :key="t" class="truncate"><mark class="bg-lapis/[0.12] text-inherit">{{ t.split(' ')[0] }}</mark> {{ t.split(' ').slice(1).join(' ') }}</p>
</div>
<div v-else-if="k === 'wave'" class="flex h-full flex-col justify-between gap-3">
<div class="flex h-14 items-center gap-[3px]">
<span v-for="(h, i) in wave" :key="i" class="flex-1 rounded-full" :class="i > 30 ? 'bg-ink/15' : 'bg-lapis'" :style="{ height: h + '%' }" />
</div>
<p class="text-[15px] leading-7">سلام، برای پیگیری سفارشم تماس گرفتم، <span class="rounded-[3px] bg-verm/[0.12] px-1 text-verm">کِی</span> می‌رسه؟</p>
</div>
<div v-else-if="k === 'terminal'" dir="ltr" class="flex h-full flex-col justify-center gap-[7px] text-left font-mono text-[14px]">
<p><span class="text-mute">$</span> bandar deploy --prod</p>
<p class="text-mute">build ······ 14.2s</p><p class="text-mute">health ····· 3/3 ok</p>
<p class="text-mute">traffic ···· 0 → 100%</p><p class="text-lapis">● live in 41s</p>
</div>
<div v-else-if="k === 'keys'" class="flex h-full flex-col justify-center gap-[10px] text-[14px]">
<div v-for="[n, on] in apps" :key="n" class="flex items-center justify-between">
<span>{{ n }}</span>
<span class="relative h-[18px] w-8 rounded-full" :class="on ? 'bg-lapis' : 'bg-ink/15'">
<span class="absolute top-[3px] h-3 w-3 rounded-full bg-white" :class="on ? 'end-[3px]' : 'start-[3px]'" />
</span>
</div>
</div>
<div v-else-if="k === 'storage'" class="flex h-full flex-col justify-center gap-3 text-[14px]">
<div v-for="[n, p, w] in buckets" :key="n" class="flex flex-col gap-[6px]">
<div class="flex items-center justify-between"><bdi dir="ltr" class="font-mono">{{ n }}</bdi><span class="text-mute">{{ p }}</span></div>
<span class="h-[6px] rounded-full bg-ink/[0.07]"><span class="block h-[6px] rounded-full bg-lapis" :style="{ width: w }" /></span>
</div>
</div>
<div v-else-if="k === 'api'" dir="ltr" class="flex h-full flex-col justify-center gap-[6px] text-left font-mono text-[14px]">
<p><span class="text-lapis">GET</span> /v2/orders/8841 <span class="text-mute">200 · 2.1ms</span></p>
<p class="text-mute">{</p><p class="ps-4">"status": <span class="text-verm">"shipped"</span>,</p><p class="ps-4">"city": "Tabriz"</p><p class="text-mute">}</p>
</div>
<div v-else-if="k === 'chat'" class="flex h-full flex-col justify-center gap-2 text-[14px]">
<p class="max-w-[80%] self-start rounded-[12px] rounded-ss-[3px] bg-ink/[0.06] px-3 py-2">نسخهٔ جدید «بندر» آماده است؟</p>
<p class="max-w-[80%] self-end rounded-[12px] rounded-se-[3px] bg-lapis px-3 py-2 text-white">بله، ساعت ۱۶ منتشر می‌شود.</p>
<p class="self-start text-mute">نیلوفر در حال نوشتن…</p>
</div>
<div v-else-if="k === 'calendar'" class="grid h-full grid-cols-6 gap-[5px] text-center text-[14px]">
<span v-for="d in days" :key="d" class="text-mute">{{ d }}</span>
<span v-for="i in 24" :key="i" class="rounded-[4px]" :class="i - 1 === 9 ? 'bg-verm' : booked.has(i - 1) ? 'bg-lapis/70' : 'bg-ink/[0.06]'" />
</div>
<svg v-else-if="k === 'map'" viewBox="0 0 300 140" class="h-full w-full" aria-hidden="true">
<line v-for="i in 7" :key="'v' + i" :x1="(i - 1) * 50" :x2="(i - 1) * 50 + 20" y1="0" y2="140" stroke="#14213A" stroke-opacity=".07" />
<line v-for="i in 4" :key="'h' + i" x1="0" x2="300" :y1="(i - 1) * 40 + 10" :y2="(i - 1) * 40 + 18" stroke="#14213A" stroke-opacity=".07" />
<path d="M280 120 C 240 110, 230 70, 190 72 S 130 40, 100 52 S 40 30, 22 20" fill="none" stroke="#2341B8" stroke-width="2.5" />
<circle v-for="([x, y], i) in [[280, 120], [190, 72], [100, 52], [22, 20]]" :key="i" :cx="x" :cy="y" :r="i === 3 ? 6 : 4"
:fill="i === 3 ? '#C2330F' : '#F8F9FB'" :stroke="i === 3 ? 'none' : '#2341B8'" stroke-width="2" />
</svg>
</div>
</figure>
</template>