Initial commit: Brachnha Insight project setup
- Next.js 14+ with App Router and TypeScript - Tailwind CSS and ShadCN UI styling - Zustand state management - Dexie.js for IndexedDB (local-first data) - Auth.js v5 for authentication - BMAD framework integration Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
118
src/app/(session)/chat/page.tsx
Normal file
118
src/app/(session)/chat/page.tsx
Normal file
@@ -0,0 +1,118 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { ChatWindow } from '@/components/features/chat/chat-window';
|
||||
import { ChatInput } from '@/components/features/chat/chat-input';
|
||||
import { useSessionStore, useActiveSessionId, useTeacherStatus } from '@/store/use-session';
|
||||
import { ChatService } from '@/services/chat-service';
|
||||
import { toast } from 'sonner';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DraftViewSheet } from "@/components/features/draft/DraftViewSheet";
|
||||
import { useChatStore } from "@/lib/store/chat-store";
|
||||
import { CheckCircle, Loader2, ArrowLeft, Sparkles } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function ChatPage() {
|
||||
const activeSessionId = useActiveSessionId();
|
||||
const teacherStatus = useTeacherStatus();
|
||||
const { setActiveSession } = useSessionStore((s) => s.actions);
|
||||
const isDrafting = useChatStore((s) => s.isDrafting);
|
||||
|
||||
// Initialize Session on Mount
|
||||
useEffect(() => {
|
||||
const initSession = async () => {
|
||||
if (!activeSessionId) {
|
||||
try {
|
||||
const newSessionId = await ChatService.createSession();
|
||||
setActiveSession(newSessionId);
|
||||
} catch (error) {
|
||||
console.error("Failed to create session:", error);
|
||||
toast.error("Failed to start session. Check your database.");
|
||||
}
|
||||
}
|
||||
};
|
||||
initSession();
|
||||
}, [activeSessionId, setActiveSession]);
|
||||
|
||||
const handleSend = async (message: string) => {
|
||||
if (!activeSessionId) return;
|
||||
|
||||
try {
|
||||
await ChatService.sendMessage(message, activeSessionId);
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
if (error.message === 'AI Provider not configured') {
|
||||
toast.error("Please configure your AI Provider in Settings", {
|
||||
action: {
|
||||
label: "Go to Settings",
|
||||
onClick: () => window.location.href = '/settings'
|
||||
}
|
||||
});
|
||||
} else {
|
||||
toast.error("Failed to send message. Please check connection.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleFinishSession = async () => {
|
||||
if (!activeSessionId) return;
|
||||
|
||||
try {
|
||||
toast.info("Generating your learning summary...");
|
||||
// Ensure store has latest messages for this session
|
||||
await useChatStore.getState().hydrate(activeSessionId);
|
||||
// Trigger Ghostwriter
|
||||
await useChatStore.getState().generateDraft(activeSessionId);
|
||||
} catch (error) {
|
||||
console.error("Failed to generate draft:", error);
|
||||
toast.error("Failed to generate summary. Please try again.");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-background">
|
||||
{/* Session Header */}
|
||||
<div className="flex items-center justify-between px-4 py-3 bg-white border-b border-slate-200 shrink-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/" className="text-slate-500 hover:text-slate-700 transition-colors">
|
||||
<ArrowLeft className="w-5 h-5" />
|
||||
</Link>
|
||||
<div className="font-medium text-slate-700">
|
||||
Current Session
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleFinishSession}
|
||||
disabled={isDrafting}
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="bg-indigo-600 hover:bg-indigo-700"
|
||||
>
|
||||
{isDrafting ? (
|
||||
<>
|
||||
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
||||
Drafting...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Sparkles className="w-4 h-4 mr-2" />
|
||||
Draft Post
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Chat Messages - Scrollable Area */}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<ChatWindow sessionId={activeSessionId} />
|
||||
</div>
|
||||
|
||||
<DraftViewSheet />
|
||||
|
||||
{/* Chat Input - Fixed at Bottom */}
|
||||
<div className="shrink-0 bg-white border-t border-slate-200">
|
||||
<ChatInput onSend={handleSend} isLoading={teacherStatus !== 'idle'} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user