11"use client" ;
22
33import { useEffect , useState } from "react" ;
4- import { env } from "next-runtime-env " ;
4+ import { authenticatedFetchV2 } from "../../../../../../../utils/api " ;
55import useNotebookLLM from "./useNotebookLLM" ;
66
7- // Lightweight decoder copied from previous implementation
8- const tryDecodePayload = ( p ) => {
9- if ( p === null || p === undefined ) return p ;
10- if ( typeof p === "object" ) return p ;
11- if ( typeof p !== "string" ) return p ;
12- const s = p . trim ( ) ;
13- if ( s . startsWith ( "{" ) || s . startsWith ( "[" ) ) {
14- try {
15- return JSON . parse ( s ) ;
16- } catch ( e ) { }
17- }
18- try {
19- let b64 = s . replace ( / - / g, "+" ) . replace ( / _ / g, "/" ) ;
20- while ( b64 . length % 4 !== 0 ) b64 += "=" ;
21- const decoded = atob ( b64 ) ;
22- try {
23- return JSON . parse ( decoded ) ;
24- } catch ( e ) {
25- try {
26- const utf8 = decodeURIComponent (
27- Array . prototype . map
28- . call (
29- decoded ,
30- ( c ) =>
31- "%" +
32- ( "00" + c . charCodeAt ( 0 ) . toString ( 16 ) ) . slice ( - 2 ) ,
33- )
34- . join ( "" ) ,
35- ) ;
36- try {
37- return JSON . parse ( utf8 ) ;
38- } catch ( e2 ) {
39- return utf8 ;
40- }
41- } catch ( e3 ) {
42- return decoded ;
43- }
44- }
45- } catch ( err ) {
46- return s ;
47- }
48- } ;
49-
50- const removeEmpty = ( obj ) => {
51- if ( obj === null || obj === undefined ) return null ;
52- if ( Array . isArray ( obj ) )
53- return obj . map ( removeEmpty ) . filter ( ( i ) => i !== null ) ;
54- if ( typeof obj === "object" ) {
55- return Object . entries ( obj )
56- . map ( ( [ k , v ] ) => [ k , removeEmpty ( v ) ] )
57- . filter ( ( [ , v ] ) => v !== null && v !== "" && v !== undefined )
58- . reduce ( ( acc , [ k , v ] ) => ( { ...acc , [ k ] : v } ) , { } ) ;
59- }
60- return obj ;
61- } ;
7+ // ... (helper functions remain the same)
628
639export default function useNotebookFetch ( notebookId , problemId ) {
6410 const [ loading , setLoading ] = useState ( true ) ;
@@ -113,67 +59,54 @@ export default function useNotebookFetch(notebookId, problemId) {
11359 setError ( null ) ;
11460
11561 try {
116- const base = env ( "NEXT_PUBLIC_BACKEND_BASE_URL" ) ?? "http://localhost:8080" ;
117- const token = localStorage . getItem ( "token" ) ;
118- const headers = {
119- "Content-Type" : "application/json" ,
120- } ;
121- if ( token ) {
122- headers [ "Authorization" ] = `Bearer ${ token } ` ;
123- }
124-
125- const res = await fetch ( `${ base } /api/v1/notebooks/${ notebookId } ` , {
126- method : "GET" ,
127- headers : headers ,
62+ const notebookData = await authenticatedFetchV2 ( `/api/v1/notebooks/${ notebookId } ` , {
12863 signal : controller . signal ,
12964 } ) ;
13065
131-
132- if ( res . status === 401 ) {
133- window . location . href = "/auth" ;
134- return ;
66+ if ( notebookData . notebook && notebookData . notebook . requirements ) {
67+ setInitialRequirements ( getRequirementsAsString ( notebookData . notebook . requirements ) ) ;
68+ } else if ( notebookData . requirements ) {
69+ setInitialRequirements ( getRequirementsAsString ( notebookData . requirements ) ) ;
13570 }
71+ const currentCells = notebookData ?. cells ?? [ ] ;
72+
73+ if ( currentCells . length > 0 ) {
74+ console . log ( "Notebook found with cells, loading content." ) ;
75+ const mappedCells = currentCells . map ( ( c , i ) => ( {
76+ ...c ,
77+ id : c . id , // Use frontend ID
78+ idx : i ,
79+ cell_name : getCellNameAsString ( c . cell_name ) , // Correctly parse cell_name
80+ source : c . source || "" ,
81+ execution_count : c . execution_count || 0 ,
82+ } ) ) ;
83+ setInitialCells ( mappedCells ) ;
84+ setLoading ( false ) ;
85+ return ; // Done
86+ }
87+ console . log ( "Notebook found, but it is empty. Generating content." ) ;
13688
137- // Scenario A: Notebook exists
138- if ( res . ok ) {
139- const notebookData = await res . json ( ) ;
140- if ( notebookData . notebook && notebookData . notebook . requirements ) {
141- setInitialRequirements ( getRequirementsAsString ( notebookData . notebook . requirements ) ) ;
142- } else if ( notebookData . requirements ) {
143- setInitialRequirements ( getRequirementsAsString ( notebookData . requirements ) ) ;
144- }
145- const currentCells = notebookData ?. cells ?? [ ] ;
146-
147- if ( currentCells . length > 0 ) {
148- console . log ( "Notebook found with cells, loading content." ) ;
149- const mappedCells = currentCells . map ( ( c , i ) => ( {
150- ...c ,
151- id : c . id , // Use frontend ID
152- idx : i ,
153- cell_name : getCellNameAsString ( c . cell_name ) , // Correctly parse cell_name
154- source : c . source || "" ,
155- execution_count : c . execution_count || 0 ,
156- } ) ) ;
157- setInitialCells ( mappedCells ) ;
158- return ; // Done
159- }
160- // If notebook exists but is empty, fall through to generation
161- console . log ( "Notebook found, but it is empty. Generating content." ) ;
162- } else if ( res . status !== 404 ) {
163- // Handle errors other than "Not Found"
164- const errorText = await res . text ( ) ;
165- throw new Error ( `Failed to fetch notebook: ${ res . status } ${ errorText } ` ) ;
166- } else {
89+ } catch ( err ) {
90+ if ( err . message . includes ( "404" ) ) {
16791 console . log ( "Notebook not found. Creating and generating a new one." ) ;
168- // This is a new notebook, we need to create the DB entry first
169- // The backend should handle creating the notebook entry on generate
170- }
171-
172- // Scenario B: Notebook is new or empty, so we generate it.
173- if ( ! problemId ) {
174- throw new Error ( "Cannot generate notebook: Missing Problem ID." ) ;
92+ } else if ( controller . signal . aborted ) {
93+ return ;
94+ } else {
95+ console . error ( "Failed to fetch notebook:" , err ) ;
96+ setError ( `Failed to fetch notebook: ${ err . message } ` ) ;
97+ setLoading ( false ) ;
98+ return ;
17599 }
100+ }
101+
102+ // Scenario B: Notebook is new or empty, so we generate it.
103+ if ( ! problemId ) {
104+ setError ( "Cannot generate notebook: Missing Problem ID." ) ;
105+ setLoading ( false ) ;
106+ return ;
107+ }
176108
109+ try {
177110 const llmResult = await generateNotebook ( problemId ) ;
178111
179112 if ( ! llmResult || ! llmResult . notebook || ! llmResult . notebook . cells ) {
@@ -182,7 +115,8 @@ export default function useNotebookFetch(notebookId, problemId) {
182115
183116 if ( llmResult . notebook && llmResult . notebook . requirements ) {
184117 setInitialRequirements ( llmResult . notebook . requirements ) ;
185- } else if ( llmResult . requirements ) {
118+ }
119+ else if ( llmResult . requirements ) {
186120 setInitialRequirements ( llmResult . requirements ) ;
187121 }
188122
@@ -200,8 +134,8 @@ export default function useNotebookFetch(notebookId, problemId) {
200134
201135 } catch ( err ) {
202136 if ( controller . signal . aborted ) return ;
203- console . error ( "Error during notebook fetch/ generation:" , err ) ;
204- setError ( err . message || "An unknown error occurred." ) ;
137+ console . error ( "Error during notebook generation:" , err ) ;
138+ setError ( err . message || "An unknown error occurred during generation ." ) ;
205139 setInitialCells ( [ ] ) ;
206140 } finally {
207141 if ( mounted ) setLoading ( false ) ;
0 commit comments