بلاک‌ها · معرفی محصول

لندینگِ معاملهٔ هوشمند

پیش‌نمایش تمام‌صفحه

لندینگِ سفید و آبی برای پلتفرمِ معامله با عامل‌های هوشمند: پیش‌نمایشِ گفت‌وگو و گردش‌کارِ گره‌ای، کادرِ امتحان با پیشنهادها، منابعِ داده، کارت‌های پرسش با نمودار، سه اصلِ کنترل، پلن‌ها و فراخوان.

۱. نصب کامپوننت‌ها

این بلاک از ۸ آیتم دیگ استفاده می‌کند: badgebuttonchart-presetscontrol-sizeiconsprompt-inputrevealtoggle-group

پکیج‌منیجر پیش‌فرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیج‌منیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/chart-presets.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/prompt-input.json https://docs.digdesign.ir/r/reveal.json https://docs.digdesign.ir/r/toggle-group.json
pnpm dlx digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/chart-presets.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/prompt-input.json https://docs.digdesign.ir/r/reveal.json https://docs.digdesign.ir/r/toggle-group.json
yarn dlx digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/chart-presets.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/prompt-input.json https://docs.digdesign.ir/r/reveal.json https://docs.digdesign.ir/r/toggle-group.json
bunx --bun digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/chart-presets.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/prompt-input.json https://docs.digdesign.ir/r/reveal.json https://docs.digdesign.ir/r/toggle-group.json

۲. کد صفحه

کد را در app/<route>/page.tsx بگذارید و متن‌ها، داده و هندلرها را با محصول خودتان عوض کنید.

landing-trading.tsx
"use client"

import * as React from "react"

import { ArrowUpIcon, BarChartIcon, CheckIcon, EyeOffIcon, FlashIcon, GlobeIcon, ShieldCheckIcon, SparklesIcon, TrendingUpIcon } from "@/components/icons"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { AreaChart } from "@/components/ui/chart-presets"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { PromptInput, PromptInputSubmitButton, PromptInputTextarea, PromptInputToolbar, PromptInputTools } from "@/components/ui/prompt-input"
import { Reveal } from "@/components/ui/reveal"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { cn } from "@/lib/utils"

const SUGGESTIONS = ["اگر طلا ٪۲ افت کرد، بخر", "هر روز گزارشِ سبد را بفرست", "سهامِ پربازده‌ترِ هفته", "هشدارِ نوسانِ دلار"]
const PRICE = [
  { t: "۹", v: 182 },
  { t: "۱۰", v: 186 },
  { t: "۱۱", v: 184 },
  { t: "۱۲", v: 191 },
  { t: "۱۳", v: 189 },
  { t: "۱۴", v: 196 },
  { t: "۱۵", v: 201 },
]
const SOURCES = ["بورسِ تهران", "فرابورس", "بورسِ کالا", "بازارِ طلا", "صرافیِ ملی", "صندوق‌ها"]
const PLANS = [
  { name: "شروع", month: 290, text: "برای امتحانِ ایده‌ها روی معاملهٔ آزمایشی.", features: ["۳ عاملِ فعال", "دادهٔ تأخیری", "معاملهٔ آزمایشی"], featured: false },
  { name: "حرفه‌ای", month: 790, text: "برای معامله‌گرِ فعال با دادهٔ لحظه‌ای.", features: ["۲۰ عاملِ فعال", "دادهٔ لحظه‌ای", "اتصال به کارگزاری", "هشدارِ پیامکی"], featured: true },
  { name: "سبدگردان", month: 2390, text: "برای تیم و صندوق با سقفِ بالا.", features: ["عاملِ نامحدود", "چند حساب", "گزارشِ حسابرسی", "پشتیبانیِ اختصاصی"], featured: false },
]

/**
 * لندینگِ پلتفرمِ معاملهٔ هوشمند، سفید و آبی: هیرو با پیش‌نمایشِ اپ (گفت‌وگو و گردش‌کارِ
 * گره‌ای)، کادرِ «امتحان کن» با پیشنهادها، شبکهٔ منابعِ داده، کارت‌های «بپرس، نمودار بگیر» با
 * نمودارِ واقعی، سه اصلِ کنترل، پلن‌ها با سوییچِ ماهانه/سالانه و فراخوانِ پایانی.
 */
