- Add birth_date, created_at/updated_at to Employee; remove username field - Introduce EmployeeAction for tracking HR events and is_actually_active/status properties - Create BotSubscriber model (OneToOne relation) for TG/WA binding - Implement Aiogram-based Telegram bot: • request contact to bind by phone or @username • department selection keyboard from DEPARTMENTS dict • async ORM via sync_to_async, custom filters for bound & active employees - Update profile view & template: • show “Bind Telegram/WhatsApp” button only when not already bound • preview avatar on upload - Remove registration tokens in favor of contact-based auth - Clean up templates, forms and add avatar validation mixin
100 lines
3.4 KiB
HTML
100 lines
3.4 KiB
HTML
{% extends 'base.html' %}
|
||
{% load static django_bootstrap5 %}
|
||
|
||
{% block content %}
|
||
<div class="container py-5">
|
||
<div class="row g-5">
|
||
<!-- Блок с аватаром -->
|
||
<div class="col-md-4 text-center">
|
||
<div class="card shadow">
|
||
<div class="card-body">
|
||
{% if user.avatar and user.avatar.url %}
|
||
<img src="{{ user.avatar.url }}"
|
||
alt="Аватар {{ user.first_name }} {{ user.last_name }}"
|
||
class="img-fluid rounded-circle mb-3"
|
||
style="width: 200px; height: 200px; object-fit: cover;">
|
||
{% else %}
|
||
<div class="bg-light rounded-circle d-flex align-items-center justify-content-center"
|
||
style="width: 200px; height: 200px; margin: 0 auto;">
|
||
<i class="bi bi-person-circle fs-1 text-muted"></i>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Форма редактирования -->
|
||
<div class="col-md-8">
|
||
<div class="card shadow">
|
||
<div class="card-body">
|
||
<h2 class="card-title mb-4">Редактирование профиля</h2>
|
||
|
||
<form method="post" enctype="multipart/form-data" novalidate>
|
||
{% csrf_token %}
|
||
<div class="row g-3">
|
||
{% bootstrap_form form layout='horizontal' %}
|
||
</div>
|
||
<div class="d-flex gap-2 mt-4">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="bi bi-save me-2"></i>Сохранить изменения
|
||
</button>
|
||
<a href="{% url 'profile' %}" class="btn btn-outline-secondary">
|
||
Отмена
|
||
</a>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Блок привязки Telegram -->
|
||
{% comment %}
|
||
Показываем, только если в контексте есть bot_sub и Telegram ещё не привязан
|
||
{% endcomment %}
|
||
{% if bot_sub and not bot_sub.telegram_id %}
|
||
<div class="row">
|
||
<div class="col-12">
|
||
<div class="alert alert-info mt-4">
|
||
<b>Для привязки Telegram:</b>
|
||
<a href="{{ tg_link }}" target="_blank" class="btn btn-success ms-2">
|
||
Привязать Telegram
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
{% if bot_sub and not bot_sub.whatsapp_id %}
|
||
<div class="row">
|
||
<div class="col-12">
|
||
<div class="alert alert-info mt-4">
|
||
<b>Для привязки WhatsApp:</b>
|
||
<a href="{{ tg_link }}" target="_blank" class="btn btn-success ms-2">
|
||
Привязать WhatsApp
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block extra_js %}
|
||
<script>
|
||
// Предпросмотр аватара
|
||
const avatarInput = document.getElementById('avatarInput');
|
||
if (avatarInput) {
|
||
avatarInput.addEventListener('change', function(e) {
|
||
const file = e.target.files[0];
|
||
if (file) {
|
||
const preview = document.querySelector('.rounded-circle');
|
||
if (preview.tagName === 'IMG') {
|
||
preview.src = URL.createObjectURL(file);
|
||
preview.onload = () => URL.revokeObjectURL(preview.src);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
</script>
|
||
{% endblock %}
|