Template
90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
'use client';
|
|
|
|
import type { ChatStatus } from 'ai';
|
|
import { ChatInput, type PromptInputMessage } from './ChatInput';
|
|
import { Suggestion } from '@/components/ai-elements/suggestion';
|
|
import { RiOpenaiLine } from '@remixicon/react';
|
|
import { Shimmer } from '@/components/ai-elements/shimmer';
|
|
import type { OpenRouterModelId } from '@/lib/openrouter';
|
|
import {
|
|
offlineSuggestions,
|
|
webSearchSuggestions,
|
|
type PromptSuggestion,
|
|
} from '@/config/suggestions';
|
|
|
|
export type { PromptSuggestion } from '@/config/suggestions';
|
|
|
|
interface ChatPromptProps {
|
|
value: string;
|
|
onChange: (value: string) => void;
|
|
onSubmit: (message: PromptInputMessage) => void;
|
|
modelId: OpenRouterModelId;
|
|
onModelChange: (modelId: OpenRouterModelId) => void;
|
|
onStop?: () => void;
|
|
status?: ChatStatus;
|
|
suggestions?: PromptSuggestion[];
|
|
webSearchEnabled?: boolean;
|
|
}
|
|
|
|
export function ChatPrompt({
|
|
value,
|
|
onChange,
|
|
onSubmit,
|
|
modelId,
|
|
onModelChange,
|
|
onStop,
|
|
status = 'ready',
|
|
suggestions,
|
|
webSearchEnabled = false,
|
|
}: ChatPromptProps) {
|
|
const displayedSuggestions =
|
|
suggestions ?? (webSearchEnabled ? webSearchSuggestions : offlineSuggestions);
|
|
|
|
const handleSuggestionClick = (suggestion: string) => {
|
|
onChange(suggestion);
|
|
};
|
|
|
|
return (
|
|
<div className="flex h-screen flex-col items-center justify-center gap-6 bg-muted p-4">
|
|
<div className="space-y-3 text-center">
|
|
<div className="flex items-center justify-center gap-2 text-primary">
|
|
<div className="flex items-center justify-center size-12 rounded-xl bg-black">
|
|
<RiOpenaiLine className="size-6 text-white animate-pulse" />
|
|
</div>
|
|
</div>
|
|
<Shimmer as="h1" className="text-3xl font-bold tracking-tight">
|
|
ChatGPT Agent
|
|
</Shimmer>
|
|
<p className="text-muted-foreground max-w-md mx-auto">
|
|
{webSearchEnabled
|
|
? "Ask anything — I'll search the web in real time to find accurate, up-to-date answers with sources."
|
|
: 'Ask anything — I can help research, explain, compare, and summarize.'}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="w-full max-w-2xl">
|
|
<ChatInput
|
|
value={value}
|
|
onChange={onChange}
|
|
onSubmit={onSubmit}
|
|
modelId={modelId}
|
|
onModelChange={onModelChange}
|
|
onStop={onStop}
|
|
status={status}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-wrap justify-center gap-2">
|
|
{displayedSuggestions.map((suggestion) => (
|
|
<Suggestion
|
|
key={suggestion.key}
|
|
className="bg-background text-foreground dark:bg-background dark:text-foreground"
|
|
suggestion={suggestion.key}
|
|
onClick={() => handleSuggestionClick(suggestion.value)}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|