import { useState } from "react";
const chapters = [
{
id: 0, emoji: "๐ต", title: "์์ด๋ธํค์ด ๋ญ์์?",
color: "#7F77DD", light: "#EEEDFE", dark: "#3C3489",
render: () => {
const [flip, setFlip] = useState(null);
const cards = [
{ q: "์์ด๋ธํค์\n๋ญ์์?", a: "์ปดํจํฐ๋ก ์์
์ ๋ง๋๋ ํ๋ก๊ทธ๋จ์ด์์!\n๋ ๊ณ ์ฒ๋ผ ์๋ฆฌ ๋ธ๋ก์ ์์์ ๋
ธ๋๋ฅผ ๋ง๋ค์ด์ ๐ฎ", emoji: "๐ป" },
{ q: "๋๊ฐ\n์จ์?", a: "DJ, ์๊ณก๊ฐ, ์ ํ๋ฒ, ๊ฒ์ ์์
๋ง๋๋ ์ฌ๋ ๋ฑ\n์ ์ธ๊ณ ์๋ฐฑ๋ง ๋ช
์ด ์ฐ๊ณ ์์ด์! ๐", emoji: "๐ค" },
{ q: "์ด๋ ต์ง\n์์์?", a: "์ฒ์์ ๋ฏ์ค์ง๋ง ์ฐจ๊ทผ์ฐจ๊ทผ ํ๋ฉด ๋ผ์!\n์ด ๊ฐ์ด๋๋ฅผ ๋ฐ๋ผํ๋ฉด ๋๊ตฌ๋ ํ ์ ์์ด์ ๐ช", emoji: "๐" },
{ q: "๋ญ ๋ง๋ค\n์ ์์ด์?", a: "ํํฉ, ํ, ์ ์์์
, ๊ฒ์ BGM, ์ ํ๋ธ ๋ฐฐ๊ฒฝ์์
\n๋ญ๋ ๋ง๋ค ์ ์์ด์! ๐ธ", emoji: "๐ผ" },
];
return (
๋๋ผ์ ์์
์ ์ฌ์ฅ๋ฐ๋์ด์์! ๐ซ
์ธ ๊ฐ์ง ์๋ฆฌ๋ง ์์ผ๋ฉด ๊ธฐ๋ณธ ๋๋ผ์ด ์์ฑ๋ผ์.
{rows.map(r => (
{r.emoji}
{r.name}
{r.desc}
))}
{beats.map(b => [0,1,2,3].map(s => (
{s === 0 ? `${b}๋ฐ` : ""}
)))}
{rows.map(row => (
{row.emoji} {row.name.split(" ")[0]}
{pads[row.key].map((on, i) => (
{i % 4 === 0 && i > 0 &&
}
toggle(row.key, i)}
style={{ width: 24, height: 24, borderRadius: 5, background: on ? row.color : "#333", border: `1.5px solid ${on ? row.color : "#444"}`, cursor: "pointer", transition: "all .1s", marginRight: 4 }} />
))}
))}
๐ฎ ์์ด๋ธํค์์ ํ๋ ๋ฒ!
1. MIDI ํธ๋ ๋ง๋ค๊ธฐ (์ฐํด๋ฆญ โ Insert MIDI Track)
2. ํ์ผ ์ฐฝ โ Drums โ ๋๋ผ ํท ๋๋๊ทธ
3. ํธ๋์ ํด๋ฆฝ ๋๋ธํด๋ฆญ ์์ฑ
4. ํด๋ฆฝ ๋๋ธํด๋ฆญ โ ํผ์๋
ธ ๋กค ์ด๋ฆผ
5. ์ ํจํด์ฒ๋ผ ์ํ ์ฐ๊ธฐ!
);
}
},
{
id: 3, emoji: "๐น", title: "์ฝ๋(ํ์) ์ดํดํ๊ธฐ",
color: "#7F77DD", light: "#EEEDFE", dark: "#3C3489",
render: () => {
const [selChord, setSelChord] = useState(0);
const [pressed, setPressed] = useState([]);
const notes = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B","C","D","E","F","G","A","B"];
const whiteKeys = [0,2,4,5,7,9,11,12,14,16,17,19,21,23];
const blackKeys = [1,3,null,6,8,10,null,13,15,null,18,20,22];
const blackLabels = ["C#","D#","","F#","G#","A#","","C#","D#","","F#","G#","A#"];
const chords = [
{ name: "C ์ฝ๋ (๋๋ฏธ์)", notes: ["C","E","G"], feel: "๋ฐ๊ณ ํ๋ณตํ ๋๋ โ๏ธ", color: "#7F77DD", indices: [0,4,7] },
{ name: "G ์ฝ๋ (์์๋ )", notes: ["G","B","D"], feel: "ํ์ฐจ๊ณ ์ ๋๋ ๋๋ ๐ช", color: "#1D9E75", indices: [7,11,14] },
{ name: "Am ์ฝ๋ (๋ผ๋๋ฏธ)", notes: ["A","C","E"], feel: "์ฌํ๊ณ ๊ฐ์ฑ์ ์ธ ๋๋ ๐", color: "#D85A30", indices: [9,12,16] },
{ name: "F ์ฝ๋ (ํ๋ผ๋)", notes: ["F","A","C"], feel: "๋ฐ๋ปํ๊ณ ์์ ์ ์ธ ๋๋ ๐ธ", color: "#BA7517", indices: [5,9,12] },
];
const ch = chords[selChord];
return (
์ฝ๋๋ ์ฌ๋ฌ ์์ ๋์์ ๋๋ฅด๋ ๊ฒ์ด์์!
์๋ค์ด ํจ๊ป ์ธ๋ฆฌ๋ฉด ํน๋ณํ ๊ฐ์ ์ด ์๊ฒจ์ ๐ญ
{chords.map((c, i) => (
setSelChord(i)}
style={{ padding: "10px 12px", borderRadius: 12, border: `2px solid ${selChord === i ? c.color : "#eee"}`, background: selChord === i ? `${c.color}18` : "#fff", cursor: "pointer" }}>
{c.name}
{c.feel}
))}
{/* ๊ฑด๋ฐ */}
{ch.color === "#7F77DD" ? "๐ฃ" : ch.color === "#1D9E75" ? "๐ข" : ch.color === "#D85A30" ? "๐ " : "๐ก"} {ch.name} โ ์ด ๊ฑด๋ฐ๋ค์ ๋์์ ๋๋ฌ์!
{/* ๊ตฌ์ฑ์ */}
{ch.notes.map((n, i) => (
{n}
))}
๐น ์์ด๋ธํค์์ ์ฝ๋ ์ฐ๋ ๋ฒ!
ํผ์๋
ธ ๋กค์์ ๊ฐ์ ์์น์ ์ฌ๋ฌ ์ํ๋ฅผ ์ธ๋ก๋ก ์์ผ๋ฉด ์ฝ๋๊ฐ ๋ผ์!
C์ฝ๋ = C4 + E4 + G4 ๋์์ ํด๋ฆญ!
);
}
},
{
id: 4, emoji: "๐ต", title: "๋ฉ๋ก๋ ๋ง๋ค๊ธฐ",
color: "#BA7517", light: "#FAEEDA", dark: "#633806",
render: () => {
const noteSeq = [
{ note: "๋", key: "C", y: 70, color: "#7F77DD", len: 60 },
{ note: "๋ ", key: "D", y: 55, color: "#7F77DD", len: 45 },
{ note: "๋ฏธ", key: "E", y: 40, color: "#1D9E75", len: 45 },
{ note: "์", key: "G", y: 25, color: "#1D9E75", len: 60 },
{ note: "๋ฏธ", key: "E", y: 40, color: "#D85A30", len: 45 },
{ note: "๋ ", key: "D", y: 55, color: "#D85A30", len: 45 },
{ note: "๋", key: "C", y: 70, color: "#BA7517", len: 80 },
];
const rules = [
{ icon: "๐", title: "์งง๊ฒ ์์", body: "2~4๊ฐ ์์ผ๋ก ์์ํด์.\n'๋๋ ๋ฏธ' ์ฒ๋ผ ์งง์ ํจํด์ ๋ง๋ค์ด์." },
{ icon: "โ๏ธ", title: "์ฌ๋ผ๊ฐ๋ค ๋ด๋ ค์ค๊ธฐ", body: "์์ด ์ฌ๋ผ๊ฐ๋ฉด ์ ๋๊ณ \n๋ด๋ ค์ค๋ฉด ์์ ๋๋ ๋๋์ด์์." },
{ icon: "โธ๏ธ", title: "์ฌ๋ ๊ตฌ๊ฐ ๋ฃ๊ธฐ", body: "๊ณ์ ์๋ง ๋ฃ์ผ๋ฉด ๋ต๋ตํด์.\n์ค๊ฐ์ ์ผํ(๋น ๊ณต๊ฐ)๋ฅผ ๋ฃ์ด์." },
{ icon: "๐", title: "๋ฐ๋ณต + ๋ณํ", body: "๊ฐ์ ํจํด์ ๋ฐ๋ณตํ๋\n๋ง์ง๋ง์ ์ด์ง ๋ฌ๋ฆฌ ๋๋ด์." },
];
let xPos = 10;
return (
๋ฉ๋ก๋๋ ์๋ค์ด ์ด์ด์ง๋ ์ ์จ์ด์์!
์ด๋ฆด ๋ ํฅ์ผ๊ฑฐ๋ฆฌ๋ ๋
ธ๋๊ฐ ๋ฐ๋ก ๋ฉ๋ก๋์์ ๐ถ
{/* ๋ฉ๋ก๋ ์๊ฐํ */}
๐ต ๋๋ ๋ฏธ์๋ฏธ๋ ๋ โ ์ฌ๋ผ๊ฐ๋ค๊ฐ ๋ด๋ ค์ค๋ ๋ฉ๋ก๋
{rules.map((r, i) => (
{r.icon}
{r.title}
{r.body}
))}
๐น ์์ด๋ธํค์์ ๋ฉ๋ก๋ ์ฐ๋ ๋ฒ!
ํผ์๋
ธ ๋กค โ Scale ๋ฒํผ ON โ C์ฅ์กฐ ์ ํ
โ ๋
ธ๋ ๊ฑด๋ฐ๋ง ํด๋ฆญํ๋ฉด ์ ์ดํ ์์ด ๋ฉ๋ก๋ ์์ฑ!
);
}
},
{
id: 5, emoji: "๐๏ธ", title: "๋
ธ๋ ๊ตฌ์กฐ ๋ง๋ค๊ธฐ",
color: "#185FA5", light: "#E6F1FB", dark: "#0C447C",
render: () => {
const [selSec, setSelSec] = useState(null);
const sections = [
{ label: "์ธํธ๋ก", bars: "4๋ง๋", color: "#888", desc: "๊ณก์ ์์์ด์์!\n๋๋ผ๋ง ๋์ค๊ฑฐ๋ ์์ฃผ ์กฐ์ฉํ๊ฒ ์์ํด์.\n์ฒญ์ค์ด '์ด? ๋ญ ๋
ธ๋์ง?' ํ๊ฒ ๋ง๋ค์ด์ ๐คซ", emoji: "๐ฌ", energy: 2 },
{ label: "๋ฒ์ค", bars: "8๋ง๋", color: "#7F77DD", desc: "์ด์ผ๊ธฐ๋ฅผ ๋ค๋ ค์ฃผ๋ ๋ถ๋ถ์ด์์!\n๋๋ผ+๋ฒ ์ด์ค+๋ฉ๋ก๋๊ฐ ๋ชจ๋ ๋ค์ด์์.\n์ฝ๋ฌ์ค๋ณด๋ค ์กฐ์ฉํด์ ๐", emoji: "๐", energy: 5 },
{ label: "์ฝ๋ฌ์ค", bars: "8๋ง๋", color: "#D85A30", desc: "๊ฐ์ฅ ์ ๋๋ ๋ถ๋ถ์ด์์!\n๋ชจ๋ ์
๊ธฐ๊ฐ ์ต๋๋ก ๋์์.\n'ํ
'์ด๋ผ๊ณ ๋ ๋ถ๋ฌ์ ๐ฅ", emoji: "๐", energy: 9 },
{ label: "๋ฒ์ค2", bars: "8๋ง๋", color: "#7F77DD", desc: "๋ฒ์ค๊ฐ ๋ค์ ๋์์!\n์กฐ๊ธ ๋ค๋ฅธ ๋ด์ฉ์ด์ง๋ง ๋น์ทํ ๋๋์ด์์ ๐", emoji: "๐", energy: 5 },
{ label: "์ฝ๋ฌ์ค2", bars: "8๋ง๋", color: "#D85A30", desc: "์ฝ๋ฌ์ค๊ฐ ๋ค์! ๋ ๊ฐํ๊ฒ!\n์
๊ธฐ๋ฅผ ํ๋ ๋ ์ถ๊ฐํด์ ํ์ฑํ๊ฒ ํด์ ๐", emoji: "๐", energy: 10 },
{ label: "์์ํธ๋ก", bars: "4๋ง๋", color: "#888", desc: "๊ณก์ด ๋๋๊ฐ์!\n์๋ฆฌ๊ฐ ์์ํ ์์์ง๊ฑฐ๋ ๊ฐ์๊ธฐ ๋์ด์.\n'ํ์ด๋์์'์ด๋ผ๊ณ ๋ ํด์ ๐", emoji: "๐
", energy: 2 },
];
const sel = selSec !== null ? sections[selSec] : null;
return (
๋
ธ๋๋ ์ด์ผ๊ธฐ์ฒ๋ผ ์์๊ฐ ์์ด์!
์์ โ ์ค๊ฐ โ ํด๋ผ์ด๋งฅ์ค โ ๋ ์ด๋ฐ ํ๋ฆ์ด์์ ๐
{/* ๊ตฌ์กฐ ๋ฐ */}
{sections.map((sec, i) => (
setSelSec(selSec === i ? null : i)}
style={{ flex: 1, background: selSec === i ? sec.color : `${sec.color}88`, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", borderRight: "1px solid rgba(255,255,255,.2)", transition: "all .2s" }}>
{sec.emoji}
{sec.label}
))}
{/* ์๋์ง ๊ทธ๋ํ */}
{sel ? (
{sel.emoji} {sel.label} ({sel.bars})
{sel.desc}
) : (
์ ๊ตฌ๊ฐ์ ๋๋ฌ๋ณด์ธ์! โ๏ธ
)}
๐๏ธ ์์ด๋ธํค์์ ๊ตฌ์กฐ ๋ง๋๋ ๋ฒ!
์ด๋ ์ธ์ง๋จผํธ ๋ทฐ์์ ํด๋ฆฝ์ ๋ณต์ฌ(Ctrl+D)ํด์
๊ฐ ์น์
์ ๋ถ์ฌ๋ฃ๊ธฐ ํ๋ฉด ๋ผ์!
);
}
},
{
id: 6, emoji: "๐๏ธ", title: "์๋ฆฌ ๋ค๋ฌ๊ธฐ (๋ฏน์ฑ)",
color: "#993556", light: "#FBEAF0", dark: "#72243E",
render: () => {
const [vols, setVols] = useState({ drum: 75, bass: 65, chord: 55, melody: 60 });
const tracks = [
{ key: "drum", label: "๐ฅ ๋๋ผ", color: "#7F77DD", desc: "๊ฐ์ฅ ์ค์ฌ!" },
{ key: "bass", label: "๐ธ ๋ฒ ์ด์ค", color: "#1D9E75", desc: "๋๋ผ๋ณด๋ค ์ด์ง ๋ฎ๊ฒ" },
{ key: "chord", label: "๐น ์ฝ๋", color: "#BA7517", desc: "๋ฐฐ๊ฒฝ ๋๋์ผ๋ก" },
{ key: "melody", label: "๐ต ๋ฉ๋ก๋", color: "#D85A30", desc: "์ ๋ค๋ ค์ผ ํด์" },
];
const rules = [
{ emoji: "๐", title: "๋ณผ๋ฅจ ๊ท ํ", body: "๋๋ผ์ด ์ ์ผ ํฌ๊ณ \n๋ฒ ์ด์ค โ ๋ฉ๋ก๋ โ ์ฝ๋ ์์๋ก ์กฐ์ ํด์" },
{ emoji: "โ๏ธ", title: "EQ (์ดํ๋ผ์ด์ )", body: "์
๊ธฐ๋ง๋ค ์๊ธฐ ์ฃผํ์ ์์ญ์ด ์์ด์.\n๊ฒน์น๋ฉด ๋ญ๊ฐ์ง๋๊น ์๋ผ์ค์" },
{ emoji: "๐๏ธ", title: "๋ฆฌ๋ฒ๋ธ", body: "์๋ฆฌ์ ๊ณต๊ฐ๊ฐ์ ์ฃผ๋ ๊ฑฐ์์.\n์ค์์ค์์ ๋
ธ๋ํ๋ ๊ฒ์ฒ๋ผ ์ธ๋ฆผ์ ์ถ๊ฐํด์" },
{ emoji: "โก", title: "์ปดํ๋ ์", body: "๋๋ฌด ํฐ ์๋ฆฌ๋ฅผ ์๋์ผ๋ก ๋๋ฌ์ค์.\n์๋์ด ๊ณ ๋ฅด๊ฒ ์ ์ง๋ผ์" },
];
return (
๋ฏน์ฑ์ ๋ชจ๋ ์๋ฆฌ์ ๋ณผ๋ฅจ๊ณผ ์๊น์ ์กฐ์ ํ๋ ๊ฑฐ์์!
์๋ฆฌ๋ก ์น๋ฉด ๊ฐ์ ๋ง์ถ๋ ๊ฒ ๊ฐ์์ ๐ณ
{/* ๊ฐ์ ๋ฏน์ */}
๐๏ธ ์ฌ๋ผ์ด๋๋ฅผ ์์ง์ฌ์ ๋ณผ๋ฅจ์ ์กฐ์ ํด๋ด์!
{tracks.map(t => (
{t.label}
setVols(v => ({ ...v, [t.key]: +e.target.value }))}
style={{ flex: 1, accentColor: t.color }} />
{vols[t.key]}
))}
{rules.map((r, i) => (
{r.emoji}
{r.title}
{r.body}
))}
โ ๏ธ ๋ง์คํฐ ๋ณผ๋ฅจ ์กฐ์ฌ!
๋ง์คํฐ ํธ๋ ๋ฏธํฐ๊ฐ ๋นจ๊ฐ์ = ์๋ฆฌ ๊นจ์ง!
๋นจ๊ฐ๋ถ ์ผ์ง๋ฉด ๊ฐ ํธ๋ ๋ณผ๋ฅจ์ ๋ฎ์ถฐ์ผ ํด์ ๐ด
);
}
},
{
id: 7, emoji: "โจ๏ธ", title: "๊ผญ ์ธ์ธ ๋จ์ถํค",
color: "#1D9E75", light: "#E1F5EE", dark: "#085041",
render: () => {
const [quiz, setQuiz] = useState(false);
const [qIdx, setQIdx] = useState(0);
const [sel, setSel] = useState(null);
const shortcuts = [
{ key: "Space", desc: "โถ ์ฌ์ / โ ์ ์ง", emoji: "โถ๏ธ" },
{ key: "Tab", desc: "์ธ์
๋ทฐ โ ์ด๋ ์ธ์ง ๋ทฐ ์ ํ", emoji: "๐" },
{ key: "Ctrl + Z", desc: "์ค์ ๋๋๋ฆฌ๊ธฐ (์ทจ์)", emoji: "โฉ๏ธ" },
{ key: "Ctrl + S", desc: "์ ์ฅํ๊ธฐ", emoji: "๐พ" },
{ key: "Ctrl + D", desc: "ํด๋ฆฝ ๋ณต์ ", emoji: "๐" },
{ key: "Ctrl + A", desc: "์ ์ฒด ์ ํ", emoji: "โ๏ธ" },
{ key: "Ctrl + U", desc: "ํํ์ด์ฆ (๋ฐ์ ์ ๋ ฌ)", emoji: "๐" },
{ key: "Ctrl + ,", desc: "์ค์ (Preferences) ์ด๊ธฐ", emoji: "โ๏ธ" },
{ key: "M", desc: "์ปดํจํฐ ํค๋ณด๋๋ก ํผ์๋
ธ ์ฐ์ฃผ", emoji: "๐น" },
{ key: "Ctrl + Shift + R", desc: "์์ฑ ํ์ผ ๋ด๋ณด๋ด๊ธฐ(Export)", emoji: "๐ค" },
];
const quizItems = [
{ q: "์ค์ํ์ ๋ ๋๋๋ฆฌ๋ ค๋ฉด?", a: "Ctrl + Z", opts: ["Ctrl + Z", "Ctrl + S", "Tab", "Space"] },
{ q: "์ ์ฅํ ๋ ์ฐ๋ ๋จ์ถํค๋?", a: "Ctrl + S", opts: ["Ctrl + D", "Ctrl + S", "Ctrl + A", "Ctrl + Z"] },
{ q: "์ฌ์/์ ์ง ๋จ์ถํค๋?", a: "Space", opts: ["Tab", "M", "Space", "Ctrl + D"] },
{ q: "๋ ๋ทฐ๋ฅผ ์ ํํ๋ ๋จ์ถํค๋?", a: "Tab", opts: ["Space", "Tab", "Ctrl + Z", "M"] },
{ q: "ํ์ผ์ ๋ด๋ณด๋ผ ๋๋?", a: "Ctrl + Shift + R", opts: ["Ctrl + S", "Ctrl + D", "Ctrl + Shift + R", "Ctrl + A"] },
];
const q = quizItems[qIdx];
const handleAns = (ans) => {
setSel(ans);
setTimeout(() => {
if (qIdx < quizItems.length - 1) { setQIdx(i => i + 1); setSel(null); }
else { setQuiz(false); setQIdx(0); setSel(null); }
}, 1200);
};
return (
์ด ๋จ์ถํค๋ค๋ง ์ธ์๋ ์์
์๋๊ฐ 2๋ฐฐ ๋นจ๋ผ์ ธ์!
์ฒ์์ ์ธ์ฐ๊ธฐ ์ด๋ ต์ง๋ง ์ฐ๋ค ๋ณด๋ฉด ์์ด ๊ธฐ์ตํด์ ๐ค
{!quiz ? (
<>
{shortcuts.map((s, i) => (
{s.emoji}
{s.key.split(" + ").map((k, j) => (
{j > 0 && +}
{k}
))}
{s.desc}
))}
>
) : (
๋ฌธ์ {qIdx + 1} / {quizItems.length}
{q.q}
{q.opts.map((opt, i) => {
const isAns = opt === q.a;
const isSel = sel === opt;
let bg = "#fff", border = "#ddd", color = "#333";
if (sel !== null) {
if (isAns) { bg = "#E1F5EE"; border = "#1D9E75"; color = "#085041"; }
else if (isSel) { bg = "#FCEBEB"; border = "#E24B4A"; color = "#791F1F"; }
else { bg = "#f0f0f0"; color = "#aaa"; }
}
return (
);
})}
)}
);
}
},
{
id: 8, emoji: "๐", title: "์ฒซ ๊ณก ๋ง๋ค๊ธฐ ์์",
color: "#D85A30", light: "#FAECE7", dark: "#712B13",
render: () => {
const [done, setDone] = useState(Array(12).fill(false));
const toggle = i => setDone(d => d.map((v, idx) => idx === i ? !v : v));
const doneCount = done.filter(Boolean).length;
const steps = [
{ group: "๐ง ์ค๋น", color: "#7F77DD", items: ["์์ด๋ธํค ์ผ๊ธฐ", "Preferences โ ASIO ๋๋ผ์ด๋ฒ ์ค์ ", "์ ํ๋ก์ ํธ ๋ง๋ค๊ณ ์ ์ฅ (Ctrl+S)"] },
{ group: "๐ฅ ๋๋ผ", color: "#1D9E75", items: ["MIDI ํธ๋ ์ถ๊ฐ (Ctrl+Shift+T)", "ํ์ผ ์ฐฝ โ Drums โ ํท ๋๋๊ทธ", "8๋ง๋ ํด๋ฆฝ ๋ง๋ค๊ณ ํฅยท์ค๋ค์ดยทํ์ดํ ์ฐ๊ธฐ"] },
{ group: "๐ต ์์
", color: "#BA7517", items: ["์ฝ๋ ํธ๋ ์ถ๊ฐ โ ์
๊ธฐ ๋ก๋", "ํผ์๋
ธ ๋กค โ Scale ON โ ์ฝ๋ ์
๋ ฅ", "๋ฉ๋ก๋ ํธ๋ ์ถ๊ฐ โ ๋ฉ๋ก๋ ์ฐ๊ธฐ"] },
{ group: "๐๏ธ ์์ฑ", color: "#D85A30", items: ["์ด๋ ์ธ์ง๋จผํธ ๋ทฐ์์ ๊ตฌ์กฐ ๋ฐฐ์น (Tab)", "์คํ ๋ฉ์ด์
์ผ๋ก ๋ณผ๋ฅจ ์กฐ์ (Aํค)", "Ctrl+Shift+R โ WAV๋ก Export!"] },
];
let idx = 0;
return (
๐ผ
์ฒซ ๊ณก ์์ฑ ๋์ !
์๋ ๋จ๊ณ๋ฅผ ์์๋๋ก ํ๋ฉด ๊ณก์ด ์์ฑ๋ผ์!
{/* ์งํ๋ฅ */}
{steps.map((grp, gi) => (
{grp.group}
{grp.items.map((item, ii) => {
const i = idx++;
return (
toggle(i)}
style={{ display: "flex", alignItems: "flex-start", gap: 10, padding: "11px 13px", background: done[i] ? "#E1F5EE" : "#fff", borderRadius: 11, marginBottom: 6, border: `1.5px solid ${done[i] ? "#1D9E75" : "#eee"}`, cursor: "pointer", transition: "all .2s" }}>
{done[i] ? "โ" : i + 1}
{item}
);
})}
))}
{doneCount === 12 && (
๐
์ฒซ ๊ณก ์์ฑ! ๋๋จํด์!
์ด์ ์ง์ง ์์
ํ๋ก๋์๊ฐ ๋์ด์!
๊ณ์ ๋ง๋ค๋ค ๋ณด๋ฉด ์ค๋ ฅ์ด ์ฅ์ฅ ๋์ด์ ๐
)}
);
}
},
];
export default function App() {
const [active, setActive] = useState(0);
const ch = chapters[active];
return (
{/* ํค๋ */}
์ด๋ฑํ์๋ OK! ์์ด๋ธํค ๊ธฐ์ด
๐ผ ์์
๋ง๋ค๊ธฐ ์ฒซ๊ฑธ์
{active + 1}/{chapters.length} โ {ch.title}
{/* ํญ */}
{chapters.map((c, i) => (
))}
{/* ์นด๋ */}
{/* ์ด์ /๋ค์ */}
{active > 0 && (
)}
{active < chapters.length - 1 && (
)}
);
}