160 lines
6.9 KiB
HTML
160 lines
6.9 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Реестр жильцов - МКД ЛенКом 37{% endblock %}
|
||
{% block nav_users %}active{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||
<div>
|
||
<h4 class="mb-1" style="font-size: 16px; font-weight: bold;">Реестр жильцов и доступ к ИИ</h4>
|
||
<div class="small text-muted">Управление верификацией и статусом доступа к юридическому модулю</div>
|
||
</div>
|
||
{% if current_filter %}
|
||
<div>
|
||
<span class="badge-status badge-info">
|
||
ФИЛЬТР:
|
||
{% if current_filter == 'verified' %}ВЕРИФИЦИРОВАНЫ
|
||
{% elif current_filter == 'unverified' %}ОЖИДАНИЕ
|
||
{% elif current_filter == 'ig' %}ИНИЦИАТИВНАЯ ГРУППА
|
||
{% elif current_filter == 'active_unverified' %}АКТИВНЫЕ
|
||
{% else %}ВСЕ{% endif %}
|
||
</span>
|
||
<a href="/users" class="btn-unix ms-2">Сбросить фильтр</a>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Статистика и фильтры -->
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-3">
|
||
<div class="card h-100" style="cursor: pointer;" onclick="location.href='/users'">
|
||
<div class="card-header d-flex justify-content-between">
|
||
<span>ВСЕГО</span>
|
||
<i class="bi bi-people"></i>
|
||
</div>
|
||
<div class="card-body text-center">
|
||
<div style="font-size: 22px; font-weight: bold;">{{ total_count }}</div>
|
||
<div class="small text-muted">Все пользователи</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="card h-100" style="cursor: pointer;" onclick="location.href='/users?filter=verified'">
|
||
<div class="card-header d-flex justify-content-between">
|
||
<span>ВЕРИФИЦИРОВАНЫ</span>
|
||
<i class="bi bi-patch-check"></i>
|
||
</div>
|
||
<div class="card-body text-center">
|
||
<div style="font-size: 22px; font-weight: bold;">{{ verified_count }}</div>
|
||
<div class="small text-muted">С подтверждением</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="card h-100" style="cursor: pointer;" onclick="location.href='/users?filter=ig'">
|
||
<div class="card-header d-flex justify-content-between">
|
||
<span>СОВЕТ ДОМА / ИГ</span>
|
||
<i class="bi bi-shield-check"></i>
|
||
</div>
|
||
<div class="card-body text-center">
|
||
<div style="font-size: 22px; font-weight: bold;">{{ ig_count }}</div>
|
||
<div class="small text-muted">Инициативная группа</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<div class="card h-100" style="cursor: pointer;" onclick="location.href='/users?filter=active_unverified'">
|
||
<div class="card-header d-flex justify-content-between">
|
||
<span>ГОСТИ</span>
|
||
<i class="bi bi-chat-dots"></i>
|
||
</div>
|
||
<div class="card-body text-center">
|
||
<div style="font-size: 22px; font-weight: bold;">{{ active_unverified }}</div>
|
||
<div class="small text-muted">Без верификации</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Поиск -->
|
||
<div class="card mb-3">
|
||
<div class="card-body p-2">
|
||
<form method="GET" action="/users" class="row g-2 align-items-center">
|
||
<div class="col-md-10">
|
||
<input type="text" class="form-control" name="search" placeholder="Поиск по ID, имени, квартире..." value="{{ search }}">
|
||
</div>
|
||
<div class="col-md-2">
|
||
<button type="submit" class="btn-unix btn-unix-primary w-100">Найти</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Таблица -->
|
||
<div class="card">
|
||
<div class="card-header">СПИСОК СОБСТВЕННИКОВ И ЖИТЕЛЕЙ</div>
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive">
|
||
<table class="table mb-0">
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 100px;">ID</th>
|
||
<th>Имя</th>
|
||
<th>Username</th>
|
||
<th>Квартира</th>
|
||
<th>Статус</th>
|
||
<th style="width: 110px;">Доступ Юрист</th>
|
||
<th>Рейтинг</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for user in users %}
|
||
<tr>
|
||
<td><code>{{ user.user_id }}</code></td>
|
||
<td>{{ user.first_name }} {{ user.last_name or '' }}</td>
|
||
<td>
|
||
{% if user.username %}
|
||
<a href="https://t.me/{{ user.username }}" target="_blank">@{{ user.username }}</a>
|
||
{% else %}
|
||
<span class="text-muted">—</span>
|
||
{% endif %}
|
||
</td>
|
||
<td><b>{{ user.apartment or '—' }}</b></td>
|
||
<td>
|
||
{% if user.verified %}
|
||
<span class="badge-status badge-success">Верифицирован</span>
|
||
{% else %}
|
||
<span class="badge-status badge-warning">Не подтвержден</span>
|
||
{% endif %}
|
||
{% if user.user_id in ig_user_ids %}
|
||
<span class="badge-status badge-info ms-1">ИГ</span>
|
||
{% endif %}
|
||
</td>
|
||
<td class="text-center">
|
||
<div class="form-check form-switch d-inline-block">
|
||
<input class="form-check-input" type="checkbox" role="switch"
|
||
{% if user.has_ai_access %}checked{% endif %}
|
||
onclick="toggleAI({{ user.user_id }})">
|
||
</div>
|
||
</td>
|
||
<td>{{ user.rating }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
async function toggleAI(userId) {
|
||
try {
|
||
const response = await fetch(`/api/user/${userId}/toggle_ai`, { method: 'POST' });
|
||
const result = await response.json();
|
||
if (!result.success) alert('Ошибка: ' + result.error);
|
||
} catch (e) {
|
||
alert('Ошибка связи с сервером');
|
||
}
|
||
}
|
||
</script>
|
||
{% endblock %}
|