@@ -3,14 +3,16 @@ import {useState, useEffect, useRef, useCallback, useSyncExternalStore} from "re
33import  { notFound }  from  "next/navigation" ; 
44import  { Pencil }  from  "lucide-react" ; 
55import  { Editor }  from  "./Editor.jsx" ; 
6- import  { getNotebookById ,  createNotebook ,  addNotebook ,  saveNotebook }  from  "./api.js" ; 
6+ import  { getNotebookById ,  createNotebook ,  addNotebook ,  saveNotebook ,   getNotebooks }  from  "./api.js" ; 
77import  { isDirtyStore ,  countStore }  from  "./store.js" ; 
88import  { cn }  from  "./cn.js" ; 
9+ import  { SafeLink }  from  "./SafeLink.jsx" ; 
910
1011const  UNSET  =  Symbol ( "UNSET" ) ; 
1112
1213export  function  EditorPage ( { id : initialId } )  { 
1314  const  [ notebook ,  setNotebook ]  =  useState ( UNSET ) ; 
15+   const  [ notebookList ,  setNotebookList ]  =  useState ( [ ] ) ; 
1416  const  [ showInput ,  setShowInput ]  =  useState ( false ) ; 
1517  const  [ autoRun ,  setAutoRun ]  =  useState ( false ) ; 
1618  const  [ id ,  setId ]  =  useState ( initialId ) ; 
@@ -59,6 +61,11 @@ export function EditorPage({id: initialId}) {
5961    } ,  100 ) ; 
6062  } ,  [ notebook ,  isAdded ] ) ; 
6163
64+   useEffect ( ( )  =>  { 
65+     const  notebooks  =  getNotebooks ( ) ; 
66+     setNotebookList ( notebooks . slice ( 0 ,  4 ) ) ; 
67+   } ,  [ isAdded ] ) ; 
68+ 
6269  useEffect ( ( )  =>  { 
6370    const  onBeforeUnload  =  ( e )  =>  { 
6471      if  ( isDirty )  e . preventDefault ( ) ; 
@@ -137,44 +144,98 @@ export function EditorPage({id: initialId}) {
137144  } 
138145
139146  return  ( 
140-     < div  className = { cn ( "max-w-screen-lg lg:mx-auto mx-4 lg:my-10 my-4 editor-page" ) } > 
141-       < Editor 
142-         initialCode = { initialCode } 
143-         key = { notebook . id } 
144-         onUserInput = { onUserInput } 
145-         onBeforeEachRun = { onBeforeEachRun } 
146-         autoRun = { autoRun } 
147-         toolBarStart = { 
148-           < div  className = { cn ( "flex items-center gap-2" ) } > 
149-             { ! isAdded  &&  ( 
150-               < button 
151-                 onClick = { onSave } 
152-                 className = { cn ( "bg-green-700 text-white rounded-md px-3 py-1 text-sm hover:bg-green-800" ) } 
153-               > 
154-                 Create
155-               </ button > 
147+     < div > 
148+       { ! isAdded  &&  notebookList . length  >  0  &&  ( 
149+         < div  className = { cn ( "flex h-[72px] bg-gray-100 p-2 w-full border-b border-gray-200" ) } > 
150+           < div 
151+             className = { cn ( 
152+               "flex items-center justify-between gap-2 h-full max-w-screen-lg lg:mx-auto mx-4 w-full hidden md:flex" , 
156153            ) } 
157-             { ! showInput  &&  isAdded  &&  ( 
158-               < button  onClick = { onRename } > 
159-                 < Pencil  className = "w-4 h-4"  /> 
160-               </ button > 
161-             ) } 
162-             { showInput  ||  ! isAdded  ? ( 
163-               < input 
164-                 type = "text" 
165-                 value = { title } 
166-                 onChange = { onTitleChange } 
167-                 onBlur = { onTitleBlur } 
168-                 onKeyDown = { onTitleKeyDown } 
169-                 ref = { titleRef } 
170-                 className = { cn ( "border border-gray-200 rounded-md px-3 py-1 text-sm bg-white" ) } 
171-               /> 
172-             )  : ( 
173-               < span  className = { cn ( "text-sm py-1 border border-gray-100 rounded-md" ) } > { notebook . title } </ span > 
154+           > 
155+             { notebookList . map ( ( notebook )  =>  ( 
156+               < div  key = { notebook . id }  className = { cn ( "flex items-start flex-col gap-1" ) } > 
157+                 < SafeLink 
158+                   href = { `/notebooks/${ notebook . id }  } 
159+                   key = { notebook . id } 
160+                   className = { cn ( 
161+                     "font-semibold hover:underline text-blue-500 whitespace-nowrap line-clamp-1 max-w-[150px] text-ellipsis" , 
162+                   ) } 
163+                 > 
164+                   { notebook . title } 
165+                 </ SafeLink > 
166+                 < span 
167+                   className = { cn ( "text-xs text-gray-500 line-clamp-1 whitespace-nowrap max-w-[150px] text-ellipsis" ) } 
168+                 > 
169+                   Created { new  Date ( notebook . created ) . toLocaleDateString ( ) } 
170+                 </ span > 
171+               </ div > 
172+             ) ) } 
173+             < SafeLink  href = "/notebooks"  className = { cn ( "font-semibold text-blue-500 hover:underline" ) } > 
174+               View your notebooks
175+             </ SafeLink > 
176+           </ div > 
177+           < div 
178+             className = { cn ( 
179+               "flex items-center justify-between gap-2 h-full max-w-screen-lg lg:mx-auto mx-4 w-full md:hidden" , 
174180            ) } 
181+           > 
182+             < SafeLink 
183+               href = "/notebooks" 
184+               className = { cn ( 
185+                 "font-medium w-full border border-gray-300 rounded-md px-3 py-2 text-sm text-center hover:bg-gray-200" , 
186+               ) } 
187+             > 
188+               View your notebooks
189+             </ SafeLink > 
175190          </ div > 
176-         } 
177-       /> 
191+         </ div > 
192+       ) } 
193+       { ! isAdded  &&  notebookList . length  ===  0  &&  ( 
194+         < div  className = { cn ( "flex items-center justify-center h-[72px] mt-6 mb-10 lg:mb-0" ) } > 
195+           < p  className = { cn ( "text-3xl text-gray-800 font-light text-center mx-10" ) } > 
196+             Explore code and art with instant feedback.
197+           </ p > 
198+         </ div > 
199+       ) } 
200+       < div  className = { cn ( "max-w-screen-lg lg:mx-auto mx-4 lg:my-10 my-4 editor-page" ) } > 
201+         < Editor 
202+           initialCode = { initialCode } 
203+           key = { notebook . id } 
204+           onUserInput = { onUserInput } 
205+           onBeforeEachRun = { onBeforeEachRun } 
206+           autoRun = { autoRun } 
207+           toolBarStart = { 
208+             < div  className = { cn ( "flex items-center gap-2" ) } > 
209+               { ! isAdded  &&  ( 
210+                 < button 
211+                   onClick = { onSave } 
212+                   className = { cn ( "bg-green-700 text-white rounded-md px-3 py-1 text-sm hover:bg-green-800" ) } 
213+                 > 
214+                   Create
215+                 </ button > 
216+               ) } 
217+               { ! showInput  &&  isAdded  &&  ( 
218+                 < button  onClick = { onRename } > 
219+                   < Pencil  className = "w-4 h-4"  /> 
220+                 </ button > 
221+               ) } 
222+               { showInput  ||  ! isAdded  ? ( 
223+                 < input 
224+                   type = "text" 
225+                   value = { title } 
226+                   onChange = { onTitleChange } 
227+                   onBlur = { onTitleBlur } 
228+                   onKeyDown = { onTitleKeyDown } 
229+                   ref = { titleRef } 
230+                   className = { cn ( "border border-gray-200 rounded-md px-3 py-1 text-sm bg-white" ) } 
231+                 /> 
232+               )  : ( 
233+                 < span  className = { cn ( "text-sm py-1 border border-gray-100 rounded-md" ) } > { notebook . title } </ span > 
234+               ) } 
235+             </ div > 
236+           } 
237+         /> 
238+       </ div > 
178239    </ div > 
179240  ) ; 
180241} 
0 commit comments