Skip to content

Commit e297e5b

Browse files
sidebar added
1 parent fd6ae24 commit e297e5b

File tree

3 files changed

+534
-14
lines changed

3 files changed

+534
-14
lines changed

app/page.tsx

Lines changed: 93 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ import { ChatPicker } from '@/components/chat-picker'
88
import { ChatSettings } from '@/components/chat-settings'
99
import { NavBar } from '@/components/navbar'
1010
import { Preview } from '@/components/preview'
11+
import Sidebar from '@/components/sidebar'
1112
import { useAuth } from '@/lib/auth'
13+
import { Project, createProject, saveMessage, getProjectMessages, generateProjectTitle } from '@/lib/database'
1214
import { Message, toAISDKMessages, toMessageImage } from '@/lib/messages'
1315
import { LLMModelConfig } from '@/lib/models'
1416
import modelsList from '@/lib/models.json'
1517
import { FragmentSchema, fragmentSchema as schema } from '@/lib/schema'
1618
import { supabase } from '@/lib/supabase'
1719
import templates, { TemplateId } from '@/lib/templates'
1820
import { ExecutionResult } from '@/lib/types'
21+
import { cn } from '@/lib/utils'
1922
import { DeepPartial } from 'ai'
2023
import { experimental_useObject as useObject } from 'ai/react'
2124
import { usePostHog } from 'posthog-js/react'
@@ -25,9 +28,7 @@ import { useLocalStorage } from 'usehooks-ts'
2528
export default function Home() {
2629
const [chatInput, setChatInput] = useLocalStorage('chat', '')
2730
const [files, setFiles] = useState<File[]>([])
28-
const [selectedTemplate, setSelectedTemplate] = useState<'auto' | TemplateId>(
29-
'auto',
30-
)
31+
const [selectedTemplate, setSelectedTemplate] = useState<'auto' | TemplateId>('auto')
3132
const [languageModel, setLanguageModel] = useLocalStorage<LLMModelConfig>(
3233
'languageModel',
3334
{
@@ -46,6 +47,14 @@ export default function Home() {
4647
const [authView, setAuthView] = useState<ViewType>('sign_in')
4748
const [isRateLimited, setIsRateLimited] = useState(false)
4849
const [errorMessage, setErrorMessage] = useState('')
50+
51+
// Project management state
52+
const [currentProject, setCurrentProject] = useState<Project | null>(null)
53+
const [isLoadingProject, setIsLoadingProject] = useState(false)
54+
55+
// Sidebar open state
56+
const [isSidebarOpen, setSidebarOpen] = useState(false)
57+
4958
const { session, userTeam } = useAuth(setAuthDialog, setAuthView)
5059

5160
const filteredModels = modelsList.models.filter((model) => {
@@ -64,6 +73,12 @@ export default function Home() {
6473
: { [selectedTemplate]: templates[selectedTemplate] }
6574
const lastMessage = messages[messages.length - 1]
6675

76+
useEffect(() => {
77+
if (lastMessage) {
78+
console.log('Last message:', lastMessage)
79+
}
80+
}, [lastMessage])
81+
6782
const { object, submit, isLoading, stop, error } = useObject({
6883
api: '/api/chat',
6984
schema,
@@ -72,13 +87,10 @@ export default function Home() {
7287
if (error.message.includes('limit')) {
7388
setIsRateLimited(true)
7489
}
75-
7690
setErrorMessage(error.message)
7791
},
7892
onFinish: async ({ object: fragment, error }) => {
7993
if (!error) {
80-
// send it to /api/sandbox
81-
console.log('fragment', fragment)
8294
setIsPreviewLoading(true)
8395
posthog.capture('fragment_generated', {
8496
template: fragment?.template,
@@ -95,7 +107,6 @@ export default function Home() {
95107
})
96108

97109
const result = await response.json()
98-
console.log('result', result)
99110
posthog.capture('sandbox_created', { url: result.url })
100111

101112
setResult(result)
@@ -107,6 +118,37 @@ export default function Home() {
107118
},
108119
})
109120

121+
useEffect(() => {
122+
async function loadProjectMessages() {
123+
if (!currentProject) {
124+
setMessages([])
125+
return
126+
}
127+
128+
setIsLoadingProject(true)
129+
const projectMessages = await getProjectMessages(currentProject.id)
130+
setMessages(projectMessages)
131+
setIsLoadingProject(false)
132+
}
133+
134+
loadProjectMessages()
135+
}, [currentProject])
136+
137+
useEffect(() => {
138+
async function saveMessagesToDb() {
139+
if (!currentProject || !session || messages.length === 0) return
140+
141+
const lastMessage = messages[messages.length - 1]
142+
const sequenceNumber = messages.length - 1
143+
144+
await saveMessage(currentProject.id, lastMessage, sequenceNumber)
145+
}
146+
147+
if (messages.length > 0 && currentProject && session) {
148+
saveMessagesToDb()
149+
}
150+
}, [messages, currentProject, session])
151+
110152
useEffect(() => {
111153
if (object) {
112154
setFragment(object)
@@ -149,7 +191,6 @@ export default function Home() {
149191
...previousMessages[index ?? previousMessages.length - 1],
150192
...message,
151193
}
152-
153194
return updatedMessages
154195
})
155196
}
@@ -165,6 +206,15 @@ export default function Home() {
165206
stop()
166207
}
167208

209+
// Create new project if none exists
210+
if (!currentProject) {
211+
const title = await generateProjectTitle(chatInput)
212+
const newProject = await createProject(title, selectedTemplate === 'auto' ? undefined : selectedTemplate)
213+
if (newProject) {
214+
setCurrentProject(newProject)
215+
}
216+
}
217+
168218
const content: Message['content'] = [{ type: 'text', text: chatInput }]
169219
const images = await toMessageImage(files)
170220

@@ -253,6 +303,7 @@ export default function Home() {
253303
setResult(undefined)
254304
setCurrentTab('code')
255305
setIsPreviewLoading(false)
306+
setCurrentProject(null)
256307
}
257308

258309
function setCurrentPreview(preview: {
@@ -268,6 +319,18 @@ export default function Home() {
268319
setCurrentPreview({ fragment: undefined, result: undefined })
269320
}
270321

322+
function handleProjectSelect(project: Project | null) {
323+
setCurrentProject(project)
324+
if (!project) {
325+
handleClearChat()
326+
}
327+
}
328+
329+
async function handleNewProject() {
330+
setCurrentProject(null)
331+
handleClearChat()
332+
}
333+
271334
return (
272335
<main className="flex min-h-screen max-h-screen">
273336
{supabase && (
@@ -278,7 +341,15 @@ export default function Home() {
278341
supabase={supabase}
279342
/>
280343
)}
281-
<div className="grid w-full md:grid-cols-2">
344+
345+
<Sidebar onStateChange={setSidebarOpen} userName={userTeam?.name} userPlan={userTeam?.tier} />
346+
347+
348+
{/* Main content with left margin to account for collapsed sidebar */}
349+
<div className={cn(
350+
"grid w-full md:grid-cols-2 transition-all duration-300",
351+
session ? "ml-16" : "ml-0"
352+
)}>
282353
<div
283354
className={`flex flex-col w-full max-h-full max-w-[800px] mx-auto px-4 overflow-auto ${fragment ? 'col-span-1' : 'col-span-2'}`}
284355
>
@@ -292,11 +363,19 @@ export default function Home() {
292363
canUndo={messages.length > 1 && !isLoading}
293364
onUndo={handleUndo}
294365
/>
295-
<Chat
296-
messages={messages}
297-
isLoading={isLoading}
298-
setCurrentPreview={setCurrentPreview}
299-
/>
366+
367+
{isLoadingProject ? (
368+
<div className="flex items-center justify-center h-32">
369+
<div className="text-muted-foreground">Loading project...</div>
370+
</div>
371+
) : (
372+
<Chat
373+
messages={messages}
374+
isLoading={isLoading}
375+
setCurrentPreview={setCurrentPreview}
376+
/>
377+
)}
378+
300379
<ChatInput
301380
retry={retry}
302381
isErrored={error !== undefined}

0 commit comments

Comments
 (0)