kaauh_ats/templates/user/portal_profile.html

276 lines
10 KiB
HTML

{% extends "portal_base.html" %}
{% load static %}
{% load i18n crispy_forms_tags %}
{% block title %}{% trans "User Profile" %} - KAAUH ATS{% endblock %}
{% block customCSS %}
<style>
/* Theme Variables based on Teal Accent */
:root {
--bs-primary: #00636e;
--bs-primary-rgb: 0, 99, 110;
--bs-primary-light: #007a88;
--bs-body-bg: #f3f5f8; /* Soft light gray background */
--bs-body-color: #212529;
--bs-border-color: #e9ecef; /* Lighter, softer border */
}
/* Card Refinements for Depth and Geometry */
.card {
border: none;
border-radius: 1rem;
box-shadow: 0 8px 30px rgba(0,0,0,0.08); /* Deeper, softer shadow */
transition: transform 0.2s ease-out, box-shadow 0.2s ease-out;
}
.card:hover {
transform: translateY(-2px); /* Subtle lift on hover */
box-shadow: 0 12px 35px rgba(0,0,0,0.1);
}
/* Profile Header Consistency */
.profile-header {
border-bottom: 2px solid var(--bs-border-color);
padding-bottom: 1.5rem;
margin-bottom: 2rem;
}
/* Form Consistency */
.form-control {
border-radius: 0.5rem;
padding: 0.75rem 1rem;
border-color: var(--bs-border-color);
transition: border-color 0.2s, box-shadow 0.2s;
font-size: 0.95rem; /* Slightly larger text in fields */
}
.form-control:focus {
border-color: var(--bs-primary-light);
box-shadow: 0 0 0 0.15rem rgba(0, 99, 110, 0.15);
}
.form-label {
font-size: 0.9rem;
font-weight: 600;
color: #495057; /* Slightly darker than default mute */
margin-bottom: 0.5rem;
}
/* Button Consistency (Primary) */
.btn-primary {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
font-weight: 700;
border-radius: 0.6rem;
padding: 0.65rem 1.5rem;
box-shadow: 0 5px 15px rgba(0, 99, 110, 0.3);
transition: all 0.2s ease;
}
.btn-primary:hover {
background-color: var(--bs-primary-light);
border-color: var(--bs-primary-light);
box-shadow: 0 8px 18px rgba(0, 99, 110, 0.4);
transform: translateY(-1px);
}
/* Button Consistency (Outline/Secondary) */
.btn-outline-secondary {
color: #495057;
border-color: var(--bs-border-color);
font-weight: 500;
transition: all 0.2s ease;
}
.btn-outline-secondary:hover {
color: var(--bs-primary); /* Accent text color on hover */
background-color: rgba(0, 99, 110, 0.05);
border-color: var(--bs-primary);
}
/* Accent & Info Text */
.text-accent {
color: var(--bs-primary) !important;
font-weight: 600;
}
.info-value {
font-weight: 700; /* Bolder status values */
color: var(--bs-body-color);
}
.info-label {
color: #6c757d;
font-size: 0.85rem;
margin-bottom: 0.2rem;
}
</style>
{% endblock %}
{% block content %}
<div class="container mt-4" style="max-width: 900px;">
<div class="profile-header d-flex align-items-center justify-content-between">
<div>
<h1 class="h3 fw-bold mb-1">{% trans "Account Settings" %}</h1>
<p class="text-muted mb-0">{% trans "Manage your personal details and security." %}</p>
</div>
<div class="rounded-circle bg-primary-subtle text-accent d-flex align-items-center justify-content-center" style="width: 50px; height: 50px; font-size: 1.5rem;">
{% if user.first_name %}{{ user.first_name.0 }}{% else %}<i class="fas fa-user"></i>{% endif %}
</div>
</div>
<div class="row g-4">
<div class="col-lg-7">
<div class="card p-5">
<h5 class="fw-bold mb-4 text-accent">{% trans "Personal Information" %}</h5>
<form method="POST" action="{% url 'user_detail' user.pk %}">
{% csrf_token %}
<div class="row g-4"> <div class="col-md-6">
<label for="id_first_name" class="form-label">{% trans "First Name" %}</label>
<input type="text" class="form-control" id="id_first_name" name="first_name" value="{{ user.first_name|default:'' }}">
</div>
<div class="col-md-6">
<label for="id_last_name" class="form-label">{% trans "Last Name" %}</label>
<input type="text" class="form-control" id="id_last_name" name="last_name" value="{{ user.last_name|default:'' }}">
</div>
<div class="col-12">
<label for="id_email" class="form-label">{% trans "Email Address" %}</label>
<input type="email" class="form-control" id="id_email" value="{{ user.email }}" disabled>
</div>
<div class="col-12 mt-4 pt-2">
<button type="submit" class="btn btn-primary">{% trans "Save Changes" %}</button>
</div>
</div>
</form>
</div>
</div>
<div class="col-lg-5">
<div class="card p-4 mb-4">
<h5 class="fw-bold mb-4 text-accent">{% trans "Security" %}</h5>
<div class="d-grid gap-3">
<button type="button" class="btn btn-outline-danger w-100 rounded-pill py-2" data-bs-toggle="modal" data-bs-target="#passwordModal">
<i class="fas fa-lock me-2"></i> {% trans "Change Password" %}
</button>
<button type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#myModalForm">
<i class="fas fa-image me-1"></i> {% trans "Change Profile Image" %}
</button>
</div>
</div>
<div class="card p-4">
<h5 class="fw-bold mb-4 text-accent">{% trans "Account Status" %}</h5>
<div class="mb-3">
<div class="info-label">{% trans "Username" %}</div>
<div class="info-value">{{ user.username }}</div>
</div>
<div class="mb-3">
<div class="info-label">{% trans "Last Login" %}</div>
<div class="info-value">
{% if user.last_login %}{{ user.last_login|date:"F d, Y P" }}{% else %}N/A{% endif %}
</div>
</div>
<div>
<div class="info-label">{% trans "Date Joined" %}</div>
<div class="info-value">{{ user.date_joined|date:"F d, Y" }}</div>
</div>
</div>
</div>
</div>
</div>
<!--modal class for password change-->
<div class="modal fade mt-4" id="passwordModal" tabindex="-1" aria-labelledby="passwordModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="passwordModalLabel">{% trans "Change Password" %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="passwordModalBody">
<form action="{% url 'portal_password_reset' user.pk %}" method="post">
{% csrf_token %}
{{password_reset_form|crispy}}
<button type="submit" class="btn btn-primary">{% trans "Change Password" %}</button>
</form>
</div>
</div>
</div>
</div>
<!--modal class for image upload-->
<div class="modal fade mt-4" id="myModalForm" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="myModalLabel">Upload Profile image</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="post" action="{% url 'user_profile_image_update' user.pk %}" enctype="multipart/form-data" >
{% csrf_token %}
<div class="mb-3">
<label for="{{ profile_form.profile_image.id_for_label }}" class="form-label">Profile Image</label>
{# 1. Check if an image currently exists on the bound instance #}
{% if profile_form.instance.profile_image %}
<div class="mb-2">
<small class="text-muted d-block">Current Image:</small>
{# Display Link to View Current Image #}
<a href="{{ profile_form.instance.profile_image.url }}" target="_blank" class="d-inline-block me-3 text-info fw-bold">
View/Download ({{ profile_form.instance.profile_image.name }})
</a>
{# Image Preview #}
<div class="mt-2">
<img src="{{ profile_form.instance.profile_image.url }}"
alt="Profile Image"
style="max-width: 150px; height: auto; border: 1px solid #ccc; border-radius: 4px;">
</div>
</div>
{# 2. Explicitly render the 'Clear' checkbox and the Change input #}
<div class="form-check mt-3">
{# The ClearableFileInput widget renders itself here. It provides the "Clear" checkbox and the "Change" input field. #}
{{ profile_form.profile_image }}
</div>
{% else %}
{# If no image exists, just render the file input for upload #}
<div class="form-control p-0 border-0">
{{ profile_form.profile_image }}
</div>
{% endif %}
{# Display any validation errors #}
{% for error in profile_form.profile_image.errors %}
<div class="text-danger small mt-1">{{ error }}</div>
{% endfor %}
</div>
<div class="modal-footer mt-4">
<button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}