Mobile-friendly UI: hamburger nav, responsive layouts, restyle login/admin pages, fix iOS upload

This commit is contained in:
Georges Haddad
2026-04-10 16:50:15 +03:00
parent 61b9c23803
commit 7e1e0ac426
8 changed files with 391 additions and 80 deletions
+14 -1
View File
@@ -12,7 +12,10 @@
<nav class="navbar">
<div class="nav-container">
<a class="nav-brand" href="/">🏠 سجل العقارات</a>
<div class="nav-links">
<button class="nav-toggle" id="navToggle" aria-label="القائمة">
<span></span><span></span><span></span>
</button>
<div class="nav-links" id="navLinks">
<a href="/" class="nav-link">رفع وثائق</a>
<a href="/review/next" class="nav-link">مراجعة</a>
<a href="/search" class="nav-link">بحث</a>
@@ -28,6 +31,16 @@
{% block content %}{% endblock %}
</main>
<script>
const navToggle = document.getElementById('navToggle');
const navLinks = document.getElementById('navLinks');
if (navToggle) {
navToggle.addEventListener('click', () => {
navLinks.classList.toggle('open');
navToggle.classList.toggle('active');
});
}
</script>
{% block scripts %}{% endblock %}
</body>
</html>
+4 -4
View File
@@ -23,12 +23,12 @@
<div class="upload-card">
<form id="uploadForm" action="/upload" method="post" enctype="multipart/form-data">
<div class="drop-zone" id="dropZone">
<input type="file" name="files" id="fileInput" multiple accept=".jpg,.jpeg,.png,.webp,.pdf" class="file-input">
<label for="fileInput" class="drop-zone" id="dropZone">
<div class="drop-icon">📄</div>
<p class="drop-text">اسحب الملفات هنا أو انقر للاختيار</p>
<p class="drop-hint">JPG، PNG، PDF — يمكن رفع عدة ملفات دفعة واحدة</p>
<input type="file" name="files" id="fileInput" multiple accept=".jpg,.jpeg,.png,.webp,.pdf" class="file-input">
</div>
</label>
<div id="fileList" class="file-list hidden"></div>
@@ -77,7 +77,7 @@ const fileInput = document.getElementById('fileInput');
const fileList = document.getElementById('fileList');
const uploadActions = document.getElementById('uploadActions');
dropZone.addEventListener('click', () => fileInput.click());
// label[for] natively triggers the file input on all platforms including iOS
dropZone.addEventListener('dragover', e => {
e.preventDefault();
+13 -13
View File
@@ -5,25 +5,25 @@
{% block navbar %}{% endblock %}
{% block content %}
<div class="login-container" style="max-width: 400px; margin: 50px auto; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
<h2>تسجيل الدخول</h2>
<div class="login-card">
<h2>🏠 تسجيل الدخول</h2>
{% if error %}
<div style="color: red; margin-bottom: 10px;">{{ error }}</div>
<div class="login-error">{{ error }}</div>
{% endif %}
<form method="post" action="/auth/login">
<div style="margin-bottom: 15px;">
<label for="username" style="display: block; margin-bottom: 5px;">اسم المستخدم:</label>
<input type="text" id="username" name="username" required style="width: 100%; padding: 8px;">
<div class="form-group">
<label for="username">اسم المستخدم</label>
<input type="text" id="username" name="username" required placeholder="أدخل اسم المستخدم">
</div>
<div style="margin-bottom: 15px;">
<label for="password" style="display: block; margin-bottom: 5px;">كلمة المرور:</label>
<input type="password" id="password" name="password" required style="width: 100%; padding: 8px;">
<div class="form-group">
<label for="password">كلمة المرور</label>
<input type="password" id="password" name="password" required placeholder="أدخل كلمة المرور">
</div>
<button type="submit" style="width: 100%; padding: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">
<button type="submit" class="btn btn-primary btn-large" style="width:100%; justify-content:center; margin-top:.5rem;">
دخول
</button>
</form>
+5 -5
View File
@@ -9,13 +9,13 @@
</div>
<div>
{% set scopes = documents | selectattr('search_scope') | map(attribute='search_scope') | unique | list %}
<div class="export-dropdown" style="position: relative; display: inline-block;">
<div class="export-dropdown">
<button class="btn btn-primary" onclick="this.nextElementSibling.classList.toggle('show')">📥 تصدير كملف إكسل ▾</button>
<div class="export-menu" style="display:none; position:absolute; left:0; top:100%; background:#fff; border:1px solid #ddd; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,.15); z-index:100; min-width:220px; margin-top:4px;">
<a href="/persons/{{ person.id }}/export" class="export-option" download style="display:block; padding:10px 16px; text-decoration:none; color:#333; border-bottom:1px solid #eee;">📥 تصدير الكل</a>
<div class="export-menu">
<a href="/persons/{{ person.id }}/export" class="export-option" download>📥 تصدير الكل</a>
{% for scope in scopes %}
{% if scope %}
<a href="/persons/{{ person.id }}/export?qaza={{ scope|urlencode }}" class="export-option" download style="display:block; padding:10px 16px; text-decoration:none; color:#333;">📥 {{ scope }}</a>
<a href="/persons/{{ person.id }}/export?qaza={{ scope|urlencode }}" class="export-option" download>📥 {{ scope }}</a>
{% endif %}
{% endfor %}
</div>
@@ -75,7 +75,7 @@
</table>
</div>
{% else %}
<div style="margin: 1rem 0; padding: 15px; background-color: #fff3f3; border: 1px solid #ffcaca; border-radius: 8px; color: #dc3545; font-weight: bold; text-align: center;">
<div class="error-banner" style="justify-content:center;">
⚠️ نتيجة البحث: لا يملك أي عقار في نطاق البحث المذكور.
</div>
{% endif %}
+5 -5
View File
@@ -64,13 +64,13 @@
<div style="margin-top:1rem">
<a href="/persons/{{ selected_person.person.id }}" class="btn btn-secondary">عرض التفاصيل كاملة</a>
{% set scopes = selected_person.documents | selectattr('search_scope') | map(attribute='search_scope') | unique | list %}
<div class="export-dropdown" style="position: relative; display: inline-block;">
<div class="export-dropdown">
<button class="btn btn-primary" onclick="this.nextElementSibling.classList.toggle('show')">📥 تصدير كملف إكسل ▾</button>
<div class="export-menu" style="display:none; position:absolute; left:0; top:100%; background:#fff; border:1px solid #ddd; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,.15); z-index:100; min-width:220px; margin-top:4px;">
<a href="/persons/{{ selected_person.person.id }}/export" class="export-option" download style="display:block; padding:10px 16px; text-decoration:none; color:#333; border-bottom:1px solid #eee;">📥 تصدير الكل</a>
<div class="export-menu">
<a href="/persons/{{ selected_person.person.id }}/export" class="export-option" download>📥 تصدير الكل</a>
{% for scope in scopes %}
{% if scope %}
<a href="/persons/{{ selected_person.person.id }}/export?qaza={{ scope|urlencode }}" class="export-option" download style="display:block; padding:10px 16px; text-decoration:none; color:#333;">📥 {{ scope }}</a>
<a href="/persons/{{ selected_person.person.id }}/export?qaza={{ scope|urlencode }}" class="export-option" download>📥 {{ scope }}</a>
{% endif %}
{% endfor %}
</div>
@@ -112,7 +112,7 @@
</table>
</div>
{% else %}
<div style="margin-top: 1rem; padding: 15px; background-color: #fff3f3; border: 1px solid #ffcaca; border-radius: 8px; color: #dc3545; font-weight: bold; text-align: center;">
<div class="error-banner" style="margin-top:1rem; justify-content:center;">
⚠️ نتيجة البحث: لا يملك أي عقار في القضاء المذكور.
</div>
{% endif %}
+51 -49
View File
@@ -3,62 +3,64 @@
{% block title %}إدارة المستخدمين - سجل العقارات اللبناني{% endblock %}
{% block content %}
<div class="users-container" style="max-width: 800px; margin: 20px auto; padding: 20px;">
<h2>إدارة النظام والمستخدمين</h2>
{% if backup_msg %}
<div style="padding: 10px; background-color: #d4edda; color: #155724; border-radius: 4px; margin-bottom: 15px;">
{{ backup_msg }}
</div>
{% endif %}
<div style="margin-bottom: 30px; padding: 15px; border: 1px solid #ddd; border-radius: 8px;">
<h3>نسخ احتياطي لقاعدة البيانات</h3>
<p>قم بإنشاء نسخة احتياطية من قاعدة البيانات الحالية.</p>
<a href="/auth/backup" style="display: inline-block; padding: 8px 15px; background-color: #28a745; color: white; text-decoration: none; border-radius: 4px;">إنشاء نسخة احتياطية</a>
<div class="admin-container">
<div class="page-header">
<h1>إدارة النظام والمستخدمين</h1>
</div>
<div style="margin-bottom: 30px; padding: 15px; border: 1px solid #ddd; border-radius: 8px;">
<h3>إضافة مستخدم جديد</h3>
<form method="post" action="/auth/users/create" style="display: flex; gap: 10px; align-items: flex-end;">
<div>
<label for="username" style="display: block; margin-bottom: 5px;">اسم المستخدم</label>
<input type="text" id="username" name="username" required style="padding: 8px;">
{% if backup_msg %}
<div class="success-banner">{{ backup_msg }}</div>
{% endif %}
<div class="admin-section">
<h3>💾 نسخ احتياطي لقاعدة البيانات</h3>
<p>قم بإنشاء نسخة احتياطية من قاعدة البيانات الحالية.</p>
<a href="/auth/backup" class="btn btn-success">إنشاء نسخة احتياطية</a>
</div>
<div class="admin-section">
<h3> إضافة مستخدم جديد</h3>
<form method="post" action="/auth/users/create" class="add-user-form">
<div class="form-group">
<label for="username">اسم المستخدم</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password" style="display: block; margin-bottom: 5px;">كلمة المرور</label>
<input type="password" id="password" name="password" required style="padding: 8px;">
<div class="form-group">
<label for="password">كلمة المرور</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit" style="padding: 9px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">إضافة</button>
<button type="submit" class="btn btn-primary">إضافة</button>
</form>
</div>
<div style="padding: 15px; border: 1px solid #ddd; border-radius: 8px;">
<h3>المستخدمين</h3>
<table style="width: 100%; border-collapse: collapse; margin-top: 10px;">
<thead>
<tr style="background-color: #f8f9fa;">
<th style="padding: 10px; border-bottom: 2px solid #dee2e6; text-align: right;">الرقم</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6; text-align: right;">اسم المستخدم</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6; text-align: right;">تاريخ الإنشاء</th>
<th style="padding: 10px; border-bottom: 2px solid #dee2e6; text-align: right;">إجراءات</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td style="padding: 10px; border-bottom: 1px solid #dee2e6;">{{ user.id }}</td>
<td style="padding: 10px; border-bottom: 1px solid #dee2e6;">{{ user.username }}</td>
<td style="padding: 10px; border-bottom: 1px solid #dee2e6;">{{ user.created_at }}</td>
<td style="padding: 10px; border-bottom: 1px solid #dee2e6;">
<form method="post" action="/auth/users/delete/{{ user.id }}" onsubmit="return confirm('هل أنت متأكد من حذف هذا المستخدم؟');" style="display: inline;">
<button type="submit" style="padding: 5px 10px; background-color: #dc3545; color: white; border: none; border-radius: 4px; cursor: pointer;">حذف</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="admin-section">
<h3>👥 المستخدمين</h3>
<div class="table-wrapper">
<table class="results-table">
<thead>
<tr>
<th>الرقم</th>
<th>اسم المستخدم</th>
<th>تاريخ الإنشاء</th>
<th></th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.created_at }}</td>
<td>
<form method="post" action="/auth/users/delete/{{ user.id }}" onsubmit="return confirm('هل أنت متأكد من حذف هذا المستخدم؟');" style="display:inline;">
<button type="submit" class="btn btn-sm btn-danger">حذف</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}