Calendar grid: tap day opens bottom sheet with event list
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Instead of direct links on colored cells, tapping a day with events
opens a bottom sheet modal showing all events for that day with:
- Event type color dot, title, time, location
- Tap event row to navigate to details
- Polish month names in modal title ("25 marca 2026")
- Smooth slide-up animation, overlay tap to close
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
12dcb9c21c
commit
88cc65091f
@ -454,6 +454,76 @@
|
||||
|
||||
.calendar-day.empty { background: #f9fafb; }
|
||||
|
||||
.calendar-day.has-events { cursor: pointer; }
|
||||
|
||||
/* Day modal - bottom sheet */
|
||||
.day-modal-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: rgba(0,0,0,0.4);
|
||||
z-index: 9998;
|
||||
}
|
||||
.day-modal-overlay.show { display: block; }
|
||||
|
||||
.day-modal {
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
background: white;
|
||||
border-radius: 16px 16px 0 0;
|
||||
box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
|
||||
z-index: 9999;
|
||||
padding-bottom: env(safe-area-inset-bottom, 16px);
|
||||
visibility: hidden;
|
||||
transform: translateY(100%);
|
||||
transition: transform 0.25s ease-out, visibility 0s 0.25s;
|
||||
pointer-events: none;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.day-modal.show {
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
transition: transform 0.25s ease-out, visibility 0s 0s;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.day-modal-handle {
|
||||
width: 36px; height: 4px;
|
||||
background: #d1d5db; border-radius: 2px;
|
||||
margin: 10px auto 4px;
|
||||
}
|
||||
.day-modal-title {
|
||||
padding: 8px 16px 12px;
|
||||
font-size: 17px; font-weight: 600;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.day-modal-event {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 14px 16px;
|
||||
text-decoration: none;
|
||||
color: var(--text-primary);
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
.day-modal-event:active { background: #f1f5f9; }
|
||||
.day-modal-event-dot {
|
||||
width: 12px; height: 12px;
|
||||
border-radius: 3px; flex-shrink: 0;
|
||||
}
|
||||
.day-modal-event-dot.meeting { background: #3b82f6; }
|
||||
.day-modal-event-dot.networking { background: #f59e0b; }
|
||||
.day-modal-event-dot.webinar { background: #22c55e; }
|
||||
.day-modal-event-dot.other { background: #a855f7; }
|
||||
.day-modal-event-dot.external { background: #94a3b8; }
|
||||
.day-modal-event-info { flex: 1; }
|
||||
.day-modal-event-title { font-weight: 600; font-size: 15px; }
|
||||
.day-modal-event-meta { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }
|
||||
.day-modal-event-arrow { color: #94a3b8; font-size: 18px; }
|
||||
|
||||
.event-card {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@ -559,18 +629,22 @@
|
||||
{% for day in week %}
|
||||
{% set is_weekend = loop.index > 5 %}
|
||||
{% set day_events = events_by_day.get(day, []) if day != 0 else [] %}
|
||||
<div class="calendar-day {% if day == 0 %}empty{% endif %}{% if day == today.day and month == today.month and year == today.year %} today{% endif %}{% if is_weekend and day != 0 %} weekend{% endif %}{% if day_events %} has-events has-{{ day_events|length }}-event{% endif %}">
|
||||
<div class="calendar-day {% if day == 0 %}empty{% endif %}{% if day == today.day and month == today.month and year == today.year %} today{% endif %}{% if is_weekend and day != 0 %} weekend{% endif %}{% if day_events %} has-events has-{{ day_events|length }}-event{% endif %}"
|
||||
{% if day_events %}onclick="openDayModal({{ day }}, {{ month }}, {{ year }})"{% endif %}
|
||||
data-day="{{ day }}">
|
||||
{% if day != 0 %}
|
||||
<div class="day-number">{{ day }}</div>
|
||||
{% if day_events %}
|
||||
<div class="calendar-events-wrap">
|
||||
{% for event in day_events %}
|
||||
<a href="{{ url_for('calendar.calendar_event', event_id=event.id) }}"
|
||||
class="calendar-event {{ 'external' if event.is_external else event.event_type }}"
|
||||
data-external="{{ 'true' if event.is_external else 'false' }}"
|
||||
title="{{ event.title }}{% if event.time_start %} - {{ event.time_start.strftime('%H:%M') }}{% endif %}{% if event.is_external %} ({{ event.external_source }}){% endif %}">
|
||||
{% if event.time_start %}{{ event.time_start.strftime('%H:%M') }} {% endif %}{{ event.title[:18] }}{% if event.title|length > 18 %}...{% endif %}
|
||||
</a>
|
||||
<div class="calendar-event {{ 'external' if event.is_external else event.event_type }}"
|
||||
data-event-id="{{ event.id }}"
|
||||
data-event-title="{{ event.title }}"
|
||||
data-event-time="{% if event.time_start %}{{ event.time_start.strftime('%H:%M') }}{% if event.time_end %}-{{ event.time_end.strftime('%H:%M') }}{% endif %}{% endif %}"
|
||||
data-event-type="{{ 'Zewnętrzne' if event.is_external else ({'meeting':'Spotkanie','networking':'Networking','webinar':'Webinar','conference':'Konferencja','workshop':'Warsztaty'}.get(event.event_type, event.event_type)) }}"
|
||||
data-event-location="{{ event.location or '' }}"
|
||||
data-event-url="{{ url_for('calendar.calendar_event', event_id=event.id) }}">
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -581,6 +655,14 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Day events modal (bottom sheet) -->
|
||||
<div class="day-modal-overlay" id="dayModalOverlay" onclick="closeDayModal()"></div>
|
||||
<div class="day-modal" id="dayModal">
|
||||
<div class="day-modal-handle"></div>
|
||||
<div class="day-modal-title" id="dayModalTitle"></div>
|
||||
<div id="dayModalEvents"></div>
|
||||
</div>
|
||||
|
||||
<!-- Legenda typów wydarzeń -->
|
||||
<div style="margin-top: var(--spacing-lg); display: flex; gap: var(--spacing-lg); flex-wrap: wrap; font-size: var(--font-size-sm); color: var(--text-secondary);">
|
||||
<span><span class="badge-type meeting">Spotkanie</span></span>
|
||||
@ -765,6 +847,54 @@ async function toggleListRSVP(btn) {
|
||||
applyFilter();
|
||||
})();
|
||||
|
||||
var plMonths = ['','stycznia','lutego','marca','kwietnia','maja','czerwca','lipca','sierpnia','września','października','listopada','grudnia'];
|
||||
|
||||
function openDayModal(day, month, year) {
|
||||
var modal = document.getElementById('dayModal');
|
||||
var overlay = document.getElementById('dayModalOverlay');
|
||||
var title = document.getElementById('dayModalTitle');
|
||||
var eventsDiv = document.getElementById('dayModalEvents');
|
||||
|
||||
title.textContent = day + ' ' + plMonths[month] + ' ' + year;
|
||||
|
||||
// Find events for this day from DOM
|
||||
var dayCell = document.querySelector('.calendar-day[data-day="' + day + '"].has-events');
|
||||
if (!dayCell) return;
|
||||
|
||||
var events = dayCell.querySelectorAll('.calendar-event');
|
||||
var html = '';
|
||||
events.forEach(function(ev) {
|
||||
var eventType = '';
|
||||
['meeting','networking','webinar','other','external'].forEach(function(t) {
|
||||
if (ev.classList.contains(t)) eventType = t;
|
||||
});
|
||||
var time = ev.dataset.eventTime || '';
|
||||
var loc = ev.dataset.eventLocation || '';
|
||||
var meta = [];
|
||||
if (ev.dataset.eventType) meta.push(ev.dataset.eventType);
|
||||
if (time) meta.push(time);
|
||||
if (loc) meta.push(loc);
|
||||
|
||||
html += '<a href="' + ev.dataset.eventUrl + '" class="day-modal-event">' +
|
||||
'<div class="day-modal-event-dot ' + eventType + '"></div>' +
|
||||
'<div class="day-modal-event-info">' +
|
||||
'<div class="day-modal-event-title">' + ev.dataset.eventTitle + '</div>' +
|
||||
(meta.length ? '<div class="day-modal-event-meta">' + meta.join(' · ') + '</div>' : '') +
|
||||
'</div>' +
|
||||
'<span class="day-modal-event-arrow">›</span>' +
|
||||
'</a>';
|
||||
});
|
||||
|
||||
eventsDiv.innerHTML = html;
|
||||
overlay.classList.add('show');
|
||||
modal.classList.add('show');
|
||||
}
|
||||
|
||||
function closeDayModal() {
|
||||
document.getElementById('dayModal').classList.remove('show');
|
||||
document.getElementById('dayModalOverlay').classList.remove('show');
|
||||
}
|
||||
|
||||
function showSubscribeModal() {
|
||||
document.getElementById('subscribeModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user