add superadmin dashboard. subscriptions
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
{% extends 'superadmin/layout.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="sa-header">
|
||||
<h1>Организации</h1>
|
||||
</div>
|
||||
|
||||
{% for alert in get_alerts() %}
|
||||
<div class="alert alert-{{ alert.type }}">{{ alert.message }}</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="sa-card">
|
||||
<div class="sa-card-body">
|
||||
<div id="organizations-table">
|
||||
{# Динамическая таблица #}
|
||||
{{ tableHtml|raw }}
|
||||
{# CSRF токен для AJAX запросов #}
|
||||
{{ csrf_field()|raw }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/modules/data-table.css">
|
||||
<script src="/assets/js/modules/DataTable.js"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Инициализация DataTable
|
||||
document.querySelectorAll('.data-table').forEach(function(container) {
|
||||
const id = container.id;
|
||||
const url = container.dataset.url;
|
||||
const perPage = parseInt(container.dataset.perPage) || 10;
|
||||
|
||||
if (window.dataTables && window.dataTables[id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const table = new DataTable(id, {
|
||||
url: url,
|
||||
perPage: perPage
|
||||
});
|
||||
|
||||
window.dataTables = window.dataTables || {};
|
||||
window.dataTables[id] = table;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,220 @@
|
||||
{% extends 'superadmin/layout.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="sa-header">
|
||||
<h1>Организация: {{ organization.name }}</h1>
|
||||
<a href="{{ base_url('/superadmin/organizations') }}" class="btn btn-primary">← Назад</a>
|
||||
</div>
|
||||
|
||||
{% for alert in get_alerts() %}
|
||||
<div class="alert alert-{{ alert.type }}">{{ alert.message }}</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="grid-2">
|
||||
<div class="sa-card">
|
||||
<div class="sa-card-header">
|
||||
<h2>Информация об организации</h2>
|
||||
</div>
|
||||
<div class="sa-card-body">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th style="width: 150px;">ID</th>
|
||||
<td>{{ organization.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Название</th>
|
||||
<td>{{ organization.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Тип</th>
|
||||
<td>
|
||||
{% if organization.type == 'business' %}
|
||||
<span class="badge badge-info">Бизнес</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">Личное пространство</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Тариф</th>
|
||||
<td>
|
||||
{% if currentSubscription %}
|
||||
{% set plan = plans|filter(p => p.id == currentSubscription.plan_id)|first %}
|
||||
{% if plan %}
|
||||
<span class="badge badge-primary">{{ plan.name }}</span>
|
||||
{% else %}
|
||||
<span class="badge badge-secondary">ID: {{ currentSubscription.plan_id }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="badge badge-secondary">Не назначен</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Статус подписки</th>
|
||||
<td>
|
||||
{% if currentSubscription %}
|
||||
{% if currentSubscription.status == 'active' %}
|
||||
<span class="badge badge-success">Активна</span>
|
||||
{% elseif currentSubscription.status == 'expired' %}
|
||||
<span class="badge badge-danger">Истёкшая</span>
|
||||
{% elseif currentSubscription.status == 'trial' %}
|
||||
<span class="badge badge-info">Пробный период</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">{{ currentSubscription.status }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="badge badge-secondary">Нет подписки</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Срок действия</th>
|
||||
<td>
|
||||
{% if currentSubscription and currentSubscription.expires_at %}
|
||||
до {{ currentSubscription.expires_at|date('d.m.Y H:i') }}
|
||||
{% else %}
|
||||
Не ограничен
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Статус организации</th>
|
||||
<td>
|
||||
{% if organization.status == 'active' %}
|
||||
<span class="badge badge-success">Активна</span>
|
||||
{% elseif organization.status == 'blocked' %}
|
||||
<span class="badge badge-danger">Заблокирована</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">{{ organization.status|default('Не определён') }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Создана</th>
|
||||
<td>{{ organization.created_at|date('d.m.Y H:i') }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div style="margin-top: 20px; display: flex; gap: 10px; flex-wrap: wrap;">
|
||||
{% if organization.status == 'active' %}
|
||||
<a href="{{ base_url('/superadmin/organizations/block/' ~ organization.id) }}" class="btn btn-warning" onclick="return confirm('Заблокировать организацию?')">🚫 Заблокировать</a>
|
||||
{% else %}
|
||||
<a href="{{ base_url('/superadmin/organizations/unblock/' ~ organization.id) }}" class="btn btn-success" onclick="return confirm('Разблокировать организацию?')">✅ Разблокировать</a>
|
||||
{% endif %}
|
||||
<a href="{{ base_url('/superadmin/organizations/delete/' ~ organization.id) }}" class="btn btn-danger" onclick="return confirm('Удалить организацию? Это действие нельзя отменить!')">🗑️ Удалить</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sa-card">
|
||||
<div class="sa-card-header">
|
||||
<h2>Управление тарифом</h2>
|
||||
</div>
|
||||
<div class="sa-card-body">
|
||||
<form action="{{ base_url('/superadmin/organizations/set-plan/' ~ organization.id) }}" method="post">
|
||||
{{ csrf_field()|raw }}
|
||||
|
||||
<div class="form-group">
|
||||
<label for="plan_id">Выберите тариф</label>
|
||||
<select name="plan_id" id="plan_id" class="form-control" required>
|
||||
<option value="">-- Выберите тариф --</option>
|
||||
{% for plan in plans %}
|
||||
<option value="{{ plan.id }}" {{ currentSubscription and currentSubscription.plan_id == plan.id ? 'selected' : '' }}>
|
||||
{{ plan.name }} - {{ plan.price }} {{ plan.currency }}/{{ plan.billing_period }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="duration_days">Срок действия (дней)</label>
|
||||
<input type="number" name="duration_days" id="duration_days" class="form-control"
|
||||
value="30" min="0" max="365000" placeholder="30">
|
||||
<small class="text-muted">Оставьте пустым или 0 для неограниченного срока</small>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Назначить тариф</button>
|
||||
</form>
|
||||
|
||||
<hr style="margin: 20px 0; border: none; border-top: 1px solid #eee;">
|
||||
|
||||
<h4>Статистика</h4>
|
||||
<div style="text-align: center; padding: 20px;">
|
||||
<div style="font-size: 48px; font-weight: bold; color: #3498db;">{{ users|length }}</div>
|
||||
<div style="color: #7f8c8d;">Участников</div>
|
||||
</div>
|
||||
<hr style="margin: 20px 0; border: none; border-top: 1px solid #eee;">
|
||||
<div style="display: flex; justify-content: space-around; text-align: center;">
|
||||
<div>
|
||||
<div style="font-size: 24px; font-weight: bold; color: #27ae60;">
|
||||
{% set owner_count = users|filter(u => u.role == 'owner')|length %}
|
||||
{{ owner_count }}
|
||||
</div>
|
||||
<div style="color: #7f8c8d; font-size: 12px;">Владельцы</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 24px; font-weight: bold; color: #f39c12;">
|
||||
{% set admin_count = users|filter(u => u.role == 'admin')|length %}
|
||||
{{ admin_count }}
|
||||
</div>
|
||||
<div style="color: #7f8c8d; font-size: 12px;">Админы</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 24px; font-weight: bold; color: #9b59b6;">
|
||||
{% set manager_count = users|filter(u => u.role == 'manager')|length %}
|
||||
{{ manager_count }}
|
||||
</div>
|
||||
<div style="color: #7f8c8d; font-size: 12px;">Менеджеры</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sa-card" style="margin-top: 20px;">
|
||||
<div class="sa-card-header">
|
||||
<h2>Участники организации</h2>
|
||||
</div>
|
||||
<div class="sa-card-body">
|
||||
{% if users is empty %}
|
||||
<p style="color: #7f8c8d; text-align: center; padding: 40px;">Участников пока нет</p>
|
||||
{% else %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Пользователь</th>
|
||||
<th>Email</th>
|
||||
<th>Роль</th>
|
||||
<th>Статус</th>
|
||||
<th>Дата добавления</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{ user.name|default('—') }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
<span class="badge {{ user.role == 'owner' ? 'badge-danger' : (user.role == 'admin' ? 'badge-warning' : 'badge-info') }}">
|
||||
{{ user.role }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if user.status == 'active' %}
|
||||
<span class="badge badge-success">Активен</span>
|
||||
{% elseif user.status == 'blocked' %}
|
||||
<span class="badge badge-danger">Заблокирован</span>
|
||||
{% else %}
|
||||
<span class="badge badge-warning">{{ user.status }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ user.created_at|date('d.m.Y') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user