// Sygnal app mockups — recreated to match the latest actual UI at sygnal-main/frontend. // Nav, copy, components, and color tokens all follow the real frontend. /* ───────── Icons (lucide-react style: stroke = currentColor) ───────── */ const Icon = ({ d, size = 15, fill = "none", strokeWidth = 1.8, viewBox = "0 0 24 24", children }) => ( {d ? : children} ); const IconDatabase = (p) => ; const IconList = (p) => ; const IconSend = (p) => ; const IconTrendingUp = (p) => ; const IconSparkles = (p) => ; const IconBan = (p) => ; const IconSettings = (p) => ; const IconBuilding = (p) => ; const IconCheck = (p) => ; const IconCheckCircle = (p) => ; const IconXCircle = (p) => ; const IconAlertTriangle = (p) => ; const IconClock = (p) => ; const IconShield = (p) => ; const IconSearch = (p) => ; const IconFilter = (p) => ; const IconChevronRight = (p) => ; const IconChevronDown = (p) => ; const IconPlay = (p) => ; const IconPause = (p) => ; const IconArrowRight = (p) => ; const IconLink = (p) => ; const IconCursor = (p) => ; const IconCalendar = (p) => ; const IconUser = (p) => ; const IconTarget = (p) => ; const IconHelp = (p) => ; const IconExternal = (p) => ; const IconDot = ({ color = "#16A34A" }) => ( ); /* ───────── Sygnal brand mark (3 vertical bars — matches real frontend) ───────── */ const Mark = ({ scale = 1 }) => ( ); /* ───────── Generic window chrome ───────── Renders at a fixed PC size (1440x900) inside a landscape frame that is scaled down to fit its container, so the screenshot keeps a real desktop-browser aspect ratio instead of going portrait. */ const WinChrome = ({ addr = "app.sygnal.jp", children }) => (
{addr}
{children}
); /* ───────── Shared sidebar (matches layout.tsx menuItems) ───────── */ const Sidebar = ({ active = "campaigns" }) => { const items = [ { key: "database", label: "企業データベース", Ic: IconDatabase }, { key: "lists", label: "リスト管理", Ic: IconList }, { key: "campaigns", label: "案件管理", Ic: IconSend }, { key: "sales-management", label: "営業管理", Ic: IconTrendingUp }, { key: "insights", label: "AI分析", Ic: IconSparkles }, { key: "ng-companies", label: "NG企業", Ic: IconBan }, { key: "settings", label: "設定", Ic: IconSettings }, ]; return ( ); }; /* ───────── shared styles ───────── */ const panel = { border: "1px solid #E5E5E5", borderRadius: 8, background: "#fff", overflow: "hidden" }; const panelHead = { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "11px 14px", borderBottom: "1px solid #f0f0f0", background: "#fff" }; const th = { padding: "8px 14px", fontWeight: 400, color: "#666", fontSize: 11 }; const td = { padding: "10px 14px", verticalAlign: "middle" }; const btnGhost = { display: "inline-flex", alignItems: "center", gap: 6, padding: "6px 10px", borderRadius: 4, border: "1px solid #E5E5E5", background: "#fff", fontSize: 11.5, color: "#666", cursor: "default" }; const btnPrimary = { ...btnGhost, background: "#111", color: "#fff", borderColor: "#111" }; /* ───────── Status badge (matches campaign-status.ts) ───────── */ const StatusBadge = ({ status }) => { const map = { "実行中": { bg: "#F0FDF4", fg: "#16A34A", border: "#D1FAE5" }, "一時停止": { bg: "#FFFBEB", fg: "#D97706", border: "#FDE68A" }, "完了": { bg: "#F5F5F5", fg: "#666", border: "#E5E5E5" }, "待機": { bg: "#EFF6FF", fg: "#2563EB", border: "#DBEAFE" }, "下書き": { bg: "#F5F5F5", fg: "#999", border: "#E5E5E5" }, "予約済み": { bg: "#EFF6FF", fg: "#2563EB", border: "#DBEAFE" }, }; const c = map[status] || map["完了"]; return ( {status === "実行中" && } {status} ); }; /* ============================================================ 1) HERO — Campaign Detail (案件詳細) in running state ============================================================ */ const HeroCampaignDetail = () => { // Match the actual campaign-detail UI: title row, tabs (成功/失敗/スキップ/AI生成結果/タイムライン), success rate progress const total = 1284, success = 942, failed = 218, skipped = 47; const sent = success + failed + skipped; const pct = (n) => ((n / total) * 100).toFixed(1); const sentPct = ((sent / total) * 100).toFixed(0); // Recent send history const rows = [ { n: "株式会社グランドワークス", url: "grandworks.co.jp", at: "16:42", state: "success" }, { n: "サンライズ工業株式会社", url: "sunrise-ind.jp", at: "16:40", state: "success" }, { n: "Helix Robotics株式会社", url: "helix-robotics.jp", at: "16:38", state: "clicked" }, { n: "ミライ食品株式会社", url: "mirai-foods.co.jp", at: "16:36", state: "failed" }, { n: "株式会社オリオン物流", url: "orion-logistics.jp", at: "16:34", state: "skipped" }, { n: "アクシス精機株式会社", url: "axis-seiki.co.jp", at: "16:32", state: "success" }, { n: "Crest Medical株式会社", url: "crestmed.jp", at: "16:30", state: "success" }, ]; const stateChip = (s) => { if (s === "success") return 成功; if (s === "clicked") return クリック; if (s === "failed") return 失敗; if (s === "skipped") return スキップ; return null; }; // Bars data const bars = [12, 22, 31, 38, 42, 36, 44, 51, 48, 43, 38, 32, 24, 14]; const maxBar = Math.max(...bars); return (
{/* Breadcrumb */}
案件管理2026年Q2 製造業アタック
{/* Header */}

2026年Q2 製造業アタック

商材: 自社サービスA · リスト: 製造業_関東_50-300名(1,284社) · 開始: 4/12 09:00
{/* KPI strip — matches campaign-detail style: 進捗 + 件数 ribbon */}
{/* Progress stacked bar */}
{/* Tabs — matches latest campaign-detail.tsx */}
{["送信文面", "成功の詳細", "失敗の詳細", "スキップの詳細", "クリック企業"].map((t, i) => (
{t}
))}
{/* Two-column area */}
{/* Send volume chart */}
送信ボリューム — 直近14時間
1時間ごと
{bars.map((b, i) => = 12 ? .4 : 1 }} />)}
03:0009:0015:0021:00
{/* Failure reason breakdown */}
失敗・スキップ理由
本日
{/* Send history table */}
送信履歴
すべて 成功 失敗
{rows.map((r, i) => ( ))}
企業ドメイン送信時刻結果
{r.n} {r.url} {r.at} {stateChip(r.state)}
); }; /* Small atoms */ const chip = { display: "inline-flex", alignItems: "center", gap: 5, fontSize: 11, padding: "3px 8px", borderRadius: 4, background: "#F5F5F5", color: "#666", fontWeight: 400, border: "1px solid #E5E5E5" }; const Kpi = ({ label, value, sub, tone }) => { const color = tone === "green" ? "#16A34A" : tone === "red" ? "#DC2626" : tone === "amber" ? "#D97706" : "#111"; return (
{label}
{value}
{sub}
); }; const ReasonRow = ({ label, v, max, tone, last }) => (
{label}{v}件
); /* ============================================================ 2) DATABASE — 企業データベース ============================================================ */ const DatabaseMock = () => { const companies = [ { n: "株式会社グランドワークス", ind: "建設業", area: "東京都港区", emp: "120名", rev: "23億", status: "未送信" }, { n: "サンライズ工業株式会社", ind: "製造業 / 金属加工", area: "神奈川県川崎市", emp: "84名", rev: "12億", status: "送信済" }, { n: "Helix Robotics株式会社", ind: "製造業 / 産業機械", area: "東京都品川区", emp: "240名", rev: "58億", status: "クリック" }, { n: "ミライ食品株式会社", ind: "製造業 / 食品", area: "埼玉県さいたま市", emp: "67名", rev: "8億", status: "NG企業", ng: true }, { n: "Crest Medical株式会社", ind: "製造業 / 医療機器", area: "東京都中央区", emp: "310名", rev: "94億", status: "未送信" }, { n: "株式会社ノーザンライト", ind: "小売業", area: "北海道札幌市", emp: "52名", rev: "6億", status: "未送信" }, { n: "アクシス精機株式会社", ind: "製造業 / 精密機械", area: "長野県諏訪市", emp: "180名", rev: "31億", status: "送信済" }, { n: "株式会社トウカイ電子", ind: "製造業 / 電子部品", area: "愛知県名古屋市", emp: "210名", rev: "44億", status: "クリック" }, { n: "明和樹脂工業株式会社", ind: "製造業 / 樹脂成形", area: "大阪府東大阪市", emp: "96名", rev: "15億", status: "未送信" }, { n: "株式会社ブルーポート物流", ind: "運輸業", area: "兵庫県神戸市", emp: "148名", rev: "27億", status: "送信済" }, { n: "日峰メディカル株式会社", ind: "製造業 / 医療機器", area: "福岡県福岡市", emp: "275名", rev: "71億", status: "未送信" }, { n: "株式会社セイワ製作所", ind: "製造業 / 金属加工", area: "静岡県浜松市", emp: "63名", rev: "9億", status: "未送信" }, { n: "クロスフィールド株式会社", ind: "情報通信業", area: "東京都渋谷区", emp: "88名", rev: "18億", status: "送信済" }, ]; return (

企業データベース

日々更新される法人データベースから市場を条件抽出

{/* Filter chips */}
+ 条件を追加
{/* Search and results meta */}
1,284社 がヒット · 13社 選択中
{/* Table */}
{companies.map((c, i) => ( ))}
企業名 業種 所在地 従業員 売上高 送信状況
{c.n} {c.ind} {c.area} {c.emp} {c.rev} {c.status === "クリック" ? クリック : c.status === "送信済" ? 送信済 : c.status === "NG企業" ? NG企業 : 未送信}
); }; const FilterChip = ({ label, value }) => ( {label}: {value} ); /* ============================================================ 3) AI MESSAGE — Phase 2 文面作成(AI文面生成 / 手動入力) Matches the actual campaign-wizard/phase3-message.tsx UI: - messageMode radio: AI文面生成 / 手動入力 - 文字数制限に応じて2パターン生成 checkbox - トラッキングURL選択 (LP / 日程調整 / 資料DL) toggle chips - generated subject / body preview with 500文字未満用 / 500文字以上用 tabs ============================================================ */ const AIMessageMock = () => { return (
案件作成Phase 2文面作成
{/* Wizard step indicator — 3 phases (matches latest wizard) */}
{[ { n: 1, t: "基本情報", done: true }, { n: 2, t: "文面作成", done: false, active: true }, { n: 3, t: "送信設定", done: false }, ].map((s, i) => (
{s.done ? : s.n} {s.t}
{i < 2 &&
} ))}

文面作成

送信する文面を作成します
{/* Two columns so the screen fits a real 1440x900 desktop window */}
{/* LEFT — mode + generation settings */}
文面生成方法
AI文面生成
送信先に合わせた文面をAIが作成します。
手動入力
自分で作成した文面を全企業に送信します。
{/* AI generation settings */}
AI文面生成
AIが文面を作成します
文字数制限に応じて2パターン生成
500文字未満用と500文字以上用の2種類の文面を生成します
AIに含めるトラッキングURL
2/4件 選択中
{/* RIGHT — generated content */}
生成完了 - 内容を確認・編集してください
件名
製造業のリード獲得をAIで自動化するご提案
本文 2パターン生成済み
500文字未満用
500文字以上用
💡500文字未満の問い合わせフォームで使用されます
製造業のご担当者様

突然のご連絡失礼いたします。
貴社ホームページを拝見し、ご連絡いたしました。

営業リードを増やしたい中堅製造業様向けに、
AIによるフォーム営業の自動化サービスをご案内しています。

同規模10社で平均3.4倍の問い合わせ獲得を実現しています。
ご興味があれば15分でご案内可能です。

▼日程調整はこちら
https://timerex.net/s/example
418 / 500文字推奨 OK

各企業の問い合わせフォームの文字数制限に応じて、最適な文面が自動選択されます

); }; /* TrackUrlRow — tracking URL toggle chips inside AI panel */ const TrackUrlRow = ({ icon, label, items }) => (
{icon} {label}
{items.map((it, i) => ( {it.name} ))}
); /* ============================================================ 4) INSIGHTS — AI分析(攻めるべき市場 × 刺さる訴求 × 推奨アクション) ============================================================ */ const InsightsMock = () => { // Recommendation badge config — matches insights-dashboard.tsx RECOMMENDATION_CONFIG const recBadge = (r) => { const m = { expand: { l: "伸ばす", bg: "#F0FDF4", fg: "#10B981", border: "#BBF7D0" }, maintain: { l: "維持", bg: "#EFF6FF", fg: "#3B82F6", border: "#BFDBFE" }, reduce: { l: "絞る", bg: "#FEF2F2", fg: "#EF4444", border: "#FECACA" }, test: { l: "テスト", bg: "#FEF3C7", fg: "#F59E0B", border: "#FDE68A" }, }[r]; return {m.l}; }; const priorityBadge = (p) => { const m = { high: { l: "高", bg: "#FEF2F2", fg: "#EF4444" }, medium: { l: "中", bg: "#FEF3C7", fg: "#F59E0B" }, low: { l: "低", bg: "#F0FDF4", fg: "#10B981" }, }[p]; return {m.l}; }; const segments = [ { seg: "医療機器", success: 96, click: 12, score: 87, rec: "expand" }, { seg: "産業機械", success: 94, click: 9, score: 76, rec: "expand" }, { seg: "食品製造", success: 89, click: 7, score: 64, rec: "maintain" }, { seg: "建設業", success: 82, click: 5, score: 52, rec: "maintain" }, { seg: "小売業", success: 71, click: 3, score: 38, rec: "reduce" }, ]; const patterns = [ { cr: 14, count: 6, top: true, flow: [ { k: "objective", v: "日程調整誘導" }, { k: "problem", v: "営業リード不足" }, { k: "value", v: "数字で効果実証" }, { k: "trust", v: "導入120社" }, { k: "cta", v: "15分カレンダー" }, ], bd: [["医療機器", 18], ["産業機械", 12]], }, { cr: 9, count: 8, top: true, flow: [ { k: "objective", v: "資料DL誘導" }, { k: "problem", v: "人手不足" }, { k: "value", v: "工数1/10" }, { k: "cta", v: "資料DL" }, ], bd: [["産業機械", 11], ["建設業", 6]], }, ]; const actions = [ { cat: "market", seg: "業種 / 医療機器", title: "医療機器セグメントを次回優先で抽出", reason: "成功率96%・有望度87と他セグメント比2.1倍。300社規模で集中アタックを推奨。", pri: "high" }, { cat: "appeal", seg: "訴求 / 数字実証 + 15分CTA", title: "件名に「導入事例の数字」を含める運用に統一", reason: "数字訴求パターンのクリック率が他比 +3.4pt。", pri: "medium" }, { cat: "combined", seg: "送信時間 / 火・水 10:00-11:30", title: "送信ウィンドウを午前帯に絞る", reason: "クリック発生時刻の62%が10:00〜11:30台に集中。", pri: "medium" }, ]; const catIc = (c) => c === "market" ? : c === "appeal" ? : ; const tagBg = (k) => ({ objective: { bg: "#FEF3C7", fg: "#92400E" }, problem: { bg: "#FEE2E2", fg: "#991B1B" }, value: { bg: "#DBEAFE", fg: "#1D4ED8" }, trust: { bg: "#D1FAE5", fg: "#065F46" }, cta: { bg: "#E9D5FF", fg: "#6D28D9" }, }[k]); return (

AI分析

送信結果をAIが分析し、効果的な営業戦略を提案します

直近28日
全期間
{/* KPI cards */}
} label="送信成功率" value="89%" color="#16A34A" /> } label="クリック率" value="8%" color="#3B82F6" /> } label="案件数" value="14" color="#111" /> } label="最終更新" value="5/12 14:32" color="#666" small />
{/* Two columns: 攻めるべき市場 / 刺さる訴求 */}
{/* 攻めるべき市場 */}
攻めるべき市場
業種
従業員規模
エリア
{segments.map((s, i) => ( ))}
セグメント 成功率 クリック率 有望度 推奨
{s.seg} {s.success}% {s.click}% {s.score} {recBadge(s.rec)}
AI分析: 医療機器・産業機械セグメントの有望度が突出。次回案件はこの2セグメントへ集中投下を推奨します。
{/* 刺さる訴求 */}
刺さる訴求
{patterns.map((p, i) => (
#{i + 1} クリック率 {p.cr}% / {p.count}キャンペーン
{p.flow.map((f, j) => ( {j > 0 && } {f.v} ))}
{p.bd.map(([seg, cr], k) => ( {seg}: {cr}% ))}
))}
{/* 今週の推奨アクション */}
今週の推奨アクション
{actions.map((a, i) => (
{catIc(a.cat)}{a.seg} {priorityBadge(a.pri)}

{a.title}

{a.reason}

))}
); }; const KpiInsight = ({ ic, label, value, color, small }) => (
{ic}{label}
{value}
); /* ============================================================ 5) SALES — 営業管理(カンバン) ============================================================ */ const SalesMock = () => { const cols = [ { stage: "クリック", count: 14, color: "#3B82F6", cards: [ { n: "Crest Medical株式会社", ind: "製造業 / 医療機器", at: "8分前", asg: "田中" }, { n: "サンライズ工業株式会社", ind: "製造業 / 金属加工", at: "32分前", asg: "佐藤" }, { n: "アクシス精機株式会社", ind: "製造業 / 精密機械", at: "1時間前", asg: "田中" }, { n: "株式会社トウカイ電子", ind: "製造業 / 電子部品", at: "3時間前", asg: "鈴木" }, { n: "日峰メディカル株式会社", ind: "製造業 / 医療機器", at: "5時間前", asg: "佐藤" }, { n: "株式会社ヤマト計測機器", ind: "製造業 / 精密機械", at: "本日 09:12", asg: "未割当" }, ]}, { stage: "アプローチ中", count: 6, color: "#F59E0B", cards: [ { n: "株式会社ノーザンライト", ind: "小売業", at: "本日 11:30", asg: "佐藤" }, { n: "ミライ食品株式会社", ind: "製造業 / 食品", at: "昨日", asg: "田中" }, { n: "クロスフィールド株式会社", ind: "情報通信業", at: "2日前", asg: "鈴木" }, { n: "三葉化成工業株式会社", ind: "製造業 / 化学", at: "3日前", asg: "田中" }, ]}, { stage: "商談化", count: 3, color: "#8B5CF6", cards: [ { n: "Helix Robotics株式会社", ind: "製造業 / 産業機械", at: "2日前", asg: "田中", amount: "¥1,800,000" }, { n: "明和樹脂工業株式会社", ind: "製造業 / 樹脂成形", at: "4日前", asg: "佐藤", amount: "¥960,000" }, { n: "株式会社ブルーポート物流", ind: "運輸業", at: "1週間前", asg: "鈴木", amount: "¥1,200,000" }, ]}, { stage: "成約", count: 2, color: "#10B981", cards: [ { n: "株式会社グランドワークス", ind: "建設業", at: "1週間前", asg: "佐藤", amount: "¥2,400,000" }, { n: "株式会社アペックス空調", ind: "建設業 / 設備", at: "3週間前", asg: "田中", amount: "¥1,650,000" }, ]}, ]; return (

営業管理

クリックのあった企業の営業進捗を、カンバンで一元管理

カンバン
リスト
{/* Kanban */}
{cols.map((c, i) => (
{c.stage}
{c.count}件
{c.cards.map((card, j) => (
{card.n}
{card.ind}
{card.at} {card.asg}
{card.amount && (
{card.amount}
)}
))}
))}
); }; /* ───────── Render hero into slot ───────── */ const heroSlot = document.getElementById("hero-window-slot"); if (heroSlot) ReactDOM.createRoot(heroSlot).render(); // Expose to sections script (precheck removed — no longer in product) window.SygnalMocks = { DatabaseMock, AIMessageMock, InsightsMock, SalesMock, HeroCampaignDetail }; /* ───────── Scale each fixed 1440x900 window to fit its container ───────── */ (function () { const W = 1440; const fit = () => document.querySelectorAll('.mock-frame').forEach(f => { const inner = f.querySelector('.mock-scale'); if (inner && f.clientWidth) inner.style.transform = 'scale(' + (f.clientWidth / W) + ')'; }); const mo = new MutationObserver(fit); mo.observe(document.body, { childList: true, subtree: true }); window.addEventListener('resize', fit); fit(); [50, 200, 600, 1500].forEach(t => setTimeout(fit, t)); })();