Spaces:
Running
Running
Update index.html
Browse files- index.html +544 -55
index.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
<!DOCTYPE html>
|
| 2 |
<html lang="ar" dir="rtl">
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
|
@@ -75,6 +75,47 @@
|
|
| 75 |
.animate-pulse {
|
| 76 |
animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
| 77 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
</style>
|
| 79 |
</head>
|
| 80 |
<body class="flex justify-center">
|
|
@@ -114,6 +155,8 @@
|
|
| 114 |
CloudRain: (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="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M16 18v2"/><path d="M8 18v2"/><path d="M12 18v2"/></svg>`,
|
| 115 |
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>`,
|
| 116 |
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>`,
|
|
|
|
|
|
|
| 117 |
WhatsApp: (cls) => ICONS.Share2(cls),
|
| 118 |
};
|
| 119 |
|
|
@@ -129,6 +172,15 @@
|
|
| 129 |
|
| 130 |
|
| 131 |
// --- 2. بيانات التطبيق الثابتة ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
|
| 133 |
const APP_NAME = "Tifawin";
|
| 134 |
const APP_NAME_LETTERS = "TIMMUZIT";
|
|
@@ -152,16 +204,38 @@
|
|
| 152 |
{ letter: 'ⴰ', word_tifinagh: '', word_arabic: 'جدار-ⴰⴳⴰⴷⵉⵔ', image: 'images/2947c16d27f8042f7d60783c6808519a.jpg', audio: 'audio/aman.mp3' },
|
| 153 |
{ letter: 'ⴱ', word_tifinagh: '', word_arabic: 'فراشة-ⵉⴱⵔⴱⵉⵍⵍⵓ', image: 'images/3fd6beebd231e2f325469a40b0831b59.jpg', audio: 'audio/barbi.mp3' },
|
| 154 |
{ letter: 'ⴳ', word_tifinagh: '', word_arabic: 'دخان-ⴰⴳⴳⵓ', image: 'images/c0094eb5dcc49d7cce573d42f270d8de.jpg', audio: 'audio/ca.mp3' },
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
const animalsData = [
|
| 158 |
{ word_tifinagh: 'ⴰⵎⵓⵛⵛ', word_arabic: 'قط ', image: 'images/cat.jpeg', audio: 'audio/animaux.ogg' },
|
| 159 |
{ word_tifinagh: 'ⴰⵢⴷⵉ', word_arabic: 'كلب', image: 'images/124419894dcfde81ffbca1e072804c71.jpg', audio: 'audio/dog.mp3' },
|
|
|
|
|
|
|
| 160 |
];
|
| 161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
const numbersData = [
|
| 163 |
-
{ number: '0', word_tifinagh: 'ⴰⵎⵢⴰ', word_arabic: 'صفر ', image: 'images/d3a43a956f3129b847739dec5f10c81f.jpg', audio: 'audio/
|
| 164 |
{ number: '1', word_tifinagh: 'ⵢⴰⵏ ', word_arabic: ' واحد', image: 'images/b26681eaa5caacbf1c7bfb112f546def.jpg', audio: 'audio/one.mp3' },
|
|
|
|
|
|
|
| 165 |
];
|
| 166 |
|
| 167 |
const LEARNING_DATA = {
|
|
@@ -183,7 +257,7 @@
|
|
| 183 |
audioUrl: item.audio,
|
| 184 |
})),
|
| 185 |
tools: [{ main: 'ⴰⴽⵕⵕⴰⵊ', word: 'قلم رصاص', imageUrl: 'images/37b71533177feb9d55d55efba947309e.jpg', audioUrl: 'audio/schoolSupplies/pencil.mp3' }],
|
| 186 |
-
fruits:
|
| 187 |
vegetables: [{ main: 'ⵜⴰⵎⴰⵟⵉⵛⵜ', word: 'طماطم', imageUrl: 'images/6056d9839a962b5a78cddc402ef88c09.jpg', audioUrl: 'audio/vegetables/tomato.mp3' }],
|
| 188 |
animals: animalsData.map(item => ({ main: item.word_tifinagh, word: item.word_arabic, imageUrl: item.image, audioUrl: item.audio })),
|
| 189 |
body: [{ main: 'ⵉⵅⴼ', word: 'الرأس', imageUrl: 'images/33dda7fe89cfd5526918246dae320059.jpg', audioUrl: 'audio/bodyParts/head.mp3' }],
|
|
@@ -193,14 +267,59 @@
|
|
| 193 |
colors: [
|
| 194 |
{ main: 'ⴰⵣⴳⴳⵯⴰⵖ', word: 'أحمر', imageUrl: 'images/b008721ac76def4ddfdbdb51fc82d320.jpg', audioUrl: 'audio/colors/red.mp3', colorClass: 'bg-red-600' },
|
| 195 |
{ main: 'ⴰⵣⴳⴳⵯⴰⵖ', word: 'أزرق', imageUrl: 'images/b008721ac76def4ddfdbdb51fc82d320.jpg', audioUrl: 'audio/colors/blue.mp3', colorClass: 'bg-blue-600' },
|
| 196 |
-
{ main: 'ⴰⵣⴳⴳⵯⴰⵖ', word: 'أخضر', imageUrl: 'images/b008721ac76def4ddfdbdb51fc82d320.jpg', audioUrl: 'audio/colors/green.mp3', colorClass: 'bg-green-600' },
|
| 197 |
-
{ main: 'ⴰⵣⴳⴳⵯⴰⵖ', word: 'أبيض', imageUrl: 'images/b008721ac76def4ddfdbdb51fc82d320.jpg', audioUrl: 'audio/colors/white.mp3', colorClass: 'bg-white' },
|
| 198 |
],
|
| 199 |
seasons: [{ main: 'ⵜⴰⴳⵔⵙⵜ', word: 'الشتاء', imageUrl: 'images/b2d331ea13a2df600219904dabd028fa.jpg', audioUrl: 'audio/AUD-20250926-WA0003.opus' }],
|
| 200 |
games: [{ main: "أسد صغير شجاع", word: "في غابة بعيدة، عاش أسد صغير اسمه سمير...", imageUrl: "images/Screenshot_20250927_141840_One Read.jpg", audioUrl: null }],
|
| 201 |
stories: [{ main: "السلحفاة والأرنب", word: "في غابة خضراء، قرر أرنب وسلحفاة...", imageUrl: "images/73b552bd0d3472c121adccc68a5bbb7f.jpg", audioUrl: null }],
|
| 202 |
};
|
| 203 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
const CATEGORIES = [
|
| 206 |
{ id: 'tifinaghLetters', title: 'تعلم الحروف', subtitle: 'ⴰ, ⴱ, ⴳ...', iconName: 'AArrowUp', imageUrl: 'images/6e318d538a2d8f0b5ad685db558ffe4e.jpg' },
|
|
@@ -230,14 +349,43 @@
|
|
| 230 |
isDarkMode: false,
|
| 231 |
isAppMuted: false,
|
| 232 |
isRecording: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
};
|
| 234 |
|
| 235 |
// دالة تحديث الحالة وإعادة رسم التطبيق
|
| 236 |
window.setState = (newState) => {
|
| 237 |
if (newState.currentScreen && newState.currentScreen !== appState.selectedCategory) {
|
| 238 |
appState.currentIndex = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
}
|
| 240 |
|
|
|
|
| 241 |
Object.assign(appState, newState);
|
| 242 |
|
| 243 |
// تطبيق الوضع الليلي فوراً على الجسم والحاوية
|
|
@@ -273,7 +421,11 @@
|
|
| 273 |
const categoryMeta = CATEGORIES.find(c => c.id === appState.selectedCategory);
|
| 274 |
|
| 275 |
let title = APP_NAME;
|
| 276 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
title = categoryMeta.title;
|
| 278 |
} else if (appState.currentScreen === 'settings') {
|
| 279 |
title = 'الإعدادات';
|
|
@@ -281,16 +433,20 @@
|
|
| 281 |
title = 'حول التطبيق';
|
| 282 |
} else if (appState.currentScreen === 'appDefinition') {
|
| 283 |
title = 'تعريف التطبيق';
|
|
|
|
|
|
|
| 284 |
}
|
| 285 |
|
| 286 |
headerElement.innerHTML = `
|
| 287 |
<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">
|
| 288 |
-
<button onclick="
|
| 289 |
-
|
| 290 |
-
|
|
|
|
|
|
|
| 291 |
</button>
|
| 292 |
<h1 class="text-xl font-extrabold text-white">${title}</h1>
|
| 293 |
-
<button onclick="setState({currentScreen: 'appDefinition', selectedCategory: null})"
|
| 294 |
class="w-8 h-8 rounded-full bg-yellow-400 border-2 border-white flex items-center justify-center text-sm font-bold text-blue-900 shadow-md transition-shadow hover:shadow-lg"
|
| 295 |
aria-label="تعريف التطبيق">
|
| 296 |
${renderIcon('BookOpen', 'w-4 h-4 text-blue-900', 3)}
|
|
@@ -300,6 +456,7 @@
|
|
| 300 |
};
|
| 301 |
|
| 302 |
const renderFooter = () => {
|
|
|
|
| 303 |
const footerElement = document.getElementById('app-footer');
|
| 304 |
const navItems = [
|
| 305 |
{ id: 'home', iconName: 'Home', label: 'الرئيسية' },
|
|
@@ -319,7 +476,7 @@
|
|
| 319 |
${navItems.map(item => {
|
| 320 |
const isActive = item.id === activeScreen;
|
| 321 |
|
| 322 |
-
let clickAction = `setState({currentScreen: '${item.id}', selectedCategory: null})`;
|
| 323 |
if (item.id === 'whatsapp') {
|
| 324 |
clickAction = `window.open('${WHATSAPP_LINK}', '_blank')`;
|
| 325 |
}
|
|
@@ -344,7 +501,8 @@
|
|
| 344 |
|
| 345 |
// --- 5. شاشة 1: شاشة الترحيب (Welcome Screen) ---
|
| 346 |
const renderWelcomeScreen = () => {
|
| 347 |
-
|
|
|
|
| 348 |
|
| 349 |
const logoHTML = `
|
| 350 |
<div class="flex flex-col items-center">
|
|
@@ -384,6 +542,7 @@
|
|
| 384 |
|
| 385 |
// --- 6. شاشة 2: الشاشة الرئيسية (Home Screen) ---
|
| 386 |
const renderHomeScreen = () => {
|
|
|
|
| 387 |
const content = document.getElementById('app-content');
|
| 388 |
|
| 389 |
const cardsHTML = CATEGORIES.map(category => `
|
|
@@ -421,7 +580,8 @@
|
|
| 421 |
|
| 422 |
// --- 7. شاشة التعلم العامة (Learning Screen) ---
|
| 423 |
const renderLearningScreen = () => {
|
| 424 |
-
|
|
|
|
| 425 |
const content = document.getElementById('app-content');
|
| 426 |
const data = LEARNING_DATA[categoryId] || [];
|
| 427 |
const categoryMeta = CATEGORIES.find(c => c.id === categoryId);
|
|
@@ -562,7 +722,8 @@
|
|
| 562 |
|
| 563 |
// --- 7.1 شاشة الإعدادات (Settings Screen) ---
|
| 564 |
const renderSettingsScreen = () => {
|
| 565 |
-
|
|
|
|
| 566 |
|
| 567 |
const renderToggle = (id, label, stateKey) => `
|
| 568 |
<div class="flex items-center justify-between p-4 bg-white dark:bg-gray-700 rounded-xl shadow-md transition-colors">
|
|
@@ -601,7 +762,8 @@
|
|
| 601 |
|
| 602 |
// --- 7.2 شاشة حول التطبيق (Info Screen) ---
|
| 603 |
const renderInfoScreen = () => {
|
| 604 |
-
|
|
|
|
| 605 |
|
| 606 |
const artistsHTML = VOICE_OVER_ARTISTS.map(artist => `
|
| 607 |
<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">
|
|
@@ -640,7 +802,8 @@
|
|
| 640 |
|
| 641 |
// --- 7.3 شاشة تعريف التطبيق (App Definition Screen) ---
|
| 642 |
const renderAppDefinitionScreen = () => {
|
| 643 |
-
|
|
|
|
| 644 |
|
| 645 |
const features = [
|
| 646 |
{ title: 'تعلم الأحرف والأرقام', description: 'أساسيات لغة الأمازيغية (تيفيناغ) مع النطق الواضح.', icon: 'AArrowUp' },
|
|
@@ -690,53 +853,320 @@
|
|
| 690 |
};
|
| 691 |
|
| 692 |
|
| 693 |
-
// --- 8. ا
|
| 694 |
-
const renderMenu = () => {
|
| 695 |
-
if (!appState.isMenuOpen) return '';
|
| 696 |
|
| 697 |
-
|
| 698 |
-
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
|
| 703 |
-
|
| 704 |
-
|
| 705 |
-
|
| 706 |
-
|
| 707 |
-
|
| 708 |
-
|
| 709 |
-
|
| 710 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 711 |
</div>
|
| 712 |
-
|
| 713 |
-
|
| 714 |
-
</button>
|
| 715 |
-
`).join('');
|
| 716 |
|
| 717 |
-
|
| 718 |
-
|
| 719 |
-
|
| 720 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 721 |
|
| 722 |
-
<div class="
|
| 723 |
-
|
| 724 |
-
|
| 725 |
-
|
| 726 |
-
<h3 class="text-2xl font-black">جميع الأقسام</h3>
|
| 727 |
-
<p class="text-sm opacity-80 mt-1">اختر ما تريد تعلمه الآن:</p>
|
| 728 |
</div>
|
|
|
|
| 729 |
|
| 730 |
-
|
| 731 |
-
|
| 732 |
-
|
| 733 |
-
|
| 734 |
-
<button onclick="
|
| 735 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 736 |
</div>
|
| 737 |
</div>
|
| 738 |
`;
|
| 739 |
};
|
|
|
|
| 740 |
|
| 741 |
// --- 9. دالة الرسم الرئيسية والتهيئة ---
|
| 742 |
|
|
@@ -777,6 +1207,16 @@
|
|
| 777 |
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 778 |
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
| 779 |
renderAppDefinitionScreen();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 780 |
} else if (CATEGORIES.some(c => c.id === screen)) {
|
| 781 |
content.style.paddingTop = shouldShowNav ? '4rem' : '0';
|
| 782 |
content.style.paddingBottom = shouldShowNav ? '5rem' : '0';
|
|
@@ -785,7 +1225,7 @@
|
|
| 785 |
content.innerHTML = `
|
| 786 |
<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">
|
| 787 |
<p class="text-xl font-bold text-purple-600 dark:text-purple-400 mb-4">هذا القسم قيد الإنشاء!</p>
|
| 788 |
-
<button onclick="setState({currentScreen: 'home', selectedCategory: null})"
|
| 789 |
class="px-6 py-3 bg-purple-600 text-white font-bold rounded-xl shadow-lg hover:bg-purple-700 card-shadow">
|
| 790 |
العودة للرئيسية
|
| 791 |
</button>
|
|
@@ -806,6 +1246,55 @@
|
|
| 806 |
existingMenu.remove();
|
| 807 |
}
|
| 808 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 809 |
|
| 810 |
// تهيئة التطبيق عند تحميل النافذة
|
| 811 |
window.onload = () => {
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
<html lang="ar" dir="rtl">
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
|
|
|
| 75 |
.animate-pulse {
|
| 76 |
animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
| 77 |
}
|
| 78 |
+
|
| 79 |
+
/* Game specific styles */
|
| 80 |
+
.card-flip {
|
| 81 |
+
transform-style: preserve-3d;
|
| 82 |
+
transition: transform 0.5s;
|
| 83 |
+
}
|
| 84 |
+
.card-flip.flipped {
|
| 85 |
+
transform: rotateY(180deg);
|
| 86 |
+
}
|
| 87 |
+
.card-face {
|
| 88 |
+
backface-visibility: hidden;
|
| 89 |
+
position: absolute;
|
| 90 |
+
width: 100%;
|
| 91 |
+
height: 100%;
|
| 92 |
+
display: flex;
|
| 93 |
+
align-items: center;
|
| 94 |
+
justify-content: center;
|
| 95 |
+
border-radius: 0.5rem;
|
| 96 |
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
| 97 |
+
}
|
| 98 |
+
.card-back {
|
| 99 |
+
background-color: #4f46e5;
|
| 100 |
+
transform: rotateY(180deg);
|
| 101 |
+
}
|
| 102 |
+
.card-matched {
|
| 103 |
+
opacity: 0.5;
|
| 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">
|
|
|
|
| 155 |
CloudRain: (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="M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"/><path d="M16 18v2"/><path d="M8 18v2"/><path d="M12 18v2"/></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 |
};
|
| 162 |
|
|
|
|
| 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--) {
|
| 179 |
+
const j = Math.floor(Math.random() * (i + 1));
|
| 180 |
+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
| 181 |
+
}
|
| 182 |
+
return shuffled;
|
| 183 |
+
};
|
| 184 |
|
| 185 |
const APP_NAME = "Tifawin";
|
| 186 |
const APP_NAME_LETTERS = "TIMMUZIT";
|
|
|
|
| 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 = {
|
|
|
|
| 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' }],
|
|
|
|
| 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' },
|
|
|
|
| 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 |
// تطبيق الوضع الليلي فوراً على الجسم والحاوية
|
|
|
|
| 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') {
|
| 431 |
title = 'الإعدادات';
|
|
|
|
| 433 |
title = 'حول التطبيق';
|
| 434 |
} else if (appState.currentScreen === 'appDefinition') {
|
| 435 |
title = 'تعريف التطبيق';
|
| 436 |
+
} else if (appState.currentScreen === 'games') {
|
| 437 |
+
title = 'الألعاب التعليمية';
|
| 438 |
}
|
| 439 |
|
| 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')}
|
| 447 |
</button>
|
| 448 |
<h1 class="text-xl font-extrabold text-white">${title}</h1>
|
| 449 |
+
<button onclick="setState({currentScreen: 'appDefinition', selectedCategory: null, currentGameState: null})"
|
| 450 |
class="w-8 h-8 rounded-full bg-yellow-400 border-2 border-white flex items-center justify-center text-sm font-bold text-blue-900 shadow-md transition-shadow hover:shadow-lg"
|
| 451 |
aria-label="تعريف التطبيق">
|
| 452 |
${renderIcon('BookOpen', 'w-4 h-4 text-blue-900', 3)}
|
|
|
|
| 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: 'الرئيسية' },
|
|
|
|
| 476 |
${navItems.map(item => {
|
| 477 |
const isActive = item.id === activeScreen;
|
| 478 |
|
| 479 |
+
let clickAction = `setState({currentScreen: '${item.id}', selectedCategory: null, currentGameState: null})`;
|
| 480 |
if (item.id === 'whatsapp') {
|
| 481 |
clickAction = `window.open('${WHATSAPP_LINK}', '_blank')`;
|
| 482 |
}
|
|
|
|
| 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">
|
|
|
|
| 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 => `
|
|
|
|
| 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);
|
|
|
|
| 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">
|
|
|
|
| 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">
|
|
|
|
| 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' },
|
|
|
|
| 853 |
};
|
| 854 |
|
| 855 |
|
| 856 |
+
// --- 8. شاشات الألعاب الجديدة ---
|
|
|
|
|
|
|
| 857 |
|
| 858 |
+
const renderGamesHome = () => {
|
| 859 |
+
const content = document.getElementById('app-content');
|
| 860 |
+
|
| 861 |
+
const gameCards = [
|
| 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 |
+
|
| 880 |
+
content.innerHTML = `
|
| 881 |
+
<div class="p-4 pt-6 min-h-[calc(100vh-130px)] bg-gray-50 dark:bg-gray-900 transition-colors">
|
| 882 |
+
<h2 class="text-3xl font-black text-gray-800 dark:text-white mb-6 text-center">اختر لعبة</h2>
|
| 883 |
+
|
| 884 |
+
<div class="space-y-4 max-w-sm mx-auto">
|
| 885 |
+
${gameCards.map(game => `
|
| 886 |
+
<button onclick="${game.action}"
|
| 887 |
+
class="w-full p-5 flex items-center ${game.color} text-white rounded-2xl shadow-xl card-shadow group">
|
| 888 |
+
<div class="p-3 bg-white/30 rounded-full group-hover:bg-white/50 transition-colors">
|
| 889 |
+
${renderIcon(game.iconName, 'w-8 h-8 text-white')}
|
| 890 |
+
</div>
|
| 891 |
+
<div class="mr-4 text-right">
|
| 892 |
+
<h3 class="text-xl font-black">${game.title}</h3>
|
| 893 |
+
<p class="text-sm opacity-90 mt-1">${game.subtitle}</p>
|
| 894 |
+
</div>
|
| 895 |
+
</button>
|
| 896 |
+
`).join('')}
|
| 897 |
+
</div>
|
| 898 |
+
</div>
|
| 899 |
+
`;
|
| 900 |
+
};
|
| 901 |
+
|
| 902 |
+
// --- 8.1 لعبة الذاكرة (Memory Game) ---
|
| 903 |
+
|
| 904 |
+
window.initMemoryGame = () => {
|
| 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({
|
| 916 |
+
gameData: shuffleArray(cards).map((card, index) => ({...card, index: index, isFlipped: false, isMatched: false})),
|
| 917 |
+
memoryGame: { flippedCards: [], matchedCards: [], lockBoard: false },
|
| 918 |
+
currentGameState: 'memory',
|
| 919 |
+
currentLevel: levelData.level,
|
| 920 |
+
});
|
| 921 |
+
};
|
| 922 |
+
|
| 923 |
+
window.handleCardClick = (cardIndex) => {
|
| 924 |
+
if (appState.memoryGame.lockBoard ||
|
| 925 |
+
appState.gameData[cardIndex].isFlipped ||
|
| 926 |
+
appState.gameData[cardIndex].isMatched) return;
|
| 927 |
+
|
| 928 |
+
const newGameData = [...appState.gameData];
|
| 929 |
+
newGameData[cardIndex].isFlipped = true;
|
| 930 |
+
|
| 931 |
+
const newFlippedCards = [...appState.memoryGame.flippedCards, cardIndex];
|
| 932 |
+
|
| 933 |
+
if (newFlippedCards.length === 2) {
|
| 934 |
+
const [index1, index2] = newFlippedCards;
|
| 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;
|
| 942 |
+
const newMatchedCards = [...appState.memoryGame.matchedCards, card1.id];
|
| 943 |
+
|
| 944 |
+
setState({
|
| 945 |
+
gameData: newGameData,
|
| 946 |
+
memoryGame: { flippedCards: [], matchedCards: newMatchedCards, lockBoard: false }
|
| 947 |
+
});
|
| 948 |
+
|
| 949 |
+
// Check for win condition
|
| 950 |
+
if (newMatchedCards.length === memoryGameLevels[appState.currentLevel - 1].pairs) {
|
| 951 |
+
setTimeout(() => {
|
| 952 |
+
if (appState.currentLevel < memoryGameLevels.length) {
|
| 953 |
+
alert(`أحسنت! أكملت المستوى ${appState.currentLevel}. لننتقل إلى المستوى التالي.`);
|
| 954 |
+
setState({ currentLevel: appState.currentLevel + 1 });
|
| 955 |
+
initMemoryGame();
|
| 956 |
+
} else {
|
| 957 |
+
alert('تهانينا! لقد أنهيت لعبة الذاكرة بنجاح!');
|
| 958 |
+
setState({ currentGameState: null });
|
| 959 |
+
}
|
| 960 |
+
}, 800);
|
| 961 |
+
}
|
| 962 |
+
} else {
|
| 963 |
+
// No match
|
| 964 |
+
setState({ memoryGame: { ...appState.memoryGame, lockBoard: true } });
|
| 965 |
+
setTimeout(() => {
|
| 966 |
+
newGameData[index1].isFlipped = false;
|
| 967 |
+
newGameData[index2].isFlipped = false;
|
| 968 |
+
setState({
|
| 969 |
+
gameData: newGameData,
|
| 970 |
+
memoryGame: { ...appState.memoryGame, flippedCards: [], lockBoard: false }
|
| 971 |
+
});
|
| 972 |
+
}, 1000);
|
| 973 |
+
}
|
| 974 |
+
} else {
|
| 975 |
+
setState({ gameData: newGameData, memoryGame: { ...appState.memoryGame, flippedCards: newFlippedCards } });
|
| 976 |
+
}
|
| 977 |
+
};
|
| 978 |
+
|
| 979 |
+
|
| 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">
|
| 993 |
+
<h3 class="text-2xl font-black text-gray-800 dark:text-white mb-2 text-center">
|
| 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));">
|
| 1001 |
+
${appState.gameData.map((card, index) => `
|
| 1002 |
+
<div class="relative h-20 sm:h-24 perspective" onclick="handleCardClick(${index})">
|
| 1003 |
+
<div class="card-flip w-full h-full ${card.isFlipped || card.isMatched ? 'flipped' : ''}">
|
| 1004 |
+
|
| 1005 |
+
<div class="card-face bg-white dark:bg-gray-700 p-1 overflow-hidden border-2 border-blue-500/20 ${card.isMatched ? 'card-matched' : ''}">
|
| 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 |
+
|
| 1013 |
+
<div class="card-face card-back text-white">
|
| 1014 |
+
${renderIcon('Brain', 'w-8 h-8 text-white', 3)}
|
| 1015 |
+
</div>
|
| 1016 |
+
</div>
|
| 1017 |
</div>
|
| 1018 |
+
`).join('')}
|
| 1019 |
+
</div>
|
|
|
|
|
|
|
| 1020 |
|
| 1021 |
+
<div class="mt-8 text-center">
|
| 1022 |
+
<button onclick="initMemoryGame()"
|
| 1023 |
+
class="px-4 py-2 bg-yellow-500 text-white font-bold rounded-xl shadow-lg hover:bg-yellow-600">
|
| 1024 |
+
إعادة المستوى
|
| 1025 |
+
</button>
|
| 1026 |
+
</div>
|
| 1027 |
+
</div>
|
| 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>
|
| 1165 |
</div>
|
| 1166 |
</div>
|
| 1167 |
`;
|
| 1168 |
};
|
| 1169 |
+
|
| 1170 |
|
| 1171 |
// --- 9. دالة الرسم الرئيسية والتهيئة ---
|
| 1172 |
|
|
|
|
| 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';
|
|
|
|
| 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>
|
|
|
|
| 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 = () => {
|