bp/app/Modules/Tasks/Views/tasks/calendar.twig

171 lines
7.1 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.

{% extends 'layouts/base.twig' %}
{% block title %}{{ title }} — Бизнес.Точка{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="h3 mb-0">{{ title }}</h1>
<div class="btn-group">
<a href="{{ base_url('/tasks') }}" class="btn btn-outline-secondary">
<i class="fa-solid fa-list me-2"></i>Список
</a>
<a href="{{ base_url('/tasks/kanban') }}" class="btn btn-outline-primary">
<i class="fa-solid fa-table-columns me-2"></i>Канбан
</a>
</div>
</div>
{# Статистика #}
<div class="row g-3 mb-4">
<div class="col-md-3">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h5 class="card-title text-muted mb-0">Всего</h5>
<h2 class="mb-0">{{ stats.total }}</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h5 class="card-title text-muted mb-0">Выполнено</h5>
<h2 class="mb-0 text-success">{{ stats.completed }}</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h5 class="card-title text-muted mb-0">В ожидании</h5>
<h2 class="mb-0 text-primary">{{ stats.pending }}</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h5 class="card-title text-muted mb-0">Просрочено</h5>
<h2 class="mb-0 text-danger">{{ stats.overdue }}</h2>
</div>
</div>
</div>
</div>
<div class="card border-0 shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<div class="btn-group">
<a href="{{ base_url('/tasks/calendar?month=' ~ prevMonth) }}" class="btn btn-outline-secondary btn-sm">
<i class="fa-solid fa-chevron-left"></i>
</a>
<a href="{{ base_url('/tasks/calendar?month=' ~ nextMonth) }}" class="btn btn-outline-secondary btn-sm">
<i class="fa-solid fa-chevron-right"></i>
</a>
</div>
<h5 class="mb-0">{{ monthName }}</h5>
<a href="{{ base_url('/tasks/calendar') }}" class="btn btn-outline-secondary btn-sm">
Сегодня
</a>
</div>
<div class="card-body">
<div class="calendar-container">
{# Дни недели #}
<div class="calendar-weekdays mb-2">
{% for day in ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'] %}
<div class="calendar-weekday text-center text-muted fw-bold" style="flex: 1;">{{ day }}</div>
{% endfor %}
</div>
{# Календарная сетка #}
<div class="calendar-grid">
{% set firstDay = firstDayOfWeek %}
{% set daysInMonth = daysInMonth %}
{# Пустые ячейки до первого дня #}
{% for i in 0..(firstDay - 1) %}
<div class="calendar-day p-2 border bg-light"></div>
{% endfor %}
{# Дни месяца #}
{% for day in 1..daysInMonth %}
{% set dateStr = currentMonth ~ '-' ~ (day < 10 ? '0' ~ day : day) %}
{% set isToday = dateStr == today %}
{% set isPast = dateStr < today %}
{% set dayEvents = eventsByDate[dateStr]|default([]) %}
<div class="calendar-day p-2 border {% if isToday %}bg-primary bg-opacity-10{% endif %}">
<div class="d-flex justify-content-between align-items-start mb-1">
<span class="calendar-day-number fw-bold {% if isToday %}text-primary{% endif %}">{{ day }}</span>
{% if dayEvents|length > 0 %}
<span class="badge bg-primary" style="font-size: 0.6rem;">{{ dayEvents|length }}</span>
{% endif %}
</div>
<div class="calendar-events">
{% for event in dayEvents|slice(0, 3) %}
<a href="{{ base_url(event.url) }}"
class="calendar-event d-block text-decoration-none mb-1 px-1 py-1 rounded small"
style="font-size: 0.75rem; background-color: {{ event.column_color }}20; border-left: 3px solid {{ event.column_color }}; color: #333;"
title="{{ event.title }}">
<i class="fa-solid fa-circle me-1" style="font-size: 0.5rem; color: {{ event.column_color }};"></i>
{{ event.title|length > 15 ? event.title|slice(0, 15) ~ '...' : event.title }}
{% if event.priority == 'urgent' or event.priority == 'high' %}
<i class="fa-solid fa-flag text-danger ms-1" style="font-size: 0.5rem;"></i>
{% endif %}
</a>
{% endfor %}
{% if dayEvents|length > 3 %}
<div class="text-muted small text-center">
+{{ dayEvents|length - 3 }} ещё
</div>
{% endif %}
</div>
</div>
{% endfor %}
{# Пустые ячейки после последнего дня #}
{% set remaining = 7 - ((firstDay + daysInMonth) % 7) %}
{% if remaining < 7 %}
{% for i in 1..remaining %}
<div class="calendar-day p-2 border bg-light"></div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
<style>
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 1px;
background-color: #dee2e6;
border: 1px solid #dee2e6;
}
.calendar-day {
min-height: 100px;
background-color: white;
}
.calendar-day.bg-light {
background-color: #f8f9fa;
}
.calendar-event:hover {
background-color: {{ event.column_color }}40 !important;
}
</style>
{% endblock %}
{% block scripts %}
<script>
// Навигация по месяцам при клике на заголовок
document.querySelector('h5.mb-0').style.cursor = 'pointer';
document.querySelector('h5.mb-0').addEventListener('click', function() {
window.location.href = '{{ base_url('/tasks/calendar') }}';
});
</script>
{% endblock %}