@squadbase/vantage-template 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +112 -0
  2. package/base-template/.squadbase/skills/vantage-add-feature/SKILL.md +162 -0
  3. package/base-template/.squadbase/skills/vantage-app/SKILL.md +120 -0
  4. package/base-template/.squadbase/skills/vantage-pitfalls/SKILL.md +137 -0
  5. package/base-template/AGENTS.md +339 -0
  6. package/base-template/_404.tsx +18 -0
  7. package/base-template/_error.tsx +14 -0
  8. package/base-template/_gitignore +5 -0
  9. package/base-template/_layout.tsx +60 -0
  10. package/base-template/components/user-card.tsx +132 -0
  11. package/base-template/index.tsx +59 -0
  12. package/base-template/package.json +27 -0
  13. package/base-template/server/api/health.ts +12 -0
  14. package/base-template/squadbase.yml +5 -0
  15. package/base-template/styles.css +18 -0
  16. package/base-template/tsconfig.json +28 -0
  17. package/chart-presets/berry.css +16 -0
  18. package/chart-presets/blue.css +16 -0
  19. package/chart-presets/forest.css +16 -0
  20. package/chart-presets/mono.css +16 -0
  21. package/chart-presets/ocean.css +16 -0
  22. package/chart-presets/sunset.css +16 -0
  23. package/dist/index.js +1157 -0
  24. package/package.json +55 -0
  25. package/ui-templates/CLAUDE.md +200 -0
  26. package/ui-templates/blank/manifest.json +8 -0
  27. package/ui-templates/blank/pages/index.tsx +33 -0
  28. package/ui-templates/blank-ja/manifest.json +8 -0
  29. package/ui-templates/blank-ja/pages/index.tsx +33 -0
  30. package/ui-templates/chart-grid/lib/mock-data.ts +139 -0
  31. package/ui-templates/chart-grid/lib/types.ts +31 -0
  32. package/ui-templates/chart-grid/manifest.json +10 -0
  33. package/ui-templates/chart-grid/pages/index.tsx +331 -0
  34. package/ui-templates/chart-grid/preview-square.png +0 -0
  35. package/ui-templates/chart-grid/preview-wide.png +0 -0
  36. package/ui-templates/chart-grid-ja/lib/mock-data.ts +139 -0
  37. package/ui-templates/chart-grid-ja/lib/types.ts +31 -0
  38. package/ui-templates/chart-grid-ja/manifest.json +10 -0
  39. package/ui-templates/chart-grid-ja/pages/index.tsx +331 -0
  40. package/ui-templates/chart-grid-ja/preview-square.png +0 -0
  41. package/ui-templates/chart-grid-ja/preview-wide.png +0 -0
  42. package/ui-templates/funnel/components/chart-helpers.ts +11 -0
  43. package/ui-templates/funnel/components/stage-table.tsx +63 -0
  44. package/ui-templates/funnel/lib/mock-data.ts +22 -0
  45. package/ui-templates/funnel/lib/types.ts +11 -0
  46. package/ui-templates/funnel/manifest.json +12 -0
  47. package/ui-templates/funnel/pages/index.tsx +252 -0
  48. package/ui-templates/funnel/preview-square.png +0 -0
  49. package/ui-templates/funnel/preview-wide.png +0 -0
  50. package/ui-templates/funnel-ja/components/chart-helpers.ts +11 -0
  51. package/ui-templates/funnel-ja/components/stage-table.tsx +63 -0
  52. package/ui-templates/funnel-ja/lib/mock-data.ts +22 -0
  53. package/ui-templates/funnel-ja/lib/types.ts +11 -0
  54. package/ui-templates/funnel-ja/manifest.json +12 -0
  55. package/ui-templates/funnel-ja/pages/index.tsx +251 -0
  56. package/ui-templates/funnel-ja/preview-square.png +0 -0
  57. package/ui-templates/funnel-ja/preview-wide.png +0 -0
  58. package/ui-templates/kpi-chart-advanced/components/campaign-table.tsx +69 -0
  59. package/ui-templates/kpi-chart-advanced/lib/mock-data.ts +109 -0
  60. package/ui-templates/kpi-chart-advanced/lib/types.ts +38 -0
  61. package/ui-templates/kpi-chart-advanced/manifest.json +11 -0
  62. package/ui-templates/kpi-chart-advanced/pages/index.tsx +339 -0
  63. package/ui-templates/kpi-chart-advanced/preview-square.png +0 -0
  64. package/ui-templates/kpi-chart-advanced/preview-wide.png +0 -0
  65. package/ui-templates/kpi-chart-advanced-ja/components/campaign-table.tsx +69 -0
  66. package/ui-templates/kpi-chart-advanced-ja/lib/mock-data.ts +109 -0
  67. package/ui-templates/kpi-chart-advanced-ja/lib/types.ts +38 -0
  68. package/ui-templates/kpi-chart-advanced-ja/manifest.json +11 -0
  69. package/ui-templates/kpi-chart-advanced-ja/pages/index.tsx +333 -0
  70. package/ui-templates/kpi-chart-advanced-ja/preview-square.png +0 -0
  71. package/ui-templates/kpi-chart-advanced-ja/preview-wide.png +0 -0
  72. package/ui-templates/kpi-chart-simple/components/top-items-table.tsx +73 -0
  73. package/ui-templates/kpi-chart-simple/lib/types.ts +44 -0
  74. package/ui-templates/kpi-chart-simple/manifest.json +11 -0
  75. package/ui-templates/kpi-chart-simple/pages/index.tsx +200 -0
  76. package/ui-templates/kpi-chart-simple/preview-square.png +0 -0
  77. package/ui-templates/kpi-chart-simple/preview-wide.png +0 -0
  78. package/ui-templates/kpi-chart-simple/server/kpi-summary.ts +141 -0
  79. package/ui-templates/kpi-chart-simple-ja/components/top-items-table.tsx +73 -0
  80. package/ui-templates/kpi-chart-simple-ja/lib/types.ts +44 -0
  81. package/ui-templates/kpi-chart-simple-ja/manifest.json +11 -0
  82. package/ui-templates/kpi-chart-simple-ja/pages/index.tsx +200 -0
  83. package/ui-templates/kpi-chart-simple-ja/preview-square.png +0 -0
  84. package/ui-templates/kpi-chart-simple-ja/preview-wide.png +0 -0
  85. package/ui-templates/kpi-chart-simple-ja/server/kpi-summary.ts +141 -0
  86. package/ui-templates/table-focus/components/detail-table.tsx +88 -0
  87. package/ui-templates/table-focus/lib/mock-data.ts +69 -0
  88. package/ui-templates/table-focus/lib/types.ts +24 -0
  89. package/ui-templates/table-focus/manifest.json +11 -0
  90. package/ui-templates/table-focus/pages/index.tsx +180 -0
  91. package/ui-templates/table-focus/preview-square.png +0 -0
  92. package/ui-templates/table-focus/preview-wide.png +0 -0
  93. package/ui-templates/table-focus-ja/components/detail-table.tsx +95 -0
  94. package/ui-templates/table-focus-ja/lib/mock-data.ts +69 -0
  95. package/ui-templates/table-focus-ja/lib/types.ts +24 -0
  96. package/ui-templates/table-focus-ja/manifest.json +11 -0
  97. package/ui-templates/table-focus-ja/pages/index.tsx +180 -0
  98. package/ui-templates/table-focus-ja/preview-square.png +0 -0
  99. package/ui-templates/table-focus-ja/preview-wide.png +0 -0
