Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -479,8 +479,12 @@ ADMIN_TEMPLATE = """
|
|
| 479 |
.user-bonuses { text-align: center; margin-bottom: 1rem; }
|
| 480 |
.user-bonuses .label { font-size: 0.9em; color: var(--admin-secondary); }
|
| 481 |
.user-bonuses .amount { font-size: 1.8em; font-weight: 700; color: var(--admin-primary-dark); }
|
| 482 |
-
.user-actions
|
| 483 |
-
.user-actions
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
.no-users { text-align: center; color: var(--admin-secondary); margin-top: 2rem; font-size: 1.1em; }
|
| 485 |
.modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(5px); }
|
| 486 |
.modal-content { background-color: var(--admin-bg); margin: 10% auto; padding: var(--padding); border: 1px solid var(--admin-border); width: 90%; max-width: 600px; border-radius: var(--border-radius); position: relative; box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
|
|
@@ -535,6 +539,7 @@ ADMIN_TEMPLATE = """
|
|
| 535 |
</div>
|
| 536 |
<div class="user-actions">
|
| 537 |
<button class="btn-manage" onclick='openTransactionModal({{ user|tojson }})'>Управление бонусами</button>
|
|
|
|
| 538 |
</div>
|
| 539 |
</div>
|
| 540 |
{% endfor %}
|
|
@@ -755,6 +760,31 @@ ADMIN_TEMPLATE = """
|
|
| 755 |
statusEl.textContent = `Ошибка: ${error.message}`;
|
| 756 |
}
|
| 757 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 758 |
|
| 759 |
window.onclick = function(event) {
|
| 760 |
if (event.target == transactionModal) {
|
|
@@ -969,6 +999,41 @@ def add_transaction():
|
|
| 969 |
logging.exception("Error in /admin/add_transaction endpoint")
|
| 970 |
return jsonify({"status": "error", "message": str(e)}), 500
|
| 971 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 972 |
if __name__ == '__main__':
|
| 973 |
print("--- DRUZHBA BONUS SYSTEM SERVER ---")
|
| 974 |
print(f"Server starting on http://{HOST}:{PORT}")
|
|
|
|
| 479 |
.user-bonuses { text-align: center; margin-bottom: 1rem; }
|
| 480 |
.user-bonuses .label { font-size: 0.9em; color: var(--admin-secondary); }
|
| 481 |
.user-bonuses .amount { font-size: 1.8em; font-weight: 700; color: var(--admin-primary-dark); }
|
| 482 |
+
.user-actions { display: flex; flex-direction: column; gap: 0.5rem; margin-top: auto; }
|
| 483 |
+
.user-actions button { display: block; width: 100%; padding: 10px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: background-color 0.2s; }
|
| 484 |
+
.btn-manage { background-color: var(--admin-primary); color: #000; }
|
| 485 |
+
.btn-manage:hover { background-color: var(--admin-primary-dark); }
|
| 486 |
+
.btn-delete { background-color: #e4e6e8; color: var(--admin-text); }
|
| 487 |
+
.btn-delete:hover { background-color: var(--admin-danger); color: white; }
|
| 488 |
.no-users { text-align: center; color: var(--admin-secondary); margin-top: 2rem; font-size: 1.1em; }
|
| 489 |
.modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.5); backdrop-filter: blur(5px); }
|
| 490 |
.modal-content { background-color: var(--admin-bg); margin: 10% auto; padding: var(--padding); border: 1px solid var(--admin-border); width: 90%; max-width: 600px; border-radius: var(--border-radius); position: relative; box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
|
|
|
|
| 539 |
</div>
|
| 540 |
<div class="user-actions">
|
| 541 |
<button class="btn-manage" onclick='openTransactionModal({{ user|tojson }})'>Управление бонусами</button>
|
| 542 |
+
<button class="btn-delete" onclick='deleteClient("{{ user.id }}", "{{ (user.first_name or "") + " " + (user.last_name or "") }}")'>Удалить клиента</button>
|
| 543 |
</div>
|
| 544 |
</div>
|
| 545 |
{% endfor %}
|
|
|
|
| 760 |
statusEl.textContent = `Ошибка: ${error.message}`;
|
| 761 |
}
|
| 762 |
}
|
| 763 |
+
|
| 764 |
+
async function deleteClient(userId, userName) {
|
| 765 |
+
const fullName = (userName || `ID ${userId}`).trim();
|
| 766 |
+
if (!confirm(`Вы уверены, что хотите удалить клиента "${fullName}"? Это действие необратимо и удалит всю его историю и бонусы.`)) {
|
| 767 |
+
return;
|
| 768 |
+
}
|
| 769 |
+
|
| 770 |
+
try {
|
| 771 |
+
const response = await fetch('/admin/delete_client', {
|
| 772 |
+
method: 'POST',
|
| 773 |
+
headers: { 'Content-Type': 'application/json' },
|
| 774 |
+
body: JSON.stringify({ user_id: userId })
|
| 775 |
+
});
|
| 776 |
+
|
| 777 |
+
const result = await response.json();
|
| 778 |
+
if (response.ok) {
|
| 779 |
+
alert(result.message || 'Клиент успешно удален.');
|
| 780 |
+
location.reload();
|
| 781 |
+
} else {
|
| 782 |
+
throw new Error(result.message || 'Произошла ошибка на сервере.');
|
| 783 |
+
}
|
| 784 |
+
} catch (error) {
|
| 785 |
+
alert(`Ошибка при удалении: ${error.message}`);
|
| 786 |
+
}
|
| 787 |
+
}
|
| 788 |
|
| 789 |
window.onclick = function(event) {
|
| 790 |
if (event.target == transactionModal) {
|
|
|
|
| 999 |
logging.exception("Error in /admin/add_transaction endpoint")
|
| 1000 |
return jsonify({"status": "error", "message": str(e)}), 500
|
| 1001 |
|
| 1002 |
+
@app.route('/admin/delete_client', methods=['POST'])
|
| 1003 |
+
def delete_client():
|
| 1004 |
+
try:
|
| 1005 |
+
data = request.get_json()
|
| 1006 |
+
user_id = data.get('user_id')
|
| 1007 |
+
|
| 1008 |
+
if not user_id:
|
| 1009 |
+
return jsonify({"status": "error", "message": "User ID is required"}), 400
|
| 1010 |
+
|
| 1011 |
+
user_id_str = str(user_id)
|
| 1012 |
+
|
| 1013 |
+
with _data_lock:
|
| 1014 |
+
all_data = load_visitor_data()
|
| 1015 |
+
|
| 1016 |
+
if user_id_str not in all_data:
|
| 1017 |
+
return jsonify({"status": "error", "message": "User not found"}), 404
|
| 1018 |
+
|
| 1019 |
+
del all_data[user_id_str]
|
| 1020 |
+
|
| 1021 |
+
try:
|
| 1022 |
+
with open(DATA_FILE, 'w', encoding='utf-8') as f:
|
| 1023 |
+
json.dump(all_data, f, ensure_ascii=False, indent=4)
|
| 1024 |
+
logging.info(f"User {user_id_str} deleted. Data file rewritten.")
|
| 1025 |
+
upload_data_to_hf_async()
|
| 1026 |
+
except Exception as e:
|
| 1027 |
+
logging.error(f"Error writing file after deletion: {e}")
|
| 1028 |
+
return jsonify({"status": "error", "message": "Failed to save changes to disk."}), 500
|
| 1029 |
+
|
| 1030 |
+
return jsonify({"status": "ok", "message": "Клиен�� успешно удален."}), 200
|
| 1031 |
+
|
| 1032 |
+
except Exception as e:
|
| 1033 |
+
logging.exception("Error in /admin/delete_client endpoint")
|
| 1034 |
+
return jsonify({"status": "error", "message": str(e)}), 500
|
| 1035 |
+
|
| 1036 |
+
|
| 1037 |
if __name__ == '__main__':
|
| 1038 |
print("--- DRUZHBA BONUS SYSTEM SERVER ---")
|
| 1039 |
print(f"Server starting on http://{HOST}:{PORT}")
|