anycoder-cc6b160d / index.html
moha77edhassan's picture
Upload folder using huggingface_hub
27cb93f verified
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>مهامي - منظم المهام اليومية</title>
<!-- استيراد خط Cairo من Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
/*
* =========================================
* 1. المتغيرات والتنسيق العام (CSS Variables & Reset)
* =========================================
*/
:root {
--primary-color: #3b82f6; /* أزرق فاتح حيوي */
--primary-hover: #2563eb; /* أزرق أغمق للتمرير */
--bg-color: #f0f7ff; /* خلفية زرقاء فاتحة جداً */
--card-bg: #ffffff; /* أبيض نقي */
--text-main: #1e293b; /* رمادي غامق للنصوص */
--text-light: #94a3b8; /* رمادي فاتح للنصوص الثانوية */
--danger-color: #ef4444; /* أحمر للحذف */
--success-color: #10b981; /* أخضر للإكمال */
--shadow-soft: 0 10px 25px -5px rgba(59, 130, 246, 0.15);
--shadow-hover: 0 20px 25px -5px rgba(59, 130, 246, 0.2);
--radius: 16px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Cairo', sans-serif;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
background-image: radial-gradient(#e0eafc 1px, transparent 1px);
background-size: 20px 20px;
}
/*
* =========================================
* 2. حاوية التطبيق (Main Container)
* =========================================
*/
.app-container {
background: var(--card-bg);
width: 100%;
max-width: 480px;
border-radius: var(--radius);
box-shadow: var(--shadow-soft);
padding: 2rem;
position: relative;
transition: var(--transition);
}
.app-container:hover {
box-shadow: var(--shadow-hover);
transform: translateY(-2px);
}
/*
* =========================================
* 3. الترويسة (Header)
* =========================================
*/
header {
text-align: center;
margin-bottom: 2rem;
}
h1 {
font-size: 1.8rem;
font-weight: 700;
color: var(--primary-color);
margin-bottom: 0.5rem;
}
.subtitle {
color: var(--text-light);
font-size: 0.9rem;
}
/* رابط "Built with anycoder" */
.anycoder-link {
display: inline-block;
margin-top: 10px;
font-size: 0.75rem;
color: var(--text-light);
text-decoration: none;
padding: 4px 12px;
background: #f1f5f9;
border-radius: 20px;
transition: var(--transition);
}
.anycoder-link:hover {
background: var(--primary-color);
color: white;
}
/*
* =========================================
* 4. قسم الإدخال (Input Section)
* =========================================
*/
.input-group {
display: flex;
gap: 10px;
margin-bottom: 1.5rem;
position: relative;
}
input[type="text"] {
flex-grow: 1;
padding: 14px 20px;
border: 2px solid #e2e8f0;
border-radius: 12px;
font-size: 1rem;
outline: none;
transition: var(--transition);
background: #f8fafc;
}
input[type="text"]:focus {
border-color: var(--primary-color);
background: #fff;
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1);
}
/* تأثير الخطأ */
input[type="text"].error {
border-color: var(--danger-color);
animation: shake 0.4s ease-in-out;
}
.add-btn {
background: var(--primary-color);
color: white;
border: none;
width: 54px;
border-radius: 12px;
cursor: pointer;
font-size: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
transition: var(--transition);
}
.add-btn:hover {
background: var(--primary-hover);
transform: scale(1.05);
}
/*
* =========================================
* 5. قائمة المهام (Task List)
* =========================================
*/
.tasks-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #f1f5f9;
}
.tasks-count {
font-size: 0.9rem;
font-weight: 600;
color: var(--text-main);
}
.clear-btn {
background: none;
border: none;
color: var(--text-light);
font-size: 0.8rem;
cursor: pointer;
transition: var(--transition);
padding: 5px 10px;
border-radius: 6px;
}
.clear-btn:hover {
color: var(--danger-color);
background: #fee2e2;
}
ul {
list-style: none;
max-height: 400px;
overflow-y: auto;
padding-right: 5px; /* مساحة لشريط التمرير */
}
/* تخصيص شريط التمرير */
ul::-webkit-scrollbar {
width: 6px;
}
ul::-webkit-scrollbar-track {
background: transparent;
}
ul::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 10px;
}
/* عنصر المهمة الواحدة */
.task-item {
background: #fff;
border: 1px solid #f1f5f9;
border-radius: 12px;
padding: 12px 16px;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
transition: var(--transition);
animation: slideIn 0.3s ease-out forwards;
}
.task-item:hover {
border-color: #bfdbfe;
transform: translateX(-3px);
}
.task-content {
display: flex;
align-items: center;
gap: 12px;
flex-grow: 1;
cursor: pointer;
}
/* تصميم الدائرة (Checkbox) */
.custom-checkbox {
width: 22px;
height: 22px;
border: 2px solid #cbd5e1;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: var(--transition);
flex-shrink: 0;
}
.task-item.completed .custom-checkbox {
background: var(--success-color);
border-color: var(--success-color);
}
.task-item.completed .custom-checkbox::after {
content: '✓';
color: white;
font-size: 14px;
font-weight: bold;
}
.task-text {
font-size: 1rem;
transition: var(--transition);
word-break: break-all;
}
.task-item.completed .task-text {
text-decoration: line-through;
color: var(--text-light);
}
/* زر الحذف */
.delete-btn {
background: none;
border: none;
color: #cbd5e1;
cursor: pointer;
padding: 5px;
border-radius: 8px;
transition: var(--transition);
opacity: 0; /* مخفي افتراضياً */
}
.task-item:hover .delete-btn {
opacity: 1; /* يظهر عند التمرير */
}
.delete-btn:hover {
color: var(--danger-color);
background: #fee2e2;
}
/*
* =========================================
* 6. الحالة الفارغة (Empty State)
* =========================================
*/
.empty-state {
text-align: center;
padding: 2rem 0;
color: var(--text-light);
display: none; /* مخفي افتراضياً */
}
.empty-state svg {
width: 80px;
height: 80px;
margin-bottom: 1rem;
opacity: 0.5;
fill: #e2e8f0;
}
/*
* =========================================
* 7. الحركات (Animations)
* =========================================
*/
@keyframes slideIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
/*
* =========================================
* 8. التجاوب (Responsive)
* =========================================
*/
@media (max-width: 480px) {
.app-container {
padding: 1.5rem;
height: 100vh;
max-height: 100vh;
border-radius: 0;
box-shadow: none;
display: flex;
flex-direction: column;
}
ul {
flex-grow: 1;
}
.delete-btn {
opacity: 1; /* إظهار زر الحذف دائماً في الموبايل */
}
}
</style>
</head>
<body>
<div class="app-container">
<header>
<h1>مهامي اليومية</h1>
<p class="subtitle">نظم وقتك، حقق أهدافك</p>
<!-- رابط أي كودر المطلوب -->
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
Built with anycoder
</a>
</header>
<section class="input-group">
<input type="text" id="taskInput" placeholder="أضف مهمة جديدة..." autocomplete="off">
<button class="add-btn" id="addBtn">+</button>
</section>
<div class="tasks-header">
<span class="tasks-count" id="tasksCount">0 مهام متبقية</span>
<button class="clear-btn" id="clearBtn">مسح الكل</button>
</div>
<ul id="taskList">
<!-- سيتم إضافة المهام هنا بواسطة JavaScript -->
</ul>
<div class="empty-state" id="emptyState">
<svg viewBox="0 0 24 24">
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>
</svg>
<p>لا توجد مهام حالياً. استمتع بوقتك!</p>
</div>
</div>
<script>
/*
* =========================================
* منطق التطبيق (JavaScript Logic)
* =========================================
*/
// 1. تحديد العناصر من DOM
const taskInput = document.getElementById('taskInput');
const addBtn = document.getElementById('addBtn');
const taskList = document.getElementById('taskList');
const tasksCount = document.getElementById('tasksCount');
const emptyState = document.getElementById('emptyState');
const clearBtn = document.getElementById('clearBtn');
// 2. تحميل المهام من LocalStorage عند بدء التشغيل
let tasks = JSON.parse(localStorage.getItem('myTasks')) || [];
// 3. دالة حفظ المهام
function saveTasks() {
localStorage.setItem('myTasks', JSON.stringify(tasks));
renderTasks();
}
// 4. دالة إضافة مهمة جديدة
function addTask() {
const text = taskInput.value.trim();
if (text === '') {
// تأثير الخطأ (هزة الحقل)
taskInput.classList.add('error');
setTimeout(() => taskInput.classList.remove('error'), 500);
return;
}
const newTask = {
id: Date.now(), // استخدام الوقت الحالي كمعرف فريد
text: text,
completed: false
};
tasks.unshift(newTask); // إضافة المهمة في بداية القائمة
taskInput.value = '';
saveTasks();
}
// 5. دالة حذف مهمة
function deleteTask(id) {
tasks = tasks.filter(task => task.id !== id);
saveTasks();
}
// 6. دالة تبديل حالة المهمة (مكتملة / غير مكتملة)
function toggleTask(id) {
tasks = tasks.map(task => {
if (task.id === id) {
return { ...task, completed: !task.completed };
}
return task;
});
saveTasks();
}
// 7. دالة مسح جميع المهام
function clearAllTasks() {
if(confirm('هل أنت متأكد من حذف جميع المهام؟')) {
tasks = [];
saveTasks();
}
}
// 8. دالة عرض المهام (Render)
function renderTasks() {
taskList.innerHTML = ''; // مسح القائمة الحالية
// تحديث العداد
const remainingTasks = tasks.filter(t => !t.completed).length;
tasksCount.textContent = `${remainingTasks} مهام متبقية`;
// التحقق من الحالة الفارغة
if (tasks.length === 0) {
emptyState.style.display = 'block';
taskList.style.display = 'none';
} else {
emptyState.style.display = 'none';
taskList.style.display = 'block';
}
// إنشاء عناصر HTML لكل مهمة
tasks.forEach(task => {
const li = document.createElement('li');
li.className = `task-item ${task.completed ? 'completed' : ''}`;
// استخدام Template String لإنشاء HTML
li.innerHTML = `
<div class="task-content" onclick="toggleTask(${task.id})">
<div class="custom-checkbox"></div>
<span class="task-text">${escapeHtml(task.text)}</span>
</div>
<button class="delete-btn" onclick="deleteTask(${task.id})" title="حذف">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
`;
taskList.appendChild(li);
});
}
// دالة مساعدة لمنع هجمات XSS (أمان بسيط)
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 9. إضافة مستمعي الأحداث (Event Listeners)
// زر الإضافة
addBtn.addEventListener('click', addTask);
// زر Enter في لوحة المفاتيح
taskInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
addTask();
}
});
// زر مسح الكل
clearBtn.addEventListener('click', clearAllTasks);
// التشغيل الأولي
renderTasks();
</script>
</body>
</html>