mirror of https://github.com/kortix-ai/suna.git
chore(ui): add example section in dashboard
This commit is contained in:
parent
60c6ca9560
commit
380ac4cf39
|
@ -0,0 +1,65 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import {
|
||||||
|
BarChart3,
|
||||||
|
Bot,
|
||||||
|
Briefcase,
|
||||||
|
Settings,
|
||||||
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
type PromptExample = {
|
||||||
|
title: string;
|
||||||
|
query: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const prompts: PromptExample[] = [
|
||||||
|
{
|
||||||
|
title: 'Market research dashboard',
|
||||||
|
query: 'Create a comprehensive market research dashboard analyzing industry trends, customer segments, and competitive landscape. Include data visualization and actionable recommendations.',
|
||||||
|
icon: <BarChart3 size={16} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Recommendation engine development',
|
||||||
|
query: 'Develop a recommendation engine for personalized product suggestions. Include collaborative filtering, content-based filtering, and hybrid approaches with evaluation metrics.',
|
||||||
|
icon: <Bot size={16} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Go-to-market strategy',
|
||||||
|
query: 'Develop a comprehensive go-to-market strategy for a new product. Include market sizing, customer acquisition channels, pricing strategy, and launch timeline.',
|
||||||
|
icon: <Briefcase size={16} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Data pipeline automation',
|
||||||
|
query: 'Create an automated data pipeline for ETL processes. Include data validation, error handling, monitoring, and scalable architecture design.',
|
||||||
|
icon: <Settings size={16} />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Examples = ({
|
||||||
|
onSelectPrompt,
|
||||||
|
}: {
|
||||||
|
onSelectPrompt?: (query: string) => void;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="w-full max-w-3xl mx-auto px-4">
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-2 xl:grid-cols-4 gap-4">
|
||||||
|
{prompts.map((prompt, index) => (
|
||||||
|
<Card
|
||||||
|
key={index}
|
||||||
|
className="group cursor-pointer h-full shadow-none transition-all bg-sidebar hover:bg-neutral-100 dark:hover:bg-neutral-800/60"
|
||||||
|
onClick={() => onSelectPrompt && onSelectPrompt(prompt.query)}
|
||||||
|
>
|
||||||
|
<CardContent className="px-4 pt-0">
|
||||||
|
<p className="group-hover:text-foreground transition-all text-muted-foreground text-sm line-clamp-3">
|
||||||
|
{prompt.query}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -27,6 +27,7 @@ import { cn } from '@/lib/utils';
|
||||||
import { useInitiateAgentWithInvalidation } from '@/hooks/react-query/dashboard/use-initiate-agent';
|
import { useInitiateAgentWithInvalidation } from '@/hooks/react-query/dashboard/use-initiate-agent';
|
||||||
import { ModalProviders } from '@/providers/modal-providers';
|
import { ModalProviders } from '@/providers/modal-providers';
|
||||||
import { useModal } from '@/hooks/use-modal-store';
|
import { useModal } from '@/hooks/use-modal-store';
|
||||||
|
import { Examples } from './_components/suggestions/examples';
|
||||||
|
|
||||||
const PENDING_PROMPT_KEY = 'pendingAgentPrompt';
|
const PENDING_PROMPT_KEY = 'pendingAgentPrompt';
|
||||||
|
|
||||||
|
@ -105,7 +106,6 @@ function DashboardContent() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
const pendingPrompt = localStorage.getItem(PENDING_PROMPT_KEY);
|
const pendingPrompt = localStorage.getItem(PENDING_PROMPT_KEY);
|
||||||
|
@ -133,7 +133,7 @@ function DashboardContent() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ModalProviders />
|
<ModalProviders />
|
||||||
<div className="flex flex-col items-center justify-center h-full w-full">
|
<div className="flex flex-col h-screen w-full">
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
<div className="absolute top-4 left-4 z-10">
|
<div className="absolute top-4 left-4 z-10">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
@ -153,25 +153,49 @@ function DashboardContent() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-[650px] max-w-[90%]">
|
<div className={cn(
|
||||||
<div className="flex flex-col items-center text-center mb-2 w-full">
|
"flex-1 flex flex-col items-center justify-center px-4",
|
||||||
<h1 className={cn('tracking-tight text-4xl font-semibold leading-tight')}>
|
"lg:justify-center",
|
||||||
|
"sm:justify-center sm:px-6"
|
||||||
|
)}>
|
||||||
|
<div className={cn(
|
||||||
|
"flex flex-col items-center text-center w-full",
|
||||||
|
"max-w-full",
|
||||||
|
"sm:max-w-3xl"
|
||||||
|
)}>
|
||||||
|
<h1 className={cn(
|
||||||
|
'tracking-tight font-semibold leading-tight',
|
||||||
|
'text-3xl',
|
||||||
|
'sm:text-4xl'
|
||||||
|
)}>
|
||||||
Hey
|
Hey
|
||||||
</h1>
|
</h1>
|
||||||
<p className="tracking-tight text-3xl font-normal text-muted-foreground/80 mt-2 flex items-center gap-2">
|
<p className={cn(
|
||||||
|
"tracking-tight font-normal text-muted-foreground/80 mt-2 flex items-center gap-2",
|
||||||
|
"text-2xl",
|
||||||
|
"sm:text-3xl sm:mt-3 sm:px-4"
|
||||||
|
)}>
|
||||||
What would you like Suna to do today?
|
What would you like Suna to do today?
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ChatInput
|
<div className={cn(
|
||||||
ref={chatInputRef}
|
"w-full mb-2",
|
||||||
onSubmit={handleSubmit}
|
"max-w-full",
|
||||||
loading={isSubmitting}
|
"sm:max-w-3xl"
|
||||||
placeholder="Describe what you need help with..."
|
)}>
|
||||||
value={inputValue}
|
<ChatInput
|
||||||
onChange={setInputValue}
|
ref={chatInputRef}
|
||||||
hideAttachments={false}
|
onSubmit={handleSubmit}
|
||||||
/>
|
loading={isSubmitting}
|
||||||
|
placeholder="Describe what you need help with..."
|
||||||
|
value={inputValue}
|
||||||
|
onChange={setInputValue}
|
||||||
|
hideAttachments={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Examples onSelectPrompt={setInputValue} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BillingErrorAlert
|
<BillingErrorAlert
|
||||||
|
@ -191,16 +215,18 @@ export default function DashboardPage() {
|
||||||
return (
|
return (
|
||||||
<Suspense
|
<Suspense
|
||||||
fallback={
|
fallback={
|
||||||
<div className="flex flex-col items-center justify-center h-full w-full">
|
<div className="flex flex-col h-full w-full">
|
||||||
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-[560px] max-w-[90%]">
|
<div className="flex-1 flex flex-col items-center justify-center px-4">
|
||||||
<div className="flex flex-col items-center text-center mb-10">
|
<div className={cn(
|
||||||
<Skeleton className="h-10 w-40 mb-2" />
|
"flex flex-col items-center text-center w-full space-y-8",
|
||||||
<Skeleton className="h-7 w-56" />
|
"max-w-[850px] sm:max-w-full sm:px-4"
|
||||||
</div>
|
)}>
|
||||||
|
<Skeleton className="h-10 w-40 sm:h-8 sm:w-32" />
|
||||||
<Skeleton className="w-full h-[100px] rounded-xl" />
|
<Skeleton className="h-7 w-56 sm:h-6 sm:w-48" />
|
||||||
<div className="flex justify-center mt-3">
|
<Skeleton className="w-full h-[100px] rounded-xl sm:h-[80px]" />
|
||||||
<Skeleton className="h-5 w-16" />
|
<div className="block sm:hidden lg:block w-full">
|
||||||
|
<Skeleton className="h-20 w-full" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -209,4 +235,4 @@ export default function DashboardPage() {
|
||||||
<DashboardContent />
|
<DashboardContent />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -230,7 +230,7 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="w-full text-sm flex flex-col justify-between items-start rounded-lg">
|
<div className="w-full text-sm flex flex-col justify-between items-start rounded-lg">
|
||||||
<CardContent className="w-full p-1.5 pb-2 bg-sidebar rounded-2xl border">
|
<CardContent className="w-full p-1.5 pb-2 bg-[#efefef] dark:bg-sidebar rounded-2xl border">
|
||||||
<AttachmentGroup
|
<AttachmentGroup
|
||||||
files={uploadedFiles || []}
|
files={uploadedFiles || []}
|
||||||
sandboxId={sandboxId}
|
sandboxId={sandboxId}
|
||||||
|
|
Loading…
Reference in New Issue