@@ -0,0 +1,69 @@
1
+ import type { DetailRow, SummaryRow, TrendPoint } from "./types"
2
+
3
+ export const detailRows: DetailRow[] = [
4
+ { id: "row-01", name: "項目1", owner: "担当者1", status: "active", category: "カテゴリ1", revenue: 111569, units: 630, margin: 24.7, updated: "2024-03-26" },
5
+ { id: "row-02", name: "項目2", owner: "担当者2", status: "active", category: "カテゴリ2", revenue: 64510, units: 1418, margin: 42.8, updated: "2024-03-24" },
6
+ { id: "row-03", name: "項目3", owner: "担当者3", status: "active", category: "カテゴリ3", revenue: 178768, units: 700, margin: 27.3, updated: "2024-03-29" },
7
+ { id: "row-04", name: "項目4", owner: "担当者4", status: "paused", category: "カテゴリ4", revenue: 108664, units: 541, margin: 27.4, updated: "2024-03-24" },
8
+ { id: "row-05", name: "項目5", owner: "担当者5", status: "draft", category: "カテゴリ5", revenue: 89259, units: 453, margin: 41.7, updated: "2024-03-25" },
9
+ { id: "row-06", name: "項目6", owner: "担当者6", status: "active", category: "カテゴリ1", revenue: 171912, units: 1271, margin: 35.2, updated: "2024-03-31" },
10
+ { id: "row-07", name: "項目7", owner: "担当者1", status: "active", category: "カテゴリ2", revenue: 46499, units: 1024, margin: 43.3, updated: "2024-03-18" },
11
+ { id: "row-08", name: "項目8", owner: "担当者2", status: "active", category: "カテゴリ3", revenue: 90305, units: 624, margin: 39.3, updated: "2024-03-20" },
12
+ { id: "row-09", name: "項目9", owner: "担当者3", status: "paused", category: "カテゴリ4", revenue: 123575, units: 804, margin: 49.1, updated: "2024-03-27" },
13
+ { id: "row-10", name: "項目10", owner: "担当者4", status: "draft", category: "カテゴリ5", revenue: 191742, units: 2477, margin: 29.4, updated: "2024-03-26" },
14
+ { id: "row-11", name: "項目11", owner: "担当者5", status: "active", category: "カテゴリ1", revenue: 174313, units: 682, margin: 25.1, updated: "2024-03-26" },
15
+ { id: "row-12", name: "項目12", owner: "担当者6", status: "active", category: "カテゴリ2", revenue: 140422, units: 592, margin: 26.2, updated: "2024-03-21" },
16
+ { id: "row-13", name: "項目13", owner: "担当者1", status: "active", category: "カテゴリ3", revenue: 171059, units: 765, margin: 39.3, updated: "2024-03-26" },
17
+ { id: "row-14", name: "項目14", owner: "担当者2", status: "paused", category: "カテゴリ4", revenue: 127951, units: 542, margin: 20.4, updated: "2024-03-20" },
18
+ { id: "row-15", name: "項目15", owner: "担当者3", status: "draft", category: "カテゴリ5", revenue: 169122, units: 1824, margin: 19.8, updated: "2024-03-20" },
19
+ { id: "row-16", name: "項目16", owner: "担当者4", status: "active", category: "カテゴリ1", revenue: 91117, units: 479, margin: 30.2, updated: "2024-03-21" },
20
+ { id: "row-17", name: "項目17", owner: "担当者5", status: "active", category: "カテゴリ2", revenue: 57885, units: 249, margin: 46.5, updated: "2024-03-21" },
21
+ { id: "row-18", name: "項目18", owner: "担当者6", status: "active", category: "カテゴリ3", revenue: 156340, units: 1804, margin: 19.5, updated: "2024-03-27" },
22
+ { id: "row-19", name: "項目19", owner: "担当者1", status: "paused", category: "カテゴリ4", revenue: 58582, units: 471, margin: 23.5, updated: "2024-03-31" },
23
+ { id: "row-20", name: "項目20", owner: "担当者2", status: "draft", category: "カテゴリ5", revenue: 70782, units: 411, margin: 28.7, updated: "2024-03-19" },
24
+ { id: "row-21", name: "項目21", owner: "担当者3", status: "active", category: "カテゴリ1", revenue: 48743, units: 334, margin: 46.3, updated: "2024-03-18" },
25
+ { id: "row-22", name: "項目22", owner: "担当者4", status: "active", category: "カテゴリ2", revenue: 180121, units: 1042, margin: 40.5, updated: "2024-03-18" },
26
+ { id: "row-23", name: "項目23", owner: "担当者5", status: "active", category: "カテゴリ3", revenue: 113309, units: 562, margin: 20.4, updated: "2024-03-19" },
27
+ { id: "row-24", name: "項目24", owner: "担当者6", status: "paused", category: "カテゴリ4", revenue: 112999, units: 574, margin: 25.8, updated: "2024-03-27" },
28
+ ]
29
+
30
+ export const summaryRows: SummaryRow[] = [
31
+ { segment: "カテゴリ3", count: 5, revenue: 709781, avgMargin: 29.2, share: 0.2491 },
32
+ { segment: "カテゴリ1", count: 5, revenue: 597654, avgMargin: 32.3, share: 0.2097 },
33
+ { segment: "カテゴリ4", count: 5, revenue: 531771, avgMargin: 29.2, share: 0.1866 },
34
+ { segment: "カテゴリ5", count: 4, revenue: 520905, avgMargin: 29.9, share: 0.1828 },
35
+ { segment: "カテゴリ2", count: 5, revenue: 489437, avgMargin: 39.9, share: 0.1718 },
36
+ ]
37
+
38
+ export const trendSeries: TrendPoint[] = [
39
+ { date: "2024-03-02", value: 20590 },
40
+ { date: "2024-03-03", value: 19289 },
41
+ { date: "2024-03-04", value: 23339 },
42
+ { date: "2024-03-05", value: 20609 },
43
+ { date: "2024-03-06", value: 23415 },
44
+ { date: "2024-03-07", value: 25849 },
45
+ { date: "2024-03-08", value: 25114 },
46
+ { date: "2024-03-09", value: 22860 },
47
+ { date: "2024-03-10", value: 24511 },
48
+ { date: "2024-03-11", value: 24606 },
49
+ { date: "2024-03-12", value: 26125 },
50
+ { date: "2024-03-13", value: 21827 },
51
+ { date: "2024-03-14", value: 27583 },
52
+ { date: "2024-03-15", value: 23709 },
53
+ { date: "2024-03-16", value: 26295 },
54
+ { date: "2024-03-17", value: 24547 },
55
+ { date: "2024-03-18", value: 24112 },
56
+ { date: "2024-03-19", value: 28416 },
57
+ { date: "2024-03-20", value: 23997 },
58
+ { date: "2024-03-21", value: 23835 },
59
+ { date: "2024-03-22", value: 24690 },
60
+ { date: "2024-03-23", value: 28432 },
61
+ { date: "2024-03-24", value: 25377 },
62
+ { date: "2024-03-25", value: 29616 },
63
+ { date: "2024-03-26", value: 28354 },
64
+ { date: "2024-03-27", value: 25239 },
65
+ { date: "2024-03-28", value: 27696 },
66
+ { date: "2024-03-29", value: 26262 },
67
+ { date: "2024-03-30", value: 25920 },
68
+ { date: "2024-03-31", value: 27428 },
69
+ ]
@@ -0,0 +1,24 @@
1
+ export interface DetailRow {
2
+ id: string
3
+ name: string
4
+ owner: string
5
+ status: "active" | "paused" | "draft"
6
+ category: string
7
+ revenue: number
8
+ units: number
9
+ margin: number
10
+ updated: string
11
+ }
12
+
13
+ export interface SummaryRow {
14
+ segment: string
15
+ count: number
16
+ revenue: number
17
+ avgMargin: number
18
+ share: number
19
+ }
20
+
21
+ export interface TrendPoint {
22
+ date: string
23
+ value: number
24
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "table-focus-ja",
3
+ "description": "[日本語] テーブル重視 — ヘッダーに検索+エクスポート、ステータスフィルタチップ、詳細テーブル(24行以上、ソート可)を主役とし、右サイドにトレンドチャートとセグメント内訳を配置する作業画面構成",
4
+ "version": "0.1.0",
5
+ "files": [
6
+ { "src": "pages/index.tsx", "dest": "index.tsx", "action": "replace" },
7
+ { "src": "components/detail-table.tsx", "dest": "components/table-focus/detail-table.tsx", "action": "add" },
8
+ { "src": "lib/mock-data.ts", "dest": "components/table-focus/mock-data.ts", "action": "add", "relabel": false },
9
+ { "src": "lib/types.ts", "dest": "components/table-focus/types.ts", "action": "add", "relabel": false }
10
+ ]
11
+ }
@@ -0,0 +1,180 @@
1
+ import { useMemo, useState } from "react"
2
+ import { Download, Search } from "lucide-react"
3
+
4
+ import { definePage } from "@squadbase/vantage"
5
+ import {
6
+ DashboardCardPreset,
7
+ EChart,
8
+ PageShell,
9
+ PageShellContent,
10
+ PageShellDescription,
11
+ PageShellHeader,
12
+ PageShellHeaderEnd,
13
+ PageShellHeading,
14
+ PageShellTitle,
15
+ Placeholder,
16
+ type EChartsOption,
17
+ } from "@squadbase/vantage/components"
18
+ import { Button, Input, ToggleGroup, ToggleGroupItem } from "@squadbase/vantage/ui"
19
+
20
+ import { DetailTable } from "./components/table-focus/detail-table"
21
+ import {
22
+ detailRows,
23
+ summaryRows,
24
+ trendSeries,
25
+ } from "./components/table-focus/mock-data"
26
+ import type { DetailRow, TrendPoint } from "./components/table-focus/types"
27
+
28
+ export const page = definePage({
29
+ title: "レコード",
30
+ description:
31
+ "ヘッダーに検索+エクスポート、ステータスフィルタチップ、ソート可能な詳細テーブルを主役とし、右サイドにトレンドチャートとセグメント内訳を配置する作業画面構成。",
32
+ })
33
+
34
+ // ── chart helpers ───────────────────────────────────────────────────────────
35
+
36
+ function getBaseGrid() {
37
+ return { left: "3%", right: "4%", bottom: "10%", containLabel: true }
38
+ }
39
+
40
+ function formatNumber(n: number): string {
41
+ const sign = n < 0 ? "-" : ""
42
+ const abs = Math.abs(n)
43
+ if (abs >= 100_000_000) return `${sign}${(abs / 100_000_000).toFixed(1)}億`
44
+ if (abs >= 10_000) return `${sign}${(abs / 10_000).toFixed(0)}万`
45
+ return n.toLocaleString("ja-JP")
46
+ }
47
+
48
+ // ── chart options ────────────────────────────────────────────────────────────
49
+
50
+ function trendOption(data: TrendPoint[]): EChartsOption {
51
+ return {
52
+ tooltip: { trigger: "axis" },
53
+ legend: { bottom: 0 },
54
+ grid: getBaseGrid(),
55
+ xAxis: {
56
+ type: "category",
57
+ data: data.map((d) => d.date),
58
+ boundaryGap: false,
59
+ axisLabel: { formatter: (v: string) => v.slice(5) },
60
+ },
61
+ yAxis: { type: "value", axisLabel: { formatter: (v: number) => formatNumber(v) } },
62
+ series: [
63
+ {
64
+ name: "系列A",
65
+ type: "line",
66
+ smooth: true,
67
+ showSymbol: false,
68
+ data: data.map((d) => d.value),
69
+ areaStyle: { opacity: 0.18 },
70
+ },
71
+ ],
72
+ }
73
+ }
74
+
75
+ // ── page ─────────────────────────────────────────────────────────────────────
76
+
77
+ type StatusFilter = "all" | DetailRow["status"]
78
+
79
+ export default function HomePage() {
80
+ const [query, setQuery] = useState("")
81
+ const [status, setStatus] = useState<StatusFilter>("all")
82
+
83
+ const filtered = useMemo(() => {
84
+ const q = query.trim().toLowerCase()
85
+ return detailRows.filter((r) => {
86
+ if (status !== "all" && r.status !== status) return false
87
+ if (q && !r.name.toLowerCase().includes(q) && !r.owner.toLowerCase().includes(q)) return false
88
+ return true
89
+ })
90
+ }, [query, status])
91
+
92
+ return (
93
+ <PageShell>
94
+ <PageShellHeader>
95
+ <PageShellHeading>
96
+ <PageShellTitle>[テンプレート] レコード</PageShellTitle>
97
+ <PageShellDescription>
98
+ 全レコードを閲覧・絞り込み・検索できます。
99
+ </PageShellDescription>
100
+ </PageShellHeading>
101
+ <PageShellHeaderEnd className="flex-row items-center gap-2">
102
+ <div className="relative">
103
+ <Search className="pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
104
+ <Input
105
+ value={query}
106
+ onChange={(e) => setQuery(e.target.value)}
107
+ placeholder="検索..."
108
+ className="h-9 w-64 pl-8"
109
+ />
110
+ </div>
111
+ <Button variant="outline" size="sm" className="gap-1.5">
112
+ <Download className="size-4" />
113
+ </Button>
114
+ </PageShellHeaderEnd>
115
+ </PageShellHeader>
116
+
117
+ <PageShellContent className="space-y-4">
118
+ <div className="flex flex-wrap items-center justify-between gap-3">
119
+ {/* Base UI の ToggleGroup は単一選択でも value が配列 */}
120
+ <ToggleGroup
121
+ value={[status]}
122
+ onValueChange={(values) => {
123
+ const next = values[0]
124
+ if (next) setStatus(next as StatusFilter)
125
+ }}
126
+ variant="outline"
127
+ size="sm"
128
+ >
129
+ <ToggleGroupItem value="all">すべて</ToggleGroupItem>
130
+ <ToggleGroupItem value="active">選択肢A</ToggleGroupItem>
131
+ <ToggleGroupItem value="paused">選択肢B</ToggleGroupItem>
132
+ <ToggleGroupItem value="draft">選択肢C</ToggleGroupItem>
133
+ </ToggleGroup>
134
+ <span className="text-xs text-muted-foreground">
135
+ {filtered.length} 件
136
+ </span>
137
+ </div>
138
+
139
+ <div className="grid gap-4 lg:grid-cols-3">
140
+ <div className="lg:col-span-2">
141
+ <DashboardCardPreset
142
+ title="レコード"
143
+ description="現在のフィルタに該当する行"
144
+ >
145
+ <DetailTable data={filtered} />
146
+ </DashboardCardPreset>
147
+ </div>
148
+ <div className="space-y-4">
149
+ <DashboardCardPreset
150
+ title="トレンド"
151
+ description="選択期間の値"
152
+ >
153
+ <EChart option={trendOption(trendSeries)} height="220px" />
154
+ </DashboardCardPreset>
155
+ <DashboardCardPreset title="セグメント別" description="全体に占める割合">
156
+ <div className="space-y-3">
157
+ {summaryRows.map((row) => (
158
+ <div key={row.segment} className="space-y-1.5">
159
+ <div className="flex items-baseline justify-between">
160
+ <span className="text-sm font-medium">{row.segment}</span>
161
+ <Placeholder className="text-sm">
162
+ {row.revenue.toLocaleString("ja-JP")}
163
+ </Placeholder>
164
+ </div>
165
+ <div className="h-1.5 overflow-hidden rounded-full bg-muted">
166
+ <div
167
+ className="h-full rounded-full bg-primary"
168
+ style={{ width: `${(row.share * 100).toFixed(1)}%` }}
169
+ />
170
+ </div>
171
+ </div>
172
+ ))}
173
+ </div>
174
+ </DashboardCardPreset>
175
+ </div>
176
+ </div>
177
+ </PageShellContent>
178
+ </PageShell>
179
+ )
180
+ }