Spaces:
Running
Running
Update index.html
Browse files- index.html +705 -267
index.html
CHANGED
|
@@ -104,14 +104,18 @@
|
|
| 104 |
pointer-events: none;
|
| 105 |
background-color: #10b981;
|
| 106 |
}
|
| 107 |
-
.
|
| 108 |
min-height: 3rem;
|
| 109 |
}
|
| 110 |
-
.
|
| 111 |
cursor: pointer;
|
| 112 |
user-select: none;
|
| 113 |
transition: background-color 0.2s, transform 0.1s;
|
| 114 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
</style>
|
| 116 |
</head>
|
| 117 |
<body class="flex justify-center">
|
|
@@ -126,7 +130,6 @@
|
|
| 126 |
|
| 127 |
<script>
|
| 128 |
// --- 1. تعريف الأيقونات كـ SVG نصي ---
|
| 129 |
-
// (Icons definition remains the same)
|
| 130 |
const ICONS = {
|
| 131 |
Home: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>`,
|
| 132 |
Share2: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/><line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/></svg>`,
|
|
@@ -134,6 +137,7 @@
|
|
| 134 |
Settings: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.44a2 2 0 0 1-1.11 1.76l-.42.25a2 2 0 0 0-.83 1.57v.88a2 2 0 0 0 1.1 1.8l.42.25a2 2 0 0 1 1.11 1.76v.44a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.44a2 2 0 0 1 1.11-1.76l.42-.25a2 2 0 0 0 .83-1.57v-.88a2 2 0 0 0-1.1-1.8l-.42-.25a2 2 0 0 1-1.11-1.76V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
| 135 |
Info: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>`,
|
| 136 |
Menu: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>`,
|
|
|
|
| 137 |
ChevronRight: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><polyline points="9 18 15 12 9 6"/></svg>`,
|
| 138 |
Mic: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>`,
|
| 139 |
Volume2: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>`,
|
|
@@ -152,7 +156,6 @@
|
|
| 152 |
Gamepad: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12 21a2 2 0 0 1-2-2v-4H8a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h4V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4v4a2 2 0 0 1-2 2v2a2 2 0 0 1-2 2z"/><path d="M8 11h4V7H8z"/></svg>`,
|
| 153 |
BookOpen: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>`,
|
| 154 |
Brain: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12 5C6 5 3 7 3 12s3 7 9 7 9-2 9-7-3-7-9-7z"/><path d="M12 5c-3 0-5 2-5 5v2c0 3 2 5 5 5s5-2 5-5V10c0-3-2-5-5-5z"/></svg>`,
|
| 155 |
-
Pencil: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M17 3a2.85 2.85 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/><path d="M15 5l4 4"/></svg>`,
|
| 156 |
Repeat1: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="m19 14-4 4-4-4"/><path d="M15 18H8a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h12"/><path d="M10 10l4 4 4-4"/></svg>`,
|
| 157 |
WhatsApp: (cls) => ICONS.Share2(cls),
|
| 158 |
};
|
|
@@ -169,7 +172,7 @@
|
|
| 169 |
|
| 170 |
|
| 171 |
// --- 2. بيانات التطبيق الثابتة ---
|
| 172 |
-
|
| 173 |
const shuffleArray = (array) => {
|
| 174 |
const shuffled = [...array];
|
| 175 |
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
@@ -180,145 +183,144 @@
|
|
| 180 |
};
|
| 181 |
|
| 182 |
const APP_NAME = "Tifawin";
|
|
|
|
| 183 |
const WHATSAPP_LINK = "https://chat.whatsapp.com/J8bK9L0X4M7P2S1R6Q5T";
|
| 184 |
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
const tifinaghData = [
|
| 187 |
-
{ letter: 'ⴰ', word_arabic: 'جدار-ⴰⴳⴰⴷⵉⵔ', image: 'images/2947c16d27f8042f7d60783c6808519a.jpg', audio: 'audio/aman.mp3' },
|
| 188 |
-
{ letter: 'ⴱ', word_arabic: 'فراشة-ⵉⴱⵔⴱⵉⵍⵍⵓ', image: 'images/3fd6beebd231e2f325469a40b0831b59.jpg', audio: 'audio/barbi.mp3' },
|
| 189 |
-
{ letter: 'ⴳ', word_arabic: 'دخان-ⴰⴳⴳⵓ', image: 'images/c0094eb5dcc49d7cce573d42f270d8de.jpg', audio: 'audio/ca.mp3' },
|
| 190 |
-
{ letter: 'ⴷ', word_arabic: 'تمرة-ⵜⵉⵏⵉ', image: 'images/placeholder_date.jpg', audio: 'audio/da.mp3' },
|
| 191 |
-
{ letter: 'ⴹ', word_arabic: 'قدم-ⴰⴹⴰⵔ', image: 'images/placeholder_foot.jpg', audio: 'audio/dha.mp3' },
|
| 192 |
-
{ letter: 'ⴼ', word_arabic: 'عين-ⵜⵉⵟ', image: 'images/placeholder_eye.jpg', audio: 'audio/fa.mp3' },
|
| 193 |
-
{ letter: 'ⵀ', word_arabic: 'فم-ⴰⴽⵓⵎ', image: 'images/placeholder_mouth.jpg', audio: 'audio/ha.mp3' },
|
| 194 |
-
{ letter: 'ⵃ', word_arabic: 'قلب-ⵓⵍ', image: 'images/placeholder_heart.jpg', audio: 'audio/hha.mp3' },
|
| 195 |
-
{ letter: 'ⵇ', word_arabic: 'قمح-ⵉⵔⴷⵏ', image: 'images/placeholder_wheat.jpg', audio: 'audio/qa.mp3' },
|
| 196 |
-
{ letter: 'ⵅ', word_arabic: 'غيمة-ⴰⵙⴰⴼ', image: 'images/placeholder_cloud.jpg', audio: 'audio/kha.mp3' },
|
| 197 |
-
{ letter: 'ⵉ', word_arabic: 'شمس-ⴰⵢⵢⵓⵔ', image: 'images/placeholder_sun.jpg', audio: 'audio/i.mp3' },
|
| 198 |
-
{ letter: 'ⵊ', word_arabic: 'جبن-ⴰⵛⵛⴰⵔ', image: 'images/placeholder_cheese.jpg', audio: 'audio/ja.mp3' },
|
| 199 |
-
{ letter: 'ⴽ', word_arabic: 'صخرة-ⴰⴷⴳⴰⵏ', image: 'images/placeholder_rock.jpg', audio: 'audio/ka.mp3' },
|
| 200 |
-
{ letter: 'ⵍ', word_arabic: 'عسل-ⵜⴰⵎⵉⵎⵜ', image: 'images/placeholder_honey.jpg', audio: 'audio/la.mp3' },
|
| 201 |
-
{ letter: 'ⵎ', word_arabic: 'بحر-ⵉⵍⵍ', image: 'images/placeholder_sea.jpg', audio: 'audio/ma.mp3' },
|
| 202 |
-
{ letter: 'ⵏ', word_arabic: 'وجه-ⴰⵡⴷⴰⵎ', image: 'images/placeholder_face.jpg', audio: 'audio/na.mp3' },
|
| 203 |
-
{ letter: 'ⵖ', word_arabic: 'طائرة-ⴰⵢⵢⵓⵔ', image: 'images/placeholder_plane.jpg', audio: 'audio/gha.mp3' },
|
| 204 |
];
|
| 205 |
|
| 206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
const LEARNING_DATA = {
|
| 208 |
tifinaghLetters: tifinaghData.map(item => {
|
| 209 |
const parts = item.word_arabic.split('-');
|
| 210 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
}),
|
| 212 |
-
numbers:
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
|
|
|
| 218 |
tools: [{ main: 'ⴰⴽⵕⵕⴰⵊ', word: 'قلم رصاص', imageUrl: 'images/37b71533177feb9d55d55efba947309e.jpg', audioUrl: 'audio/schoolSupplies/pencil.mp3' }],
|
| 219 |
-
fruits:
|
| 220 |
-
{ main: 'ⵜⴰⴷⴼⴼⵓⵢⵜ', word: 'تفاحة', imageUrl: 'images/da1da4f2015a32322f547ae5fff5236c.jpg', audioUrl: 'audio/fruits/apple.mp3' },
|
| 221 |
-
{ main: 'ⵜⴰⴱⴰⵏⴰⵏⵜ', word: 'موز', imageUrl: 'images/placeholder_banana.jpg', audioUrl: 'audio/fruits/banana.mp3' },
|
| 222 |
-
{ main: 'ⴰⵡⵔⵉⵖ', word: 'برتقال', imageUrl: 'images/placeholder_orange.jpg', audioUrl: 'audio/fruits/orange.mp3' },
|
| 223 |
-
],
|
| 224 |
vegetables: [{ main: 'ⵜⴰⵎⴰⵟⵉⵛⵜ', word: 'طماطم', imageUrl: 'images/6056d9839a962b5a78cddc402ef88c09.jpg', audioUrl: 'audio/vegetables/tomato.mp3' }],
|
| 225 |
-
animals:
|
| 226 |
-
{ main: 'ⴰⵎⵓⵛⵛ', word: 'قط', imageUrl: 'images/cat.jpeg', audioUrl: 'audio/animaux.ogg' },
|
| 227 |
-
{ main: 'ⴰⵢⴷⵉ', word: 'كلب', imageUrl: 'images/124419894dcfde81ffbca1e072804c71.jpg', audioUrl: 'audio/dog.mp3' },
|
| 228 |
-
{ main: 'ⴰⵡⵉ', word: 'أسد', imageUrl: 'images/placeholder_lion.jpg', audioUrl: 'audio/lion.mp3' },
|
| 229 |
-
{ main: 'ⵉⵖ', word: 'خروف', imageUrl: 'images/placeholder_sheep.jpg', audioUrl: 'audio/sheep.mp3' },
|
| 230 |
-
],
|
| 231 |
body: [{ main: 'ⵉⵅⴼ', word: 'الرأس', imageUrl: 'images/33dda7fe89cfd5526918246dae320059.jpg', audioUrl: 'audio/bodyParts/head.mp3' }],
|
|
|
|
|
|
|
| 232 |
family: [{ main: 'ⵉⵎⵎⵉ', word: 'أمي', imageUrl: 'images/5957c378462b920ceb24f6aa294b5100.jpg', audioUrl: 'audio/family/mother.mp3' }],
|
| 233 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
};
|
| 235 |
-
|
| 236 |
-
const TIFINAGH_LETTERS_BASIC = LEARNING_DATA.tifinaghLetters.map(i => i.main);
|
| 237 |
-
|
| 238 |
|
| 239 |
// --- بيانات مستويات الألعاب الجديدة ---
|
| 240 |
|
| 241 |
-
|
| 242 |
-
const MEMORY_GAME_BASE_ITEMS = [
|
| 243 |
...LEARNING_DATA.animals,
|
| 244 |
...LEARNING_DATA.fruits,
|
| 245 |
-
|
| 246 |
-
...LEARNING_DATA.numbers.map(n => ({...n, main: n.transliteration || n.main})),
|
| 247 |
...LEARNING_DATA.tools,
|
|
|
|
| 248 |
{ main: 'ⵉⵎⵉ', word: 'فم', imageUrl: 'images/placeholder_mouth_game.jpg', audioUrl: null },
|
| 249 |
{ main: 'ⴰⴼⵓⵙ', word: 'يد', imageUrl: 'images/placeholder_hand_game.jpg', audioUrl: null },
|
| 250 |
{ main: 'ⴰⵛⵛⴰ', word: 'أكل', imageUrl: 'images/placeholder_eat_game.jpg', audioUrl: null },
|
| 251 |
{ main: 'ⴰⴼⵔⴰ', word: 'طير', imageUrl: 'images/placeholder_bird_game.jpg', audioUrl: null },
|
| 252 |
{ main: '���ⵎⴰⵏ', word: 'ماء', imageUrl: 'images/placeholder_water_game.jpg', audioUrl: null },
|
| 253 |
-
];
|
| 254 |
|
| 255 |
const memoryGameLevels = [
|
| 256 |
-
{ level: 1, pairs: 3, items:
|
| 257 |
-
{ level: 2, pairs: 4, items:
|
| 258 |
-
{ level: 3, pairs: 5, items:
|
| 259 |
-
{ level: 4, pairs: 6, items:
|
| 260 |
-
{ level: 5, pairs: 8, items:
|
| 261 |
-
{ level: 6, pairs: 10, items:
|
| 262 |
-
{ level: 7, pairs: 12, items:
|
| 263 |
-
{ level: 8, pairs: 14, items:
|
| 264 |
-
{ level: 9, pairs: 15, items:
|
| 265 |
-
{ level: 10, pairs: 16, items:
|
| 266 |
];
|
| 267 |
|
| 268 |
-
|
| 269 |
-
const NAMING_GAME_ITEMS_LIST = [
|
| 270 |
-
{ item: LEARNING_DATA.animals[0] }, // ⴰⵎⵓⵛⵛ
|
| 271 |
-
{ item: LEARNING_DATA.animals[1] }, // ⴰⵢⴷⵉ
|
| 272 |
-
{ item: LEARNING_DATA.fruits[0] }, // ⵜⴰⴷⴼⴼⵓⵢⵜ
|
| 273 |
-
{ item: LEARNING_DATA.vegetables[0] }, // ⵜⴰⵎⴰⵟⵉⵛⵜ
|
| 274 |
-
{ item: LEARNING_DATA.tools[0] }, // ⴰⴽⵕⵕⴰⵊ
|
| 275 |
-
{ item: LEARNING_DATA.fruits[1] }, // ⵜⴰⴱⴰⵏⴰⵏⵜ
|
| 276 |
-
{ item: LEARNING_DATA.animals[2] }, // ⴰⵡⵉ
|
| 277 |
-
{ item: LEARNING_DATA.fruits[2] }, // ⴰⵡⵔⵉⵖ
|
| 278 |
-
{ item: LEARNING_DATA.body[0] }, // ⵉⵅⴼ
|
| 279 |
-
{ item: LEARNING_DATA.family[0] }, // ⵉⵎⵎⵉ
|
| 280 |
-
].map((data, index) => ({...data, id: `name-${index}`}));
|
| 281 |
-
|
| 282 |
-
const NAMING_LEVEL_CONFIG = [
|
| 283 |
-
{ level: 1, itemIndex: 0, availableLettersCount: 5 }, // ⴰⵎⵓⵛⵛ (4 حروف)
|
| 284 |
-
{ level: 2, itemIndex: 1, availableLettersCount: 5 }, // ⴰⵢⴷⵉ (4 حروف)
|
| 285 |
-
{ level: 3, itemIndex: 2, availableLettersCount: 7 }, // ⵜⴰⴷⴼⴼⵓⵢⵜ (7 حروف)
|
| 286 |
-
{ level: 4, itemIndex: 3, availableLettersCount: 8 }, // ⵜⴰⵎⴰⵟⵉⵛⵜ (7 حروف)
|
| 287 |
-
{ level: 5, itemIndex: 4, availableLettersCount: 9 }, // ⴰⴽⵕⵕⴰⵊ (5 حروف)
|
| 288 |
-
{ level: 6, itemIndex: 5, availableLettersCount: 9 }, // ⵜⴰⴱⴰⵏⴰⵏⵜ (7 حروف)
|
| 289 |
-
{ level: 7, itemIndex: 6, availableLettersCount: 7 }, // ⴰⵡⵉ (3 حروف)
|
| 290 |
-
{ level: 8, itemIndex: 7, availableLettersCount: 8 }, // ⴰⵡⵔⵉⵖ (5 حروف)
|
| 291 |
-
{ level: 9, itemIndex: 8, availableLettersCount: 7 }, // ⵉⵅⴼ (3 حروف)
|
| 292 |
-
{ level: 10, itemIndex: 9, availableLettersCount: 9 }, // ⵉⵎⵎⵉ (3 حروف)
|
| 293 |
-
];
|
| 294 |
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
return {
|
| 313 |
-
...level,
|
| 314 |
-
item: item,
|
| 315 |
-
correctWord: correctWord,
|
| 316 |
-
availableLetters: availableLettersPool,
|
| 317 |
-
maxLetters: correctWord.length,
|
| 318 |
-
};
|
| 319 |
-
});
|
| 320 |
|
| 321 |
-
|
| 322 |
const CATEGORIES = [
|
| 323 |
{ id: 'tifinaghLetters', title: 'تعلم الحروف', subtitle: 'ⴰ, ⴱ, ⴳ...', iconName: 'AArrowUp', imageUrl: 'images/6e318d538a2d8f0b5ad685db558ffe4e.jpg' },
|
| 324 |
{ id: 'numbers', title: 'تعلم الأرقام', subtitle: '0, 1, 2...', iconName: 'Hash', imageUrl: 'images/0751e273c2de27e4b04dfeb7ee99b448.jpg' },
|
|
@@ -347,64 +349,82 @@
|
|
| 347 |
isDarkMode: false,
|
| 348 |
isAppMuted: false,
|
| 349 |
isRecording: false,
|
| 350 |
-
|
|
|
|
| 351 |
currentLevel: 1,
|
| 352 |
-
gameData: null,
|
| 353 |
memoryGame: {
|
| 354 |
-
flippedCards: [],
|
| 355 |
-
matchedCards: [],
|
| 356 |
-
lockBoard: false,
|
| 357 |
},
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
}
|
| 362 |
};
|
| 363 |
|
|
|
|
| 364 |
window.setState = (newState) => {
|
| 365 |
-
|
| 366 |
-
if (newState.currentScreen && newState.currentScreen !== appState.currentScreen) {
|
| 367 |
appState.currentIndex = 0;
|
| 368 |
-
appState.currentGameState = null;
|
| 369 |
appState.currentLevel = 1;
|
| 370 |
}
|
|
|
|
|
|
|
| 371 |
if (newState.currentGameState && newState.currentGameState !== appState.currentGameState) {
|
| 372 |
appState.currentLevel = 1;
|
| 373 |
-
appState.gameData = null;
|
| 374 |
appState.memoryGame = { flippedCards: [], matchedCards: [], lockBoard: false };
|
| 375 |
-
appState.
|
|
|
|
| 376 |
}
|
| 377 |
-
if (newState.currentLevel && newState.currentLevel !== appState.currentLevel
|
| 378 |
-
appState.gameData = null;
|
| 379 |
appState.memoryGame = { flippedCards: [], matchedCards: [], lockBoard: false };
|
| 380 |
-
appState.
|
|
|
|
| 381 |
}
|
| 382 |
|
| 383 |
|
| 384 |
Object.assign(appState, newState);
|
| 385 |
|
|
|
|
| 386 |
document.body.classList.toggle('dark', appState.isDarkMode);
|
| 387 |
document.getElementById('app-container').classList.toggle('dark', appState.isDarkMode);
|
| 388 |
|
| 389 |
renderApp();
|
| 390 |
};
|
| 391 |
|
|
|
|
| 392 |
window.toggleMenu = () => {
|
| 393 |
setState({ isMenuOpen: !appState.isMenuOpen });
|
| 394 |
};
|
| 395 |
|
| 396 |
-
//
|
| 397 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
const renderHeader = () => {
|
| 399 |
-
// ... (Code for renderHeader)
|
| 400 |
const headerElement = document.getElementById('app-header');
|
| 401 |
const categoryMeta = CATEGORIES.find(c => c.id === appState.selectedCategory);
|
| 402 |
|
| 403 |
let title = APP_NAME;
|
| 404 |
if (appState.currentGameState === 'memory') {
|
| 405 |
-
title = 'لعبة الذاكرة
|
| 406 |
-
} else if (appState.currentGameState === '
|
| 407 |
-
title = '
|
| 408 |
} else if (categoryMeta && appState.currentScreen !== 'home' && !['settings', 'info', 'appDefinition', 'games'].includes(appState.currentScreen)) {
|
| 409 |
title = categoryMeta.title;
|
| 410 |
} else if (appState.currentScreen === 'settings') {
|
|
@@ -420,7 +440,7 @@
|
|
| 420 |
headerElement.innerHTML = `
|
| 421 |
<div class="flex items-center justify-between p-4 h-16 bg-blue-800 dark:bg-gray-800 text-white shadow-lg rounded-b-xl transition-colors">
|
| 422 |
<button onclick="
|
| 423 |
-
${appState.currentGameState ? `setState({currentGameState: null, currentLevel: 1
|
| 424 |
"
|
| 425 |
class="p-1 rounded-full hover:bg-white/10 transition-colors" aria-label="العودة / القائمة">
|
| 426 |
${appState.currentGameState ? renderIcon('ChevronRight', 'w-6 h-6 text-white') : renderIcon('Menu', 'w-6 h-6 text-white')}
|
|
@@ -434,9 +454,9 @@
|
|
| 434 |
</div>
|
| 435 |
`;
|
| 436 |
};
|
| 437 |
-
|
| 438 |
const renderFooter = () => {
|
| 439 |
-
|
| 440 |
const footerElement = document.getElementById('app-footer');
|
| 441 |
const navItems = [
|
| 442 |
{ id: 'home', iconName: 'Home', label: 'الرئيسية' },
|
|
@@ -478,7 +498,363 @@
|
|
| 478 |
</div>
|
| 479 |
`;
|
| 480 |
};
|
| 481 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 482 |
const renderGamesHome = () => {
|
| 483 |
const content = document.getElementById('app-content');
|
| 484 |
|
|
@@ -486,18 +862,18 @@
|
|
| 486 |
{
|
| 487 |
id: 'memory',
|
| 488 |
title: 'لعبة الذاكرة',
|
| 489 |
-
subtitle: 'طابق الصور وال
|
| 490 |
iconName: 'Brain',
|
| 491 |
color: 'bg-green-500',
|
| 492 |
action: `setState({currentGameState: 'memory'})`
|
| 493 |
},
|
| 494 |
{
|
| 495 |
-
id: '
|
| 496 |
-
title: 'ت
|
| 497 |
-
subtitle: '
|
| 498 |
-
iconName: '
|
| 499 |
color: 'bg-red-500',
|
| 500 |
-
action: `setState({currentGameState: '
|
| 501 |
},
|
| 502 |
];
|
| 503 |
|
|
@@ -529,11 +905,11 @@
|
|
| 529 |
const levelData = memoryGameLevels[appState.currentLevel - 1];
|
| 530 |
if (!levelData) return alert('انتهت المستويات!');
|
| 531 |
|
|
|
|
| 532 |
let cards = [];
|
| 533 |
levelData.items.forEach(item => {
|
| 534 |
-
|
| 535 |
-
cards.push({ id:
|
| 536 |
-
cards.push({ id: itemId, type: 'word', content: item.main, alt: item.word });
|
| 537 |
});
|
| 538 |
|
| 539 |
setState({
|
|
@@ -559,8 +935,7 @@
|
|
| 559 |
const card1 = newGameData[index1];
|
| 560 |
const card2 = newGameData[index2];
|
| 561 |
|
| 562 |
-
|
| 563 |
-
if (card1.id === card2.id && card1.type !== card2.type) {
|
| 564 |
// Match found
|
| 565 |
newGameData[index1].isMatched = true;
|
| 566 |
newGameData[index2].isMatched = true;
|
|
@@ -580,7 +955,7 @@
|
|
| 580 |
initMemoryGame();
|
| 581 |
} else {
|
| 582 |
alert('تهانينا! لقد أنهيت لعبة الذاكرة بنجاح!');
|
| 583 |
-
setState({ currentGameState: null
|
| 584 |
}
|
| 585 |
}, 800);
|
| 586 |
}
|
|
@@ -605,16 +980,13 @@
|
|
| 605 |
const renderMemoryGame = () => {
|
| 606 |
if (!appState.gameData) {
|
| 607 |
initMemoryGame();
|
| 608 |
-
return;
|
| 609 |
}
|
| 610 |
|
| 611 |
const content = document.getElementById('app-content');
|
| 612 |
const levelData = memoryGameLevels[appState.currentLevel - 1];
|
| 613 |
-
const
|
| 614 |
-
|
| 615 |
-
if (totalCards > 16) cols = 5;
|
| 616 |
-
|
| 617 |
-
const gridClass = `grid gap-2 w-full max-w-sm mx-auto`;
|
| 618 |
|
| 619 |
content.innerHTML = `
|
| 620 |
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
|
@@ -622,7 +994,7 @@
|
|
| 622 |
لعبة الذاكرة - المستوى ${appState.currentLevel}
|
| 623 |
</h3>
|
| 624 |
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 text-center">
|
| 625 |
-
طابق ${levelData.pairs} أزواج
|
| 626 |
</p>
|
| 627 |
|
| 628 |
<div class="${gridClass}" style="grid-template-columns: repeat(${cols}, minmax(0, 1fr));">
|
|
@@ -634,7 +1006,7 @@
|
|
| 634 |
${card.type === 'image' ? `
|
| 635 |
<img src="${card.content}" alt="${card.alt}" class="w-full h-full object-cover rounded-md" onerror="this.onerror=null; this.src='https://placehold.co/80x80?text=صورة';"/>
|
| 636 |
` : `
|
| 637 |
-
<span class="text-3xl font-black text-blue-800 dark:text-white
|
| 638 |
`}
|
| 639 |
</div>
|
| 640 |
|
|
@@ -656,140 +1028,137 @@
|
|
| 656 |
`;
|
| 657 |
};
|
| 658 |
|
| 659 |
-
// --- 8.2 لعبة ت
|
| 660 |
|
| 661 |
-
window.
|
| 662 |
-
const levelData =
|
| 663 |
if (!levelData) return alert('انتهت المستويات!');
|
| 664 |
|
| 665 |
-
// إعادة تعيين حالة اللعبة الحالية
|
| 666 |
setState({
|
| 667 |
gameData: levelData,
|
| 668 |
-
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
availableLettersPool: levelData.availableLetters.map((letter, index) => ({ letter, isUsed: false, poolIndex: index }))
|
| 672 |
},
|
| 673 |
-
currentGameState: '
|
| 674 |
currentLevel: levelData.level,
|
| 675 |
});
|
| 676 |
};
|
| 677 |
|
| 678 |
-
window.
|
| 679 |
-
const
|
| 680 |
-
|
| 681 |
-
const newPool = [...state.availableLettersPool];
|
| 682 |
-
if (newPool[letterIndex].isUsed) return;
|
| 683 |
-
|
| 684 |
-
const letter = newPool[letterIndex].letter;
|
| 685 |
|
| 686 |
-
|
| 687 |
-
const slotIndex = newUserWord.findIndex(l => l === null);
|
| 688 |
-
if (slotIndex === -1) return;
|
| 689 |
|
| 690 |
-
|
| 691 |
-
|
| 692 |
-
|
| 693 |
-
|
|
|
|
| 694 |
|
| 695 |
-
if (
|
| 696 |
-
|
| 697 |
}
|
| 698 |
};
|
| 699 |
|
| 700 |
window.removeLetter = (slotIndex) => {
|
| 701 |
-
const
|
| 702 |
-
|
| 703 |
-
if (!letterItem) return;
|
| 704 |
|
| 705 |
-
const
|
| 706 |
-
|
| 707 |
|
| 708 |
-
const
|
| 709 |
-
// استخدام poolIndex للرجوع للحرف الصحيح
|
| 710 |
-
newPool[letterItem.poolIndex].isUsed = false;
|
| 711 |
|
| 712 |
-
setState({
|
|
|
|
|
|
|
| 713 |
};
|
| 714 |
|
| 715 |
-
window.
|
| 716 |
-
const
|
| 717 |
-
const isCorrect =
|
| 718 |
|
| 719 |
if (isCorrect) {
|
| 720 |
setTimeout(() => {
|
| 721 |
-
if (appState.currentLevel <
|
| 722 |
-
alert(`
|
| 723 |
setState({ currentLevel: appState.currentLevel + 1 });
|
| 724 |
-
|
| 725 |
} else {
|
| 726 |
-
alert('تهانينا! لقد أتقنت ت
|
| 727 |
-
setState({ currentGameState: null
|
| 728 |
}
|
| 729 |
}, 500);
|
| 730 |
} else {
|
| 731 |
-
alert('
|
| 732 |
}
|
| 733 |
};
|
| 734 |
|
| 735 |
|
| 736 |
-
const
|
| 737 |
if (!appState.gameData) {
|
| 738 |
-
|
| 739 |
return;
|
| 740 |
}
|
| 741 |
|
| 742 |
const content = document.getElementById('app-content');
|
| 743 |
const levelData = appState.gameData;
|
| 744 |
-
const state = appState.
|
| 745 |
-
|
| 746 |
-
// تحديد عدد الأعمدة للوحة المفاتيح
|
| 747 |
-
const keyCols = state.availableLettersPool.length > 8 ? 6 : 4;
|
| 748 |
-
const keyGridClass = `grid grid-cols-${keyCols} gap-2 mb-8 max-w-sm mx-auto`;
|
| 749 |
|
|
|
|
|
|
|
|
|
|
| 750 |
content.innerHTML = `
|
| 751 |
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 752 |
<h3 class="text-2xl font-black text-gray-800 dark:text-white mb-2 text-center">
|
| 753 |
-
ت
|
| 754 |
</h3>
|
| 755 |
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 text-center">
|
| 756 |
-
|
| 757 |
</p>
|
| 758 |
|
| 759 |
-
<div class="
|
| 760 |
-
<
|
|
|
|
|
|
|
|
|
|
| 761 |
</div>
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
<
|
| 765 |
-
|
|
|
|
| 766 |
<button onclick="removeLetter(${index})"
|
| 767 |
-
class="
|
| 768 |
-
aria-label="
|
| 769 |
-
<span class="text-2xl font-black ${
|
| 770 |
</button>
|
| 771 |
`).join('')}
|
| 772 |
</div>
|
| 773 |
|
| 774 |
<h4 class="text-lg font-bold text-gray-700 dark:text-gray-300 mt-6 mb-2 text-center">الحروف المتاحة:</h4>
|
| 775 |
-
<div class="
|
| 776 |
-
${state.
|
| 777 |
-
<button onclick="
|
| 778 |
-
|
| 779 |
-
|
| 780 |
-
|
| 781 |
-
|
|
|
|
|
|
|
| 782 |
</button>
|
| 783 |
`).join('')}
|
| 784 |
</div>
|
| 785 |
|
| 786 |
<div class="mt-8 text-center">
|
| 787 |
-
<button onclick="
|
| 788 |
class="px-6 py-3 bg-blue-600 text-white font-bold rounded-xl shadow-lg hover:bg-blue-700 disabled:opacity-50"
|
| 789 |
-
${state.
|
| 790 |
-
تحقق من ال
|
| 791 |
</button>
|
| 792 |
-
<button onclick="
|
| 793 |
class="px-4 py-2 bg-yellow-500 text-white font-bold rounded-xl shadow-lg hover:bg-yellow-600 mr-2">
|
| 794 |
إعادة المستوى
|
| 795 |
</button>
|
|
@@ -797,15 +1166,17 @@
|
|
| 797 |
</div>
|
| 798 |
`;
|
| 799 |
};
|
|
|
|
| 800 |
|
| 801 |
-
//
|
|
|
|
| 802 |
const renderApp = () => {
|
| 803 |
-
// ... (Logic for renderApp, including other screens)
|
| 804 |
const screen = appState.currentScreen;
|
| 805 |
const content = document.getElementById('app-content');
|
| 806 |
const header = document.getElementById('app-header');
|
| 807 |
const footer = document.getElementById('app-footer');
|
| 808 |
|
|
|
|
| 809 |
const shouldShowNav = screen !== 'welcome';
|
| 810 |
header.style.display = shouldShowNav ? 'block' : 'none';
|
| 811 |
footer.style.display = shouldShowNav ? 'block' : 'none';
|
|
@@ -813,54 +1184,121 @@
|
|
| 813 |
if (shouldShowNav) {
|
| 814 |
renderHeader();
|
| 815 |
renderFooter();
|
| 816 |
-
} else {
|
| 817 |
-
// Simplified welcome screen rendering (add it back if needed)
|
| 818 |
-
content.innerHTML = `
|
| 819 |
-
<div class="flex flex-col items-center justify-center min-h-screen p-4 bg-white dark:bg-gray-800">
|
| 820 |
-
<div class="text-center">
|
| 821 |
-
<h1 class="text-6xl font-black text-blue-800 dark:text-blue-300 mb-2">${APP_NAME}</h1>
|
| 822 |
-
<p class="text-2xl font-bold text-gray-700 dark:text-gray-400 mb-10">تطبيق تعليم التيفيناغ للأطفال</p>
|
| 823 |
-
<button onclick="setState({currentScreen: 'home'})"
|
| 824 |
-
class="px-10 py-4 bg-green-500 text-white text-xl font-bold rounded-full shadow-lg hover:bg-green-600 transition-transform transform hover:scale-105">
|
| 825 |
-
ابدأ التعلم
|
| 826 |
-
</button>
|
| 827 |
-
<p class="mt-6 text-sm text-gray-500 dark:text-gray-600">اضغط للبدء</p>
|
| 828 |
-
</div>
|
| 829 |
-
</div>
|
| 830 |
-
`;
|
| 831 |
}
|
| 832 |
|
| 833 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 834 |
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 835 |
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 836 |
if (appState.currentGameState === 'memory') {
|
| 837 |
renderMemoryGame();
|
| 838 |
-
} else if (appState.currentGameState === '
|
| 839 |
-
|
| 840 |
} else {
|
| 841 |
renderGamesHome();
|
| 842 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 843 |
} else {
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
|
| 848 |
-
|
| 849 |
-
|
| 850 |
-
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 857 |
}
|
| 858 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
| 859 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 860 |
window.onload = () => {
|
| 861 |
-
|
| 862 |
-
// setState({currentScreen: 'home'});
|
| 863 |
-
renderApp();
|
| 864 |
};
|
| 865 |
|
| 866 |
</script>
|
|
|
|
| 104 |
pointer-events: none;
|
| 105 |
background-color: #10b981;
|
| 106 |
}
|
| 107 |
+
.ordering-slot {
|
| 108 |
min-height: 3rem;
|
| 109 |
}
|
| 110 |
+
.ordering-letter {
|
| 111 |
cursor: pointer;
|
| 112 |
user-select: none;
|
| 113 |
transition: background-color 0.2s, transform 0.1s;
|
| 114 |
}
|
| 115 |
+
.ordering-letter.active {
|
| 116 |
+
transform: scale(0.95);
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
</style>
|
| 120 |
</head>
|
| 121 |
<body class="flex justify-center">
|
|
|
|
| 130 |
|
| 131 |
<script>
|
| 132 |
// --- 1. تعريف الأيقونات كـ SVG نصي ---
|
|
|
|
| 133 |
const ICONS = {
|
| 134 |
Home: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>`,
|
| 135 |
Share2: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" x2="15.42" y1="13.51" y2="17.49"/><line x1="15.41" x2="8.59" y1="6.51" y2="10.49"/></svg>`,
|
|
|
|
| 137 |
Settings: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.44a2 2 0 0 1-1.11 1.76l-.42.25a2 2 0 0 0-.83 1.57v.88a2 2 0 0 0 1.1 1.8l.42.25a2 2 0 0 1 1.11 1.76v.44a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.44a2 2 0 0 1 1.11-1.76l.42-.25a2 2 0 0 0 .83-1.57v-.88a2 2 0 0 0-1.1-1.8l-.42-.25a2 2 0 0 1-1.11-1.76V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
| 138 |
Info: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>`,
|
| 139 |
Menu: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>`,
|
| 140 |
+
ChevronLeft: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><polyline points="15 18 9 12 15 6"/></svg>`,
|
| 141 |
ChevronRight: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><polyline points="9 18 15 12 9 6"/></svg>`,
|
| 142 |
Mic: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>`,
|
| 143 |
Volume2: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/></svg>`,
|
|
|
|
| 156 |
Gamepad: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12 21a2 2 0 0 1-2-2v-4H8a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h4V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4v4a2 2 0 0 1-2 2v2a2 2 0 0 1-2 2z"/><path d="M8 11h4V7H8z"/></svg>`,
|
| 157 |
BookOpen: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>`,
|
| 158 |
Brain: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="M12 5C6 5 3 7 3 12s3 7 9 7 9-2 9-7-3-7-9-7z"/><path d="M12 5c-3 0-5 2-5 5v2c0 3 2 5 5 5s5-2 5-5V10c0-3-2-5-5-5z"/></svg>`,
|
|
|
|
| 159 |
Repeat1: (cls) => `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="${cls}"><path d="m19 14-4 4-4-4"/><path d="M15 18H8a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h12"/><path d="M10 10l4 4 4-4"/></svg>`,
|
| 160 |
WhatsApp: (cls) => ICONS.Share2(cls),
|
| 161 |
};
|
|
|
|
| 172 |
|
| 173 |
|
| 174 |
// --- 2. بيانات التطبيق الثابتة ---
|
| 175 |
+
// Helper to shuffle an array
|
| 176 |
const shuffleArray = (array) => {
|
| 177 |
const shuffled = [...array];
|
| 178 |
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
|
|
| 183 |
};
|
| 184 |
|
| 185 |
const APP_NAME = "Tifawin";
|
| 186 |
+
const APP_NAME_LETTERS = "TIMMUZIT";
|
| 187 |
const WHATSAPP_LINK = "https://chat.whatsapp.com/J8bK9L0X4M7P2S1R6Q5T";
|
| 188 |
|
| 189 |
+
const DEVELOPER_INFO = {
|
| 190 |
+
name: "حسن العمراني (Hassan Alamrani)",
|
| 191 |
+
title: "مطوّر الواجهة التعليمية",
|
| 192 |
+
bio: "مهندس برمجيات متخصص في تطوير واجهات المستخدم التفاعلية وتطبيقات الويب التعليمية. شغوف بدمج التكنولوجيا لتعزيز تعليم اللغات والتراث الثقافي.",
|
| 193 |
+
image: "images/developer_avatar.png"
|
| 194 |
+
};
|
| 195 |
+
|
| 196 |
+
const VOICE_OVER_ARTISTS = [
|
| 197 |
+
{ name: "فاطمة الزهراء", role: "المعلق الصوتي الأساسي (أصوات الكبار)" },
|
| 198 |
+
{ name: "أحمد الصغير", role: "معلق صوتي للأطفال (أصوات الحروف والأرقام)" },
|
| 199 |
+
{ name: "طاقم تطوان للتعابير", role: "تسجيل فصول السنة" }
|
| 200 |
+
];
|
| 201 |
+
|
| 202 |
+
// ** بيانات تعلم الأمازيغية (تيفيناغ) **
|
| 203 |
const tifinaghData = [
|
| 204 |
+
{ letter: 'ⴰ', word_tifinagh: '', word_arabic: 'جدار-ⴰⴳⴰⴷⵉⵔ', image: 'images/2947c16d27f8042f7d60783c6808519a.jpg', audio: 'audio/aman.mp3' },
|
| 205 |
+
{ letter: 'ⴱ', word_tifinagh: '', word_arabic: 'فراشة-ⵉⴱⵔⴱⵉⵍⵍⵓ', image: 'images/3fd6beebd231e2f325469a40b0831b59.jpg', audio: 'audio/barbi.mp3' },
|
| 206 |
+
{ letter: 'ⴳ', word_tifinagh: '', word_arabic: 'دخان-ⴰⴳⴳⵓ', image: 'images/c0094eb5dcc49d7cce573d42f270d8de.jpg', audio: 'audio/ca.mp3' },
|
| 207 |
+
{ letter: 'ⴷ', word_tifinagh: '', word_arabic: 'تمرة-ⵜⵉⵏⵉ', image: 'images/placeholder_date.jpg', audio: 'audio/da.mp3' },
|
| 208 |
+
{ letter: 'ⴹ', word_tifinagh: '', word_arabic: 'قدم-ⴰⴹⴰⵔ', image: 'images/placeholder_foot.jpg', audio: 'audio/dha.mp3' },
|
| 209 |
+
{ letter: 'ⴼ', word_tifinagh: '', word_arabic: 'عين-ⵜⵉⵟ', image: 'images/placeholder_eye.jpg', audio: 'audio/fa.mp3' },
|
| 210 |
+
{ letter: 'ⵀ', word_tifinagh: '', word_arabic: 'فم-ⴰⴽⵓⵎ', image: 'images/placeholder_mouth.jpg', audio: 'audio/ha.mp3' },
|
| 211 |
+
{ letter: 'ⵃ', word_tifinagh: '', word_arabic: 'قلب-ⵓⵍ', image: 'images/placeholder_heart.jpg', audio: 'audio/hha.mp3' },
|
| 212 |
+
{ letter: 'ⵇ', word_tifinagh: '', word_arabic: 'قمح-ⵉⵔⴷⵏ', image: 'images/placeholder_wheat.jpg', audio: 'audio/qa.mp3' },
|
| 213 |
+
{ letter: 'ⵅ', word_tifinagh: '', word_arabic: 'غيمة-ⴰⵙⴰⴼ', image: 'images/placeholder_cloud.jpg', audio: 'audio/kha.mp3' },
|
| 214 |
+
{ letter: 'ⵉ', word_tifinagh: '', word_arabic: 'شمس-ⴰⵢⵢⵓⵔ', image: 'images/placeholder_sun.jpg', audio: 'audio/i.mp3' },
|
| 215 |
+
{ letter: 'ⵊ', word_tifinagh: '', word_arabic: 'جبن-ⴰⵛⵛⴰⵔ', image: 'images/placeholder_cheese.jpg', audio: 'audio/ja.mp3' },
|
| 216 |
+
{ letter: 'ⴽ', word_tifinagh: '', word_arabic: 'صخرة-ⴰⴷⴳⴰⵏ', image: 'images/placeholder_rock.jpg', audio: 'audio/ka.mp3' },
|
| 217 |
+
{ letter: 'ⵍ', word_tifinagh: '', word_arabic: 'عسل-ⵜⴰⵎⵉⵎⵜ', image: 'images/placeholder_honey.jpg', audio: 'audio/la.mp3' },
|
| 218 |
+
{ letter: 'ⵎ', word_tifinagh: '', word_arabic: 'بحر-ⵉⵍⵍ', image: 'images/placeholder_sea.jpg', audio: 'audio/ma.mp3' },
|
|
|
|
|
|
|
| 219 |
];
|
| 220 |
|
| 221 |
+
const animalsData = [
|
| 222 |
+
{ word_tifinagh: 'ⴰⵎⵓⵛⵛ', word_arabic: 'قط ', image: 'images/cat.jpeg', audio: 'audio/animaux.ogg' },
|
| 223 |
+
{ word_tifinagh: 'ⴰⵢⴷⵉ', word_arabic: 'كلب', image: 'images/124419894dcfde81ffbca1e072804c71.jpg', audio: 'audio/dog.mp3' },
|
| 224 |
+
{ word_tifinagh: 'ⴰⵡⵉ', word_arabic: 'أسد', image: 'images/placeholder_lion.jpg', audio: 'audio/lion.mp3' },
|
| 225 |
+
{ word_tifinagh: 'ⵉⵖ', word_arabic: 'خروف', image: 'images/placeholder_sheep.jpg', audio: 'audio/sheep.mp3' },
|
| 226 |
+
];
|
| 227 |
+
|
| 228 |
+
const fruitsData = [
|
| 229 |
+
{ main: 'ⵜⴰⴷⴼⴼⵓⵢⵜ', word: 'تفاحة', imageUrl: 'images/da1da4f2015a32322f547ae5fff5236c.jpg', audioUrl: 'audio/fruits/apple.mp3' },
|
| 230 |
+
{ main: 'ⵜⴰⴱⴰⵏⴰⵏⵜ', word: 'موز', imageUrl: 'images/placeholder_banana.jpg', audioUrl: 'audio/fruits/banana.mp3' },
|
| 231 |
+
{ main: 'ⴰⵡⵔⵉⵖ', word: 'برتقال', imageUrl: 'images/placeholder_orange.jpg', audioUrl: 'audio/fruits/orange.mp3' },
|
| 232 |
+
];
|
| 233 |
+
|
| 234 |
+
const numbersData = [
|
| 235 |
+
{ number: '0', word_tifinagh: 'ⴰⵎⵢⴰ', word_arabic: 'صفر ', image: 'images/d3a43a956f3129b847739dec5f10c81f.jpg', audio: 'audio/zero.mp3' },
|
| 236 |
+
{ number: '1', word_tifinagh: 'ⵢⴰⵏ ', word_arabic: ' واحد', image: 'images/b26681eaa5caacbf1c7bfb112f546def.jpg', audio: 'audio/one.mp3' },
|
| 237 |
+
{ number: '2', word_tifinagh: 'ⵙⵉⵏ ', word_arabic: ' اثنان', image: 'images/placeholder_two.jpg', audio: 'audio/two.mp3' },
|
| 238 |
+
{ number: '3', word_tifinagh: 'ⴽⵕⴰⴹ ', word_arabic: ' ثلاثة', image: 'images/placeholder_three.jpg', audio: 'audio/three.mp3' },
|
| 239 |
+
];
|
| 240 |
+
|
| 241 |
const LEARNING_DATA = {
|
| 242 |
tifinaghLetters: tifinaghData.map(item => {
|
| 243 |
const parts = item.word_arabic.split('-');
|
| 244 |
+
return {
|
| 245 |
+
main: item.letter,
|
| 246 |
+
word: parts.length > 1 ? parts[0].trim() : item.word_arabic.trim(),
|
| 247 |
+
transliteration: parts.length > 1 ? parts[1].trim() : '',
|
| 248 |
+
imageUrl: item.image,
|
| 249 |
+
audioUrl: item.audio,
|
| 250 |
+
};
|
| 251 |
}),
|
| 252 |
+
numbers: numbersData.map(item => ({
|
| 253 |
+
main: item.number,
|
| 254 |
+
word: item.word_arabic.trim(),
|
| 255 |
+
transliteration: item.word_tifinagh.trim(),
|
| 256 |
+
imageUrl: item.image,
|
| 257 |
+
audioUrl: item.audio,
|
| 258 |
+
})),
|
| 259 |
tools: [{ main: 'ⴰⴽⵕⵕⴰⵊ', word: 'قلم رصاص', imageUrl: 'images/37b71533177feb9d55d55efba947309e.jpg', audioUrl: 'audio/schoolSupplies/pencil.mp3' }],
|
| 260 |
+
fruits: fruitsData,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
vegetables: [{ main: 'ⵜⴰⵎⴰⵟⵉⵛⵜ', word: 'طماطم', imageUrl: 'images/6056d9839a962b5a78cddc402ef88c09.jpg', audioUrl: 'audio/vegetables/tomato.mp3' }],
|
| 262 |
+
animals: animalsData.map(item => ({ main: item.word_tifinagh, word: item.word_arabic, imageUrl: item.image, audioUrl: item.audio })),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
body: [{ main: 'ⵉⵅⴼ', word: 'الرأس', imageUrl: 'images/33dda7fe89cfd5526918246dae320059.jpg', audioUrl: 'audio/bodyParts/head.mp3' }],
|
| 264 |
+
days: [{ main: 'ⴰⵢⵏⴰⵙ', word: 'الاثنين', imageUrl: 'images/37b71533177feb9d55d55efba947309e.jpg', audioUrl: 'audio/days/monday.mp3' }],
|
| 265 |
+
months: [{ main: 'ⵉⵏⵏⴰⵢⵔ', word: 'يناير', imageUrl: 'images/b26681eaa5caacbf1c7bfb112f546def.jpg', audioUrl: 'audio/months/january.mp3' }],
|
| 266 |
family: [{ main: 'ⵉⵎⵎⵉ', word: 'أمي', imageUrl: 'images/5957c378462b920ceb24f6aa294b5100.jpg', audioUrl: 'audio/family/mother.mp3' }],
|
| 267 |
+
colors: [
|
| 268 |
+
{ main: 'ⴰⵣⴳⴳⵯⴰⵖ', word: 'أحمر', imageUrl: 'images/b008721ac76def4ddfdbdb51fc82d320.jpg', audioUrl: 'audio/colors/red.mp3', colorClass: 'bg-red-600' },
|
| 269 |
+
{ main: 'ⴰⵣⴳⴳⵯⴰⵖ', word: 'أزرق', imageUrl: 'images/b008721ac76def4ddfdbdb51fc82d320.jpg', audioUrl: 'audio/colors/blue.mp3', colorClass: 'bg-blue-600' },
|
| 270 |
+
],
|
| 271 |
+
seasons: [{ main: 'ⵜⴰⴳⵔⵙⵜ', word: 'الشتاء', imageUrl: 'images/b2d331ea13a2df600219904dabd028fa.jpg', audioUrl: 'audio/AUD-20250926-WA0003.opus' }],
|
| 272 |
+
games: [{ main: "أسد صغير شجاع", word: "في غابة بعيدة، عاش أسد صغير اسمه سمير...", imageUrl: "images/Screenshot_20250927_141840_One Read.jpg", audioUrl: null }],
|
| 273 |
+
stories: [{ main: "السلحفاة والأرنب", word: "في غابة خضراء، قرر أرنب وسلحفاة...", imageUrl: "images/73b552bd0d3472c121adccc68a5bbb7f.jpg", audioUrl: null }],
|
| 274 |
};
|
|
|
|
|
|
|
|
|
|
| 275 |
|
| 276 |
// --- بيانات مستويات الألعاب الجديدة ---
|
| 277 |
|
| 278 |
+
const MEMORY_GAME_ITEMS = [
|
|
|
|
| 279 |
...LEARNING_DATA.animals,
|
| 280 |
...LEARNING_DATA.fruits,
|
| 281 |
+
...LEARNING_DATA.numbers,
|
|
|
|
| 282 |
...LEARNING_DATA.tools,
|
| 283 |
+
// بيانات إضافية وهمية لتغطية المستويات العليا
|
| 284 |
{ main: 'ⵉⵎⵉ', word: 'فم', imageUrl: 'images/placeholder_mouth_game.jpg', audioUrl: null },
|
| 285 |
{ main: 'ⴰⴼⵓⵙ', word: 'يد', imageUrl: 'images/placeholder_hand_game.jpg', audioUrl: null },
|
| 286 |
{ main: 'ⴰⵛⵛⴰ', word: 'أكل', imageUrl: 'images/placeholder_eat_game.jpg', audioUrl: null },
|
| 287 |
{ main: 'ⴰⴼⵔⴰ', word: 'طير', imageUrl: 'images/placeholder_bird_game.jpg', audioUrl: null },
|
| 288 |
{ main: '���ⵎⴰⵏ', word: 'ماء', imageUrl: 'images/placeholder_water_game.jpg', audioUrl: null },
|
| 289 |
+
].slice(0, 16).map((item, index) => ({...item, id: `item-${index}`})); // تحديد 16 عنصراً فريداً
|
| 290 |
|
| 291 |
const memoryGameLevels = [
|
| 292 |
+
{ level: 1, pairs: 3, items: MEMORY_GAME_ITEMS.slice(0, 3) }, // 6 cards (3x2)
|
| 293 |
+
{ level: 2, pairs: 4, items: MEMORY_GAME_ITEMS.slice(0, 4) }, // 8 cards (4x2)
|
| 294 |
+
{ level: 3, pairs: 5, items: MEMORY_GAME_ITEMS.slice(0, 5) }, // 10 cards (5x2)
|
| 295 |
+
{ level: 4, pairs: 6, items: MEMORY_GAME_ITEMS.slice(0, 6) }, // 12 cards (4x3)
|
| 296 |
+
{ level: 5, pairs: 8, items: MEMORY_GAME_ITEMS.slice(0, 8) }, // 16 cards (4x4)
|
| 297 |
+
{ level: 6, pairs: 10, items: MEMORY_GAME_ITEMS.slice(0, 10) }, // 20 cards (5x4)
|
| 298 |
+
{ level: 7, pairs: 12, items: MEMORY_GAME_ITEMS.slice(0, 12) }, // 24 cards (6x4)
|
| 299 |
+
{ level: 8, pairs: 14, items: MEMORY_GAME_ITEMS.slice(0, 14) }, // 28 cards (7x4)
|
| 300 |
+
{ level: 9, pairs: 15, items: MEMORY_GAME_ITEMS.slice(0, 15) }, // 30 cards (6x5)
|
| 301 |
+
{ level: 10, pairs: 16, items: MEMORY_GAME_ITEMS.slice(0, 16) }, // 32 cards (8x4)
|
| 302 |
];
|
| 303 |
|
| 304 |
+
const TIFINAGH_LETTERS_BASIC = LEARNING_DATA.tifinaghLetters.map(i => i.main);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 305 |
|
| 306 |
+
const tifinaghOrderingLevels = [
|
| 307 |
+
{ level: 1, letters: TIFINAGH_LETTERS_BASIC.slice(0, 4) },
|
| 308 |
+
{ level: 2, letters: TIFINAGH_LETTERS_BASIC.slice(0, 5) },
|
| 309 |
+
{ level: 3, letters: TIFINAGH_LETTERS_BASIC.slice(0, 6) },
|
| 310 |
+
{ level: 4, letters: TIFINAGH_LETTERS_BASIC.slice(0, 7) },
|
| 311 |
+
{ level: 5, letters: TIFINAGH_LETTERS_BASIC.slice(0, 8) },
|
| 312 |
+
{ level: 6, letters: TIFINAGH_LETTERS_BASIC.slice(0, 9) },
|
| 313 |
+
{ level: 7, letters: TIFINAGH_LETTERS_BASIC.slice(0, 10) },
|
| 314 |
+
{ level: 8, letters: TIFINAGH_LETTERS_BASIC.slice(0, 11) },
|
| 315 |
+
{ level: 9, letters: TIFINAGH_LETTERS_BASIC.slice(0, 12) },
|
| 316 |
+
{ level: 10, letters: TIFINAGH_LETTERS_BASIC.slice(0, 13) },
|
| 317 |
+
].map(levelData => ({
|
| 318 |
+
...levelData,
|
| 319 |
+
correctOrder: levelData.letters,
|
| 320 |
+
scrambledLetters: shuffleArray(levelData.letters),
|
| 321 |
+
}));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 322 |
|
| 323 |
+
|
| 324 |
const CATEGORIES = [
|
| 325 |
{ id: 'tifinaghLetters', title: 'تعلم الحروف', subtitle: 'ⴰ, ⴱ, ⴳ...', iconName: 'AArrowUp', imageUrl: 'images/6e318d538a2d8f0b5ad685db558ffe4e.jpg' },
|
| 326 |
{ id: 'numbers', title: 'تعلم الأرقام', subtitle: '0, 1, 2...', iconName: 'Hash', imageUrl: 'images/0751e273c2de27e4b04dfeb7ee99b448.jpg' },
|
|
|
|
| 349 |
isDarkMode: false,
|
| 350 |
isAppMuted: false,
|
| 351 |
isRecording: false,
|
| 352 |
+
// New Game State
|
| 353 |
+
currentGameState: null, // 'memory' or 'tifinagh_ordering'
|
| 354 |
currentLevel: 1,
|
| 355 |
+
gameData: null, // Stores specific data for the current game
|
| 356 |
memoryGame: {
|
| 357 |
+
flippedCards: [], // Indices of currently flipped cards
|
| 358 |
+
matchedCards: [], // IDs of matched items
|
| 359 |
+
lockBoard: false, // Prevents flipping more cards
|
| 360 |
},
|
| 361 |
+
tifinaghOrderingGame: {
|
| 362 |
+
userOrder: [], // Letters the user has placed
|
| 363 |
+
availableLetters: [], // Letters waiting to be placed
|
| 364 |
}
|
| 365 |
};
|
| 366 |
|
| 367 |
+
// دالة تحديث الحالة وإعادة رسم التطبيق
|
| 368 |
window.setState = (newState) => {
|
| 369 |
+
if (newState.currentScreen && newState.currentScreen !== appState.selectedCategory) {
|
|
|
|
| 370 |
appState.currentIndex = 0;
|
| 371 |
+
appState.currentGameState = null; // Reset game state on screen change
|
| 372 |
appState.currentLevel = 1;
|
| 373 |
}
|
| 374 |
+
|
| 375 |
+
// Handle game specific screen logic
|
| 376 |
if (newState.currentGameState && newState.currentGameState !== appState.currentGameState) {
|
| 377 |
appState.currentLevel = 1;
|
|
|
|
| 378 |
appState.memoryGame = { flippedCards: [], matchedCards: [], lockBoard: false };
|
| 379 |
+
appState.tifinaghOrderingGame = { userOrder: [], availableLetters: [] };
|
| 380 |
+
appState.gameData = null;
|
| 381 |
}
|
| 382 |
+
if (newState.currentLevel && newState.currentLevel !== appState.currentLevel) {
|
|
|
|
| 383 |
appState.memoryGame = { flippedCards: [], matchedCards: [], lockBoard: false };
|
| 384 |
+
appState.tifinaghOrderingGame = { userOrder: [], availableLetters: [] };
|
| 385 |
+
appState.gameData = null;
|
| 386 |
}
|
| 387 |
|
| 388 |
|
| 389 |
Object.assign(appState, newState);
|
| 390 |
|
| 391 |
+
// تطبيق الوضع الليلي فوراً على الجسم والحاوية
|
| 392 |
document.body.classList.toggle('dark', appState.isDarkMode);
|
| 393 |
document.getElementById('app-container').classList.toggle('dark', appState.isDarkMode);
|
| 394 |
|
| 395 |
renderApp();
|
| 396 |
};
|
| 397 |
|
| 398 |
+
// دالة تبديل حالة القائمة الجانبية
|
| 399 |
window.toggleMenu = () => {
|
| 400 |
setState({ isMenuOpen: !appState.isMenuOpen });
|
| 401 |
};
|
| 402 |
|
| 403 |
+
// الدوال الجديدة للتحكم في التسجيل (محاكاة)
|
| 404 |
+
window.startRecording = () => {
|
| 405 |
+
setState({ isRecording: true, currentScreen: appState.currentScreen });
|
| 406 |
+
console.log("Recording Started...");
|
| 407 |
+
alert("بدأ التسجيل! تحدث الآن...");
|
| 408 |
+
};
|
| 409 |
+
|
| 410 |
+
window.stopRecording = () => {
|
| 411 |
+
setState({ isRecording: false, currentScreen: appState.currentScreen });
|
| 412 |
+
console.log("Recording Stopped.");
|
| 413 |
+
alert("تم إيقاف التسجيل. (في التطبيق الحقيقي، هنا يمكن مقارنة الصوت)");
|
| 414 |
+
};
|
| 415 |
+
|
| 416 |
+
|
| 417 |
+
// --- 4. مكونات الواجهة المشتركة (رأس الصفحة وتذييلها) ---
|
| 418 |
+
|
| 419 |
const renderHeader = () => {
|
|
|
|
| 420 |
const headerElement = document.getElementById('app-header');
|
| 421 |
const categoryMeta = CATEGORIES.find(c => c.id === appState.selectedCategory);
|
| 422 |
|
| 423 |
let title = APP_NAME;
|
| 424 |
if (appState.currentGameState === 'memory') {
|
| 425 |
+
title = 'لعبة الذاكرة';
|
| 426 |
+
} else if (appState.currentGameState === 'tifinagh_ordering') {
|
| 427 |
+
title = 'ترتيب الحروف';
|
| 428 |
} else if (categoryMeta && appState.currentScreen !== 'home' && !['settings', 'info', 'appDefinition', 'games'].includes(appState.currentScreen)) {
|
| 429 |
title = categoryMeta.title;
|
| 430 |
} else if (appState.currentScreen === 'settings') {
|
|
|
|
| 440 |
headerElement.innerHTML = `
|
| 441 |
<div class="flex items-center justify-between p-4 h-16 bg-blue-800 dark:bg-gray-800 text-white shadow-lg rounded-b-xl transition-colors">
|
| 442 |
<button onclick="
|
| 443 |
+
${appState.currentGameState ? `setState({currentGameState: null, currentLevel: 1})` : `toggleMenu()`}
|
| 444 |
"
|
| 445 |
class="p-1 rounded-full hover:bg-white/10 transition-colors" aria-label="العودة / القائمة">
|
| 446 |
${appState.currentGameState ? renderIcon('ChevronRight', 'w-6 h-6 text-white') : renderIcon('Menu', 'w-6 h-6 text-white')}
|
|
|
|
| 454 |
</div>
|
| 455 |
`;
|
| 456 |
};
|
| 457 |
+
|
| 458 |
const renderFooter = () => {
|
| 459 |
+
// ... (Footer rendering remains mostly the same)
|
| 460 |
const footerElement = document.getElementById('app-footer');
|
| 461 |
const navItems = [
|
| 462 |
{ id: 'home', iconName: 'Home', label: 'الرئيسية' },
|
|
|
|
| 498 |
</div>
|
| 499 |
`;
|
| 500 |
};
|
| 501 |
+
|
| 502 |
+
// --- 5. شاشة 1: شاشة الترحيب (Welcome Screen) ---
|
| 503 |
+
const renderWelcomeScreen = () => {
|
| 504 |
+
// ... (Code remains the same)
|
| 505 |
+
const content = document.getElementById('app-content');
|
| 506 |
+
|
| 507 |
+
const logoHTML = `
|
| 508 |
+
<div class="flex flex-col items-center">
|
| 509 |
+
<div class="text-6xl font-black text-blue-600 dark:text-blue-400 mb-4 drop-shadow-lg">
|
| 510 |
+
${renderIcon('Carrot', 'w-16 h-16 text-orange-500 dark:text-orange-300 icon-shadow', 2)}
|
| 511 |
+
</div>
|
| 512 |
+
<h1 class="text-6xl font-extrabold text-gray-900 dark:text-white mb-2 leading-none">Tifawin</h1>
|
| 513 |
+
<p class="text-xl font-medium text-gray-600 dark:text-gray-300 mt-2">تعلم الأمازيغية للأطفال</p>
|
| 514 |
+
</div>
|
| 515 |
+
`;
|
| 516 |
+
|
| 517 |
+
const copyrightText = "TIFIWIN-AZIZIJAOUAD@2025";
|
| 518 |
+
|
| 519 |
+
content.innerHTML = `
|
| 520 |
+
<div class="flex flex-col items-center justify-between min-h-[calc(100vh)] p-8 bg-white dark:bg-gray-900 transition-colors">
|
| 521 |
+
|
| 522 |
+
<div class="flex-grow flex flex-col items-center justify-center text-center w-full">
|
| 523 |
+
${logoHTML}
|
| 524 |
+
|
| 525 |
+
<p class="text-lg text-gray-500 dark:text-gray-400 mt-10 max-w-xs">
|
| 526 |
+
انطلق في رحلة ممتعة لاستكشاف حروف وألوان ومفردات اللغة الأمازيغية.
|
| 527 |
+
</p>
|
| 528 |
+
</div>
|
| 529 |
+
|
| 530 |
+
<button onclick="setState({currentScreen: 'home'})"
|
| 531 |
+
class="w-full max-w-xs py-4 bg-green-500 hover:bg-green-600 text-white text-xl font-bold rounded-full shadow-2xl shadow-green-400/50 transition-all card-shadow mb-6">
|
| 532 |
+
هيا نبدأ!
|
| 533 |
+
</button>
|
| 534 |
+
|
| 535 |
+
<p class="text-xs text-gray-400 dark:text-gray-600 font-mono tracking-wider">
|
| 536 |
+
${copyrightText}
|
| 537 |
+
</p>
|
| 538 |
+
</div>
|
| 539 |
+
`;
|
| 540 |
+
};
|
| 541 |
+
|
| 542 |
+
|
| 543 |
+
// --- 6. شاشة 2: الشاشة الرئيسية (Home Screen) ---
|
| 544 |
+
const renderHomeScreen = () => {
|
| 545 |
+
// ... (Code remains the same)
|
| 546 |
+
const content = document.getElementById('app-content');
|
| 547 |
+
|
| 548 |
+
const cardsHTML = CATEGORIES.map(category => `
|
| 549 |
+
<button
|
| 550 |
+
onclick="setState({currentScreen: '${category.id}', selectedCategory: '${category.id}'})"
|
| 551 |
+
class="relative w-full h-32 rounded-2xl overflow-hidden card-shadow group"
|
| 552 |
+
aria-label="الذهاب إلى قسم ${category.title}"
|
| 553 |
+
>
|
| 554 |
+
<img
|
| 555 |
+
src="${category.imageUrl}"
|
| 556 |
+
alt="${category.title}"
|
| 557 |
+
class="w-full h-full object-cover transition-transform duration-300 group-hover:scale-110"
|
| 558 |
+
onerror="this.onerror=null; this.src='https://placehold.co/300x200/cccccc/000000?text=صورة+${category.title}';"
|
| 559 |
+
/>
|
| 560 |
+
|
| 561 |
+
<div class="absolute inset-0 flex flex-col items-center justify-center p-3 text-white font-extrabold text-lg image-overlay">
|
| 562 |
+
<span class="text-xl font-black text-center leading-tight drop-shadow-md">${category.title}</span>
|
| 563 |
+
<span class="text-xs opacity-80 mt-1 drop-shadow-sm">${category.subtitle}</span>
|
| 564 |
+
</div>
|
| 565 |
+
</button>
|
| 566 |
+
`).join('');
|
| 567 |
+
|
| 568 |
+
content.innerHTML = `
|
| 569 |
+
<div class="p-4 bg-gray-50 dark:bg-gray-900 min-h-[calc(100vh-130px)] transition-colors">
|
| 570 |
+
<h2 class="text-2xl font-bold text-gray-800 dark:text-white mb-4 text-center">أقسام التعلم</h2>
|
| 571 |
+
<div class="grid grid-cols-2 sm:grid-cols-3 gap-3">
|
| 572 |
+
${cardsHTML}
|
| 573 |
+
</div>
|
| 574 |
+
<p class="text-center text-gray-500 dark:text-gray-400 mt-6 text-sm">
|
| 575 |
+
اختر قسمًا لتبدأ رحلة التعلم الممتعة!
|
| 576 |
+
</p>
|
| 577 |
+
</div>
|
| 578 |
+
`;
|
| 579 |
+
};
|
| 580 |
+
|
| 581 |
+
// --- 7. شاشة التعلم العامة (Learning Screen) ---
|
| 582 |
+
const renderLearningScreen = () => {
|
| 583 |
+
// ... (Code remains the same)
|
| 584 |
+
const categoryId = appState.selectedCategory;
|
| 585 |
+
const content = document.getElementById('app-content');
|
| 586 |
+
const data = LEARNING_DATA[categoryId] || [];
|
| 587 |
+
const categoryMeta = CATEGORIES.find(c => c.id === categoryId);
|
| 588 |
+
|
| 589 |
+
if (data.length === 0 || !categoryMeta) {
|
| 590 |
+
content.innerHTML = `
|
| 591 |
+
<div class="p-8 min-h-[calc(100vh-130px)] flex flex-col items-center justify-center bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 592 |
+
<p class="text-xl font-bold text-red-500 mb-4 dark:text-red-400">عفواً! لا توجد بيانات لهذا القسم.</p>
|
| 593 |
+
<button onclick="setState({currentScreen: 'home', selectedCategory: null})"
|
| 594 |
+
class="px-6 py-3 bg-blue-600 text-white font-bold rounded-xl shadow-lg hover:bg-blue-700 card-shadow">
|
| 595 |
+
العودة للرئيسية
|
| 596 |
+
</button>
|
| 597 |
+
</div>
|
| 598 |
+
`;
|
| 599 |
+
return;
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
|
| 603 |
+
const currentItem = data[appState.currentIndex];
|
| 604 |
+
const isColorsCategory = categoryId === 'colors';
|
| 605 |
+
const isRecordingActive = appState.isRecording;
|
| 606 |
+
|
| 607 |
+
window.playAudio = () => {
|
| 608 |
+
if (appState.isAppMuted) {
|
| 609 |
+
console.log("Audio is muted by user setting.");
|
| 610 |
+
return;
|
| 611 |
+
}
|
| 612 |
+
if (currentItem.audioUrl) {
|
| 613 |
+
const audioPath = currentItem.audioUrl;
|
| 614 |
+
new Audio(audioPath).play().catch(e => console.error("Error playing audio:", e));
|
| 615 |
+
} else {
|
| 616 |
+
alert('ملف صوتي غير متوفر لهذا العنصر.');
|
| 617 |
+
}
|
| 618 |
+
};
|
| 619 |
+
|
| 620 |
+
window.handleNext = () => {
|
| 621 |
+
const newIndex = (appState.currentIndex + 1) % data.length;
|
| 622 |
+
setState({ currentIndex: newIndex, currentScreen: categoryId });
|
| 623 |
+
};
|
| 624 |
+
window.handlePrev = () => {
|
| 625 |
+
const newIndex = (appState.currentIndex - 1 + data.length) % data.length;
|
| 626 |
+
setState({ currentIndex: newIndex, currentScreen: categoryId });
|
| 627 |
+
};
|
| 628 |
+
|
| 629 |
+
const mainCardGradient = appState.isDarkMode
|
| 630 |
+
? 'from-gray-700 to-gray-600'
|
| 631 |
+
: (categoryId === 'tifinaghLetters' ? 'from-orange-400 to-pink-300' : 'from-blue-400 to-purple-300');
|
| 632 |
+
|
| 633 |
+
let illustrationContent;
|
| 634 |
+
if (isColorsCategory && currentItem.word !== 'أبيض') {
|
| 635 |
+
illustrationContent = `
|
| 636 |
+
<div class="w-40 h-40 sm:w-44 sm:h-44 rounded-full shadow-inner ${currentItem.colorClass || 'bg-gray-400'} border-4 border-white/80"></div>
|
| 637 |
+
`;
|
| 638 |
+
} else {
|
| 639 |
+
illustrationContent = `
|
| 640 |
+
<img
|
| 641 |
+
src="${currentItem.imageUrl || 'https://placehold.co/150x150/cccccc/000000?text=صورة'}"
|
| 642 |
+
alt="${currentItem.word}"
|
| 643 |
+
class="w-40 h-40 sm:w-44 sm:h-44 rounded-xl object-cover shadow-lg border-4 border-white/50"
|
| 644 |
+
onerror="this.onerror=null; this.src='https://placehold.co/150x150/cccccc/000000?text=صورة+${categoryMeta.title}';"
|
| 645 |
+
/>
|
| 646 |
+
`;
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
let mainWordDisplay = currentItem.main;
|
| 650 |
+
let secondaryText = currentItem.word;
|
| 651 |
+
|
| 652 |
+
const cornerElementHTML = (categoryId === 'tifinaghLetters') ? `
|
| 653 |
+
<div class="absolute top-0 right-0 p-3 bg-white/20 backdrop-blur-sm rounded-tr-3xl rounded-bl-3xl shadow-md text-white">
|
| 654 |
+
<h2 class="font-black text-4xl icon-shadow">
|
| 655 |
+
${currentItem.main}
|
| 656 |
+
</h2>
|
| 657 |
+
</div>
|
| 658 |
+
` : '';
|
| 659 |
+
|
| 660 |
+
const micAction = isRecordingActive ? 'stopRecording()' : 'startRecording()';
|
| 661 |
+
const micButtonClass = isRecordingActive
|
| 662 |
+
? 'bg-red-600 hover:bg-red-700 shadow-2xl shadow-red-400/70 animate-pulse'
|
| 663 |
+
: 'bg-red-500 hover:bg-red-600 shadow-2xl shadow-red-400/70';
|
| 664 |
+
|
| 665 |
+
|
| 666 |
+
content.innerHTML = `
|
| 667 |
+
<div class="p-4 flex flex-col items-center justify-between min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 668 |
+
|
| 669 |
+
<div class="w-full max-w-sm mx-auto bg-gradient-to-br ${mainCardGradient} rounded-3xl p-4 sm:p-6 shadow-2xl mt-2 flex flex-col justify-center items-center relative">
|
| 670 |
+
|
| 671 |
+
${cornerElementHTML}
|
| 672 |
+
|
| 673 |
+
<h2 class="text-white text-xl font-bold mb-3 drop-shadow-md mt-4">${categoryMeta.title}</h2>
|
| 674 |
+
|
| 675 |
+
<div class="flex items-center justify-center w-full p-2 mb-3">
|
| 676 |
+
${illustrationContent}
|
| 677 |
+
</div>
|
| 678 |
+
|
| 679 |
+
<div class="mt-1 text-center text-white">
|
| 680 |
+
<p class="text-3xl font-black mb-1 drop-shadow-lg leading-tight">${mainWordDisplay}</p>
|
| 681 |
+
<p class="text-sm font-medium opacity-80 italic drop-shadow-sm">
|
| 682 |
+
${secondaryText}
|
| 683 |
+
</p>
|
| 684 |
+
</div>
|
| 685 |
+
</div>
|
| 686 |
+
|
| 687 |
+
<div class="w-full max-w-sm mx-auto mt-4 bg-white dark:bg-gray-700 p-4 rounded-xl shadow-lg flex items-center gap-3 transition-colors">
|
| 688 |
+
<button onclick="playAudio()" class="p-2 rounded-full ${appState.isAppMuted ? 'bg-gray-200' : 'bg-green-100 hover:bg-green-200'} transition-colors" aria-label="تشغيل الصوت">
|
| 689 |
+
${renderIcon('Volume2', `w-7 h-7 ${appState.isAppMuted ? 'text-gray-500' : 'text-green-600'} flex-shrink-0`, 3)}
|
| 690 |
+
</button>
|
| 691 |
+
<div class="flex-grow">
|
| 692 |
+
<p class="text-sm text-gray-700 dark:text-gray-300 font-bold">استمع إلى النطق</p>
|
| 693 |
+
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1 text-left">${currentItem.audioUrl ? 'ملف الصوت متوفر' : 'ملف الصوت غير متوفر'}</p>
|
| 694 |
+
</div>
|
| 695 |
+
|
| 696 |
+
<p class="text-sm text-blue-800 dark:text-blue-300 font-bold flex-shrink-0">
|
| 697 |
+
نطق
|
| 698 |
+
</p>
|
| 699 |
+
</div>
|
| 700 |
+
|
| 701 |
+
<div class="flex justify-around w-full max-w-sm mx-auto mt-4 mb-4">
|
| 702 |
+
<button onclick="handlePrev()" class="control-btn bg-green-500 hover:bg-green-600 shadow-xl shadow-green-300/70" aria-label="العنصر السابق">
|
| 703 |
+
${renderIcon('ChevronRight', 'w-8 h-8 text-white', 3)}
|
| 704 |
+
</button>
|
| 705 |
+
|
| 706 |
+
<button onclick="${micAction}" class="control-btn p-6 ${micButtonClass}" aria-label="${isRecordingActive ? 'إيقاف التسجيل' : 'بدء التسجيل'}">
|
| 707 |
+
${renderIcon('Mic', 'w-10 h-10 text-white', 3)}
|
| 708 |
+
</button>
|
| 709 |
+
|
| 710 |
+
<button onclick="handleNext()" class="control-btn bg-blue-500 hover:bg-blue-600 shadow-xl shadow-blue-300/70" aria-label="العنصر التالي">
|
| 711 |
+
${renderIcon('ChevronLeft', 'w-8 h-8 text-white', 3)}
|
| 712 |
+
</button>
|
| 713 |
+
</div>
|
| 714 |
+
</div>
|
| 715 |
+
`;
|
| 716 |
+
// تشغيل الصوت تلقائيًا عند التحميل
|
| 717 |
+
if (!appState.isAppMuted && currentItem.audioUrl) {
|
| 718 |
+
// تأخير بسيط لضمان تحميل الواجهة
|
| 719 |
+
setTimeout(() => playAudio(currentItem.audioUrl), 500);
|
| 720 |
+
}
|
| 721 |
+
};
|
| 722 |
+
|
| 723 |
+
// --- 7.1 شاشة الإعدادات (Settings Screen) ---
|
| 724 |
+
const renderSettingsScreen = () => {
|
| 725 |
+
// ... (Code remains the same)
|
| 726 |
+
const content = document.getElementById('app-content');
|
| 727 |
+
|
| 728 |
+
const renderToggle = (id, label, stateKey) => `
|
| 729 |
+
<div class="flex items-center justify-between p-4 bg-white dark:bg-gray-700 rounded-xl shadow-md transition-colors">
|
| 730 |
+
<span class="text-gray-800 dark:text-white font-bold">${label}</span>
|
| 731 |
+
<label class="relative inline-flex items-center cursor-pointer">
|
| 732 |
+
<input type="checkbox" value="" class="sr-only peer" ${appState[stateKey] ? 'checked' : ''} onchange="setState({${stateKey}: event.target.checked, currentScreen: 'settings'})">
|
| 733 |
+
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-600 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:right-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-500 peer-checked:bg-blue-600"></div>
|
| 734 |
+
</label>
|
| 735 |
+
</div>
|
| 736 |
+
`;
|
| 737 |
+
|
| 738 |
+
content.innerHTML = `
|
| 739 |
+
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 740 |
+
<h2 class="text-3xl font-black text-gray-800 dark:text-white mb-6 text-center">الإعدادات</h2>
|
| 741 |
+
|
| 742 |
+
<div class="space-y-4 max-w-sm mx-auto">
|
| 743 |
+
|
| 744 |
+
${renderToggle('dark-mode-toggle', 'الوضع الليلي (Dark Mode)', 'isDarkMode')}
|
| 745 |
+
|
| 746 |
+
${renderToggle('mute-audio-toggle', 'كتم صوت العناصر التعليمية', 'isAppMuted')}
|
| 747 |
+
|
| 748 |
+
<div class="text-sm text-gray-500 dark:text-gray-400 p-2">
|
| 749 |
+
* ملاحظة: الإعدادات تُطبق فورًا على جميع شاشات التطبيق.
|
| 750 |
+
</div>
|
| 751 |
+
|
| 752 |
+
<div class="mt-8 pt-4 border-t border-gray-200 dark:border-gray-700">
|
| 753 |
+
<h3 class="text-xl font-bold text-gray-700 dark:text-gray-300 mb-4">خيارات أخرى</h3>
|
| 754 |
+
<button class="w-full py-3 bg-gray-200 dark:bg-gray-600 text-gray-800 dark:text-gray-200 font-bold rounded-xl hover:bg-gray-300 dark:hover:bg-gray-500 transition-colors">
|
| 755 |
+
إدارة البيانات (حذف/تصدير)
|
| 756 |
+
</button>
|
| 757 |
+
</div>
|
| 758 |
+
</div>
|
| 759 |
+
</div>
|
| 760 |
+
`;
|
| 761 |
+
};
|
| 762 |
+
|
| 763 |
+
// --- 7.2 شاشة حول التطبيق (Info Screen) ---
|
| 764 |
+
const renderInfoScreen = () => {
|
| 765 |
+
// ... (Code remains the same)
|
| 766 |
+
const content = document.getElementById('app-content');
|
| 767 |
+
|
| 768 |
+
const artistsHTML = VOICE_OVER_ARTISTS.map(artist => `
|
| 769 |
+
<li class="p-3 bg-white dark:bg-gray-700 rounded-lg shadow-sm flex flex-col sm:flex-row justify-between items-start sm:items-center transition-colors">
|
| 770 |
+
<span class="text-gray-800 dark:text-gray-200 font-bold">${artist.name}</span>
|
| 771 |
+
<span class="text-sm text-blue-600 dark:text-blue-400 italic mt-1 sm:mt-0">${artist.role}</span>
|
| 772 |
+
</li>
|
| 773 |
+
`).join('');
|
| 774 |
+
|
| 775 |
+
content.innerHTML = `
|
| 776 |
+
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 777 |
+
<h2 class="text-3xl font-black text-gray-800 dark:text-white mb-6 text-center">حول تطبيق ${APP_NAME}</h2>
|
| 778 |
+
|
| 779 |
+
<div class="max-w-md mx-auto bg-blue-100 dark:bg-blue-900/50 p-6 rounded-2xl shadow-xl mb-8 border-t-4 border-blue-500 transition-colors">
|
| 780 |
+
<h3 class="text-2xl font-black text-blue-800 dark:text-blue-300 mb-4 text-center">مطوّر البرنامج</h3>
|
| 781 |
+
<div class="flex flex-col items-center text-center">
|
| 782 |
+
<img src="${DEVELOPER_INFO.image}"
|
| 783 |
+
alt="${DEVELOPER_INFO.name}"
|
| 784 |
+
class="w-24 h-24 rounded-full object-cover border-4 border-white dark:border-gray-700 shadow-lg mb-3"
|
| 785 |
+
onerror="this.onerror=null; this.src='https://placehold.co/96x96/4A5568/ffffff?text=المطور';"
|
| 786 |
+
/>
|
| 787 |
+
<p class="text-xl font-bold text-gray-900 dark:text-white">${DEVELOPER_INFO.name}</p>
|
| 788 |
+
<p class="text-sm text-blue-700 dark:text-blue-400 mb-3">${DEVELOPER_INFO.title}</p>
|
| 789 |
+
<p class="text-gray-700 dark:text-gray-300 text-sm leading-relaxed italic">"${DEVELOPER_INFO.bio}"</p>
|
| 790 |
+
</div>
|
| 791 |
+
</div>
|
| 792 |
+
|
| 793 |
+
<div class="max-w-md mx-auto">
|
| 794 |
+
<h3 class="text-2xl font-black text-gray-800 dark:text-white mb-4 border-b pb-2 border-gray-200 dark:border-gray-700">المعلقون الصوتيون</h3>
|
| 795 |
+
<ul class="space-y-3">
|
| 796 |
+
${artistsHTML}
|
| 797 |
+
</ul>
|
| 798 |
+
</div>
|
| 799 |
+
</div>
|
| 800 |
+
`;
|
| 801 |
+
};
|
| 802 |
+
|
| 803 |
+
// --- 7.3 شاشة تعريف التطبيق (App Definition Screen) ---
|
| 804 |
+
const renderAppDefinitionScreen = () => {
|
| 805 |
+
// ... (Code remains the same)
|
| 806 |
+
const content = document.getElementById('app-content');
|
| 807 |
+
|
| 808 |
+
const features = [
|
| 809 |
+
{ title: 'تعلم الأحرف والأرقام', description: 'أساسيات لغة الأمازيغية (تيفيناغ) مع النطق الواضح.', icon: 'AArrowUp' },
|
| 810 |
+
{ title: 'المفردات المصنفة', description: 'أقسام متخصصة للحيوانات، الألوان، العائلة، وأجزاء الجسم.', icon: 'Palette' },
|
| 811 |
+
{ title: 'تفاعلي بالصوت', description: 'إمكانية الاستماع للنطق والتسجيل للمقارنة (ميزة التسجيل قيد التطوير).', icon: 'Volume2' },
|
| 812 |
+
{ title: 'إعدادات مخصصة', description: 'التحكم في الوضع الليلي وكتم الصوت لتجربة مريحة.', icon: 'Settings' },
|
| 813 |
+
];
|
| 814 |
+
|
| 815 |
+
const featuresHTML = features.map(f => `
|
| 816 |
+
<div class="flex items-start p-3 bg-white dark:bg-gray-700 rounded-xl shadow-sm transition-colors">
|
| 817 |
+
<div class="flex-shrink-0 p-2 bg-blue-100 dark:bg-blue-900 rounded-full">
|
| 818 |
+
${renderIcon(f.icon, 'w-6 h-6 text-blue-600 dark:text-blue-300')}
|
| 819 |
+
</div>
|
| 820 |
+
<div class="mr-3">
|
| 821 |
+
<h4 class="font-bold text-gray-800 dark:text-white">${f.title}</h4>
|
| 822 |
+
<p class="text-sm text-gray-600 dark:text-gray-400 mt-0.5">${f.description}</p>
|
| 823 |
+
</div>
|
| 824 |
+
</div>
|
| 825 |
+
`).join('');
|
| 826 |
+
|
| 827 |
+
content.innerHTML = `
|
| 828 |
+
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 829 |
+
<h2 class="text-3xl font-black text-gray-800 dark:text-white mb-4 text-center">ما هو تطبيق ${APP_NAME_LETTERS}؟</h2>
|
| 830 |
+
|
| 831 |
+
<div class="max-w-md mx-auto space-y-6">
|
| 832 |
+
<div class="bg-blue-500/10 dark:bg-blue-900/40 p-5 rounded-2xl border-l-4 border-blue-600">
|
| 833 |
+
<p class="text-lg text-gray-700 dark:text-gray-300 font-medium leading-relaxed">
|
| 834 |
+
تطبيق **${APP_NAME}** هو أداة تعليمية تفاعلية مصممة لتعليم الأطفال والمبتدئين
|
| 835 |
+
أساسيات **اللغة الأمازيغية (تيفيناغ)** بطريقة مسلية ومنظمة، مع التركيز على النطق الصحيح والمفردات اليومية.
|
| 836 |
+
</p>
|
| 837 |
+
</div>
|
| 838 |
+
|
| 839 |
+
<h3 class="text-2xl font-bold text-gray-800 dark:text-white border-b pb-2">المميزات الرئيسية</h3>
|
| 840 |
+
|
| 841 |
+
<div class="space-y-4">
|
| 842 |
+
${featuresHTML}
|
| 843 |
+
</div>
|
| 844 |
+
|
| 845 |
+
<div class="mt-6 pt-4 border-t border-gray-200 dark:border-gray-700 text-center">
|
| 846 |
+
<p class="text-sm text-gray-500 dark:text-gray-400">
|
| 847 |
+
الإصدار الحالي: 1.2 | جميع الحقوق محفوظة 2024
|
| 848 |
+
</p>
|
| 849 |
+
</div>
|
| 850 |
+
</div>
|
| 851 |
+
</div>
|
| 852 |
+
`;
|
| 853 |
+
};
|
| 854 |
+
|
| 855 |
+
|
| 856 |
+
// --- 8. شاشات الألعاب الجديدة ---
|
| 857 |
+
|
| 858 |
const renderGamesHome = () => {
|
| 859 |
const content = document.getElementById('app-content');
|
| 860 |
|
|
|
|
| 862 |
{
|
| 863 |
id: 'memory',
|
| 864 |
title: 'لعبة الذاكرة',
|
| 865 |
+
subtitle: 'طابق الصور والمفردات الأمازيغية',
|
| 866 |
iconName: 'Brain',
|
| 867 |
color: 'bg-green-500',
|
| 868 |
action: `setState({currentGameState: 'memory'})`
|
| 869 |
},
|
| 870 |
{
|
| 871 |
+
id: 'tifinagh_ordering',
|
| 872 |
+
title: 'ترتيب حروف تيفيناغ',
|
| 873 |
+
subtitle: 'رتّب الحروف الأمازيغية بشكل صحيح',
|
| 874 |
+
iconName: 'Repeat1',
|
| 875 |
color: 'bg-red-500',
|
| 876 |
+
action: `setState({currentGameState: 'tifinagh_ordering'})`
|
| 877 |
},
|
| 878 |
];
|
| 879 |
|
|
|
|
| 905 |
const levelData = memoryGameLevels[appState.currentLevel - 1];
|
| 906 |
if (!levelData) return alert('انتهت المستويات!');
|
| 907 |
|
| 908 |
+
// إنشاء بطاقات مزدوجة (صورة + كلمة أمازيغية)
|
| 909 |
let cards = [];
|
| 910 |
levelData.items.forEach(item => {
|
| 911 |
+
cards.push({ id: item.id, type: 'image', content: item.imageUrl, alt: item.word });
|
| 912 |
+
cards.push({ id: item.id, type: 'word', content: item.main, alt: item.word });
|
|
|
|
| 913 |
});
|
| 914 |
|
| 915 |
setState({
|
|
|
|
| 935 |
const card1 = newGameData[index1];
|
| 936 |
const card2 = newGameData[index2];
|
| 937 |
|
| 938 |
+
if (card1.id === card2.id) {
|
|
|
|
| 939 |
// Match found
|
| 940 |
newGameData[index1].isMatched = true;
|
| 941 |
newGameData[index2].isMatched = true;
|
|
|
|
| 955 |
initMemoryGame();
|
| 956 |
} else {
|
| 957 |
alert('تهانينا! لقد أنهيت لعبة الذاكرة بنجاح!');
|
| 958 |
+
setState({ currentGameState: null });
|
| 959 |
}
|
| 960 |
}, 800);
|
| 961 |
}
|
|
|
|
| 980 |
const renderMemoryGame = () => {
|
| 981 |
if (!appState.gameData) {
|
| 982 |
initMemoryGame();
|
| 983 |
+
return; // Wait for state update and re-render
|
| 984 |
}
|
| 985 |
|
| 986 |
const content = document.getElementById('app-content');
|
| 987 |
const levelData = memoryGameLevels[appState.currentLevel - 1];
|
| 988 |
+
const cols = levelData.pairs <= 4 ? 4 : (levelData.pairs <= 8 ? 4 : 5);
|
| 989 |
+
const gridClass = `grid grid-cols-${cols} gap-2 w-full max-w-sm mx-auto`;
|
|
|
|
|
|
|
|
|
|
| 990 |
|
| 991 |
content.innerHTML = `
|
| 992 |
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
|
|
|
| 994 |
لعبة الذاكرة - المستوى ${appState.currentLevel}
|
| 995 |
</h3>
|
| 996 |
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 text-center">
|
| 997 |
+
طابق ${levelData.pairs} أزواج
|
| 998 |
</p>
|
| 999 |
|
| 1000 |
<div class="${gridClass}" style="grid-template-columns: repeat(${cols}, minmax(0, 1fr));">
|
|
|
|
| 1006 |
${card.type === 'image' ? `
|
| 1007 |
<img src="${card.content}" alt="${card.alt}" class="w-full h-full object-cover rounded-md" onerror="this.onerror=null; this.src='https://placehold.co/80x80?text=صورة';"/>
|
| 1008 |
` : `
|
| 1009 |
+
<span class="text-3xl font-black text-blue-800 dark:text-white">${card.content}</span>
|
| 1010 |
`}
|
| 1011 |
</div>
|
| 1012 |
|
|
|
|
| 1028 |
`;
|
| 1029 |
};
|
| 1030 |
|
| 1031 |
+
// --- 8.2 لعبة ترتيب حروف تيفيناغ (Tifinagh Ordering Game) ---
|
| 1032 |
|
| 1033 |
+
window.initTifinaghOrderingGame = () => {
|
| 1034 |
+
const levelData = tifinaghOrderingLevels[appState.currentLevel - 1];
|
| 1035 |
if (!levelData) return alert('انتهت المستويات!');
|
| 1036 |
|
|
|
|
| 1037 |
setState({
|
| 1038 |
gameData: levelData,
|
| 1039 |
+
tifinaghOrderingGame: {
|
| 1040 |
+
userOrder: Array(levelData.letters.length).fill(null),
|
| 1041 |
+
availableLetters: shuffleArray(levelData.letters)
|
|
|
|
| 1042 |
},
|
| 1043 |
+
currentGameState: 'tifinagh_ordering',
|
| 1044 |
currentLevel: levelData.level,
|
| 1045 |
});
|
| 1046 |
};
|
| 1047 |
|
| 1048 |
+
window.placeLetter = (letter, slotIndex) => {
|
| 1049 |
+
const newOrder = [...appState.tifinaghOrderingGame.userOrder];
|
| 1050 |
+
const newAvailable = appState.tifinaghOrderingGame.availableLetters.filter(l => l !== letter);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1051 |
|
| 1052 |
+
newOrder[slotIndex] = letter;
|
|
|
|
|
|
|
| 1053 |
|
| 1054 |
+
const isCompleted = newAvailable.length === 0;
|
| 1055 |
+
|
| 1056 |
+
setState({
|
| 1057 |
+
tifinaghOrderingGame: { userOrder: newOrder, availableLetters: newAvailable }
|
| 1058 |
+
});
|
| 1059 |
|
| 1060 |
+
if (isCompleted) {
|
| 1061 |
+
checkOrderingWin(newOrder);
|
| 1062 |
}
|
| 1063 |
};
|
| 1064 |
|
| 1065 |
window.removeLetter = (slotIndex) => {
|
| 1066 |
+
const letter = appState.tifinaghOrderingGame.userOrder[slotIndex];
|
| 1067 |
+
if (!letter) return;
|
|
|
|
| 1068 |
|
| 1069 |
+
const newOrder = [...appState.tifinaghOrderingGame.userOrder];
|
| 1070 |
+
newOrder[slotIndex] = null;
|
| 1071 |
|
| 1072 |
+
const newAvailable = [...appState.tifinaghOrderingGame.availableLetters, letter];
|
|
|
|
|
|
|
| 1073 |
|
| 1074 |
+
setState({
|
| 1075 |
+
tifinaghOrderingGame: { userOrder: newOrder, availableLetters: newAvailable }
|
| 1076 |
+
});
|
| 1077 |
};
|
| 1078 |
|
| 1079 |
+
window.checkOrderingWin = (userOrder) => {
|
| 1080 |
+
const correctOrder = appState.gameData.correctOrder;
|
| 1081 |
+
const isCorrect = userOrder.every((letter, index) => letter === correctOrder[index]);
|
| 1082 |
|
| 1083 |
if (isCorrect) {
|
| 1084 |
setTimeout(() => {
|
| 1085 |
+
if (appState.currentLevel < tifinaghOrderingLevels.length) {
|
| 1086 |
+
alert(`مذهل! التسلسل صحيح. المستوى ${appState.currentLevel} مكتمل.`);
|
| 1087 |
setState({ currentLevel: appState.currentLevel + 1 });
|
| 1088 |
+
initTifinaghOrderingGame();
|
| 1089 |
} else {
|
| 1090 |
+
alert('تهانينا! لقد أتقنت ترتيب حروف تيفيناغ!');
|
| 1091 |
+
setState({ currentGameState: null });
|
| 1092 |
}
|
| 1093 |
}, 500);
|
| 1094 |
} else {
|
| 1095 |
+
alert('حاول مرة أخرى! التسلسل غير صحيح.');
|
| 1096 |
}
|
| 1097 |
};
|
| 1098 |
|
| 1099 |
|
| 1100 |
+
const renderTifinaghOrderingGame = () => {
|
| 1101 |
if (!appState.gameData) {
|
| 1102 |
+
initTifinaghOrderingGame();
|
| 1103 |
return;
|
| 1104 |
}
|
| 1105 |
|
| 1106 |
const content = document.getElementById('app-content');
|
| 1107 |
const levelData = appState.gameData;
|
| 1108 |
+
const state = appState.tifinaghOrderingGame;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1109 |
|
| 1110 |
+
const cols = levelData.letters.length <= 6 ? 6 : 7;
|
| 1111 |
+
const gridClass = `grid grid-cols-${cols} gap-2 w-full mx-auto`;
|
| 1112 |
+
|
| 1113 |
content.innerHTML = `
|
| 1114 |
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 1115 |
<h3 class="text-2xl font-black text-gray-800 dark:text-white mb-2 text-center">
|
| 1116 |
+
ترتيب الحروف - المستوى ${appState.currentLevel}
|
| 1117 |
</h3>
|
| 1118 |
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4 text-center">
|
| 1119 |
+
رتّب الحروف التالية بالضغط عليها ثم الضغط على المكان المناسب.
|
| 1120 |
</p>
|
| 1121 |
|
| 1122 |
+
<div class="bg-blue-100 dark:bg-blue-900 p-3 rounded-xl mb-4 text-center max-w-sm mx-auto">
|
| 1123 |
+
<p class="text-xs text-blue-700 dark:text-blue-300 font-bold mb-1">تسلسل الحروف (مساعدة):</p>
|
| 1124 |
+
<div class="flex justify-center flex-wrap gap-2">
|
| 1125 |
+
${levelData.correctOrder.map(l => `<span class="text-lg font-bold text-blue-800 dark:text-white">${l}</span>`).join('')}
|
| 1126 |
+
</div>
|
| 1127 |
</div>
|
| 1128 |
+
|
| 1129 |
+
|
| 1130 |
+
<h4 class="text-lg font-bold text-gray-700 dark:text-gray-300 mt-6 mb-2 text-center">مكان الترتيب:</h4>
|
| 1131 |
+
<div class="flex justify-center flex-wrap gap-2 mb-8">
|
| 1132 |
+
${state.userOrder.map((letter, index) => `
|
| 1133 |
<button onclick="removeLetter(${index})"
|
| 1134 |
+
class="ordering-slot w-10 h-10 flex items-center justify-center border-2 border-dashed ${letter ? 'border-green-500 bg-green-100 dark:bg-green-900/50' : 'border-gray-400 dark:border-gray-600'} rounded-lg transition-all"
|
| 1135 |
+
aria-label="مكان الحرف رقم ${index + 1}">
|
| 1136 |
+
<span class="text-2xl font-black ${letter ? 'text-green-800 dark:text-white' : 'text-transparent'}">${letter || ''}</span>
|
| 1137 |
</button>
|
| 1138 |
`).join('')}
|
| 1139 |
</div>
|
| 1140 |
|
| 1141 |
<h4 class="text-lg font-bold text-gray-700 dark:text-gray-300 mt-6 mb-2 text-center">الحروف المتاحة:</h4>
|
| 1142 |
+
<div class="flex justify-center flex-wrap gap-2 mb-8">
|
| 1143 |
+
${state.availableLetters.map((letter, index) => `
|
| 1144 |
+
<button onclick="
|
| 1145 |
+
const slotIndex = appState.tifinaghOrderingGame.userOrder.findIndex(l => l === null);
|
| 1146 |
+
if (slotIndex !== -1) placeLetter('${letter}', slotIndex);
|
| 1147 |
+
"
|
| 1148 |
+
class="ordering-letter w-12 h-12 flex items-center justify-center bg-purple-500 text-white text-3xl font-black rounded-lg shadow-md hover:bg-purple-600"
|
| 1149 |
+
aria-label="الحرف ${letter}">
|
| 1150 |
+
${letter}
|
| 1151 |
</button>
|
| 1152 |
`).join('')}
|
| 1153 |
</div>
|
| 1154 |
|
| 1155 |
<div class="mt-8 text-center">
|
| 1156 |
+
<button onclick="checkOrderingWin(appState.tifinaghOrderingGame.userOrder)"
|
| 1157 |
class="px-6 py-3 bg-blue-600 text-white font-bold rounded-xl shadow-lg hover:bg-blue-700 disabled:opacity-50"
|
| 1158 |
+
${state.availableLetters.length > 0 ? 'disabled' : ''}>
|
| 1159 |
+
تحقق من الترتيب
|
| 1160 |
</button>
|
| 1161 |
+
<button onclick="initTifinaghOrderingGame()"
|
| 1162 |
class="px-4 py-2 bg-yellow-500 text-white font-bold rounded-xl shadow-lg hover:bg-yellow-600 mr-2">
|
| 1163 |
إعادة المستوى
|
| 1164 |
</button>
|
|
|
|
| 1166 |
</div>
|
| 1167 |
`;
|
| 1168 |
};
|
| 1169 |
+
|
| 1170 |
|
| 1171 |
+
// --- 9. دالة الرسم الرئيسية والتهيئة ---
|
| 1172 |
+
|
| 1173 |
const renderApp = () => {
|
|
|
|
| 1174 |
const screen = appState.currentScreen;
|
| 1175 |
const content = document.getElementById('app-content');
|
| 1176 |
const header = document.getElementById('app-header');
|
| 1177 |
const footer = document.getElementById('app-footer');
|
| 1178 |
|
| 1179 |
+
// التحكم في عرض الـ Header و الـ Footer
|
| 1180 |
const shouldShowNav = screen !== 'welcome';
|
| 1181 |
header.style.display = shouldShowNav ? 'block' : 'none';
|
| 1182 |
footer.style.display = shouldShowNav ? 'block' : 'none';
|
|
|
|
| 1184 |
if (shouldShowNav) {
|
| 1185 |
renderHeader();
|
| 1186 |
renderFooter();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1187 |
}
|
| 1188 |
|
| 1189 |
+
// تحديد محتوى الشاشة
|
| 1190 |
+
if (screen === 'welcome') {
|
| 1191 |
+
renderWelcomeScreen();
|
| 1192 |
+
content.style.paddingTop = '0';
|
| 1193 |
+
content.style.paddingBottom = '0';
|
| 1194 |
+
} else if (screen === 'home' || screen === 'profile') {
|
| 1195 |
+
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 1196 |
+
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 1197 |
+
renderHomeScreen();
|
| 1198 |
+
} else if (screen === 'settings') {
|
| 1199 |
+
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 1200 |
+
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 1201 |
+
renderSettingsScreen();
|
| 1202 |
+
} else if (screen === 'info') {
|
| 1203 |
+
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 1204 |
+
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 1205 |
+
renderInfoScreen();
|
| 1206 |
+
} else if (screen === 'appDefinition') {
|
| 1207 |
+
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 1208 |
+
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 1209 |
+
renderAppDefinitionScreen();
|
| 1210 |
+
} else if (screen === 'games') {
|
| 1211 |
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 1212 |
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 1213 |
if (appState.currentGameState === 'memory') {
|
| 1214 |
renderMemoryGame();
|
| 1215 |
+
} else if (appState.currentGameState === 'tifinagh_ordering') {
|
| 1216 |
+
renderTifinaghOrderingGame();
|
| 1217 |
} else {
|
| 1218 |
renderGamesHome();
|
| 1219 |
}
|
| 1220 |
+
} else if (CATEGORIES.some(c => c.id === screen)) {
|
| 1221 |
+
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 1222 |
+
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 1223 |
+
renderLearningScreen();
|
| 1224 |
} else {
|
| 1225 |
+
content.innerHTML = `
|
| 1226 |
+
<div class="p-8 min-h-[calc(100vh-130px)] flex flex-col items-center justify-center bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 1227 |
+
<p class="text-xl font-bold text-purple-600 dark:text-purple-400 mb-4">هذا القسم قيد الإنشاء!</p>
|
| 1228 |
+
<button onclick="setState({currentScreen: 'home', selectedCategory: null, currentGameState: null})"
|
| 1229 |
+
class="px-6 py-3 bg-purple-600 text-white font-bold rounded-xl shadow-lg hover:bg-purple-700 card-shadow">
|
| 1230 |
+
العودة للرئيسية
|
| 1231 |
+
</button>
|
| 1232 |
+
</div>
|
| 1233 |
+
`;
|
| 1234 |
+
}
|
| 1235 |
+
|
| 1236 |
+
// إدارة الـ Menu Overlay
|
| 1237 |
+
const existingMenu = document.getElementById('menu-overlay');
|
| 1238 |
+
const appContainer = document.getElementById('app-container');
|
| 1239 |
+
|
| 1240 |
+
if (appState.isMenuOpen) {
|
| 1241 |
+
if (!existingMenu) {
|
| 1242 |
+
const menuHTML = renderMenu();
|
| 1243 |
+
appContainer.insertAdjacentHTML('afterend', menuHTML);
|
| 1244 |
+
}
|
| 1245 |
+
} else if (existingMenu) {
|
| 1246 |
+
existingMenu.remove();
|
| 1247 |
}
|
| 1248 |
};
|
| 1249 |
+
|
| 1250 |
+
// --- 8. القائمة الجانبية (Menu) ---
|
| 1251 |
+
const renderMenu = () => {
|
| 1252 |
+
if (!appState.isMenuOpen) return '';
|
| 1253 |
|
| 1254 |
+
const cardsHTML = CATEGORIES.map(category => `
|
| 1255 |
+
<button
|
| 1256 |
+
onclick="setState({currentScreen: '${category.id}', selectedCategory: '${category.id}', isMenuOpen: false})"
|
| 1257 |
+
class="relative w-full h-24 rounded-xl overflow-hidden card-shadow group text-right"
|
| 1258 |
+
aria-label="الذهاب إلى قسم ${category.title}"
|
| 1259 |
+
>
|
| 1260 |
+
<div class="absolute inset-0" style="background-image: url('${category.imageUrl}'); background-size: cover; background-position: center;">
|
| 1261 |
+
<div class="absolute inset-0 bg-blue-900/70 p-3 flex items-center gap-3 transition-all group-hover:bg-blue-800/80">
|
| 1262 |
+
<div class="p-2 bg-white/20 rounded-lg">
|
| 1263 |
+
${renderIcon(category.iconName, 'w-6 h-6 text-white')}
|
| 1264 |
+
</div>
|
| 1265 |
+
<div class="mr-3 text-right text-white">
|
| 1266 |
+
<span class="text-lg font-black leading-tight drop-shadow-md">${category.title}</span>
|
| 1267 |
+
<span class="text-xs opacity-80 mt-1 block">${category.subtitle}</span>
|
| 1268 |
+
</div>
|
| 1269 |
+
</div>
|
| 1270 |
+
</div>
|
| 1271 |
+
</button>
|
| 1272 |
+
`).join('');
|
| 1273 |
+
|
| 1274 |
+
return `
|
| 1275 |
+
<div id="menu-overlay"
|
| 1276 |
+
class="fixed inset-0 z-30 bg-black/50 transition-opacity duration-300"
|
| 1277 |
+
onclick="toggleMenu()">
|
| 1278 |
+
|
| 1279 |
+
<div class="absolute top-0 right-0 h-full w-full max-w-sm bg-gray-50 dark:bg-gray-800 shadow-2xl overflow-y-auto transform transition-transform duration-300 translate-x-0"
|
| 1280 |
+
onclick="event.stopPropagation()">
|
| 1281 |
+
|
| 1282 |
+
<div class="p-4 pt-16 border-b border-gray-200 dark:border-gray-700 bg-blue-800 dark:bg-gray-900 text-white rounded-bl-3xl">
|
| 1283 |
+
<h3 class="text-2xl font-black">جميع الأقسام</h3>
|
| 1284 |
+
<p class="text-sm opacity-80 mt-1">اختر ما تريد تعلمه الآن:</p>
|
| 1285 |
+
</div>
|
| 1286 |
+
|
| 1287 |
+
<div class="p-4 grid grid-cols-1 gap-3 hide-scrollbar">
|
| 1288 |
+
${cardsHTML}
|
| 1289 |
+
</div>
|
| 1290 |
+
<div class="p-4">
|
| 1291 |
+
<button onclick="toggleMenu()" class="w-full py-3 bg-red-500 text-white font-bold rounded-xl shadow-lg">إغلاق القائمة</button>
|
| 1292 |
+
</div>
|
| 1293 |
+
</div>
|
| 1294 |
+
</div>
|
| 1295 |
+
`;
|
| 1296 |
+
};
|
| 1297 |
+
|
| 1298 |
+
|
| 1299 |
+
// تهيئة التطبيق عند تحميل النافذة
|
| 1300 |
window.onload = () => {
|
| 1301 |
+
renderApp();
|
|
|
|
|
|
|
| 1302 |
};
|
| 1303 |
|
| 1304 |
</script>
|