Skip to content

Commit cc0c89b

Browse files
committed
chore(apollo-vertex): Prompt card
1 parent f1290a0 commit cc0c89b

3 files changed

Lines changed: 273 additions & 109 deletions

File tree

apps/apollo-vertex/templates/dashboard/DashboardContent.tsx

Lines changed: 106 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client";
22

33
import { useState } from "react";
4+
import { Badge } from "@/components/ui/badge";
45
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
56
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
67
import { DashboardGlow } from "./DashboardGlow";
@@ -109,6 +110,98 @@ function InsightGrid({
109110
);
110111
}
111112

113+
// --- Prompt bar ---
114+
115+
function PromptBar({ shared, cards }: { shared: string; cards: CardConfig }) {
116+
const [value, setValue] = useState("");
117+
const hasInput = value.trim().length > 0;
118+
119+
return (
120+
<div className="group rounded-2xl p-[2px] focus-within:bg-gradient-to-r focus-within:from-insight-500/75 focus-within:to-primary-400/75 transition-all">
121+
{/* Suggestion pills */}
122+
<div className="grid grid-rows-[0fr] focus-within:grid-rows-[1fr] group-focus-within:grid-rows-[1fr] transition-[grid-template-rows] duration-300">
123+
<div className="overflow-hidden">
124+
<div className="px-3 pt-2 pb-2 flex gap-2">
125+
<Badge
126+
variant="secondary"
127+
status="info"
128+
className="!bg-white/35 !text-foreground opacity-0 translate-y-2 group-focus-within:opacity-100 group-focus-within:translate-y-0 transition-all duration-300 cursor-pointer"
129+
>
130+
Show me top risk factors
131+
</Badge>
132+
<Badge
133+
variant="secondary"
134+
status="info"
135+
className="!bg-white/35 !text-foreground opacity-0 translate-y-2 group-focus-within:opacity-100 group-focus-within:translate-y-0 transition-all duration-300 delay-75 cursor-pointer"
136+
>
137+
Compare Q1 vs Q2 performance
138+
</Badge>
139+
</div>
140+
</div>
141+
</div>
142+
{/* Input */}
143+
<div
144+
className={`flex items-center rounded-[14px] px-4 py-3 !bg-white/80 backdrop-blur-sm transition-colors ${shared}`}
145+
style={cardBgStyle(
146+
cards.promptBg,
147+
cards.promptOpacity,
148+
cards.promptGradient,
149+
)}
150+
>
151+
<input
152+
type="text"
153+
value={value}
154+
onChange={(e) => setValue(e.target.value)}
155+
placeholder="What would you like to understand about loan performance?"
156+
className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
157+
/>
158+
<div className="flex items-center gap-2 ml-3">
159+
<button
160+
type="button"
161+
className="text-muted-foreground hover:text-foreground transition-colors"
162+
aria-label="Voice input"
163+
>
164+
<svg
165+
xmlns="http://www.w3.org/2000/svg"
166+
viewBox="0 0 24 24"
167+
fill="none"
168+
stroke="currentColor"
169+
strokeWidth="2"
170+
strokeLinecap="round"
171+
strokeLinejoin="round"
172+
className="size-4"
173+
>
174+
<path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" />
175+
<path d="M19 10v2a7 7 0 0 1-14 0v-2" />
176+
<line x1="12" x2="12" y1="19" y2="22" />
177+
</svg>
178+
</button>
179+
<button
180+
type="button"
181+
disabled={!hasInput}
182+
className="size-8 rounded-full bg-gradient-to-br from-insight-500 to-primary-400 flex items-center justify-center text-white transition-opacity disabled:opacity-30"
183+
aria-label="Submit"
184+
>
185+
<svg
186+
xmlns="http://www.w3.org/2000/svg"
187+
viewBox="0 0 24 24"
188+
fill="none"
189+
stroke="currentColor"
190+
strokeWidth="2"
191+
strokeLinecap="round"
192+
strokeLinejoin="round"
193+
className="size-4"
194+
>
195+
<path d="m5 12 7-7 7 7" />
196+
<path d="M12 19V5" />
197+
</svg>
198+
</button>
199+
</div>
200+
</div>
201+
</div>
202+
);
203+
}
204+
112205
// --- Layout renderers ---
113206

