bp/app/Modules/Clients/Views/_client_modal.twig

227 lines
9.9 KiB
Twig
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{#
# Модальное окно просмотра клиента
#}
{# Скрытый модальный контейнер - будет показан при клике на строку таблицы #}
<div class="modal fade" id="viewClientModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
{# Header #}
<div class="modal-header">
<div class="d-flex align-items-center">
<div id="clientAvatar" class="bg-primary text-white rounded-circle d-flex align-items-center justify-content-center me-3" style="width: 48px; height: 48px;">
<i class="fa-solid fa-user fs-5"></i>
</div>
<div>
<h5 class="modal-title mb-0" id="clientName">—</h5>
<span id="clientStatus" class="badge bg-success">Активен</span>
</div>
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
{# Body #}
<div class="modal-body">
{# Навигация по вкладкам #}
<ul class="nav nav-tabs mb-3" id="clientTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="general-tab" data-bs-toggle="tab" data-bs-target="#general" type="button" role="tab">
<i class="fa-solid fa-user me-2"></i>Основное
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact" type="button" role="tab">
<i class="fa-solid fa-address-book me-2"></i>Контакты
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes" type="button" role="tab">
<i class="fa-solid fa-note-sticky me-2"></i>Заметки
</button>
</li>
</ul>
{# Контент вкладок #}
<div class="tab-content" id="clientTabsContent">
{# Вкладка: Основное #}
<div class="tab-pane fade show active" id="general" role="tabpanel">
<div class="row">
<div class="col-md-6 mb-3">
<label class="text-muted small mb-1">Email</label>
<div id="clientEmail" class="fw-medium">—</div>
</div>
<div class="col-md-6 mb-3">
<label class="text-muted small mb-1">Телефон</label>
<div id="clientPhone" class="fw-medium">—</div>
</div>
<div class="col-md-6 mb-3">
<label class="text-muted small mb-1">Дата создания</label>
<div id="clientCreated" class="fw-medium">—</div>
</div>
<div class="col-md-6 mb-3">
<label class="text-muted small mb-1">Последнее обновление</label>
<div id="clientUpdated" class="fw-medium">—</div>
</div>
</div>
</div>
{# Вкладка: Контакты #}
<div class="tab-pane fade" id="contact" role="tabpanel">
<div class="text-center py-4 text-muted">
<i class="fa-solid fa-envelope fa-3x mb-3"></i>
<p class="mb-0">Email: <a id="contactEmail" href="#">—</a></p>
<p>Телефон: <a id="contactPhone" href="#">—</a></p>
</div>
</div>
{# Вкладка: Заметки #}
<div class="tab-pane fade" id="notes" role="tabpanel">
<div id="clientNotes" class="p-3 bg-light rounded">
</div>
</div>
</div>
</div>
{# Footer #}
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<i class="fa-solid fa-times me-2"></i>Закрыть
</button>
<a id="clientEditLink" href="#" class="btn btn-primary">
<i class="fa-solid fa-pen me-2"></i>Редактировать
</a>
</div>
</div>
</div>
</div>
<script>
let viewClientModal = null;
document.addEventListener('DOMContentLoaded', function() {
// Инициализируем модальное окно
viewClientModal = new bootstrap.Modal(document.getElementById('viewClientModal'));
});
/**
* Открыть карточку клиента
*/
function viewClient(clientId) {
// Показываем модалку с лоадером
showClientLoader();
viewClientModal.show();
// Загружаем данные
fetch('/clients/view/' + clientId)
.then(response => response.json())
.then(data => {
if (data.success) {
renderClientData(data.data);
} else {
showClientError(data.error || 'Ошибка загрузки');
}
})
.catch(error => {
console.error('Error:', error);
showClientError('Ошибка соединения');
});
}
/**
* Показать лоадер в модальном окне
*/
function showClientLoader() {
document.getElementById('clientName').textContent = 'Загрузка...';
document.getElementById('clientStatus').className = 'badge bg-secondary';
document.getElementById('clientStatus').textContent = '—';
// Очищаем поля
document.getElementById('clientEmail').textContent = '—';
document.getElementById('clientPhone').textContent = '—';
document.getElementById('clientCreated').textContent = '—';
document.getElementById('clientUpdated').textContent = '—';
document.getElementById('clientNotes').innerHTML = '—';
document.getElementById('clientNotes').classList.remove('bg-light');
document.getElementById('contactEmail').textContent = '—';
document.getElementById('contactEmail').href = '#';
document.getElementById('contactPhone').textContent = '—';
document.getElementById('contactPhone').href = '#';
document.getElementById('clientEditLink').href = '#';
}
/**
* Показать ошибку загрузки
*/
function showClientError(message) {
document.getElementById('clientName').textContent = 'Ошибка';
document.getElementById('clientNotes').innerHTML = '<span class="text-danger">' + message + '</span>';
document.getElementById('clientNotes').classList.add('bg-light');
}
/**
* Отобразить данные клиента
*/
function renderClientData(client) {
// Имя и аватар
const initials = client.name ? client.name.split(' ').map(n => n[0]).join('').substring(0, 2).toUpperCase() : '?';
const avatarEl = document.getElementById('clientAvatar');
avatarEl.innerHTML = initials;
document.getElementById('clientName').textContent = client.name || '—';
// Статус
const statusEl = document.getElementById('clientStatus');
if (client.status === 'active') {
statusEl.className = 'badge bg-success';
statusEl.textContent = 'Активен';
} else if (client.status === 'blocked') {
statusEl.className = 'badge bg-danger';
statusEl.textContent = 'Заблокирован';
} else {
statusEl.className = 'badge bg-secondary';
statusEl.textContent = client.status || '—';
}
// Основная информация
document.getElementById('clientEmail').textContent = client.email || '—';
document.getElementById('clientPhone').textContent = client.phone || '—';
document.getElementById('clientCreated').textContent = client.created_at || '—';
document.getElementById('clientUpdated').textContent = client.updated_at || '—';
// Заметки
const notesEl = document.getElementById('clientNotes');
if (client.notes && client.notes.trim()) {
notesEl.textContent = client.notes;
notesEl.classList.add('bg-light');
} else {
notesEl.innerHTML = '<em class="text-muted">Заметок нет</em>';
notesEl.classList.add('bg-light');
}
// Контакты для клика
const contactEmail = document.getElementById('contactEmail');
if (client.email) {
contactEmail.textContent = client.email;
contactEmail.href = 'mailto:' + client.email;
} else {
contactEmail.textContent = '—';
contactEmail.href = '#';
}
const contactPhone = document.getElementById('contactPhone');
if (client.phone) {
contactPhone.textContent = client.phone;
contactPhone.href = 'tel:' + client.phone;
} else {
contactPhone.textContent = '—';
contactPhone.href = '#';
}
// Ссылка на редактирование
document.getElementById('clientEditLink').href = '/clients/edit/' + client.id;
}
</script>