export default function LandingTradingBlock() {
  const [prompt, setPrompt] = React.useState("")
  const [billing, setBilling] = React.useState("month")

  return (
    <ControlSizeProvider size="xl" asChild>
      <main className="flex w-full flex-col">
        <section className="mx-auto grid w-full max-w-6xl grid-cols-1 gap-6 px-4 pt-20 sm:px-6 lg:grid-cols-[1.2fr_1fr] lg:items-end">
          <div className="flex flex-col items-start gap-5">
            <Badge color="info" variant="soft">
              تازه: عامل‌های چندمرحله‌ای
            </Badge>
            <h1 className="text-4xl leading-tight font-black text-balance sm:text-6xl sm:leading-tight">پلتفرمِ معاملهٔ هوشمند</h1>
          </div>
          <div className="flex flex-col items-start gap-4">
            <p className="leading-8 text-muted-foreground">ایده‌ات را به زبانِ ساده بگو؛ عامل‌ها داده را می‌خوانند، استراتژی را آزمایش می‌کنند و با اجازهٔ تو معامله می‌کنند.</p>
            <Button className="[--primary-foreground:var(--dig-white)] [--primary:var(--dig-blue-600)]">
              شروعِ رایگان
              <ArrowUpIcon aria-hidden className="-rotate-45" />
            </Button>
          </div>
        </section>

        <Reveal className="mx-auto mt-12 w-full max-w-6xl px-4 sm:px-6">
          <div className="grid grid-cols-1 gap-3 rounded-xl border border-border bg-subtle p-3 shadow-xl md:grid-cols-[18rem_1fr]">
            <div className="flex flex-col gap-3 rounded-lg bg-card p-4">
              <span className="text-xs text-muted-foreground">گفت‌وگو</span>
              <p className="rounded-lg bg-muted p-3 text-sm leading-6">اگر قیمتِ طلا زیرِ میانگینِ ۲۰ روزه رفت، با ٪۱۰ سبد بخر و حدِ ضرر ٪۳ بگذار.</p>
              <p className="flex items-start gap-2 text-sm leading-6 text-muted-foreground">
                <SparklesIcon aria-hidden className="mt-1 size-4 shrink-0 text-[var(--dig-blue-600)]" />
                استراتژی ساخته شد. روی دادهٔ دو سالِ اخیر ٪۱۸ بازده داشت. اجرا کنم؟
              </p>
              <div className="mt-auto flex gap-2">
                <Button size="sm" className="[--primary-foreground:var(--dig-white)] [--primary:var(--dig-blue-600)]">
                  اجرا
                </Button>
                <Button size="sm" variant="outline">
                  ویرایش
                </Button>
              </div>
            </div>
            <div aria-hidden className="relative min-h-72 overflow-hidden rounded-lg bg-card bg-[radial-gradient(var(--border)_1px,transparent_1px)] [background-size:16px_16px]">
              {[
                { x: "8%", y: "18%", label: "دادهٔ طلا", icon: <BarChartIcon /> },
                { x: "40%", y: "42%", label: "میانگینِ ۲۰ روزه", icon: <TrendingUpIcon /> },
                { x: "70%", y: "16%", label: "شرطِ خرید", icon: <FlashIcon /> },
                { x: "66%", y: "70%", label: "سفارشِ خرید", icon: <CheckIcon /> },
              ].map((node, index) => (
                <span
                  key={node.label}
                  className={cn(
                    "absolute flex items-center gap-2 rounded-lg border bg-card px-3 py-2 text-xs font-semibold shadow-sm [&>svg]:size-4",
                    index === 3 ? "border-[var(--dig-blue-500)] text-[var(--dig-blue-700)] dark:text-[var(--dig-blue-300)]" : "border-border"
                  )}
                  style={{ insetInlineStart: node.x, top: node.y }}
                >
                  {node.icon}
                  {node.label}
                </span>
              ))}
              <svg className="absolute inset-0 size-full" viewBox="0 0 100 100" preserveAspectRatio="none">
                <path d="M22 26 C 32 26 34 48 42 48 M58 48 C 66 48 66 24 72 24 M80 30 C 84 50 78 60 74 74" fill="none" strokeWidth="0.4" strokeDasharray="1.5 1" className="stroke-[var(--dig-blue-400)]" />
              </svg>
            </div>
          </div>
        </Reveal>

        <section aria-labelledby="lt-try" className="mx-auto flex w-full max-w-3xl flex-col items-center gap-6 px-4 py-24 text-center sm:px-6">
          <h2 id="lt-try" className="text-3xl font-black sm:text-4xl">
            امتحانش کن، رایگان است
          </h2>
          <p className="text-muted-foreground">یک استراتژی بنویس؛ پیش از هر معامله، نتیجه‌اش روی گذشته را می‌بینی.</p>
          <PromptInput value={prompt} onValueChange={setPrompt} className="w-full text-start">
            <PromptInputTextarea placeholder="مثلاً: هر وقت دلار از ۹۰ هزار بالاتر رفت خبرم کن" />
            <PromptInputToolbar>
              <PromptInputTools />
              <PromptInputSubmitButton />
            </PromptInputToolbar>
          </PromptInput>
          <div className="flex flex-wrap justify-center gap-2">
            {SUGGESTIONS.map((item) => (
              <Button key={item} size="sm" variant="outline" radius="full" onClick={() => setPrompt(item)}>
                {item}
              </Button>
            ))}
          </div>
        </section>

        <section aria-labelledby="lt-data" className="bg-subtle px-4 py-20 sm:px-6">
          <div className="mx-auto flex w-full max-w-6xl flex-col gap-10">
            <div className="flex max-w-xl flex-col gap-3">
              <h2 id="lt-data" className="text-3xl font-black sm:text-4xl">
                همهٔ داده‌ای که عامل‌ها لازم دارند
              </h2>
              <p className="text-muted-foreground">قیمتِ لحظه‌ای، صورت‌های مالی و اخبار، از منابعِ رسمی و یکپارچه.</p>
            </div>
            <ul className="grid grid-cols-2 gap-px overflow-hidden rounded-xl border border-border bg-border md:grid-cols-3">
              {SOURCES.map((source) => (
                <li key={source} className="flex items-center gap-3 bg-card p-6 font-bold">
                  <span aria-hidden className="flex size-9 items-center justify-center rounded-lg bg-[var(--dig-blue-100)] text-[var(--dig-blue-700)] dark:bg-[var(--dig-blue-950)] dark:text-[var(--dig-blue-300)]">
                    <GlobeIcon className="size-4" />
                  </span>
                  {source}
                </li>
              ))}
            </ul>
          </div>
        </section>

        <section aria-labelledby="lt-ask" className="mx-auto flex w-full max-w-6xl flex-col gap-10 px-4 py-24 sm:px-6">
          <h2 id="lt-ask" className="max-w-xl text-3xl font-black sm:text-4xl">
            بپرس، نمودار بگیر
          </h2>
          <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
            <div className="flex flex-col gap-4 rounded-xl border border-border bg-card p-5">
              <span className="self-end rounded-full bg-[var(--dig-blue-600)] px-3 py-1.5 text-sm text-[var(--dig-white)]">طلا امروز چطور بود؟</span>
              <div className="flex items-baseline gap-2">
                <span className="text-2xl font-black tabular-nums">۲۰۱ میلیون</span>
                <span className="text-sm font-semibold text-success-subtle-foreground">+٪۱٫۸</span>
              </div>
              <AreaChart className="h-40" data={PRICE} categoryKey="t" series={[{ key: "v", label: "قیمت", color: "var(--dig-blue-500)" }]} smooth showPoints={false} hideValueAxis showGrid={false} />
            </div>
            <div className="flex flex-col gap-4 rounded-xl border border-border bg-card p-5">
              <span className="self-end rounded-full bg-[var(--dig-blue-600)] px-3 py-1.5 text-sm text-[var(--dig-white)]">سبدم کجا ریسک دارد؟</span>
              <ul className="flex flex-col gap-3">
                {[
                  ["سهامِ پالایشی", 46, true],
                  ["طلا", 28, false],
                  ["صندوقِ درآمد ثابت", 18, false],
                  ["نقد", 8, false],
                ].map(([label, value, risky]) => (
                  <li key={String(label)} className="flex flex-col gap-1.5">
                    <span className="flex justify-between text-sm">
                      <span className="flex items-center gap-2">
                        {label}
                        {risky && (
                          <Badge color="warning" variant="soft" size="sm">
                            تمرکزِ بالا
                          </Badge>
                        )}
                      </span>
                      <span className="tabular-nums">٪{String(value).replace(/\d/g, (d) => "۰۱۲۳۴۵۶۷۸۹"[Number(d)])}</span>
                    </span>
                    <span aria-hidden className="h-2 overflow-hidden rounded-full bg-muted">
                      <span className={cn("block h-full rounded-full", risky ? "bg-[var(--dig-amber-500)]" : "bg-[var(--dig-blue-500)]")} style={{ width: `${value}%` }} />
                    </span>
                  </li>
                ))}
              </ul>
            </div>
          </div>
        </section>

        <section aria-labelledby="lt-control" className="mx-auto grid w-full max-w-6xl grid-cols-1 gap-8 border-t border-border px-4 py-20 sm:px-6 md:grid-cols-3">
          <h2 id="lt-control" className="sr-only">
            کنترل دستِ شماست
          </h2>
          {[
            { icon: <ShieldCheckIcon />, title: "بدونِ دسترسی به پول", text: "عامل فقط سفارش ثبت می‌کند؛ برداشت و انتقال ممکن نیست." },
            { icon: <EyeOffIcon />, title: "خصوصی، به‌طورِ پیش‌فرض", text: "استراتژی‌ها رمزگذاری می‌شوند و برای آموزشِ مدل استفاده نمی‌شوند." },
            { icon: <CheckIcon />, title: "با اجازهٔ شما", text: "سقفِ مبلغ و تأییدِ پیامکی برای هر معاملهٔ بزرگ." },
          ].map((item) => (
            <div key={item.title} className="flex flex-col gap-3">
              <span aria-hidden className="flex size-10 items-center justify-center rounded-lg bg-muted [&>svg]:size-5">
                {item.icon}
              </span>
              <h3 className="font-bold">{item.title}</h3>
              <p className="text-sm leading-6 text-muted-foreground">{item.text}</p>
            </div>
          ))}
        </section>

        <section aria-labelledby="lt-plans" className="mx-auto flex w-full max-w-6xl flex-col gap-10 px-4 py-20 sm:px-6">
          <div className="flex flex-col justify-between gap-4 md:flex-row md:items-end">
            <h2 id="lt-plans" className="text-3xl font-black sm:text-4xl">
              پلنِ مناسبِ استراتژی‌ات
            </h2>
            <ToggleGroup type="single" variant="segmented" value={billing} onValueChange={(value) => value && setBilling(value as string)} aria-label="دورهٔ پرداخت">
              <ToggleGroupItem value="month">ماهانه</ToggleGroupItem>
              <ToggleGroupItem value="year">سالانه، دو ماه رایگان</ToggleGroupItem>
            </ToggleGroup>
          </div>
          <ul className="grid grid-cols-1 gap-4 md:grid-cols-3">
            {PLANS.map((plan) => {
              const price = billing === "year" ? Math.round((plan.month * 10) / 12) : plan.month
              return (
                <li
                  key={plan.name}
                  className={cn(
                    "flex flex-col gap-6 rounded-xl border p-6",
                    plan.featured ? "border-transparent bg-[var(--dig-blue-600)] text-[var(--dig-white)] [--muted-foreground:var(--dig-blue-50)]" : "border-border bg-card"
                  )}
                >
                  <div className="flex flex-col gap-2">
                    <span className="flex items-center justify-between font-bold">
                      {plan.name}
                      {plan.featured && <span className="rounded-full bg-[var(--dig-white)] px-2.5 py-0.5 text-xs text-[var(--dig-blue-700)]">پرطرفدار</span>}
                    </span>
                    <span className="text-sm leading-6 text-muted-foreground">{plan.text}</span>
                  </div>
                  <span className="flex items-baseline gap-1.5">
                    <span className="text-4xl font-black tabular-nums">{price.toLocaleString("fa-IR")}</span>
                    <span className="text-sm text-muted-foreground">هزار تومان / ماه</span>
                  </span>
                  <Button fullWidth variant={plan.featured ? "default" : "outline"} className={cn(plan.featured && "[--primary-foreground:var(--dig-blue-700)] [--primary:var(--dig-white)]")}>
                    شروع
                  </Button>
                  <ul className="flex flex-col gap-2.5 text-sm">
                    {plan.features.map((feature) => (
                      <li key={feature} className="flex items-center gap-2">
                        <CheckIcon aria-hidden className="size-4" />
                        {feature}
                      </li>
                    ))}
                  </ul>
                </li>
              )
            })}
          </ul>
        </section>

        <section className="mx-auto flex w-full max-w-6xl flex-col items-start justify-between gap-6 border-t border-border px-4 py-20 sm:px-6 md:flex-row md:items-end">
          <h2 className="max-w-md text-3xl leading-snug font-black sm:text-4xl">اولین استراتژی‌ات را بنویس و امروز اجرا کن</h2>
          <div className="flex gap-3">
            <Button variant="outline">تماس با فروش</Button>
            <Button className="[--primary-foreground:var(--dig-white)] [--primary:var(--dig-blue-600)]">شروعِ رایگان</Button>
          </div>
        </section>
      </main>
    </ControlSizeProvider>
  )
}