114207
function ExecutiveLayout({
@@ -124,18 +217,12 @@ function ExecutiveLayout({
124217
const gapStyle = { gap: `${layout.gap}px` };
125218

126219
return (
127-
<div className="grid grid-cols-1 lg:grid-cols-2" style={gapStyle}>
220+
<div className="grid grid-cols-1 lg:grid-cols-2 h-full" style={gapStyle}>
128221
{/* Left half */}
129-
<div
130-
className="grid"
131-
style={{
132-
...gapStyle,
133-
gridTemplateRows: `${layout.overviewRatio}fr ${layout.promptRatio}fr`,
134-
}}
135-
>
222+
<div className="flex flex-col" style={gapStyle}>
136223
<Card
137224
variant="glass"
138-
className={`!bg-white ${shared}`}
225+
className={`!bg-white flex-1 ${shared}`}
139226
style={cardBgStyle(
140227
cards.overviewBg,
141228
cards.overviewOpacity,
@@ -155,26 +242,7 @@ function ExecutiveLayout({
155242
<p>Avg. deal cycle: 32 days (-4 days)</p>
156243
</CardContent>
157244
</Card>
158-
<Card
159-
variant="glass"
160-
className={`!bg-white/80 ${shared}`}
161-
style={cardBgStyle(
162-
cards.promptBg,
163-
cards.promptOpacity,
164-
cards.promptGradient,
165-
)}
166-
>
167-
<CardHeader>
168-
<CardTitle className="text-sm font-bold tracking-tight">
169-
Conversational Prompt Bar
170-
</CardTitle>
171-
</CardHeader>
172-
<CardContent className="text-sm text-muted-foreground">
173-
<div className="rounded-md border px-3 py-2 bg-muted/50">
174-
Ask a question about your data...
175-
</div>
176-
</CardContent>
177-
</Card>
245+
<PromptBar shared={shared} cards={cards} />
178246
</div>
179247
{/* Right half — insight grid */}
180248
<InsightGrid layout={layout} shared={shared} cards={cards} />
@@ -214,7 +282,7 @@ export function DashboardContent() {
214282

215283
return (
216284
<div
217-
className="relative"
285+
className="relative h-full"
218286
style={
219287
layoutCfg.containerBg === "none"
220288
? {}
@@ -231,7 +299,7 @@ export function DashboardContent() {
231299
onLayoutChange={setLayoutCfg}
232300
/>
233301
<div
234-
className="space-y-4 relative z-10"
302+
className="flex flex-col gap-4 relative z-10 h-full"
235303
style={{ padding: layoutCfg.padding }}
236304
>
237305
{/* Header with layout toggle */}
@@ -259,11 +327,13 @@ export function DashboardContent() {
259327
</div>
260328

261329
{/* Layout content */}
262-
{layout === "executive" && (
263-
<ExecutiveLayout cards={darkCards} layout={layoutCfg} />
264-
)}
265-
{layout === "operational" && <OperationalLayout />}
266-
{layout === "analytics" && <AnalyticsLayout />}
330+
<div className="flex-1 min-h-0">
331+
{layout === "executive" && (
332+
<ExecutiveLayout cards={darkCards} layout={layoutCfg} />
333+
)}
334+
{layout === "operational" && <OperationalLayout />}
335+
{layout === "analytics" && <AnalyticsLayout />}
336+
</div>
267337
</div>
268338
</div>
269339
);

apps/apollo-vertex/templates/dashboard/glow-config.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ export const defaultDarkGlow: GlowConfig = {
5353
export type CardSize = "sm" | "md" | "lg";
5454

5555
export type InsightCardType = "kpi" | "chart";
56-
export type ChartType = "donut" | "horizontal-bars" | "sparkline" | "area";
56+
export type ChartType =
57+
| "donut"
58+
| "horizontal-bars"
59+
| "sparkline"
60+
| "area"
61+
| "stacked-bar";
5762

5863
export interface InsightCardContent {
5964
type: InsightCardType;
@@ -109,12 +114,12 @@ export const defaultLayout: LayoutConfig = {
109114
visible: true,
110115
content: {
111116
type: "chart",
112-
chartType: "donut",
117+
chartType: "stacked-bar",
113118
title: "Pipeline",
114119
},
115120
},
116121
{
117-
size: "md",
122+
size: "sm",
118123
visible: true,
119124
content: {
120125
type: "kpi",
@@ -165,6 +170,7 @@ export const chartTypeOptions = [
165170
{ label: "Horizontal Bars", value: "horizontal-bars" },
166171
{ label: "Sparkline", value: "sparkline" },
167172
{ label: "Area", value: "area" },
173+
{ label: "Stacked Bar", value: "stacked-bar" },
168174
];
169175

170176
export const bgColorOptions = [

0 commit comments

Comments
 (0)