Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -479,12 +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 { display: flex;
|
| 483 |
-
.
|
| 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:
|
| 487 |
-
.btn-delete:hover { background-color:
|
| 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); }
|
|
@@ -538,8 +538,8 @@ ADMIN_TEMPLATE = """
|
|
| 538 |
<div class="amount">{{ "%.2f"|format(user.bonuses|float) }}</div>
|
| 539 |
</div>
|
| 540 |
<div class="user-actions">
|
| 541 |
-
<button class="btn-manage" onclick='openTransactionModal({{ user|tojson }})'
|
| 542 |
-
<button class="btn-delete" onclick='deleteClient(
|
| 543 |
</div>
|
| 544 |
</div>
|
| 545 |
{% endfor %}
|
|
@@ -760,10 +760,12 @@ ADMIN_TEMPLATE = """
|
|
| 760 |
statusEl.textContent = `Ошибка: ${error.message}`;
|
| 761 |
}
|
| 762 |
}
|
| 763 |
-
|
| 764 |
-
async function deleteClient(
|
| 765 |
-
const
|
| 766 |
-
|
|
|
|
|
|
|
| 767 |
return;
|
| 768 |
}
|
| 769 |
|
|
@@ -775,14 +777,15 @@ ADMIN_TEMPLATE = """
|
|
| 775 |
});
|
| 776 |
|
| 777 |
const result = await response.json();
|
|
|
|
| 778 |
if (response.ok) {
|
| 779 |
-
alert(
|
| 780 |
location.reload();
|
| 781 |
} else {
|
| 782 |
-
throw new Error(result.message || 'Произошла ошибка
|
| 783 |
}
|
| 784 |
} catch (error) {
|
| 785 |
-
alert(
|
| 786 |
}
|
| 787 |
}
|
| 788 |
|
|
@@ -941,6 +944,38 @@ def add_client():
|
|
| 941 |
logging.exception("Error in /admin/add_client endpoint")
|
| 942 |
return jsonify({"status": "error", "message": str(e)}), 500
|
| 943 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 944 |
|
| 945 |
@app.route('/admin/add_transaction', methods=['POST'])
|
| 946 |
def add_transaction():
|
|
@@ -999,41 +1034,6 @@ def add_transaction():
|
|
| 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}")
|
|
|
|
| 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; gap: 0.5rem; margin-top: auto; }
|
| 483 |
+
.btn-manage, .btn-delete { flex: 1; padding: 10px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: background-color 0.2s; font-size: 0.9em; }
|
| 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: var(--admin-danger); color: white; }
|
| 487 |
+
.btn-delete:hover { background-color: #c82333; }
|
| 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); }
|
|
|
|
| 538 |
<div class="amount">{{ "%.2f"|format(user.bonuses|float) }}</div>
|
| 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|tojson }})'>Удалить</button>
|
| 543 |
</div>
|
| 544 |
</div>
|
| 545 |
{% endfor %}
|
|
|
|
| 760 |
statusEl.textContent = `Ошибка: ${error.message}`;
|
| 761 |
}
|
| 762 |
}
|
| 763 |
+
|
| 764 |
+
async function deleteClient(userData) {
|
| 765 |
+
const userId = userData.id;
|
| 766 |
+
const userName = `${userData.first_name || ''} ${userData.last_name || ''}`.trim() || `@${userData.username || userData.phone_number}`;
|
| 767 |
+
|
| 768 |
+
if (!confirm(`Вы уверены, что хотите удалить клиента ${userName} (ID: ${userId})? Это действие необратимо.`)) {
|
| 769 |
return;
|
| 770 |
}
|
| 771 |
|
|
|
|
| 777 |
});
|
| 778 |
|
| 779 |
const result = await response.json();
|
| 780 |
+
|
| 781 |
if (response.ok) {
|
| 782 |
+
alert('Клиент успешно удален.');
|
| 783 |
location.reload();
|
| 784 |
} else {
|
| 785 |
+
throw new Error(result.message || 'Произошла ошибка при удалении');
|
| 786 |
}
|
| 787 |
} catch (error) {
|
| 788 |
+
alert(`Ошибка: ${error.message}`);
|
| 789 |
}
|
| 790 |
}
|
| 791 |
|
|
|
|
| 944 |
logging.exception("Error in /admin/add_client endpoint")
|
| 945 |
return jsonify({"status": "error", "message": str(e)}), 500
|
| 946 |
|
| 947 |
+
@app.route('/admin/delete_client', methods=['POST'])
|
| 948 |
+
def delete_client():
|
| 949 |
+
try:
|
| 950 |
+
data = request.get_json()
|
| 951 |
+
user_id = data.get('user_id')
|
| 952 |
+
|
| 953 |
+
if not user_id:
|
| 954 |
+
return jsonify({"status": "error", "message": "User ID is required"}), 400
|
| 955 |
+
|
| 956 |
+
user_id_str = str(user_id)
|
| 957 |
+
|
| 958 |
+
with _data_lock:
|
| 959 |
+
all_data = load_visitor_data()
|
| 960 |
+
|
| 961 |
+
if user_id_str not in all_data:
|
| 962 |
+
return jsonify({"status": "error", "message": "User not found"}), 404
|
| 963 |
+
|
| 964 |
+
del all_data[user_id_str]
|
| 965 |
+
|
| 966 |
+
with open(DATA_FILE, 'w', encoding='utf-8') as f:
|
| 967 |
+
json.dump(all_data, f, ensure_ascii=False, indent=4)
|
| 968 |
+
|
| 969 |
+
logging.info(f"User {user_id_str} deleted. Data saved to {DATA_FILE}.")
|
| 970 |
+
|
| 971 |
+
upload_data_to_hf_async()
|
| 972 |
+
|
| 973 |
+
return jsonify({"status": "ok", "message": "Client deleted successfully"}), 200
|
| 974 |
+
|
| 975 |
+
except Exception as e:
|
| 976 |
+
logging.exception("Error in /admin/delete_client endpoint")
|
| 977 |
+
return jsonify({"status": "error", "message": str(e)}), 500
|
| 978 |
+
|
| 979 |
|
| 980 |
@app.route('/admin/add_transaction', methods=['POST'])
|
| 981 |
def add_transaction():
|
|
|
|
| 1034 |
logging.exception("Error in /admin/add_transaction endpoint")
|
| 1035 |
return jsonify({"status": "error", "message": str(e)}), 500
|
| 1036 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1037 |
if __name__ == '__main__':
|
| 1038 |
print("--- DRUZHBA BONUS SYSTEM SERVER ---")
|
| 1039 |
print(f"Server starting on http://{HOST}:{PORT}")
|