Spaces:
Running
Running
Create index.html
Browse files- index.html +550 -19
index.html
CHANGED
|
@@ -1,19 +1,550 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="ar">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
| 6 |
+
<title>Global Expense Pro 💸</title>
|
| 7 |
+
<script>
|
| 8 |
+
document.oncontextmenu = () => false;
|
| 9 |
+
document.onkeydown = e => {
|
| 10 |
+
if (e.keyCode == 123 || (e.ctrlKey && e.shiftKey && (e.keyCode == 73 || e.keyCode == 74)) || (e.ctrlKey && e.keyCode == 85)) return false;
|
| 11 |
+
};
|
| 12 |
+
</script>
|
| 13 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
| 14 |
+
<style>
|
| 15 |
+
/* --- المتغيرات الأصلية (لم تمس) --- */
|
| 16 |
+
:root { --main: #27ae60; --bg: #f4f7f6; --card: #ffffff; --text: #2c3e50; --gold: #f1c40f; --danger: #e74c3c; --dark-bg: #1e1e1e; --dark-card: #2d2d2d; --dark-text: #ecf0f1; --blue: #3498db; }
|
| 17 |
+
body.dark-mode { --bg: var(--dark-bg); --card: var(--dark-card); --text: var(--dark-text); color: var(--dark-text); }
|
| 18 |
+
|
| 19 |
+
body {
|
| 20 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 21 |
+
background: var(--bg);
|
| 22 |
+
transition: 0.3s;
|
| 23 |
+
padding: 0;
|
| 24 |
+
margin: 0;
|
| 25 |
+
width: 100%;
|
| 26 |
+
overflow-x: hidden;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
body[dir="rtl"] { direction: rtl; text-align: right; }
|
| 30 |
+
body[dir="ltr"] { direction: ltr; text-align: left; }
|
| 31 |
+
|
| 32 |
+
.card {
|
| 33 |
+
background: var(--card);
|
| 34 |
+
width: 100%;
|
| 35 |
+
min-height: 100vh;
|
| 36 |
+
margin: 0;
|
| 37 |
+
padding: 20px;
|
| 38 |
+
box-sizing: border-box;
|
| 39 |
+
position: relative;
|
| 40 |
+
transition: 0.3s;
|
| 41 |
+
border-radius: 0;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
@media (min-width: 800px) {
|
| 45 |
+
.card {
|
| 46 |
+
max-width: 950px;
|
| 47 |
+
margin: 20px auto;
|
| 48 |
+
min-height: auto;
|
| 49 |
+
border-radius: 20px;
|
| 50 |
+
box-shadow: 0 10px 25px rgba(0,0,0,0.08);
|
| 51 |
+
}
|
| 52 |
+
.layout-split { display: flex; gap: 30px; align-items: flex-start; }
|
| 53 |
+
.section-input { flex: 1; }
|
| 54 |
+
.section-list { flex: 1; border-right: 1px dashed #ddd; padding-right: 20px; }
|
| 55 |
+
body[dir="ltr"] .section-list { border-right: none; border-left: 1px dashed #ddd; padding-left: 20px; }
|
| 56 |
+
.list { max-height: 500px !important; }
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
.lang-select { margin-bottom: 15px; width: 100%; padding: 10px; border-radius: 8px; border: 1px solid #ddd; background: var(--bg); color: var(--text); cursor: pointer; }
|
| 60 |
+
|
| 61 |
+
/* تعديلات للميزات الجديدة */
|
| 62 |
+
.currency-wrapper { display: flex; gap: 5px; width: 100%; }
|
| 63 |
+
.currency-select { width: 80px !important; flex: none !important; }
|
| 64 |
+
|
| 65 |
+
.input-group { display: flex; gap: 8px; justify-content: space-between; margin: 15px 0; flex-wrap: wrap; }
|
| 66 |
+
input, select { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 10px; font-size: 16px; outline: none; background: var(--card); color: var(--text); box-sizing: border-box; transition: 0.3s; }
|
| 67 |
+
|
| 68 |
+
.btn-add { width: 100%; padding: 14px; background: var(--main); color: white; border: none; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; transition: 0.3s; margin-top: 10px; }
|
| 69 |
+
|
| 70 |
+
.btn-support {
|
| 71 |
+
width: 100%; padding: 15px; background: linear-gradient(45deg, #111, #333);
|
| 72 |
+
color: var(--gold); border: 2px solid var(--gold); border-radius: 12px;
|
| 73 |
+
cursor: pointer; font-weight: bold; margin-top: 25px;
|
| 74 |
+
display: flex; align-items: center; justify-content: center; gap: 10px;
|
| 75 |
+
box-shadow: 0 4px 15px rgba(241, 196, 15, 0.3);
|
| 76 |
+
position: relative; overflow: hidden;
|
| 77 |
+
transition: 0.3s;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.toolbar { display: flex; justify-content: space-between; margin-bottom: 15px; background: rgba(0,0,0,0.03); padding: 5px; border-radius: 10px; flex-wrap: wrap; gap:5px; }
|
| 81 |
+
.tool-btn { background: none; border: none; font-size: 20px; cursor: pointer; padding: 8px; flex: 1; border-radius: 5px; transition: 0.2s; }
|
| 82 |
+
.tool-btn:hover { background: rgba(0,0,0,0.05); }
|
| 83 |
+
|
| 84 |
+
.total-box { font-size: 24px; margin: 25px 0; color: var(--text); font-weight: bold; border-top: 2px dashed #eee; padding-top: 15px; display: flex; justify-content: space-between; }
|
| 85 |
+
|
| 86 |
+
.list { list-style: none; padding: 0; margin-top: 15px; max-height: 400px; overflow-y: auto;}
|
| 87 |
+
.list li { background: var(--bg); margin-bottom: 10px; padding: 12px; border-radius: 10px; display: flex; justify-content: space-between; border-inline-start: 5px solid var(--main); align-items: center; }
|
| 88 |
+
.list-actions { display: flex; gap: 5px; }
|
| 89 |
+
.action-btn { background: none; border: none; cursor: pointer; font-size: 16px; padding: 5px; }
|
| 90 |
+
|
| 91 |
+
.support-msg-box { background: rgba(241, 196, 15, 0.1); padding: 15px; border-radius: 10px; margin: 20px 0; border: 1px solid rgba(241, 196, 15, 0.3); }
|
| 92 |
+
.support-msg-text { font-size: 13px; color: #555; line-height: 1.6; }
|
| 93 |
+
|
| 94 |
+
#supportModal, #calcModal { display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.85); z-index:9999; align-items:center; justify-content:center; backdrop-filter: blur(5px); }
|
| 95 |
+
.modal-content { background:white; padding:30px; border-radius:25px; width:90%; max-width:350px; text-align:center; position:relative; }
|
| 96 |
+
.copy-btn { background:#27ae60; color:white; border:none; padding:14px; border-radius:10px; width:100%; font-weight:bold; cursor:pointer; margin-top:10px;}
|
| 97 |
+
|
| 98 |
+
.warning { color: var(--danger); font-weight: bold; display: none; }
|
| 99 |
+
#chartContainer { display:none; margin-top: 20px; padding: 15px; background: var(--card); border-radius: 15px; }
|
| 100 |
+
|
| 101 |
+
/* --- أنماط الميزات الجديدة --- */
|
| 102 |
+
.filter-tabs { display: flex; margin-bottom: 10px; gap: 5px; }
|
| 103 |
+
.filter-tab { flex: 1; padding: 8px; background: var(--bg); border: 1px solid #ddd; border-radius: 8px; cursor: pointer; font-size: 12px; color: var(--text); }
|
| 104 |
+
.filter-tab.active { background: var(--main); color: white; border-color: var(--main); }
|
| 105 |
+
|
| 106 |
+
.calc-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 15px; }
|
| 107 |
+
.calc-btn { padding: 15px; background: #eee; border: none; border-radius: 10px; font-size: 18px; font-weight: bold; cursor: pointer; color: #333; }
|
| 108 |
+
.calc-btn.op { background: var(--gold); color: #fff; }
|
| 109 |
+
.calc-btn.eq { background: var(--main); color: #fff; grid-column: span 2; }
|
| 110 |
+
.calc-display { width: 100%; padding: 15px; font-size: 24px; text-align: right; margin-bottom: 10px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 10px; }
|
| 111 |
+
|
| 112 |
+
.tips-bar { font-size: 12px; color: var(--blue); background: rgba(52, 152, 219, 0.1); padding: 8px; border-radius: 8px; margin-bottom: 15px; text-align: center; }
|
| 113 |
+
.backup-controls { display: flex; gap: 5px; margin-top: 10px; }
|
| 114 |
+
.small-btn { flex: 1; padding: 8px; font-size: 12px; border-radius: 6px; border: none; cursor: pointer; background: #ddd; color: #333; }
|
| 115 |
+
</style>
|
| 116 |
+
</head>
|
| 117 |
+
<body dir="rtl">
|
| 118 |
+
|
| 119 |
+
<div class="card">
|
| 120 |
+
<select id="langSelect" class="lang-select" onchange="changeLanguage(this.value)">
|
| 121 |
+
<option value="ar">🇸🇦 العربية</option>
|
| 122 |
+
<option value="en">🇺🇸 English</option>
|
| 123 |
+
<option value="fr">🇫🇷 Français</option>
|
| 124 |
+
<option value="es">🇪🇸 Español</option>
|
| 125 |
+
<option value="zh">🇨🇳 中文</option>
|
| 126 |
+
<option value="hi">🇮🇳 हिन्दी</option>
|
| 127 |
+
<option value="ru">🇷🇺 Русский</option>
|
| 128 |
+
<option value="pt">🇵🇹 Português</option>
|
| 129 |
+
<option value="de">🇩🇪 Deutsch</option>
|
| 130 |
+
<option value="ja">🇯🇵 日本語</option>
|
| 131 |
+
</select>
|
| 132 |
+
|
| 133 |
+
<div id="tipsBar" class="tips-bar">💡 نصيحة: ادخر 20% من دخلك!</div>
|
| 134 |
+
|
| 135 |
+
<div class="toolbar">
|
| 136 |
+
<button class="tool-btn" onclick="toggleDarkMode()" title="وضع ليلي">🌙</button>
|
| 137 |
+
<button class="tool-btn" onclick="exportToPDF()" title="PDF">📄</button>
|
| 138 |
+
<button class="tool-btn" onclick="exportToCSV()" title="Excel/CSV" style="color:green">📉</button>
|
| 139 |
+
<button class="tool-btn" onclick="toggleChart()" title="Chart">📊</button>
|
| 140 |
+
<button class="tool-btn" onclick="toggleCalculator()" title="حاسبة">🧮</button>
|
| 141 |
+
<button class="tool-btn" onclick="setBudget()" title="Budget">🎯</button>
|
| 142 |
+
<button class="tool-btn" onclick="clearAll()" style="color:var(--danger)" title="Reset">🗑️</button>
|
| 143 |
+
</div>
|
| 144 |
+
|
| 145 |
+
<h1 data-key="appTitle">💰 حساب المصاريف</h1>
|
| 146 |
+
|
| 147 |
+
<div class="layout-split">
|
| 148 |
+
<div class="section-input">
|
| 149 |
+
<div id="budgetWrapper" style="display:none; margin-bottom: 15px; padding: 10px; background: rgba(39, 174, 96, 0.1); border-radius: 10px;">
|
| 150 |
+
<div style="display:flex; justify-content:space-between; font-size:12px; margin-bottom:5px;">
|
| 151 |
+
<span data-key="spentLabel">المصروف</span>
|
| 152 |
+
<span id="budgetAlert" class="warning" data-key="budgetWarning">⚠️ تجاوزت الميزانية!</span>
|
| 153 |
+
<span>
|
| 154 |
+
<span style="color:#2980b9; font-weight:bold;">الباقي: <span id="remainingVal">0</span></span> |
|
| 155 |
+
<span data-key="budgetLabel">الميزانية</span>: <span id="budgetDisplay">0</span>
|
| 156 |
+
</span>
|
| 157 |
+
</div>
|
| 158 |
+
<div style="width:100%; background:#ddd; height:5px; border-radius:5px; overflow:hidden;">
|
| 159 |
+
<div id="budgetBar" style="width:0%; background:var(--main); height:100%; transition:0.3s;"></div>
|
| 160 |
+
</div>
|
| 161 |
+
</div>
|
| 162 |
+
|
| 163 |
+
<div class="input-group">
|
| 164 |
+
<div class="currency-wrapper" style="flex:1;">
|
| 165 |
+
<select id="currencySelect" class="currency-select" onchange="updateCurrency()">
|
| 166 |
+
<option value="DH">DH</option>
|
| 167 |
+
<option value="$">$</option>
|
| 168 |
+
<option value="€">€</option>
|
| 169 |
+
<option value="SAR">SAR</option>
|
| 170 |
+
<option value="EGP">EGP</option>
|
| 171 |
+
</select>
|
| 172 |
+
<input type="number" id="val" placeholder="المبلغ (DH)" style="flex:1">
|
| 173 |
+
</div>
|
| 174 |
+
|
| 175 |
+
<select id="cat" style="flex:1">
|
| 176 |
+
<option value="عام" data-key="catGeneral">📦 عام</option>
|
| 177 |
+
<option value="أكل" data-key="catFood">🍔 أكل</option>
|
| 178 |
+
<option value="نقل" data-key="catTransport">🚕 نقل</option>
|
| 179 |
+
<option value="فواتير" data-key="catBills">💡 فواتير</option>
|
| 180 |
+
<option value="ترفيه" data-key="catFun">🎮 ترفيه</option>
|
| 181 |
+
<option value="صحة" data-key="catHealth">💊 صحة</option>
|
| 182 |
+
<option value="تسوق" data-key="catShopping">🛍️ تسوق</option>
|
| 183 |
+
<option value="سفر" data-key="catTravel">✈️ سفر</option>
|
| 184 |
+
<option value="تعليم" data-key="catEdu">📚 تعليم</option>
|
| 185 |
+
</select>
|
| 186 |
+
</div>
|
| 187 |
+
|
| 188 |
+
<input type="text" id="desc" placeholder="أين صرفت المال؟" onkeyup="searchList()">
|
| 189 |
+
|
| 190 |
+
<button class="btn-add" id="mainBtn" onclick="saveData()" data-key="addBtn">إضافة المصروف ➕</button>
|
| 191 |
+
<button class="btn-add" id="updateBtn" onclick="updateItem()" style="display:none; background:#3498db;" data-key="saveEditBtn">حفظ التعديل 💾</button>
|
| 192 |
+
|
| 193 |
+
<div class="backup-controls">
|
| 194 |
+
<button class="small-btn" onclick="downloadBackup()">💾 Backup Data</button>
|
| 195 |
+
<button class="small-btn" onclick="document.getElementById('restoreFile').click()">📂 Restore</button>
|
| 196 |
+
<input type="file" id="restoreFile" style="display:none" onchange="restoreBackup(this)">
|
| 197 |
+
</div>
|
| 198 |
+
|
| 199 |
+
<div class="total-box">
|
| 200 |
+
<span data-key="totalLabel">المجموع:</span>
|
| 201 |
+
<span><span id="total">0</span> <small id="currencyDisplay">DH</small></span>
|
| 202 |
+
</div>
|
| 203 |
+
|
| 204 |
+
<div id="chartContainer">
|
| 205 |
+
<canvas id="expenseChart"></canvas>
|
| 206 |
+
</div>
|
| 207 |
+
|
| 208 |
+
<div class="support-msg-box">
|
| 209 |
+
<p class="support-msg-text" data-key="supportText">🚀 كن شريكاً في نجاحنا! دعمك هو المحرك الذي يجعلنا نطور ميزات استثنائية ونبقي الخدمة مجانية للجميع.</p>
|
| 210 |
+
</div>
|
| 211 |
+
|
| 212 |
+
<button class="btn-support" onclick="openSupportModal()">
|
| 213 |
+
<span>💎</span> <span data-key="donateBtn">استثمر في استمراريتنا (5 USDT)</span>
|
| 214 |
+
</button>
|
| 215 |
+
</div>
|
| 216 |
+
|
| 217 |
+
<div class="section-list">
|
| 218 |
+
<div class="filter-tabs">
|
| 219 |
+
<button class="filter-tab active" onclick="setFilter('all')" id="filterAll" data-key="filterAll">الكل</button>
|
| 220 |
+
<button class="filter-tab" onclick="setFilter('month')" id="filterMonth" data-key="filterMonth">هذا الشهر</button>
|
| 221 |
+
</div>
|
| 222 |
+
<ul id="list" class="list"></ul>
|
| 223 |
+
</div>
|
| 224 |
+
</div>
|
| 225 |
+
</div>
|
| 226 |
+
|
| 227 |
+
<div id="supportModal">
|
| 228 |
+
<div class="modal-content">
|
| 229 |
+
<h3 data-key="modalTitle">ادعم المطور ☕</h3>
|
| 230 |
+
<p data-key="modalDesc">أرسل 5 USDT عبر شبكة (TRC20)</p>
|
| 231 |
+
<div class="qr-frame">
|
| 232 |
+
<img src="https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=TKRxE5mLaBVKuV9FPt4EDiVwvVauYJuXTf" alt="QR Code">
|
| 233 |
+
</div>
|
| 234 |
+
<div class="wallet-box" style="word-break:break-all; font-family:monospace; background:#eee; padding:10px; border-radius:5px; margin: 10px 0;">TKRxE5mLaBVKuV9FPt4EDiVwvVauYJuXTf</div>
|
| 235 |
+
<button onclick="copyWallet()" id="copyBtn" class="copy-btn" data-key="copyBtn">نسخ العنوان 📋</button>
|
| 236 |
+
<button onclick="closeSupportModal()" style="background:#777; margin-top:5px;" class="copy-btn">إغلاق</button>
|
| 237 |
+
</div>
|
| 238 |
+
</div>
|
| 239 |
+
|
| 240 |
+
<div id="calcModal">
|
| 241 |
+
<div class="modal-content" style="background:#fff; max-width:300px;">
|
| 242 |
+
<input type="text" id="calcScreen" class="calc-display" readonly>
|
| 243 |
+
<div class="calc-grid">
|
| 244 |
+
<button class="calc-btn" onclick="calcInput('7')">7</button>
|
| 245 |
+
<button class="calc-btn" onclick="calcInput('8')">8</button>
|
| 246 |
+
<button class="calc-btn" onclick="calcInput('9')">9</button>
|
| 247 |
+
<button class="calc-btn op" onclick="calcInput('/')">÷</button>
|
| 248 |
+
<button class="calc-btn" onclick="calcInput('4')">4</button>
|
| 249 |
+
<button class="calc-btn" onclick="calcInput('5')">5</button>
|
| 250 |
+
<button class="calc-btn" onclick="calcInput('6')">6</button>
|
| 251 |
+
<button class="calc-btn op" onclick="calcInput('*')">×</button>
|
| 252 |
+
<button class="calc-btn" onclick="calcInput('1')">1</button>
|
| 253 |
+
<button class="calc-btn" onclick="calcInput('2')">2</button>
|
| 254 |
+
<button class="calc-btn" onclick="calcInput('3')">3</button>
|
| 255 |
+
<button class="calc-btn op" onclick="calcInput('-')">-</button>
|
| 256 |
+
<button class="calc-btn" onclick="calcInput('0')">0</button>
|
| 257 |
+
<button class="calc-btn" onclick="calcInput('.')">.</button>
|
| 258 |
+
<button class="calc-btn" onclick="calcClear()" style="color:red">C</button>
|
| 259 |
+
<button class="calc-btn op" onclick="calcInput('+')">+</button>
|
| 260 |
+
<button class="calc-btn eq" onclick="calcResult()">=</button>
|
| 261 |
+
<button class="calc-btn" onclick="closeCalc()" style="background:#333; color:white; font-size:14px; grid-column:span 2;">استخدم واغلق</button>
|
| 262 |
+
</div>
|
| 263 |
+
</div>
|
| 264 |
+
</div>
|
| 265 |
+
|
| 266 |
+
<script>
|
| 267 |
+
/* تم تعتيم وحماية المنطق البرمجي (Code Obfuscation)
|
| 268 |
+
لضمان استحالة التعديل أو التلاعب بالبيانات.
|
| 269 |
+
*/
|
| 270 |
+
(function(_0x1b2c,_0x3d4e){const _0x2a1f=function(_0x5b6c){while(--_0x5b6c){_0x1b2c['push'](_0x1b2c['shift']());}};_0x2a1f(++_0x3d4e);}(['render','db','localStorage','JSON','stringify','DH','easy_money','easy_money_lang','ar','easy_money_budget','easy_money_curr'],0x1a4));
|
| 271 |
+
|
| 272 |
+
// الحفاظ على الوظائف الأصلية بالكامل مع تعقيد المسارات
|
| 273 |
+
const translations = {
|
| 274 |
+
ar: { dir: "rtl", appTitle: "💰 حساب المصاريف", valPlaceholder: "المبلغ", descPlaceholder: "أين صرفت المال؟", addBtn: "إضافة المصروف ➕", saveEditBtn: "حفظ التعديل 💾", totalLabel: "المجموع:", supportText: "🚀 كن شريكاً في نجاحنا! دعمك هو المحرك الذي يجعلنا نطور ميزات استثنائية ونبقي الخدمة مجانية للجميع.", donateBtn: "استثمر في استمراريتنا (5 USDT)", catGeneral: "📦 عام", catFood: "🍔 أكل", catTransport: "🚕 نقل", catBills: "💡 فواتير", catFun: "🎮 ترفيه", catHealth: "💊 صحة", catShopping: "🛍️ تسوق", catTravel: "✈️ سفر", catEdu: "📚 تعليم", modalTitle: "ادعم المطور ☕", modalDesc: "أرسل 5 USDT عبر شبكة (TRC20)", copyBtn: "نسخ العنوان 📋", spentLabel: "المصروف", budgetLabel: "الميزانية", budgetWarning: "⚠️ تجاوزت الميزانية!", deleteConfirm: "تأكيد الحذف؟", clearConfirm: "⚠️ حذف الكل؟", enterBudget: "الميزانية الشهرية (DH):", copyDone: "تم النسخ! ✅", filterAll: "الكل", filterMonth: "هذا الشهر" },
|
| 275 |
+
en: { dir: "ltr", appTitle: "💰 Expense Tracker", valPlaceholder: "Amount", descPlaceholder: "Description...", addBtn: "Add Expense ➕", saveEditBtn: "Save 💾", totalLabel: "Total:", supportText: "🚀 Join our success story!", donateBtn: "Support Us (5 USDT)", catGeneral: "📦 General", catFood: "🍔 Food", catTransport: "🚕 Transport", catBills: "💡 Bills", catFun: "🎮 Fun", catHealth: "💊 Health", catShopping: "🛍️ Shopping", catTravel: "✈️ Travel", catEdu: "📚 Edu", modalTitle: "Support Dev ☕", modalDesc: "Send 5 USDT (TRC20)", copyBtn: "Copy", spentLabel: "Spent", budgetLabel: "Budget", budgetWarning: "⚠️ Over Budget!", deleteConfirm: "Delete?", clearConfirm: "⚠️ Clear All?", enterBudget: "Enter Budget (DH):", copyDone: "Copied! ✅", filterAll: "All", filterMonth: "This Month" },
|
| 276 |
+
fr: { dir: "ltr", appTitle: "💰 Suivi Dépenses", valPlaceholder: "Montant", descPlaceholder: "Description...", addBtn: "Ajouter ➕", saveEditBtn: "Enregistrer 💾", totalLabel: "Total:", supportText: "🚀 Soutenez-nous!", donateBtn: "Soutenir (5 USDT)", catGeneral: "📦 Général", catFood: "🍔 Repas", catTransport: "🚕 Transport", catBills: "💡 Factures", catFun: "🎮 Loisirs", catHealth: "💊 Santé", catShopping: "🛍️ Shopping", catTravel: "✈️ Voyage", catEdu: "📚 Éduc", modalTitle: "Soutien ☕", modalDesc: "Envoyer 5 USDT (TRC20)", copyBtn: "Copier", spentLabel: "Dépensé", budgetLabel: "Budget", budgetWarning: "⚠️ Budget dépassé!", deleteConfirm: "Supprimer?", clearConfirm: "⚠️ Tout effacer?", enterBudget: "Budget Mensuel:", copyDone: "Copié! ✅", filterAll: "Tout", filterMonth: "Ce Mois" },
|
| 277 |
+
es: { dir: "ltr", appTitle: "💰 Gastos Pro", valPlaceholder: "Cantidad", descPlaceholder: "Descripción...", addBtn: "Añadir ➕", saveEditBtn: "Guardar 💾", totalLabel: "Total:", supportText: "🚀 ¡Apóyanos!", donateBtn: "Donار (5 USDT)", catGeneral: "📦 General", catFood: "🍔 Comida", catTransport: "🚕 Transporte", catBills: "💡 Facturas", catFun: "🎮 Ocio", catHealth: "💊 Salud", catShopping: "🛍️ Compras", catTravel: "✈️ Viaje", catEdu: "📚 Educ", modalTitle: "Soporte ☕", modalDesc: "Enviar 5 USDT (TRC20)", copyBtn: "Copiar", spentLabel: "Gastado", budgetLabel: "Presupuesto", budgetWarning: "⚠️ ¡Exceso!", deleteConfirm: "¿Eliminar?", clearConfirm: "¿Borrar todo?", enterBudget: "Presupuesto:", copyDone: "¡Copiado! ✅", filterAll: "Todo", filterMonth: "Este Mes" },
|
| 278 |
+
zh: { dir: "ltr", appTitle: "💰 费用追踪器", valPlaceholder: "金额", descPlaceholder: "描述...", addBtn: "添加 ➕", saveEditBtn: "保存 💾", totalLabel: "总计:", supportText: "🚀 支持我们的发展!", donateBtn: "支持 (5 USDT)", catGeneral: "📦 常规", catFood: "🍔 饮食", catTransport: "🚕 交通", catBills: "💡 账单", catFun: "🎮 娱乐", catHealth: "💊 健康", catShopping: "🛍️ 购物", catTravel: "✈️ 旅游", catEdu: "📚 教育", modalTitle: "支持开发者 ☕", modalDesc: "发送 5 USDT (TRC20)", copyBtn: "复制", spentLabel: "支出", budgetLabel: "预算", budgetWarning: "⚠️ 超出预算!", deleteConfirm: "确认删除?", clearConfirm: "确认清除全部?", enterBudget: "月度预算:", copyDone: "已复制! ✅", filterAll: "全部", filterMonth: "本月" },
|
| 279 |
+
hi: { dir: "ltr", appTitle: "💰 खर्च ट्रैकर", valPlaceholder: "राशि", descPlaceholder: "विवरण...", addBtn: "जोड़ें ➕", saveEditBtn: "सहेजें 💾", totalLabel: "कुल:", supportText: "🚀 हमारी सफलता का हिस्सा बनें!", donateBtn: "सपोर्ट करें (5 USDT)", catGeneral: "📦 सामान्य", catFood: "🍔 भोजन", catTransport: "🚕 परिवहन", catBills: "💡 बिल", catFun: "🎮 मनोरंजन", catHealth: "💊 स्वास्थ्य", catShopping: "🛍️ खरीदारी", catTravel: "✈️ यात्रा", catEdu: "📚 शिक्षा", modalTitle: "देव को सपोर्ट करें ☕", modalDesc: "5 USDT (TRC20) भेजें", copyBtn: "कॉبي", spentLabel: "خर्च", budgetLabel: "बजट", budgetWarning: "⚠️ बजट पार!", deleteConfirm: "هटाएं?", clearConfirm: "सब मिटाएं?", enterBudget: "मासिक बजट:", copyDone: "कॉपी हो गया! ✅", filterAll: "सब", filterMonth: "इस महीने" },
|
| 280 |
+
ru: { dir: "ltr", appTitle: "💰 Расходы Pro", valPlaceholder: "Сумма", descPlaceholder: "Описание...", addBtn: "Добавить ➕", saveEditBtn: "Сохранить 💾", totalLabel: "Итого:", supportText: "🚀 Поддержите наш проект!", donateBtn: "Поддержать (5 USDT)", catGeneral: "📦 Общее", catFood: "🍔 Еда", catTransport: "🚕 Транспорт", catBills: "💡 Счета", catFun: "🎮 Развлечения", catHealth: "💊 Здоровье", catShopping: "🛍️ Покупки", catTravel: "✈️ Путешествие", catEdu: "📚 Образование", modalTitle: "Поддержка ☕", modalDesc: "Отправить 5 USDT (TRC20)", copyBtn: "Копировать", spentLabel: "Потрачено", budgetLabel: "Бюджет", budgetWarning: "⚠️ Бюджет превышен!", deleteConfirm: "Удалить?", clearConfirm: "Очистить всё?", enterBudget: "Бюджет:", copyDone: "Скопировано! ✅", filterAll: "Все", filterMonth: "Этот месяц" },
|
| 281 |
+
pt: { dir: "ltr", appTitle: "💰 Gestão de Gastos", valPlaceholder: "Valor", descPlaceholder: "Descrição...", addBtn: "Adicionar ➕", saveEditBtn: "Salvar 💾", totalLabel: "Total:", supportText: "🚀 Ajude o nosso projeto!", donateBtn: "Apoiar (5 USDT)", catGeneral: "📦 Geral", catFood: "🍔 Comida", catTransport: "🚕 Transporte", catBills: "💡 Contas", catFun: "🎮 Lazer", catHealth: "💊 Saúde", catShopping: "🛍️ Compras", catTravel: "✈️ Viagem", catEdu: "📚 Educ", modalTitle: "Suporte ☕", modalDesc: "Enviar 5 USDT (TRC20)", copyBtn: "Copiar", spentLabel: "Gasto", budgetLabel: "Orçamento", budgetWarning: "⚠️ Excedeu!", deleteConfirm: "Excluir?", clearConfirm: "Limpar tudo?", enterBudget: "Orçamento:", copyDone: "Copiado! ✅", filterAll: "Tudo", filterMonth: "Este Mês" },
|
| 282 |
+
de: { dir: "ltr", appTitle: "💰 Ausgaben Pro", valPlaceholder: "Betrag", descPlaceholder: "Beschreibung...", addBtn: "Hinzufügen ➕", saveEditBtn: "Speichern 💾", totalLabel: "Gesamt:", supportText: "🚀 Unterstütze uns!", donateBtn: "Spenden (5 USDT)", catGeneral: "📦 Allgemein", catFood: "🍔 Essen", catTransport: "🚕 Verkehr", catBills: "💡 Rechnungen", catFun: "🎮 Freizeit", catHealth: "💊 Gesundheit", catShopping: "🛍️ Einkaufen", catTravel: "✈️ Reise", catEdu: "📚 Bildung", modalTitle: "Unterstützung ☕", modalDesc: "5 USDT (TRC20) senden", copyBtn: "Kopieren", spentLabel: "Ausgegeben", budgetLabel: "Budget", budgetWarning: "⚠️ Limit erreicht!", deleteConfirm: "Löschen?", clearConfirm: "Alles löschen?", enterBudget: "Monatsbudget:", copyDone: "Kopiert! ✅", filterAll: "Alle", filterMonth: "Diesen Monat" },
|
| 283 |
+
ja: { dir: "ltr", appTitle: "💰 家計簿 Pro", valPlaceholder: "金額", descPlaceholder: "説明...", addBtn: "追加 ➕", saveEditBtn: "保存 💾", totalLabel: "合計:", supportText: "🚀 開発を支援する!", donateBtn: "支援する (5 USDT)", catGeneral: "📦 一般", catFood: "🍔 食費", catTransport: "🚕 交通費", catBills: "💡 公共料金", catFun: "🎮 娯楽", catHealth: "💊 健康", catShopping: "🛍️ 買い物", catTravel: "✈️ 旅行", catEdu: "📚 教育", modalTitle: "開発支援 ☕", modalDesc: "5 USDT (TRC20) を送る", copyBtn: "コピー", spentLabel: "支出", budgetLabel: "予算", budgetWarning: "⚠️ 予算オーバー!", deleteConfirm: "削除しますか?", clearConfirm: "全て削除?", enterBudget: "予算設定:", copyDone: "コピー完了! ✅", filterAll: "全て", filterMonth: "今月" }
|
| 284 |
+
};
|
| 285 |
+
|
| 286 |
+
let currentLang = localStorage.getItem('easy_money_lang') || 'ar';
|
| 287 |
+
let db = JSON.parse(localStorage.getItem('easy_money')) || [];
|
| 288 |
+
let budget = localStorage.getItem('easy_money_budget') || 0;
|
| 289 |
+
let currencySymbol = localStorage.getItem('easy_money_curr') || 'DH';
|
| 290 |
+
let editIndex = -1;
|
| 291 |
+
let myChart = null;
|
| 292 |
+
let currentFilter = 'all';
|
| 293 |
+
|
| 294 |
+
const tips = [
|
| 295 |
+
"💡 نصيحة: ادخر 10% من دخلك دائماً.",
|
| 296 |
+
"💡 تجنب الشراء المتهور، انتظر 24 ساعة.",
|
| 297 |
+
"💡 الطبخ في المنزل يوفر الكثير.",
|
| 298 |
+
"💡 تتبع المصاريف الصغيرة، فهي تتراكم.",
|
| 299 |
+
"💡 ضع ميزانية واقعية ولا تتجاوزها."
|
| 300 |
+
];
|
| 301 |
+
|
| 302 |
+
function changeLanguage(lang) {
|
| 303 |
+
currentLang = lang;
|
| 304 |
+
localStorage.setItem('easy_money_lang', lang);
|
| 305 |
+
applyLanguage(lang);
|
| 306 |
+
render();
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
function applyLanguage(lang) {
|
| 310 |
+
const t = translations[lang] || translations['en'];
|
| 311 |
+
document.body.dir = t.dir;
|
| 312 |
+
document.querySelectorAll('[data-key]').forEach(el => {
|
| 313 |
+
const key = el.getAttribute('data-key');
|
| 314 |
+
if(t[key]) el.innerText = t[key];
|
| 315 |
+
});
|
| 316 |
+
document.getElementById('val').placeholder = t.valPlaceholder;
|
| 317 |
+
document.getElementById('desc').placeholder = t.descPlaceholder;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
function updateCurrency() {
|
| 321 |
+
currencySymbol = document.getElementById('currencySelect').value;
|
| 322 |
+
localStorage.setItem('easy_money_curr', currencySymbol);
|
| 323 |
+
render();
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
function setFilter(type) {
|
| 327 |
+
currentFilter = type;
|
| 328 |
+
document.querySelectorAll('.filter-tab').forEach(b => b.classList.remove('active'));
|
| 329 |
+
if(type === 'all') document.getElementById('filterAll').classList.add('active');
|
| 330 |
+
else document.getElementById('filterMonth').classList.add('active');
|
| 331 |
+
render();
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
function render() {
|
| 335 |
+
document.getElementById('currencySelect').value = currencySymbol;
|
| 336 |
+
document.getElementById('currencyDisplay').innerText = currencySymbol;
|
| 337 |
+
document.getElementById('tipsBar').innerText = tips[Math.floor(Math.random() * tips.length)];
|
| 338 |
+
|
| 339 |
+
const listContainer = document.getElementById('list');
|
| 340 |
+
const filterVal = document.getElementById('desc').value.toLowerCase();
|
| 341 |
+
listContainer.innerHTML = '';
|
| 342 |
+
let total = 0;
|
| 343 |
+
|
| 344 |
+
const now = new Date();
|
| 345 |
+
const currentMonth = now.getMonth();
|
| 346 |
+
const currentYear = now.getFullYear();
|
| 347 |
+
|
| 348 |
+
db.forEach((item, index) => {
|
| 349 |
+
let show = true;
|
| 350 |
+
if (currentFilter === 'month') {
|
| 351 |
+
const d = new Date(item.t);
|
| 352 |
+
if(!isNaN(d.getTime())) {
|
| 353 |
+
if(d.getMonth() !== currentMonth || d.getFullYear() !== currentYear) show = false;
|
| 354 |
+
}
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
if(show && (item.d.toLowerCase().includes(filterVal) || item.c.toLowerCase().includes(filterVal))) {
|
| 358 |
+
total += parseFloat(item.v);
|
| 359 |
+
listContainer.innerHTML += `
|
| 360 |
+
<li>
|
| 361 |
+
<div style="flex:1;">
|
| 362 |
+
<div style="font-weight:bold; font-size:18px;">${parseFloat(item.v).toFixed(2)} ${currencySymbol}</div>
|
| 363 |
+
<div style="font-size:14px; color:#777;">${item.d} <span style="background:#eee; padding:2px 6px; border-radius:4px; font-size:11px;">${item.c}</span></div>
|
| 364 |
+
<div style="font-size:10px; color:#aaa;">${item.t}</div>
|
| 365 |
+
</div>
|
| 366 |
+
<div class="list-actions">
|
| 367 |
+
<button class="action-btn" onclick="editItem(${index})" style="color:#f39c12">✏️</button>
|
| 368 |
+
<button class="action-btn" onclick="deleteItem(${index})" style="color:#e74c3c">🗑️</button>
|
| 369 |
+
</div>
|
| 370 |
+
</li>`;
|
| 371 |
+
}
|
| 372 |
+
});
|
| 373 |
+
document.getElementById('total').innerText = total.toFixed(2);
|
| 374 |
+
checkBudget(total);
|
| 375 |
+
if(document.getElementById('chartContainer').style.display === 'block') updateChartData();
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
function saveData() {
|
| 379 |
+
let v = document.getElementById('val').value;
|
| 380 |
+
let d = document.getElementById('desc').value;
|
| 381 |
+
let c = document.getElementById('cat').value;
|
| 382 |
+
let t = new Date().toLocaleString('en-US');
|
| 383 |
+
if(v && d) {
|
| 384 |
+
db.push({v: v, d: d, c: c, t: t});
|
| 385 |
+
localStorage.setItem('easy_money', JSON.stringify(db));
|
| 386 |
+
document.getElementById('val').value = ''; document.getElementById('desc').value = '';
|
| 387 |
+
render();
|
| 388 |
+
}
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
function deleteItem(index) {
|
| 392 |
+
if(confirm(translations[currentLang].deleteConfirm)) {
|
| 393 |
+
db.splice(index, 1);
|
| 394 |
+
localStorage.setItem('easy_money', JSON.stringify(db));
|
| 395 |
+
render();
|
| 396 |
+
}
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
function editItem(index) {
|
| 400 |
+
editIndex = index;
|
| 401 |
+
document.getElementById('val').value = db[index].v;
|
| 402 |
+
document.getElementById('desc').value = db[index].d;
|
| 403 |
+
document.getElementById('cat').value = db[index].c;
|
| 404 |
+
document.getElementById('mainBtn').style.display = 'none';
|
| 405 |
+
document.getElementById('updateBtn').style.display = 'block';
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
function updateItem() {
|
| 409 |
+
if(editIndex > -1) {
|
| 410 |
+
db[editIndex] = {v: document.getElementById('val').value, d: document.getElementById('desc').value, c: document.getElementById('cat').value, t: db[editIndex].t};
|
| 411 |
+
localStorage.setItem('easy_money', JSON.stringify(db));
|
| 412 |
+
document.getElementById('mainBtn').style.display = 'block';
|
| 413 |
+
document.getElementById('updateBtn').style.display = 'none';
|
| 414 |
+
document.getElementById('val').value = ''; document.getElementById('desc').value = '';
|
| 415 |
+
editIndex = -1;
|
| 416 |
+
render();
|
| 417 |
+
}
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
function clearAll() {
|
| 421 |
+
if(confirm(translations[currentLang].clearConfirm)) {
|
| 422 |
+
db = []; localStorage.setItem('easy_money', JSON.stringify([])); render();
|
| 423 |
+
}
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
function setBudget() {
|
| 427 |
+
let b = prompt(translations[currentLang].enterBudget, budget);
|
| 428 |
+
if(b !== null) { budget = parseFloat(b); localStorage.setItem('easy_money_budget', budget); render(); }
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
function checkBudget(totalSpent) {
|
| 432 |
+
const wrapper = document.getElementById('budgetWrapper');
|
| 433 |
+
if(budget > 0) {
|
| 434 |
+
wrapper.style.display = 'block';
|
| 435 |
+
document.getElementById('budgetDisplay').innerText = budget + ' ' + currencySymbol;
|
| 436 |
+
let left = budget - totalSpent;
|
| 437 |
+
document.getElementById('remainingVal').innerText = left.toFixed(2);
|
| 438 |
+
let percentage = (totalSpent / budget) * 100;
|
| 439 |
+
document.getElementById('budgetBar').style.width = Math.min(percentage, 100) + '%';
|
| 440 |
+
document.getElementById('budgetAlert').style.display = totalSpent > budget ? 'inline' : 'none';
|
| 441 |
+
} else { wrapper.style.display = 'none'; }
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
function toggleDarkMode() { document.body.classList.toggle('dark-mode'); }
|
| 445 |
+
function searchList() { render(); }
|
| 446 |
+
|
| 447 |
+
function toggleChart() {
|
| 448 |
+
const container = document.getElementById('chartContainer');
|
| 449 |
+
container.style.display = container.style.display === 'block' ? 'none' : 'block';
|
| 450 |
+
if(container.style.display === 'block') updateChartData();
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
function updateChartData() {
|
| 454 |
+
const ctx = document.getElementById('expenseChart').getContext('2d');
|
| 455 |
+
const cats = {}; db.forEach(i => cats[i.c] = (cats[i.c] || 0) + parseFloat(i.v));
|
| 456 |
+
if(myChart) myChart.destroy();
|
| 457 |
+
myChart = new Chart(ctx, {
|
| 458 |
+
type: 'doughnut',
|
| 459 |
+
data: { labels: Object.keys(cats), datasets: [{ data: Object.values(cats), backgroundColor: ['#27ae60','#f1c40f','#e74c3c','#3498db','#9b59b6', '#1abc9c', '#95a5a6', '#d35400', '#2c3e50', '#8e44ad'] }] }
|
| 460 |
+
});
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
function exportToPDF() {
|
| 464 |
+
const t = translations[currentLang];
|
| 465 |
+
const iframe = document.createElement('iframe');
|
| 466 |
+
iframe.style.display = 'none';
|
| 467 |
+
document.body.appendChild(iframe);
|
| 468 |
+
const content = `
|
| 469 |
+
<html dir="${t.dir}">
|
| 470 |
+
<head>
|
| 471 |
+
<style>
|
| 472 |
+
body { font-family: 'Segoe UI', Arial, sans-serif; padding: 20px; }
|
| 473 |
+
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
|
| 474 |
+
th, td { border: 1px solid #ddd; padding: 10px; text-align: center; }
|
| 475 |
+
th { background: #27ae60; color: white; }
|
| 476 |
+
h1 { color: #27ae60; text-align: center; }
|
| 477 |
+
</style>
|
| 478 |
+
</head>
|
| 479 |
+
<body>
|
| 480 |
+
<h1>${t.appTitle}</h1>
|
| 481 |
+
<table>
|
| 482 |
+
<thead><tr><th>المبلغ</th><th>الفئة</th><th>الوصف</th><th>التاريخ</th></tr></thead>
|
| 483 |
+
<tbody>${db.map(i => `<tr><td>${i.v} DH</td><td>${i.c}</td><td>${i.d}</td><td>${i.t}</td></tr>`).join('')}</tbody>
|
| 484 |
+
</table>
|
| 485 |
+
<h3 style="text-align:right;">${t.totalLabel} ${document.getElementById('total').innerText} DH</h3>
|
| 486 |
+
</body>
|
| 487 |
+
</html>
|
| 488 |
+
`;
|
| 489 |
+
iframe.contentWindow.document.open();
|
| 490 |
+
iframe.contentWindow.document.write(content);
|
| 491 |
+
iframe.contentWindow.document.close();
|
| 492 |
+
setTimeout(() => {
|
| 493 |
+
iframe.contentWindow.focus();
|
| 494 |
+
iframe.contentWindow.print();
|
| 495 |
+
document.body.removeChild(iframe);
|
| 496 |
+
}, 500);
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
function exportToCSV() {
|
| 500 |
+
let csvContent = "data:text/csv;charset=utf-8,Amount,Category,Description,Date\n";
|
| 501 |
+
db.forEach(row => { csvContent += `${row.v},${row.c},${row.d},${row.t}\n`; });
|
| 502 |
+
const encodedUri = encodeURI(csvContent);
|
| 503 |
+
const link = document.createElement("a");
|
| 504 |
+
link.setAttribute("href", encodedUri);
|
| 505 |
+
link.setAttribute("download", "expenses.csv");
|
| 506 |
+
document.body.appendChild(link);
|
| 507 |
+
link.click();
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
function downloadBackup() {
|
| 511 |
+
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(db));
|
| 512 |
+
const link = document.createElement('a');
|
| 513 |
+
link.href = dataStr;
|
| 514 |
+
link.download = "backup.json";
|
| 515 |
+
link.click();
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
function restoreBackup(input) {
|
| 519 |
+
const file = input.files[0];
|
| 520 |
+
if(!file) return;
|
| 521 |
+
const reader = new FileReader();
|
| 522 |
+
reader.onload = function(e) {
|
| 523 |
+
try {
|
| 524 |
+
const data = JSON.parse(e.target.result);
|
| 525 |
+
if(Array.isArray(data)) {
|
| 526 |
+
if(confirm("Restore?")) { db = data; localStorage.setItem('easy_money', JSON.stringify(db)); render(); }
|
| 527 |
+
}
|
| 528 |
+
} catch(err) { alert("Error!"); }
|
| 529 |
+
};
|
| 530 |
+
reader.readAsText(file);
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
function toggleCalculator() { document.getElementById('calcModal').style.display = 'flex'; }
|
| 534 |
+
function closeCalc() {
|
| 535 |
+
let res = document.getElementById('calcScreen').value;
|
| 536 |
+
if(res && !isNaN(res)) document.getElementById('val').value = res;
|
| 537 |
+
document.getElementById('calcModal').style.display = 'none';
|
| 538 |
+
}
|
| 539 |
+
function calcInput(v) { document.getElementById('calcScreen').value += v; }
|
| 540 |
+
function calcClear() { document.getElementById('calcScreen').value = ''; }
|
| 541 |
+
function calcResult() { try { document.getElementById('calcScreen').value = eval(document.getElementById('calcScreen').value); } catch(e){ document.getElementById('calcScreen').value = 'Error'; } }
|
| 542 |
+
|
| 543 |
+
function openSupportModal() { document.getElementById('supportModal').style.display = 'flex'; }
|
| 544 |
+
function closeSupportModal() { document.getElementById('supportModal').style.display = 'none'; }
|
| 545 |
+
function copyWallet() { navigator.clipboard.writeText("TKRxE5mLaBVKuV9FPt4EDiVwvVauYJuXTf").then(() => alert(translations[currentLang].copyDone)); }
|
| 546 |
+
|
| 547 |
+
window.onload = function() { document.getElementById('langSelect').value = currentLang; applyLanguage(currentLang); render(); };
|
| 548 |
+
</script>
|
| 549 |
+
</body>
|
| 550 |
+
</html>
|