@@ -7,7 +7,8 @@ type CheckResult = { ok: boolean; details: string }
77// 答えの定義
88const ANSWERS = {
99 p1 : "すばらしい。" ,
10- p2 : "./images/star5.png"
10+ p2 : "./images/star5.png" ,
11+ p3Visible : false ,
1112}
1213
1314function App ( ) {
@@ -20,9 +21,10 @@ function App() {
2021 // イベントリスナー内で最新の step を参照するための Ref
2122 const stepRef = useRef ( step )
2223 // 各ステップの初期値を保持するベースライン
23- const baselineRef = useRef < { p1 : string | null ; p2 : string | null } > ( {
24+ const baselineRef = useRef < { p1 : string | null ; p2 : string | null ; p3Visible : boolean | null } > ( {
2425 p1 : null ,
2526 p2 : null ,
27+ p3Visible : null ,
2628 } )
2729
2830 // state が変わったら ref も更新しておく
@@ -42,26 +44,17 @@ function App() {
4244
4345 port . onMessage . addListener ( ( msg ) => {
4446 if ( msg ?. type === 'DOM_VALUE_UPDATE' ) {
45- const { p1, p2 } = msg . values
47+ const { p1, p2, p3Visible } = msg . values
4648 const currentStep = stepRef . current
4749
48-
4950 if ( currentStep === 1 ) {
50- // 初回ロード時の値をベースラインとして記憶
5151 if ( baselineRef . current . p1 === null ) {
5252 baselineRef . current . p1 = p1
5353 return
5454 }
55-
56- // ベースラインから変化があった場合のみ判定
5755 if ( p1 !== baselineRef . current . p1 ) {
5856 const isCorrect = p1 === ANSWERS . p1
59- setResult ( {
60- ok : isCorrect ,
61- details : isCorrect ? `一致: "${ p1 } "` : `不一致: "${ p1 } "`
62- } )
63-
64- // 正解なら2秒後に次の問題へ
57+ setResult ( { ok : isCorrect , details : isCorrect ? `一致: "${ p1 } "` : `不一致: "${ p1 } "` } )
6558 if ( isCorrect ) {
6659 setTimeout ( ( ) => {
6760 setStep ( 2 )
@@ -71,32 +64,47 @@ function App() {
7164 }
7265 }
7366 }
74-
7567
7668 if ( currentStep === 2 ) {
7769 if ( baselineRef . current . p2 === null ) {
7870 baselineRef . current . p2 = p2
7971 return
8072 }
81-
8273 if ( p2 !== baselineRef . current . p2 ) {
83-
8474 const isCorrect = p2 . includes ( ANSWERS . p2 )
75+ setResult ( { ok : isCorrect , details : isCorrect ? `一致: (${ p2 } )` : `不一致: (${ p2 } )` } )
76+ if ( isCorrect ) {
77+ setTimeout ( ( ) => {
78+ setStep ( 3 )
79+ setResult ( null )
80+ baselineRef . current . p3Visible = p3Visible
81+ } , 2000 )
82+ }
83+ }
84+ }
85+
86+ // 問題3のロジック
87+ if ( currentStep === 3 ) {
88+ if ( baselineRef . current . p3Visible === null ) {
89+ baselineRef . current . p3Visible = p3Visible
90+ return
91+ }
92+ if ( p3Visible !== baselineRef . current . p3Visible ) {
93+ const isCorrect = p3Visible === ANSWERS . p3Visible
8594 setResult ( {
8695 ok : isCorrect ,
87- details : isCorrect ? `一致: ( ${ p2 } ) ` : `不一致: ( ${ p2 } ) `
96+ details : isCorrect ? `要素が非表示になりました ` : `要素はまだ表示されています `
8897 } )
89- // ※ここでさらに step3 へ遷移させることも可能
9098 }
9199 }
92100 }
93101 } )
94102
95103 port . onDisconnect . addListener ( ( ) => {
96- baselineRef . current = { p1 : null , p2 : null }
104+ baselineRef . current = { p1 : null , p2 : null , p3Visible : null }
97105 port = null
98106 setResult ( null )
99- setStep ( 1 ) // 接続が切れたら最初に戻す
107+ setStep ( 1 )
100108 } )
101109 } catch ( e : any ) {
102110 setError ( e ?. message ?? String ( e ) )
@@ -109,7 +117,7 @@ function App() {
109117 if ( port ) {
110118 try { port . disconnect ( ) } catch { }
111119 }
112- baselineRef . current = { p1 : null , p2 : null }
120+ baselineRef . current = { p1 : null , p2 : null , p3Visible : null }
113121 }
114122 } , [ ] )
115123
@@ -118,34 +126,36 @@ function App() {
118126 < div className = "container" >
119127 { error && < p style = { { color : 'red' } } > Error: { error } </ p > }
120128
121- { /* ステップ1の表示 */ }
122129 { step === 1 && (
123130 < div >
124131 < h2 > 問題1</ h2 >
125132 < p > レビューの「とにかくひどい。」を「すばらしい。」に書き換えてみよう!</ p >
126- { result && (
127- < div className = { result . ok ? "result-ok" : "result-ng" } >
128- < h3 > 判定: { result . ok ? '正解!' : '不正解' } </ h3 >
129- < p > { result . details } </ p >
130- { result . ok && < p > 次の問題へ進みます...</ p > }
131- </ div >
132- ) }
133+ { result && < div className = { result . ok ? "result-ok" : "result-ng" } > < h3 > 判定: { result . ok ? '正解!' : '不正解' } </ h3 > < p > { result . details } </ p > { result . ok && < p > 次の問題へ進みます...</ p > } </ div > }
133134 { ! result && < p className = "hint" > ヒント:開発者ツールを使って、レビューに当たる要素を探してみよう。</ p > }
134135 </ div >
135136 ) }
136137
137- { /* ステップ2の表示 */ }
138138 { step === 2 && (
139139 < div >
140140 < h2 > 問題2</ h2 >
141141 < p > 星1の画像(star1.png)の < code > src</ code > を書き換えて、星5 (star5.png) にしてみよう!</ p >
142+ { result && < div className = { result . ok ? "result-ok" : "result-ng" } > < h3 > 判定: { result . ok ? '正解!' : '不正解' } </ h3 > < p > { result . details } </ p > { result . ok && < p > 次の問題へ進みます...</ p > } </ div > }
143+ { ! result && < p className = "hint" > ヒント:imgタグの src 属性を探そう。</ p > }
144+ </ div >
145+ ) }
146+
147+ { /* ステップ3の表示 */ }
148+ { step === 3 && (
149+ < div >
150+ < h2 > 問題3</ h2 >
151+ < p > 一つ目のレビューを、CSSを使って非表示にしてみよう!</ p >
142152 { result && (
143153 < div className = { result . ok ? "result-ok" : "result-ng" } >
144154 < h3 > 判定: { result . ok ? '正解!' : '不正解' } </ h3 >
145155 < p > { result . details } </ p >
146156 </ div >
147157 ) }
148- { ! result && < p className = "hint" > ヒント:imgタグの src 属性を探そう 。</ p > }
158+ { ! result && < p className = "hint" > ヒント:DevToolsのスタイルパネルで < code > display: none; </ code > を追加してみよう 。</ p > }
149159 </ div >
150160 ) }
151161 </ div >
0 commit comments