poprawki dla bazy pilotów web, modul zaproszen w apce mobile

This commit is contained in:
oskarn
2026-09-21 16:17:27 +02:00
parent 8c42888f52
commit d17cba2bbb
37 changed files with 2271 additions and 833 deletions
+163
View File
@@ -0,0 +1,163 @@
<!-- Modal Rezerwacji / Zapytania Ofertowego (Clean & Streamlined UX 2026) -->
<div class="modal fade" id="bookingModal" tabindex="-1" aria-labelledby="bookingModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-md" style="max-width: 580px;">
<div class="modal-content border-0 shadow-lg" style="border-radius: var(--radius-md); overflow: hidden;">
<!-- Czysty, nowoczesny nagłówek modala -->
<div class="modal-header bg-white border-bottom py-3 px-4 d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center gap-2">
<div class="rounded-circle d-flex align-items-center justify-content-center" style="width: 32px; height: 32px; background: var(--primary-light); color: var(--primary); font-size: 1.1rem;">
<i class='bx bx-calendar-check'></i>
</div>
<h5 class="modal-title fw-bold text-navy mb-0" id="bookingModalLabel" style="font-size: 1rem;">
Zapytanie o termin
</h5>
</div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
</div>
<form id="pilotBookingForm">
<div class="modal-body p-4">
<!-- Podsumowanie wybranego pilota (Dyskretny pasek) -->
<div class="d-flex align-items-center justify-content-between p-2 px-3 rounded-2 mb-3" style="background: #f8fafd; border: 1px solid var(--border-color);">
<div class="d-flex align-items-center gap-2">
<img src="<?= $basePath ?>/assets/img/pilots/oskar-avatar.jpg" alt="Pilot" class="rounded-circle border" style="width: 32px; height: 32px; object-fit: cover;">
<div>
<span class="fw-bold text-dark" id="bookingPilotNameDisplay" style="font-size: 0.88rem;">Oskar Kaczmarek</span>
<span class="text-muted small ms-1" style="font-size: 0.75rem;">• Pilot Wycieczek</span>
</div>
</div>
<span class="badge bg-success-subtle text-success border border-success-subtle py-1 px-2" style="font-size: 0.72rem;">
<i class='bx bx-check-circle me-1'></i>Dostępny dla biura
</span>
</div>
<input type="hidden" id="bookingPilotId" value="1">
<input type="hidden" id="bookingPilotName" value="Oskar Kaczmarek">
<!-- Sekcja 1: Wybór imprezy z Travel Managera -->
<div class="mb-3">
<label class="form-label fw-bold text-dark small mb-1" for="bookingTourSelect">
Impreza z Travel Managera:
</label>
<select class="form-select form-select-sm fw-semibold" id="bookingTourSelect" style="font-size: 0.84rem; padding: 0.45rem 0.75rem;">
<option value="12" data-days="9" data-dates="16.09.2027 - 24.09.2027" data-dest="🇮🇹 Włochy (Wenecja - Florencja - Rzym)" selected>Wycieczka #12: Klasyczne Włochy (16.09 – 24.09.2027) • 44 os.</option>
<option value="15" data-days="8" data-dates="05.10.2027 - 12.10.2027" data-dest="🇮🇹 Toskania i Rzym">Wycieczka #15: Magia Toskanii i Rzym (05.10 – 12.10.2027) • 38 os.</option>
<option value="21" data-days="8" data-dates="12.11.2027 - 19.11.2027" data-dest="🇪🇸 Andaluzja i Gibraltar">Wycieczka #21: Andaluzja i Gibraltar (12.11 – 19.11.2027) • 40 os.</option>
<option value="custom" data-days="7" data-dates="" data-dest="">Wpisz termin niestandardowy / inną trasę...</option>
</select>
</div>
<!-- Sekcja 2: Termin i Trasa (2 kolumny) -->
<div class="row g-2 mb-3">
<div class="col-6">
<label class="form-label fw-bold text-dark small mb-1" for="bookingDates">Termin zlecenia:</label>
<div class="input-group input-group-sm">
<span class="input-group-text bg-light text-muted"><i class='bx bx-calendar'></i></span>
<input type="text" class="form-control fw-semibold" id="bookingDates" value="16.09.2027 - 24.09.2027" required style="font-size: 0.8rem;">
</div>
</div>
<div class="col-6">
<label class="form-label fw-bold text-dark small mb-1" for="bookingDestination">Destynacja / Trasa:</label>
<div class="input-group input-group-sm">
<span class="input-group-text bg-light text-muted"><i class='bx bx-map-pin'></i></span>
<input type="text" class="form-control fw-semibold" id="bookingDestination" value="🇮🇹 Włochy (Wenecja - Florencja - Rzym)" required style="font-size: 0.8rem;">
</div>
</div>
</div>
<!-- Sekcja 3: Finanse i Świadczenia (2 kolumny) -->
<div class="row g-2 mb-3">
<div class="col-6">
<label class="form-label fw-bold text-dark small mb-1" for="bookingRate">Stawka dzienna netto:</label>
<div class="input-group input-group-sm mb-1">
<input type="number" class="form-control fw-bold text-dark" id="bookingRate" value="550" step="50" min="200" style="font-size: 0.85rem;">
<span class="input-group-text bg-light text-muted" style="font-size: 0.74rem;">PLN/dzień</span>
</div>
<div class="text-muted" style="font-size: 0.73rem;">
Szacunkowo: <strong class="text-dark" id="bookingTotalEstimate">4 950 PLN netto</strong> <span id="bookingDaysBadge">(9 dni)</span>
</div>
</div>
<div class="col-6">
<label class="form-label fw-bold text-dark small mb-1">Zapewniane świadczenia:</label>
<div class="d-flex flex-column gap-1 pt-1" style="font-size: 0.76rem;">
<label class="form-check-label d-inline-flex align-items-center gap-2 text-dark">
<input class="form-check-input mt-0" type="checkbox" id="benefitHotel" checked> Pokój 1-osobowy w hotelach
</label>
<label class="form-check-label d-inline-flex align-items-center gap-2 text-dark">
<input class="form-check-input mt-0" type="checkbox" id="benefitMeals" checked> Wyżywienie pilota
</label>
<label class="form-check-label d-inline-flex align-items-center gap-2 text-dark">
<input class="form-check-input mt-0" type="checkbox" id="benefitInsurance" checked> Ubezpieczenie KL/NNW
</label>
</div>
</div>
</div>
<!-- Sekcja 4: Wiadomość / Uwagi -->
<div class="mb-1">
<label class="form-label fw-bold text-dark small mb-1" for="bookingMessage">Wiadomość do pilota (opcjonalnie):</label>
<textarea class="form-control" id="bookingMessage" rows="2" style="font-size: 0.8rem; line-height: 1.4;" placeholder="np. godzina zbiórki na lotnisku, specyfika grupy, preferowany język przewodnictwa..."></textarea>
</div>
</div>
<div class="modal-footer bg-light px-4 py-2 border-top d-flex justify-content-between align-items-center">
<span class="text-muted d-inline-flex align-items-center gap-1" style="font-size: 0.75rem;">
<i class='bx bx-mobile-alt text-primary'></i> Pilot ma 24h na akceptację w aplikacji
</span>
<div class="d-flex align-items-center gap-2">
<button type="button" class="btn btn-outline-secondary btn-sm px-3" data-bs-dismiss="modal" style="font-size: 0.8rem;">
Anuluj
</button>
<button type="submit" class="btn btn-primary btn-sm px-4 fw-semibold" style="font-size: 0.8rem; border-radius: var(--radius-sm);">
<i class='bx bx-paper-plane me-1'></i> Wyślij zapytanie
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tourSelect = document.getElementById('bookingTourSelect');
const datesInput = document.getElementById('bookingDates');
const destInput = document.getElementById('bookingDestination');
const rateInput = document.getElementById('bookingRate');
const totalEstimate = document.getElementById('bookingTotalEstimate');
const daysBadge = document.getElementById('bookingDaysBadge');
let currentDays = 9;
function recalculateTotal() {
const rate = parseFloat(rateInput ? rateInput.value : 550) || 550;
const total = rate * currentDays;
if (totalEstimate) totalEstimate.innerText = total.toLocaleString('pl-PL') + ' PLN netto';
if (daysBadge) daysBadge.innerText = '(' + currentDays + ' ' + (currentDays === 1 ? 'dzień' : (currentDays < 5 ? 'dni' : 'dni')) + ')';
}
if (tourSelect) {
tourSelect.addEventListener('change', function() {
const selectedOpt = this.options[this.selectedIndex];
const dates = selectedOpt.getAttribute('data-dates');
const dest = selectedOpt.getAttribute('data-dest');
const days = parseInt(selectedOpt.getAttribute('data-days'), 10) || 7;
if (dates && datesInput) datesInput.value = dates;
if (dest && destInput) destInput.value = dest;
currentDays = days;
recalculateTotal();
});
}
if (rateInput) {
rateInput.addEventListener('input', recalculateTotal);
}
});
</script>