369 lines
19 KiB
Twig
369 lines
19 KiB
Twig
{% extends 'layouts/base.twig' %}
|
||
|
||
{% block title %}{{ title }}{% endblock %}
|
||
|
||
{% block styles %}
|
||
<style>
|
||
.profile-header {
|
||
text-align: center;
|
||
padding: 2rem 0;
|
||
}
|
||
|
||
.avatar-container {
|
||
position: relative;
|
||
width: 120px;
|
||
height: 120px;
|
||
margin: 0 auto 1rem;
|
||
}
|
||
|
||
.avatar-img {
|
||
width: 120px;
|
||
height: 120px;
|
||
border-radius: 50%;
|
||
object-fit: cover;
|
||
border: 4px solid #fff;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.avatar-placeholder {
|
||
width: 120px;
|
||
height: 120px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 48px;
|
||
color: white;
|
||
border: 4px solid #fff;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.nav-pills .nav-link {
|
||
color: #495057;
|
||
border-radius: 0.5rem;
|
||
padding: 0.75rem 1.5rem;
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.nav-pills .nav-link.active {
|
||
background-color: #0d6efd;
|
||
color: white;
|
||
}
|
||
|
||
.nav-pills .nav-link:hover:not(.active) {
|
||
background-color: #e9ecef;
|
||
}
|
||
|
||
.org-current-badge {
|
||
background-color: #198754;
|
||
color: white;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
font-size: 11px;
|
||
margin-left: 8px;
|
||
text-transform: uppercase;
|
||
}
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="row justify-content-center">
|
||
<div class="col-md-3">
|
||
<!-- Боковая панель навигации -->
|
||
<div class="card mb-4">
|
||
<div class="card-body">
|
||
<div class="profile-header">
|
||
<div class="avatar-container">
|
||
{% if user.avatar %}
|
||
<img src="{{ base_url('/uploads/avatars/' ~ user.avatar) }}" alt="Аватар" class="avatar-img">
|
||
{% else %}
|
||
<div class="avatar-placeholder">
|
||
{{ user.name|first|upper }}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
<h5 class="mb-1">{{ user.name }}</h5>
|
||
<p class="text-muted mb-0">{{ user.email }}</p>
|
||
</div>
|
||
|
||
<hr>
|
||
|
||
<nav class="nav-pills flex-column">
|
||
<a href="{{ base_url('/profile') }}" class="nav-link {{ active_tab == 'general' ? 'active' : '' }}">
|
||
<i class="fa-solid fa-user me-2"></i> Основное
|
||
</a>
|
||
<a href="{{ base_url('/profile/organizations') }}" class="nav-link {{ active_tab == 'organizations' ? 'active' : '' }}">
|
||
<i class="fa-solid fa-building me-2"></i> Мои организации
|
||
</a>
|
||
<a href="{{ base_url('/profile/security') }}" class="nav-link {{ active_tab == 'security' ? 'active' : '' }}">
|
||
<i class="fa-solid fa-shield-halved me-2"></i> Безопасность
|
||
</a>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-9">
|
||
<!-- Список организаций -->
|
||
<div class="card">
|
||
<div class="card-header bg-white d-flex justify-content-between align-items-center">
|
||
<h4 class="mb-0">Мои организации</h4>
|
||
<a href="{{ base_url('/organizations/create') }}" class="btn btn-primary btn-sm">
|
||
<i class="fa-solid fa-plus me-1"></i> Создать организацию
|
||
</a>
|
||
</div>
|
||
<div class="card-body">
|
||
{% if organizations is empty %}
|
||
<div class="text-center py-5">
|
||
<i class="fa-solid fa-building text-muted mb-3" style="font-size: 48px;"></i>
|
||
<p class="text-muted mb-3">У вас пока нет организаций</p>
|
||
<a href="{{ base_url('/organizations/create') }}" class="btn btn-primary">
|
||
<i class="fa-solid fa-plus me-1"></i> Создать первую организацию
|
||
</a>
|
||
</div>
|
||
{% else %}
|
||
<div class="table-responsive">
|
||
<table class="table table-hover">
|
||
<thead>
|
||
<tr>
|
||
<th>Организация</th>
|
||
<th>Тип</th>
|
||
<th>Ваша роль</th>
|
||
<th>Дата входа</th>
|
||
<th>Действия</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for org in organizations %}
|
||
<tr>
|
||
<td>
|
||
<div class="d-flex align-items-center">
|
||
<div class="bg-primary text-white rounded me-3 d-flex align-items-center justify-content-center" style="width:40px; height:40px;">
|
||
<i class="fa-solid fa-building"></i>
|
||
</div>
|
||
<div>
|
||
<strong>{{ org.name }}</strong>
|
||
{% if org.is_current_org %}
|
||
<span class="org-current-badge">Текущая</span>
|
||
{% endif %}
|
||
<br>
|
||
<small class="text-muted">ID: {{ org.id }}</small>
|
||
</div>
|
||
</div>
|
||
</td>
|
||
<td>
|
||
{% if org.type == 'personal' %}
|
||
<span class="badge bg-info">Личное пространство</span>
|
||
{% else %}
|
||
<span class="badge bg-success">Бизнес</span>
|
||
{% endif %}
|
||
</td>
|
||
<td>
|
||
{% if org.role == 'owner' %}
|
||
<span class="badge bg-warning text-dark">Владелец</span>
|
||
{% elseif org.role == 'admin' %}
|
||
<span class="badge bg-primary">Администратор</span>
|
||
{% elseif org.role == 'manager' %}
|
||
<span class="badge bg-secondary">Менеджер</span>
|
||
{% else %}
|
||
<span class="badge bg-light text-dark">Гость</span>
|
||
{% endif %}
|
||
</td>
|
||
<td>{{ org.joined_at ? org.joined_at|date('d.m.Y H:i') : '—' }}</td>
|
||
<td>
|
||
<div class="btn-group btn-group-sm">
|
||
{# ВЛАДЕЛЕЦ #}
|
||
{% if org.is_owner %}
|
||
{# Текущая организация #}
|
||
{% if org.is_current_org %}
|
||
<a href="{{ base_url('/organizations/' ~ org.id ~ '/dashboard') }}" class="btn btn-outline-primary" title="Дашборд">
|
||
<i class="fa-solid fa-gauge-high"></i>
|
||
</a>
|
||
<a href="{{ base_url('/organizations/' ~ org.id ~ '/edit') }}" class="btn btn-outline-secondary" title="Редактировать">
|
||
<i class="fa-solid fa-pen"></i>
|
||
</a>
|
||
<button type="button" class="btn btn-outline-danger delete-org-btn"
|
||
data-org-id="{{ org.id }}"
|
||
data-org-name="{{ org.name }}"
|
||
title="Удалить">
|
||
<i class="fa-solid fa-trash"></i>
|
||
</button>
|
||
{% else %}
|
||
{# Не текущая организация #}
|
||
<a href="{{ base_url('/organizations/switch/' ~ org.id) }}" class="btn btn-outline-success" title="Выбрать">
|
||
<i class="fa-solid fa-check"></i>
|
||
</a>
|
||
<a href="{{ base_url('/organizations/' ~ org.id ~ '/edit') }}" class="btn btn-outline-secondary" title="Редактировать">
|
||
<i class="fa-solid fa-pen"></i>
|
||
</a>
|
||
<button type="button" class="btn btn-outline-danger delete-org-btn"
|
||
data-org-id="{{ org.id }}"
|
||
data-org-name="{{ org.name }}"
|
||
title="Удалить">
|
||
<i class="fa-solid fa-trash"></i>
|
||
</button>
|
||
{% endif %}
|
||
{% elseif org.role in ['admin', 'manager'] %}
|
||
{# Админ/Менеджер #}
|
||
{% if org.is_current_org %}
|
||
<a href="{{ base_url('/organizations/' ~ org.id ~ '/dashboard') }}" class="btn btn-outline-primary" title="Дашборд">
|
||
<i class="fa-solid fa-gauge-high"></i>
|
||
</a>
|
||
<button type="button" class="btn btn-outline-danger leave-org-btn"
|
||
data-org-id="{{ org.id }}"
|
||
data-org-name="{{ org.name }}"
|
||
title="Покинуть">
|
||
<i class="fa-solid fa-person-walking-arrow-right"></i>
|
||
</button>
|
||
{% else %}
|
||
<a href="{{ base_url('/organizations/switch/' ~ org.id) }}" class="btn btn-outline-success" title="Выбрать">
|
||
<i class="fa-solid fa-check"></i>
|
||
</a>
|
||
<button type="button" class="btn btn-outline-danger leave-org-btn"
|
||
data-org-id="{{ org.id }}"
|
||
data-org-name="{{ org.name }}"
|
||
title="Покинуть">
|
||
<i class="fa-solid fa-person-walking-arrow-right"></i>
|
||
</button>
|
||
{% endif %}
|
||
{% else %}
|
||
{# Гость (не owner, не admin, не manager) #}
|
||
{% if org.is_current_org %}
|
||
<button type="button" class="btn btn-outline-danger leave-org-btn"
|
||
data-org-id="{{ org.id }}"
|
||
data-org-name="{{ org.name }}"
|
||
title="Покинуть">
|
||
<i class="fa-solid fa-person-walking-arrow-right"></i>
|
||
</button>
|
||
{% else %}
|
||
<a href="{{ base_url('/organizations/switch/' ~ org.id) }}" class="btn btn-outline-success" title="Выбрать">
|
||
<i class="fa-solid fa-check"></i>
|
||
</a>
|
||
<button type="button" class="btn btn-outline-danger leave-org-btn"
|
||
data-org-id="{{ org.id }}"
|
||
data-org-name="{{ org.name }}"
|
||
title="Покинуть">
|
||
<i class="fa-solid fa-person-walking-arrow-right"></i>
|
||
</button>
|
||
{% endif %}
|
||
{% endif %}
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Модальное окно подтверждения выхода из организации -->
|
||
<div class="modal fade" id="leaveOrgModal" tabindex="-1">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">Покинуть организацию</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p>Вы уверены, что хотите покинуть организацию <strong id="leaveOrgName"></strong>?</p>
|
||
<p class="text-muted mb-0">После выхода вы потеряете доступ к данным этой организации.</p>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<button type="button" class="btn btn-danger" id="confirmLeaveOrg">
|
||
<i class="fa-solid fa-person-walking-arrow-right me-1"></i> Покинуть
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Модальное окно подтверждения удаления организации -->
|
||
<div class="modal fade" id="deleteOrgModal" tabindex="-1">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">Удалить организацию</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="text-danger"><i class="fa-solid fa-triangle-exclamation me-2"></i>Внимание! Это действие нельзя отменить.</p>
|
||
<p>Вы уверены, что хотите удалить организацию <strong id="deleteOrgName"></strong>?</p>
|
||
<p class="text-muted mb-0">Все данные организации и её участники будут удалены.</p>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||
<a href="#" class="btn btn-danger" id="confirmDeleteOrg">
|
||
<i class="fa-solid fa-trash me-1"></i> Удалить
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const leaveOrgModal = new bootstrap.Modal(document.getElementById('leaveOrgModal'));
|
||
const deleteOrgModal = new bootstrap.Modal(document.getElementById('deleteOrgModal'));
|
||
let selectedOrgId = null;
|
||
|
||
// Обработчики кнопок выхода из организации
|
||
document.querySelectorAll('.leave-org-btn').forEach(btn => {
|
||
btn.addEventListener('click', function() {
|
||
selectedOrgId = this.dataset.orgId;
|
||
const orgName = this.dataset.orgName;
|
||
|
||
document.getElementById('leaveOrgName').textContent = orgName;
|
||
leaveOrgModal.show();
|
||
});
|
||
});
|
||
|
||
// Обработчики кнопок удаления организации
|
||
document.querySelectorAll('.delete-org-btn').forEach(btn => {
|
||
btn.addEventListener('click', function() {
|
||
const orgId = this.dataset.orgId;
|
||
const orgName = this.dataset.orgName;
|
||
|
||
document.getElementById('deleteOrgName').textContent = orgName;
|
||
document.getElementById('confirmDeleteOrg').href = '{{ base_url("/organizations/") }}' + orgId + '/delete';
|
||
deleteOrgModal.show();
|
||
});
|
||
});
|
||
|
||
// Подтверждение выхода
|
||
document.getElementById('confirmLeaveOrg').addEventListener('click', function() {
|
||
if (!selectedOrgId) return;
|
||
|
||
const formData = new FormData();
|
||
|
||
fetch('{{ base_url("/organizations/") }}' + selectedOrgId + '/leave', {
|
||
method: 'POST',
|
||
body: formData
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
leaveOrgModal.hide();
|
||
|
||
if (data.success) {
|
||
alert(data.message);
|
||
window.location.reload();
|
||
} else {
|
||
alert(data.message);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
leaveOrgModal.hide();
|
||
alert('Ошибка при выходе из организации');
|
||
});
|
||
});
|
||
});
|
||
</script>
|
||
{% endblock %}
|