add CRM module start
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
{#
|
||||
calendar.twig - Универсальный компонент календаря
|
||||
|
||||
Параметры:
|
||||
- events: Массив событий
|
||||
Пример:
|
||||
events: [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Событие 1',
|
||||
date: '2026-01-15',
|
||||
color: '#3B82F6',
|
||||
url: '/path/to/event'
|
||||
}
|
||||
]
|
||||
- currentMonth: Текущий месяц в формате YYYY-MM
|
||||
- prevMonth: URL или параметр для предыдущего месяца
|
||||
- nextMonth: URL или параметр для следующего месяца
|
||||
- eventComponent: Имя Twig компонента для рендеринга событий (опционально)
|
||||
- onEventClick: JavaScript функция при клике на событие (опционально)
|
||||
- showLegend: Показывать легенду (опционально, по умолчанию true)
|
||||
- legend: Массив для легенды (опционально)
|
||||
Пример:
|
||||
legend: [
|
||||
{ name: 'Этап 1', color: '#3B82F6' }
|
||||
]
|
||||
#}
|
||||
{# Навигация по месяцам #}
|
||||
{% if showNavigation|default(true) %}
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body d-flex justify-content-between align-items-center">
|
||||
<a href="{{ prevMonth }}" class="btn btn-outline-secondary">
|
||||
<i class="fa-solid fa-chevron-left me-1"></i>Предыдущий
|
||||
</a>
|
||||
<h5 class="mb-0">{{ monthName }}</h5>
|
||||
<a href="{{ nextMonth }}" class="btn btn-outline-secondary">
|
||||
Следующий<i class="fa-solid fa-chevron-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Календарь #}
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-0">
|
||||
<div class="calendar">
|
||||
{# Дни недели #}
|
||||
<div class="calendar-header bg-light">
|
||||
{% for day in ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'] %}
|
||||
<div class="calendar-header-cell text-center py-2 text-muted small fw-normal">
|
||||
{{ day }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{# Сетка календаря #}
|
||||
<div class="calendar-grid">
|
||||
{# Пустые ячейки до первого дня #}
|
||||
{% for i in 0..(firstDayOfWeek - 1) %}
|
||||
<div class="calendar-cell bg-light"></div>
|
||||
{% endfor %}
|
||||
|
||||
{# Дни месяца #}
|
||||
{% for day in 1..daysInMonth %}
|
||||
{% set dateStr = currentMonth ~ '-' ~ (day < 10 ? '0' ~ day : day) %}
|
||||
{% set dayEvents = eventsByDate[dateStr]|default([]) %}
|
||||
{% set isToday = dateStr == today %}
|
||||
|
||||
<div class="calendar-cell {{ isToday ? 'calendar-cell-today' : '' }}">
|
||||
<div class="calendar-day-number {{ isToday ? 'text-primary fw-bold' : '' }}">
|
||||
{{ day }}
|
||||
</div>
|
||||
|
||||
<div class="calendar-events">
|
||||
{% for event in dayEvents|slice(0, 3) %}
|
||||
{% if eventComponent is defined %}
|
||||
{{ include(eventComponent, {event: event}) }}
|
||||
{% else %}
|
||||
{{ include('@components/calendar/default_event.twig', {event: event, onEventClick: onEventClick|default('')}) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if dayEvents|length > 3 %}
|
||||
<div class="calendar-events-more text-muted small">
|
||||
+{{ dayEvents|length - 3 }} ещё
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{# Пустые ячейки после последнего дня #}
|
||||
{% set remainingCells = 7 - ((firstDayOfWeek + daysInMonth) % 7) %}
|
||||
{% if remainingCells < 7 %}
|
||||
{% for i in 1..remainingCells %}
|
||||
<div class="calendar-cell bg-light"></div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Легенда #}
|
||||
{% if showLegend|default(true) and (legend is defined or events is defined) %}
|
||||
<div class="card shadow-sm mt-4">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Легенда</h6>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
{% if legend is defined %}
|
||||
{% for item in legend %}
|
||||
<span class="badge"
|
||||
style="background-color: {{ item.color }}20; color: {{ item.color }}; border: 1px solid {{ item.color }}40;">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{# Автоматическая легенда из типов событий #}
|
||||
{% set uniqueColors = {} %}
|
||||
{% for event in events %}
|
||||
{% if event.color is defined and event.color not in uniqueColors %}
|
||||
<span class="badge"
|
||||
style="background-color: {{ event.color }}20; color: {{ event.color }}; border: 1px solid {{ event.color }}40;">
|
||||
{{ event.title }}
|
||||
</span>
|
||||
{% set uniqueColors = uniqueColors|merge([event.color]) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,29 @@
|
||||
{#
|
||||
default_event.twig - Событие по умолчанию для Календаря
|
||||
|
||||
Параметры:
|
||||
- event: Объект события
|
||||
Ожидаемые поля:
|
||||
- id: Идентификатор
|
||||
- title: Заголовок
|
||||
- date: Дата события (для сравнения с today)
|
||||
- color: Цвет для бордера
|
||||
- url: Ссылка (опционально)
|
||||
- onEventClick: JavaScript функция при клике (опционально)
|
||||
#}
|
||||
{% if event.url %}
|
||||
<a href="{{ event.url }}"
|
||||
class="calendar-event"
|
||||
style="border-left-color: {{ event.color|default('#6B7280') }}"
|
||||
{% if onEventClick %}onclick="{{ onEventClick }}({{ event.id }}); return false;"{% endif %}
|
||||
title="{{ event.title }}">
|
||||
{{ event.title|length > 15 ? event.title|slice(0, 15) ~ '...' : event.title }}
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="calendar-event"
|
||||
style="border-left-color: {{ event.color|default('#6B7280') }}"
|
||||
{% if onEventClick %}onclick="{{ onEventClick }}({{ event.id }});"{% endif %}
|
||||
title="{{ event.title }}">
|
||||
{{ event.title|length > 15 ? event.title|slice(0, 15) ~ '...' : event.title }}
|
||||
</div>
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user