"use client"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { useSession, signIn, signOut } from "next-auth/react"; import Link from "next/link"; import { Search, Settings, LogIn, LogOut, X, Plus, MessageSquare, Loader2, Menu, } from "lucide-react"; export default function HomeDashboard() { const router = useRouter(); const { data: session, status: authStatus } = useSession(); // Core data states const [characters, setCharacters] = useState([]); const [chats, setChats] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(""); const [showUpgradeModal, setShowUpgradeModal] = useState(false); const [userCredits, setUserCredits] = useState(50); const [showSidebar, setShowSidebar] = useState(false); // Create Character Modal states const [showCreateModal, setShowCreateModal] = useState(false); const [newChar, setNewChar] = useState({ name: "", avatar: "🤖", profile_url: "", description: "", personality: "", systemPrompt: "", greeting: "", is_public: true, }); const [isCreating, setIsCreating] = useState(false); useEffect(() => { fetchInitialData(); }, [authStatus]); useEffect(() => { if (session?.user) { setUserCredits(session.user.credits); } }, [session]); const fetchInitialData = async () => { try { setLoading(true); // Fetch all characters from DB const charRes = await fetch("/api/characters"); const charData = await charRes.json(); if (charData.characters) { setCharacters(charData.characters); } if (authStatus === "authenticated") { // Sync active chats from SQLite/DB const chatRes = await fetch("/api/chats"); const chatData = await chatRes.json(); if (chatData.chats) { setChats(chatData.chats); } } } catch (err) { console.error("Failed to load initial workspace data", err); } finally { setLoading(false); } }; // Triggers creation of a chat session const handleStartChat = async (characterId, characterName) => { if (authStatus !== "authenticated") { signIn("google"); return; } try { const res = await fetch("/api/chats", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ character_id: characterId }), }); const data = await res.json(); if (data.chat) { const slug = characterName.toLowerCase().replace(/ /g, "-"); router.push(`/${slug}/${data.chat.id}`); } } catch (err) { console.error("Failed to instantiate chat thread", err); } }; const handleCreateCharacter = async (e) => { e.preventDefault(); if (authStatus !== "authenticated") { signIn("google"); return; } try { setIsCreating(true); const res = await fetch("/api/characters", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newChar), }); const data = await res.json(); if (data.character) { setCharacters((prev) => [...prev, data.character]); setShowCreateModal(false); setNewChar({ name: "", avatar: "🤖", profile_url: "", description: "", personality: "", systemPrompt: "", greeting: "", is_public: true, }); await handleStartChat(data.character.id, data.character.name); } } catch (error) { console.error(error); } finally { setIsCreating(false); } }; const executeUpgrade = () => { setUserCredits((prev) => prev + 100); setShowUpgradeModal(false); alert( "Successfully upgraded to c.ai+! Added 100 premium credits to your balance.", ); }; // Derive unique recent characters from chat history const recentCharactersMap = new Map(); chats.forEach((c) => { if (c.character && !recentCharactersMap.has(c.character.id)) { recentCharactersMap.set(c.character.id, c.character); } }); const recentCharacters = Array.from(recentCharactersMap.values()); // Filter characters based on search const filteredCharacters = characters.filter((c) => { const q = searchQuery.toLowerCase(); return ( c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q) ); }); return (
{char.description}
No characters found matching "{searchQuery}".
Gain instant access to unlimited thinking engine telemetry, zero-wait premium response models (GPT-4o, DeepSeek R1), and +100 bonus credits!