Files
docupulse/templates/contacts/form.html
2025-05-27 10:53:06 +02:00

199 lines
11 KiB
HTML

{% extends "common/base.html" %}
{% block content %}
<div class="container mx-auto px-4 py-8">
<div class="max-w-2xl mx-auto">
<div class="d-flex justify-content-between align-items-center mb-6">
<div>
<h3 class="mb-0">
<i class="fas fa-user me-2" style="color:#16767b;"></i>
{% if title %}
{{ title }}
{% else %}
User Form
{% endif %}
</h3>
<p class="text-muted mb-0 mt-2 small">Add or edit contact information</p>
</div>
<a href="{{ url_for('contacts.contacts_list') }}"
class="btn btn-sm btn-outline-secondary">
<i class="fas fa-arrow-left me-1"></i>
Back to Contacts
</a>
</div>
<div class="bg-white rounded-lg shadow p-6">
<form method="POST" class="space-y-6" enctype="multipart/form-data">
{{ form.hidden_tag() }}
<!-- Profile Picture Upload (matches profile page style) -->
<div class="flex flex-col items-center mb-6">
<div class="relative group flex flex-col items-center">
<label for="profile_picture" class="cursor-pointer">
<img id="avatarPreview" src="{{ url_for('profile_pic', filename=form.profile_picture.data or user.profile_picture) if (form.profile_picture.data or (user and user.profile_picture)) else url_for('static', filename='default-avatar.png') }}" alt="Profile Picture" class="w-32 h-32 rounded-full object-cover border-4 border-gray-200 mb-0 transition duration-200 group-hover:opacity-80 group-hover:ring-4 group-hover:ring-primary-200 shadow-sm">
<input id="profile_picture" type="file" name="profile_picture" accept="image/*" class="hidden" onchange="previewAvatar(event)" />
</label>
{% if user and user.profile_picture %}
<button type="submit" name="remove_picture" value="1" class="mt-2 mb-2 text-xs px-3 py-1 rounded bg-red-100 text-red-700 border border-red-200 hover:bg-red-200 transition">Remove Picture</button>
{% endif %}
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
{{ form.first_name.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.first_name(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500") }}
{% if form.first_name.errors %}
{% for error in form.first_name.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
<div>
{{ form.last_name.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.last_name(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500") }}
{% if form.last_name.errors %}
{% for error in form.last_name.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
</div>
<div>
{{ form.email.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.email(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500") }}
{% if form.email.errors %}
{% for error in form.email.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
{% if current_user.is_admin %}
<div class="relative">
{{ form.new_password.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.new_password(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 pr-10", autocomplete="new-password", id="new_password") }}
<button type="button" tabindex="-1" class="absolute right-2 top-9 text-gray-500" style="background: none; border: none;" onmousedown="showPwd('new_password')" onmouseup="hidePwd('new_password')" onmouseleave="hidePwd('new_password')">
<i class="fas fa-eye"></i>
</button>
</div>
<div class="relative">
{{ form.confirm_password.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.confirm_password(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 pr-10", autocomplete="new-password", id="confirm_password") }}
<button type="button" tabindex="-1" class="absolute right-2 top-9 text-gray-500" style="background: none; border: none;" onmousedown="showPwd('confirm_password')" onmouseup="hidePwd('confirm_password')" onmouseleave="hidePwd('confirm_password')">
<i class="fas fa-eye"></i>
</button>
{% if form.confirm_password.errors %}
{% for error in form.confirm_password.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
<script>
function showPwd(id) {
document.getElementById(id).type = 'text';
}
function hidePwd(id) {
document.getElementById(id).type = 'password';
}
</script>
{% endif %}
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
{{ form.phone.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.phone(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500") }}
{% if form.phone.errors %}
{% for error in form.phone.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
<div>
{{ form.company.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.company(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500") }}
{% if form.company.errors %}
{% for error in form.company.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
</div>
<div>
{{ form.position.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.position(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500") }}
{% if form.position.errors %}
{% for error in form.position.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
<div>
{{ form.notes.label(class="block text-sm font-medium text-gray-700 mb-1") }}
{{ form.notes(class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500", rows="4") }}
{% if form.notes.errors %}
{% for error in form.notes.errors %}
<p class="mt-1 text-sm text-red-600">{{ error }}</p>
{% endfor %}
{% endif %}
</div>
<div class="flex flex-col space-y-4">
<div class="flex items-center space-x-4">
<div class="flex items-center relative group">
{% set is_last_admin = current_user.is_admin and total_admins <= 1 %}
{{ form.is_admin(
class="h-4 w-4 focus:ring-blue-500 border-gray-300 rounded",
style="accent-color: #16767b;",
disabled=is_last_admin and form.is_admin.data
) }}
{{ form.is_admin.label(class="ml-2 block text-sm text-gray-900") }}
{% if is_last_admin and form.is_admin.data %}
<input type="hidden" name="is_admin" value="y">
{% endif %}
<div class="absolute left-0 bottom-full mb-2 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 w-48">
Admin users have full access to manage contacts and system settings.
</div>
{% if is_last_admin and form.is_admin.data %}
<div class="ml-2 text-sm text-amber-600">
<i class="fas fa-exclamation-circle"></i>
You are the only admin
</div>
{% endif %}
</div>
</div>
{% if form.is_admin.errors %}
<div class="p-3 bg-red-50 border border-red-200 rounded-lg">
{% for error in form.is_admin.errors %}
<p class="text-sm text-red-700">{{ error }}</p>
{% endfor %}
</div>
{% endif %}
</div>
<div class="flex justify-end">
{{ form.submit(class="text-white px-6 py-2 rounded-lg transition duration-200", style="background-color: #16767b; border: 1px solid #16767b;", onmouseover="this.style.backgroundColor='#1a8a90'", onmouseout="this.style.backgroundColor='#16767b'") }}
</div>
</form>
</div>
</div>
</div>
<script>
function previewAvatar(event) {
const [file] = event.target.files;
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
document.getElementById('avatarPreview').src = e.target.result;
};
reader.readAsDataURL(file);
}
}
</script>
{% endblock %}