Загрузка данных
{% extends "base.html" %}
{% block title %}{{ intern.full_name }}{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-start mb-3 flex-wrap gap-2">
<div>
<a href="{{ url_for('interns.list_interns') }}" class="btn btn-sm btn-outline-secondary mb-2">
<i class="bi bi-arrow-left"></i> К списку
</a>
<h4 class="mb-0">{{ intern.full_name }}</h4>
<small class="text-muted">
{{ intern.direction or '—' }} · Наставник: {{ intern.mentor.full_name if intern.mentor else '—' }}
</small>
</div>
<a class="btn btn-success"
href="{{ url_for('reports.export_excel', date_from=date_from, date_to=date_to) }}">
<i class="bi bi-file-earmark-excel"></i> Excel
</a>
</div>
<!-- Метрики за период -->
<div class="row g-3 mb-4">
<div class="col-6 col-md-3">
<div class="card stat-card"><div class="card-body">
<div class="text-muted small">Посещаемость (30 дн.)</div>
<div class="fs-3 fw-bold text-primary">{{ stats_period.rate }}%</div>
</div></div>
</div>
<div class="col-6 col-md-3">
<div class="card stat-card"><div class="card-body">
<div class="text-muted small">Присутствовал</div>
<div class="fs-4 fw-bold text-success">{{ stats_period.present }}</div>
</div></div>
</div>
<div class="col-6 col-md-3">
<div class="card stat-card"><div class="card-body">
<div class="text-muted small">Опоздал / Отсутствовал</div>
<div class="fs-4 fw-bold">
<span class="text-warning">{{ stats_period.late }}</span> /
<span class="text-danger">{{ stats_period.absent }}</span>
</div>
</div></div>
</div>
<div class="col-6 col-md-3">
<div class="card stat-card"><div class="card-body">
<div class="text-muted small">Всего отметок</div>
<div class="fs-4 fw-bold">{{ stats_all.total }}</div>
</div></div>
</div>
</div>
<!-- Календарь -->
<div class="card stat-card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3">
<a class="btn btn-outline-primary btn-sm"
href="?year={{ prev_year }}&month={{ prev_month }}">
<i class="bi bi-chevron-left"></i> {{ MONTH_NAMES[prev_month] }} {{ prev_year }}
</a>
<h5 class="mb-0">{{ MONTH_NAMES[month] }} {{ year }}</h5>
<a class="btn btn-outline-primary btn-sm"
href="?year={{ next_year }}&month={{ next_month }}">
{{ MONTH_NAMES[next_month] }} {{ next_year }} <i class="bi bi-chevron-right"></i>
</a>
</div>
<div class="table-responsive">
<table class="table table-bordered calendar-table mb-0">
<thead>
<tr class="text-center table-light">
<th>Пн</th><th>Вт</th><th>Ср</th><th>Чт</th><th>Пт</th>
<th class="text-muted">Сб</th><th class="text-muted">Вс</th>
</tr>
</thead>
<tbody>
{% for week in weeks %}
<tr>
{% for day in week %}
{% set is_current = (day.month == month) %}
{% set record = att_map.get(day.day) if is_current else None %}
<td class="{{ '' if is_current else 'empty' }}
{% if is_current %}calendar-cell{% endif %}
{% if is_current and day == today %}today{% endif %}"
{% if is_current %}
data-date="{{ day.isoformat() }}"
data-intern="{{ intern.id }}"
data-status="{{ record.status if record else '' }}"
{% endif %}>
{% if is_current %}
<div class="d-flex justify-content-between align-items-start">
<span class="day-number">{{ day.day }}</span>
{% if record %}
<span class="badge bg-{{ STATUS_COLORS[record.status] }} status-badge">
{{ STATUS_LABELS[record.status] }}
</span>
{% endif %}
</div>
{% if record and record.note %}
<div class="note">{{ record.note }}</div>
{% endif %}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="mt-3 d-flex flex-wrap gap-3 small text-muted">
{% for key, label in STATUS_LABELS.items() %}
<div><span class="badge bg-{{ STATUS_COLORS[key] }}"> </span> {{ label }}</div>
{% endfor %}
</div>
</div>
</div>
<!-- Модалка отметки -->
<div class="modal fade" id="markModal" tabindex="-1">
<div class="modal-dialog">
<form method="post" action="{{ url_for('attendance.mark') }}" 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">
<input type="hidden" name="intern_id" value="{{ intern.id }}">
<input type="hidden" name="date" id="markDate">
<p class="mb-3">Дата: <strong id="markDateLabel"></strong></p>
<div class="mb-3">
<label class="form-label">Статус</label>
<select name="status" id="markStatus" class="form-select" required>
<option value="present">Присутствовал</option>
<option value="absent">Отсутствовал</option>
<option value="late">Опоздал</option>
<option value="excused">Уважительная причина</option>
</select>
</div>
<div class="mb-2">
<label class="form-label">Заметка (необязательно)</label>
<input type="text" name="note" class="form-control" maxlength="255">
</div>
</div>
<div class="modal-footer justify-content-between">
<button type="submit" class="btn btn-outline-danger"
formaction="{{ url_for('attendance.clear') }}"
onclick="return confirm('Удалить отметку за этот день?')">
<i class="bi bi-trash"></i> Удалить
</button>
<div>
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
<button type="submit" class="btn btn-primary">Сохранить</button>
</div>
</div>
</form>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
const markModalEl = document.getElementById('markModal');
const markModal = new bootstrap.Modal(markModalEl);
const dateInput = document.getElementById('markDate');
const dateLabel = document.getElementById('markDateLabel');
const statusSelect = document.getElementById('markStatus');
document.querySelectorAll('.calendar-cell').forEach(cell => {
cell.addEventListener('click', () => {
const d = cell.dataset.date;
dateInput.value = d;
const [y, m, day] = d.split('-');
dateLabel.textContent = `${day}.${m}.${y}`;
const s = cell.dataset.status;
statusSelect.value = s || 'present';
markModal.show();
});
});
</script>
{% endblock %}