@@ -279,6 +279,7 @@ const copy = {
279279 zh : {
280280 brandLine : "AI Coding 工程工作流手册" ,
281281 plannerMode : "学习清单" ,
282+ scheduleMode : "学习计划" ,
282283 readerMode : "全文阅读" ,
283284 navKicker : "Feynman Loop" ,
284285 navTitle : "19 章 · 36 天费曼间隔练习" ,
@@ -303,6 +304,10 @@ const copy = {
303304 noteKicker : "Teach Back" ,
304305 noteTitle : "费曼讲解草稿" ,
305306 notePlaceholder : "我会这样向一个刚开始用 AI Coding 的朋友解释今天的内容..." ,
307+ scheduleKicker : "Learning Plan" ,
308+ scheduleTitle : "36 天学习计划" ,
309+ scheduleSummary : "每天一个新章,到期旧章按 2-3-5-7 间隔短复述。" ,
310+ scheduleOpenDay : "回到今日清单" ,
306311 matrixKicker : "Schedule Table" ,
307312 matrixTitle : "间隔学习总表" ,
308313 resetMatrix : "清空表格勾选" ,
@@ -344,6 +349,7 @@ const copy = {
344349 en : {
345350 brandLine : "AI coding engineering workflow" ,
346351 plannerMode : "Checklist" ,
352+ scheduleMode : "Plan" ,
347353 readerMode : "Reader" ,
348354 navKicker : "Feynman Loop" ,
349355 navTitle : "19 Chapters · 36-Day Feynman Spacing" ,
@@ -368,6 +374,10 @@ const copy = {
368374 noteKicker : "Teach Back" ,
369375 noteTitle : "Feynman Draft" ,
370376 notePlaceholder : "I would explain today's material to a friend starting AI coding like this..." ,
377+ scheduleKicker : "Learning Plan" ,
378+ scheduleTitle : "36-Day Learning Plan" ,
379+ scheduleSummary : "One new chapter per day; due reviews return on a 2-3-5-7 cadence." ,
380+ scheduleOpenDay : "Today's checklist" ,
371381 matrixKicker : "Schedule Table" ,
372382 matrixTitle : "Spaced Learning Table" ,
373383 resetMatrix : "Clear table checks" ,
@@ -508,12 +518,14 @@ const els = {
508518 body : document . body ,
509519 brandLine : document . querySelector ( "#brand-line" ) ,
510520 plannerModeLabel : document . querySelector ( "#planner-mode-label" ) ,
521+ scheduleModeLabel : document . querySelector ( "#schedule-mode-label" ) ,
511522 readerModeLabel : document . querySelector ( "#reader-mode-label" ) ,
512523 plannerView : document . querySelector ( "#planner-view" ) ,
524+ scheduleView : document . querySelector ( "#schedule-view" ) ,
513525 readerView : document . querySelector ( "#reader-view" ) ,
514526 plannerNav : document . querySelector ( "#planner-nav" ) ,
515527 readerNav : document . querySelector ( "#reader-nav" ) ,
516- modeButtons : [ ...document . querySelectorAll ( "button[data-mode]" ) ] ,
528+ modeButtons : [ ...document . querySelectorAll ( ".view-toggle button[data-mode]" ) ] ,
517529 langButtons : [ ...document . querySelectorAll ( "button[data-lang]" ) ] ,
518530 pdf : document . querySelector ( "#pdf-link" ) ,
519531 plannerNavKicker : document . querySelector ( "#planner-nav-kicker" ) ,
@@ -554,6 +566,10 @@ const els = {
554566 noteKicker : document . querySelector ( "#note-kicker" ) ,
555567 noteTitle : document . querySelector ( "#note-title" ) ,
556568 note : document . querySelector ( "#explain-note" ) ,
569+ scheduleKicker : document . querySelector ( "#schedule-kicker" ) ,
570+ scheduleTitle : document . querySelector ( "#schedule-title" ) ,
571+ scheduleSummary : document . querySelector ( "#schedule-summary" ) ,
572+ scheduleOpenDayLabel : document . querySelector ( "#schedule-open-day-label" ) ,
557573 checklistKicker : document . querySelector ( "#checklist-kicker" ) ,
558574 checklistTitle : document . querySelector ( "#checklist-title" ) ,
559575 resetDay : document . querySelector ( "#reset-day-button" ) ,
@@ -588,7 +604,9 @@ function preferredLanguage() {
588604function preferredMode ( ) {
589605 const params = new URLSearchParams ( window . location . search ) ;
590606 const requested = params . get ( "view" ) || params . get ( "mode" ) ;
591- return requested === "reader" || requested === "read" ? "reader" : "planner" ;
607+ if ( requested === "reader" || requested === "read" ) return "reader" ;
608+ if ( requested === "schedule" || requested === "plan" ) return "schedule" ;
609+ return "planner" ;
592610}
593611
594612function preferredDay ( ) {
@@ -793,6 +811,7 @@ function setLanguageChrome(lang) {
793811 document . documentElement . lang = lang === "zh" ? "zh-CN" : "en" ;
794812 els . brandLine . textContent = text . brandLine ;
795813 els . plannerModeLabel . textContent = text . plannerMode ;
814+ els . scheduleModeLabel . textContent = text . scheduleMode ;
796815 els . readerModeLabel . textContent = text . readerMode ;
797816 els . pdf . href = doc . pdf ;
798817 els . pdf . title = text . pdf ;
@@ -814,11 +833,13 @@ function setLanguageChrome(lang) {
814833}
815834
816835function setMode ( mode , shouldUpdateUrl = true ) {
817- state . mode = mode === "reader" ? "reader" : "planner" ;
836+ const modes = new Set ( [ "planner" , "schedule" , "reader" ] ) ;
837+ state . mode = modes . has ( mode ) ? mode : "planner" ;
818838 els . body . dataset . mode = state . mode ;
819839 els . plannerView . hidden = state . mode !== "planner" ;
840+ els . scheduleView . hidden = state . mode !== "schedule" ;
820841 els . readerView . hidden = state . mode !== "reader" ;
821- els . plannerNav . hidden = state . mode !== "planner ";
842+ els . plannerNav . hidden = state . mode === "reader ";
822843 els . readerNav . hidden = state . mode !== "reader" ;
823844
824845 els . modeButtons . forEach ( ( button ) => {
@@ -836,7 +857,7 @@ function updateUrl() {
836857 const params = new URLSearchParams ( window . location . search ) ;
837858 params . set ( "lang" , state . lang ) ;
838859 params . set ( "day" , String ( state . day ) ) ;
839- params . set ( "view" , state . mode === "reader" ? "reader" : "planner" ) ;
860+ params . set ( "view" , state . mode ) ;
840861 const hash = state . mode === "reader" ? window . location . hash : "" ;
841862 window . history . replaceState ( null , "" , `${ window . location . pathname } ?${ params . toString ( ) } ${ hash } ` ) ;
842863}
@@ -958,9 +979,6 @@ function renderPlanner() {
958979 els . overallStatLabel . textContent = text . overallStat ;
959980 els . scopeKicker . textContent = text . scopeKicker ;
960981 els . scopeTitle . textContent = text . scopeTitle ;
961- els . matrixKicker . textContent = text . matrixKicker ;
962- els . matrixTitle . textContent = text . matrixTitle ;
963- els . resetMatrixLabel . textContent = text . resetMatrix ;
964982 els . noteKicker . textContent = text . noteKicker ;
965983 els . noteTitle . textContent = text . noteTitle ;
966984 els . note . placeholder = text . notePlaceholder ;
@@ -973,13 +991,27 @@ function renderPlanner() {
973991 els . note . value = getStoredText ( noteId ( state . day ) ) ;
974992
975993 renderDayList ( ) ;
976- renderScheduleTable ( ) ;
977994 renderScope ( ) ;
978995 renderChecklist ( ) ;
979996 updatePlannerProgress ( ) ;
980997 window . lucide ?. createIcons ( ) ;
981998}
982999
1000+ function renderSchedulePlan ( ) {
1001+ const text = copy [ state . lang ] ;
1002+
1003+ els . scheduleKicker . textContent = text . scheduleKicker ;
1004+ els . scheduleTitle . textContent = text . scheduleTitle ;
1005+ els . scheduleSummary . textContent = text . scheduleSummary ;
1006+ els . scheduleOpenDayLabel . textContent = text . scheduleOpenDay ;
1007+ els . matrixKicker . textContent = text . matrixKicker ;
1008+ els . matrixTitle . textContent = text . matrixTitle ;
1009+ els . resetMatrixLabel . textContent = text . resetMatrix ;
1010+
1011+ renderScheduleTable ( ) ;
1012+ window . lucide ?. createIcons ( ) ;
1013+ }
1014+
9831015function renderDayList ( ) {
9841016 const text = copy [ state . lang ] ;
9851017 els . dayList . innerHTML = "" ;
@@ -1289,6 +1321,7 @@ function setDay(day, shouldUpdateUrl = true) {
12891321 state . day = next ;
12901322 setStoredText ( "feynman:v4:last-day" , String ( next ) ) ;
12911323 renderPlanner ( ) ;
1324+ renderSchedulePlan ( ) ;
12921325 if ( shouldUpdateUrl ) updateUrl ( ) ;
12931326 window . scrollTo ( { top : 0 , behavior : "smooth" } ) ;
12941327}
@@ -1297,6 +1330,7 @@ function resetDay(day) {
12971330 getDayTaskDefs ( day ) . forEach ( ( task ) => removeStored ( task . id ) ) ;
12981331 removeStored ( noteId ( day ) ) ;
12991332 renderPlanner ( ) ;
1333+ renderSchedulePlan ( ) ;
13001334}
13011335
13021336function resetAllProgress ( ) {
@@ -1308,6 +1342,7 @@ function resetAllProgress() {
13081342 removeStored ( noteId ( day ) ) ;
13091343 }
13101344 renderPlanner ( ) ;
1345+ renderSchedulePlan ( ) ;
13111346}
13121347
13131348function resetMatrixProgress ( ) {
@@ -1316,13 +1351,14 @@ function resetMatrixProgress() {
13161351 for ( let day = 1 ; day <= PLAN_DAY_COUNT ; day += 1 ) {
13171352 getScheduleMatrixItems ( day ) . forEach ( ( item ) => removeStored ( item . id ) ) ;
13181353 }
1319- renderScheduleTable ( ) ;
1354+ renderSchedulePlan ( ) ;
13201355}
13211356
13221357async function loadGuide ( lang , shouldUpdateUrl = true ) {
13231358 state . lang = lang ;
13241359 setLanguageChrome ( lang ) ;
13251360 renderPlanner ( ) ;
1361+ renderSchedulePlan ( ) ;
13261362 els . article . classList . add ( "loading" ) ;
13271363 els . article . innerHTML = copy [ lang ] . loading ;
13281364 els . status . textContent = `${ docs [ lang ] . status } · loading` ;
@@ -1527,7 +1563,11 @@ document.addEventListener("click", (event) => {
15271563
15281564 const dayButton = event . target . closest ( "button[data-day]" ) ;
15291565 if ( dayButton ) {
1566+ const isScheduleDay = Boolean ( dayButton . closest ( "#schedule-table" ) ) ;
15301567 setDay ( Number ( dayButton . dataset . day ) ) ;
1568+ if ( isScheduleDay ) {
1569+ setMode ( "planner" ) ;
1570+ }
15311571 return ;
15321572 }
15331573
@@ -1586,5 +1626,6 @@ state.mode = preferredMode();
15861626state . day = preferredDay ( ) ;
15871627setLanguageChrome ( state . lang ) ;
15881628renderPlanner ( ) ;
1629+ renderSchedulePlan ( ) ;
15891630setMode ( state . mode , false ) ;
15901631state . guidePromise = loadGuide ( state . lang , false ) . catch ( showError ) ;
0 commit comments