@@ -7,130 +7,20 @@ import Editor, { Monaco } from "@monaco-editor/react";
77import { Flex , useColorMode } from "@chakra-ui/react" ;
88import { useEffect , useState , useRef , useCallback } from "react" ;
99import MyBtn from "../MyBtn" ;
10- import {
11- tryFormattingCode ,
12- validateCode ,
13- restorePreviousValidation ,
14- hasValidationResult ,
15- } from "@/lib/client-functions" ;
10+ import { tryFormattingCode , validateCode } from "@/lib/client-functions" ;
1611import FiChevronRight from "@/app/styles/icons/HiChevronRightGreen" ;
1712import { useRouter } from "next/navigation" ;
18- import { useUserSolutionStore , useEditorStore } from "@/lib/stores" ;
13+ import { useEditorStore } from "@/lib/stores" ;
1914import { sendGAEvent } from "@next/third-parties/google" ;
2015import { CodeFile , OutputResult } from "@/lib/types" ;
2116import { OutputReducerAction } from "@/lib/reducers" ;
2217import CertificateButton from "../CertificateButton/CertificateButton" ;
23-
24- // Custom hook for editor theme setup
25- const useEditorTheme = ( monaco : Monaco , colorMode : "dark" | "light" ) => {
26- useEffect ( ( ) => {
27- if ( monaco ) {
28- monaco . editor . defineTheme ( "my-theme" , {
29- base : "vs-dark" ,
30- inherit : true ,
31- rules : [ ] ,
32- colors : {
33- "editor.background" : "#1f1f1f" ,
34- } ,
35- } ) ;
36- monaco . editor . setTheme ( colorMode === "light" ? "light" : "my-theme" ) ;
37- }
38- } , [ monaco , colorMode ] ) ;
39- } ;
40-
41- // Custom hook for keyboard shortcuts
42- const useValidationShortcut = (
43- handleValidate : ( ) => void ,
44- codeString : string ,
45- ) => {
46- useEffect ( ( ) => {
47- const handleKeyDown = ( event : KeyboardEvent ) => {
48- if ( event . key === "Enter" && event . shiftKey ) {
49- sendGAEvent ( "event" , "buttonClicked" , {
50- value : "Validate (through shortcut)" ,
51- } ) ;
52- event . preventDefault ( ) ;
53- handleValidate ( ) ;
54- }
55- } ;
56-
57- document . addEventListener ( "keydown" , handleKeyDown ) ;
58- return ( ) => {
59- document . removeEventListener ( "keydown" , handleKeyDown ) ;
60- } ;
61- } , [ handleValidate , codeString ] ) ;
62- } ;
63-
64- // Custom hook for code persistence
65- const useCodePersistence = (
66- chapterIndex : number ,
67- stepIndex : number ,
68- codeString : string ,
69- setCodeString : ( value : string ) => void ,
70- codeFile : CodeFile ,
71- ) => {
72- const userSolutionStore = useUserSolutionStore ( ) ;
73-
74- // Load saved code
75- useEffect ( ( ) => {
76- const savedCode = userSolutionStore . getSavedUserSolutionByLesson (
77- chapterIndex ,
78- stepIndex ,
79- ) ;
80- if ( savedCode && savedCode !== codeString ) {
81- setCodeString ( savedCode ) ;
82- }
83- } , [ chapterIndex , stepIndex ] ) ;
84-
85- // Save code changes
86- useEffect ( ( ) => {
87- userSolutionStore . saveUserSolutionForLesson (
88- chapterIndex ,
89- stepIndex ,
90- codeString ,
91- ) ;
92- } , [ codeString , chapterIndex , stepIndex ] ) ;
93-
94- // Initialize code if no saved solutions
95- useEffect ( ( ) => {
96- if ( Object . keys ( userSolutionStore . userSolutionsByLesson ) . length === 0 ) {
97- setCodeString ( JSON . stringify ( codeFile . code , null , 2 ) ) ;
98- }
99- } , [ userSolutionStore ] ) ;
100- } ;
101-
102- // Custom hook for validation restoration
103- const useValidationRestore = (
104- chapterIndex : number ,
105- stepIndex : number ,
106- dispatchOutput : React . Dispatch < OutputReducerAction > ,
107- setCodeString : ( value : string ) => void ,
108- ) => {
109- const [ isRestored , setIsRestored ] = useState ( false ) ;
110-
111- useEffect ( ( ) => {
112- // Restore previous validation on component mount or when lesson changes
113- if ( ! isRestored && hasValidationResult ( chapterIndex , stepIndex ) ) {
114- try {
115- const { restored } = restorePreviousValidation (
116- chapterIndex ,
117- stepIndex ,
118- dispatchOutput ,
119- setCodeString
120- ) ;
121- if ( restored ) {
122- setIsRestored ( true ) ;
123- console . log ( '✅ Previous validation restored for lesson:' , chapterIndex , stepIndex ) ;
124- }
125- } catch ( error ) {
126- console . error ( 'Failed to restore validation:' , error ) ;
127- }
128- }
129- } , [ chapterIndex , stepIndex , isRestored , dispatchOutput , setCodeString ] ) ;
130-
131- return { isRestored } ;
132- } ;
133-
18+ import {
19+ useEditorTheme ,
20+ useValidationShortcut ,
21+ useCodePersistence ,
22+ useValidationRestore ,
23+ } from "@/app/utils/hooks" ;
13424
13525// EditorControls component for the buttons section
13626const EditorControls = ( {
@@ -230,7 +120,7 @@ export default function CodeEditor({
230120 ) ;
231121 setIsValidating ( false ) ;
232122 } , 500 ) ;
233- } , [ codeString , codeFile , dispatchOutput , stepIndex , chapterIndex ] ) ;
123+ } , [ codeString , codeFile , dispatchOutput , stepIndex , chapterIndex , setCodeString ] ) ;
234124
235125 useValidationShortcut ( handleValidate , codeString ) ;
236126 useCodePersistence (
@@ -241,19 +131,21 @@ export default function CodeEditor({
241131 codeFile ,
242132 ) ;
243133
134+ // Restore previous validation on lesson revisit
244135 const { isRestored } = useValidationRestore (
245136 chapterIndex ,
246137 stepIndex ,
247138 dispatchOutput ,
248139 setCodeString ,
249140 ) ;
250141
142+ // Reset code to initial state
251143 const resetCode = ( ) => {
252144 setCodeString ( JSON . stringify ( codeFile . code , null , 2 ) ) ;
253145 dispatchOutput ( { type : "RESET" } ) ;
254146 } ;
255147
256- const handleEditorMount = ( editor : monaco . editor . IStandaloneCodeEditor , monacoInstance : Monaco ) => {
148+ const handleEditorMount = ( editor : any , monacoInstance : Monaco ) => {
257149 setMonaco ( monacoInstance ) ;
258150
259151 editorRef . current = editor ;
@@ -263,6 +155,7 @@ export default function CodeEditor({
263155
264156 return (
265157 < >
158+ { /* Show success banner when previous validation is restored */ }
266159 { isRestored && (
267160 < div
268161 style = { {
0 commit comments