feat: Add user edit functionality in admin panel
- Add /admin/users/<id>/update endpoint to update name, email, phone - Add edit button with pencil icon to users table - Add edit modal with form fields - Add JavaScript functions for edit modal handling
This commit is contained in:
parent
6b7046bf49
commit
d82dc0caec
55
app.py
55
app.py
@ -2094,6 +2094,61 @@ def admin_user_toggle_verified(user_id):
|
||||
db.close()
|
||||
|
||||
|
||||
@app.route('/admin/users/<int:user_id>/update', methods=['POST'])
|
||||
@login_required
|
||||
def admin_user_update(user_id):
|
||||
"""Update user data (name, email)"""
|
||||
if not current_user.is_admin:
|
||||
return jsonify({'success': False, 'error': 'Brak uprawnień'}), 403
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
user = db.query(User).filter(User.id == user_id).first()
|
||||
if not user:
|
||||
return jsonify({'success': False, 'error': 'Użytkownik nie znaleziony'}), 404
|
||||
|
||||
data = request.get_json() or {}
|
||||
|
||||
# Update name if provided
|
||||
if 'name' in data:
|
||||
user.name = data['name'].strip() if data['name'] else None
|
||||
|
||||
# Update email if provided (with validation)
|
||||
if 'email' in data:
|
||||
new_email = data['email'].strip().lower()
|
||||
if new_email and new_email != user.email:
|
||||
# Check if email already exists
|
||||
existing = db.query(User).filter(User.email == new_email, User.id != user_id).first()
|
||||
if existing:
|
||||
return jsonify({'success': False, 'error': 'Ten email jest już używany'}), 400
|
||||
user.email = new_email
|
||||
|
||||
# Update phone if provided
|
||||
if 'phone' in data:
|
||||
user.phone = data['phone'].strip() if data['phone'] else None
|
||||
|
||||
db.commit()
|
||||
|
||||
logger.info(f"Admin {current_user.email} updated user {user.email}: name={user.name}, phone={user.phone}")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'user': {
|
||||
'id': user.id,
|
||||
'name': user.name,
|
||||
'email': user.email,
|
||||
'phone': user.phone
|
||||
},
|
||||
'message': 'Dane użytkownika zaktualizowane'
|
||||
})
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f"Error updating user {user_id}: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@app.route('/admin/users/<int:user_id>/assign-company', methods=['POST'])
|
||||
@login_required
|
||||
def admin_user_assign_company(user_id):
|
||||
|
||||
@ -1127,6 +1127,15 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<!-- Edit User -->
|
||||
<button class="btn-icon"
|
||||
onclick="openEditUserModal({{ user.id }}, '{{ user.name|e if user.name else '' }}', '{{ user.email|e }}', '{{ user.phone|e if user.phone else '' }}')"
|
||||
title="Edytuj dane">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Toggle Admin -->
|
||||
<button class="btn-icon admin-toggle {{ 'active' if user.is_admin else '' }}"
|
||||
onclick="toggleAdmin({{ user.id }})"
|
||||
@ -1309,6 +1318,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit User Modal -->
|
||||
<div id="editUserModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">Edytuj użytkownika</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Imię i nazwisko</label>
|
||||
<input type="text" id="editUserName" class="form-control" placeholder="Jan Kowalski">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" id="editUserEmail" class="form-control" placeholder="jan@firma.pl">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Telefon</label>
|
||||
<input type="text" id="editUserPhone" class="form-control" placeholder="+48 123 456 789">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" onclick="closeEditUserModal()">Anuluj</button>
|
||||
<button class="btn btn-primary" onclick="saveEditUser()">Zapisz zmiany</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Confirmation Modal -->
|
||||
<div id="confirmModal" class="modal">
|
||||
<div class="modal-content">
|
||||
@ -1517,6 +1551,60 @@ Lub format CSV, Excel, lista emaili..."></textarea>
|
||||
const csrfToken = '{{ csrf_token() }}';
|
||||
let currentUserId = null;
|
||||
let confirmCallback = null;
|
||||
let editUserId = null;
|
||||
|
||||
// Edit User functions
|
||||
function openEditUserModal(userId, name, email, phone) {
|
||||
editUserId = userId;
|
||||
document.getElementById('editUserName').value = name || '';
|
||||
document.getElementById('editUserEmail').value = email || '';
|
||||
document.getElementById('editUserPhone').value = phone || '';
|
||||
document.getElementById('editUserModal').classList.add('active');
|
||||
}
|
||||
|
||||
function closeEditUserModal() {
|
||||
editUserId = null;
|
||||
document.getElementById('editUserModal').classList.remove('active');
|
||||
}
|
||||
|
||||
async function saveEditUser() {
|
||||
if (!editUserId) return;
|
||||
|
||||
const name = document.getElementById('editUserName').value.trim();
|
||||
const email = document.getElementById('editUserEmail').value.trim();
|
||||
const phone = document.getElementById('editUserPhone').value.trim();
|
||||
|
||||
if (!email) {
|
||||
showToast('Email jest wymagany', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/admin/users/${editUserId}/update`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: name || null,
|
||||
email: email,
|
||||
phone: phone || null
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
closeEditUserModal();
|
||||
showToast(data.message || 'Zapisano zmiany', 'success');
|
||||
location.reload();
|
||||
} else {
|
||||
showToast(data.error || 'Wystąpił błąd', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
showToast('Błąd połączenia', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Toast notification system
|
||||
function showToast(message, type = 'success') {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user