Compare commits
9 Commits
2d749776fc
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 142c40b00b | |||
| 8b92aac1db | |||
| e6ba6152a6 | |||
| 7905529880 | |||
| de562d164c | |||
| 2c1f1b2a20 | |||
| af946d338a | |||
| caaf914865 | |||
| 83d3499164 |
@@ -0,0 +1,496 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-invoice.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid flex-grow-1 container-p-y">
|
||||
|
||||
<!-- Header & Form Buttons -->
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-4 gap-3">
|
||||
<div class="d-flex flex-column justify-content-center">
|
||||
<h4 class="mb-1 text-body"><i class="bx bx-repeat me-2 text-primary"></i>Nowy Szablon Faktury Cyklicznej</h4>
|
||||
<p class="text-muted mb-0">Skonfiguruj reguły automatycznego generowania i wystawiania dokumentów abonamentowych</p>
|
||||
</div>
|
||||
<div class="d-flex align-content-center flex-wrap gap-2">
|
||||
<a href="app-invoice-recurring-list.php" class="btn btn-label-secondary">Anuluj</a>
|
||||
<button type="submit" form="recurringForm" class="btn btn-primary"><i class="bx bx-save me-1"></i> Zapisz szablon cyklu</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="recurringForm" onsubmit="return false">
|
||||
|
||||
<!-- Top Section: Status & Cycle Rules -->
|
||||
<div class="row mb-4">
|
||||
|
||||
<!-- Card 1: Harmonogram i Reguły Cyklu -->
|
||||
<div class="col-lg-6 mb-4 mb-lg-0">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom py-3 d-flex justify-content-between align-items-center bg-label-primary">
|
||||
<h6 class="card-title m-0 text-primary"><i class="bx bx-calendar-repeat me-2"></i>Harmonogram i Reguły Cyklu</h6>
|
||||
|
||||
<!-- Global Master Switch ON/OFF -->
|
||||
<div class="d-flex align-items-center gap-2 me-4">
|
||||
<span class="fw-bold small text-body">Status cyklu:</span>
|
||||
<div class="form-check form-switch m-0 d-flex align-items-center">
|
||||
<input class="form-check-input mt-0 me-3" type="checkbox" id="masterStatusToggle" checked style="width: 2.5em; height: 1.3em; cursor: pointer;">
|
||||
<label class="form-check-label mb-0 ms-1" for="masterStatusToggle" style="cursor: pointer;">
|
||||
<span class="badge bg-label-success" id="statusLabelText">AKTYWNY (ON)</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-3">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Nazwa własna cyklu / Szablonu</label>
|
||||
<input type="text" class="form-control" placeholder="np. Abonament IT - Usługi Chmurowe (ABC Logistics)" value="Abonament IT i Wsparcie Techniczne">
|
||||
<small class="text-muted">Nazwa widoczna w rejestrze cykli dla ułatwienia identyfikacji.</small>
|
||||
</div>
|
||||
|
||||
<!-- Przebudowany Konfigurator Cyklu -->
|
||||
<div class="card shadow-none border bg-lighter mb-3">
|
||||
<div class="card-body p-3">
|
||||
<h6 class="fw-bold mb-3 text-primary"><i class="bx bx-time-five me-1"></i>Konfiguracja Powtarzania</h6>
|
||||
|
||||
<!-- Data rozpoczęcia & Cykl rozliczeń -->
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Data rozpoczęcia</label>
|
||||
<input type="text" class="form-control date-picker" id="startDateInput" value="2026-08-01">
|
||||
<small class="text-muted">Dzień wystawienia pierwszej faktury.</small>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Cykl rozliczeń</label>
|
||||
<select class="form-select" id="cycleUnitSelect">
|
||||
<option value="miesiac" selected>Miesiąc</option>
|
||||
<option value="rok">Rok</option>
|
||||
<option value="dzien">Dzień</option>
|
||||
</select>
|
||||
<small class="text-muted">Jednostka czasu dla powtarzania.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Interwał & Obowiązuje do -->
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Interwał (Co ile cykli)</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">Co</span>
|
||||
<input type="number" class="form-control" value="1" min="1" id="intervalInput">
|
||||
<span class="input-group-text" id="intervalUnitText">miesiąc</span>
|
||||
</div>
|
||||
<small class="text-muted">np. "1" = co miesiąc, "3" = kwartalnie, "12" = co rok.</small>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Obowiązuje do</label>
|
||||
<input type="text" class="form-control date-picker" id="endDateInput" placeholder="RRRR-MM-DD (Bezterminowo)">
|
||||
<small class="text-muted">Data, po której system automatycznie wyłączy cykl.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Informacyjna ramka dynamicznego opisu -->
|
||||
<div class="alert alert-primary mb-0 p-2 d-flex align-items-center" role="alert">
|
||||
<i class="bx bx-info-circle fs-4 me-2"></i>
|
||||
<span class="small" id="summaryDescription">
|
||||
Faktura będzie generowana <strong>co 1 miesiąc</strong>, rozpoczynając od dnia <strong>01.08.2026 r.</strong> bezterminowo.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-3">
|
||||
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="emailAutoSend" checked>
|
||||
<label class="form-check-label fw-bold" for="emailAutoSend">Automatyczna wysyłka e-mail do kontrahenta</label>
|
||||
<div class="text-muted small">Wyślij e-mail z podpiętą fakturą w PDF zaraz po automatycznym wystawieniu (zgodnie z <b>globalnym szablonem e-mail</b> zdefiniowanym w Ustawieniach Systemowych).</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 2: Kontrahent - Nabywca i Odbiorca -->
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom py-3 d-flex justify-content-between align-items-center">
|
||||
<h6 class="card-title m-0"><i class="bx bx-user-check me-2 text-primary"></i>Kontrahent (Nabywca i Odbiorca)</h6>
|
||||
</div>
|
||||
<div class="card-body pt-3">
|
||||
|
||||
<!-- Nabywca -->
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Nabywca (Główny kontrahent / Płatnik)</label>
|
||||
<div class="card shadow-none border bg-lighter">
|
||||
<div class="card-body p-3 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h6 class="mb-1 text-primary fw-bold">ABC Logistics Sp. z o.o.</h6>
|
||||
<p class="mb-0 small text-muted">NIP: PL 865 223 11 90 • ul. Warszawska 45, 00-001 Warszawa</p>
|
||||
<p class="mb-0 small text-muted">E-mail do faktur: ksiegowosc@abclogistics.pl</p>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm"><i class="bx bx-refresh me-1"></i> Zmień</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Switches for Recipient and Extra -->
|
||||
<div class="d-flex flex-column gap-2 mb-3">
|
||||
<label class="form-check form-switch m-0">
|
||||
<input class="form-check-input" type="checkbox" id="recipientToggle">
|
||||
<span class="form-check-label fw-bold">Wskaż innego Odbiorcę / Miejsce dostawy</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Odbiorca Container (Domyślnie ukryty) -->
|
||||
<div class="card shadow-none border mb-3 bg-white d-none" id="recipientBox">
|
||||
<div class="card-header py-2 bg-label-secondary d-flex justify-content-between align-items-center">
|
||||
<span class="small fw-bold"><i class="bx bx-buildings me-1"></i>Dane Odbiorcy (np. Szkoła, Oddział, Filia)</span>
|
||||
<button type="button" class="btn btn-xs btn-outline-secondary">Wybierz z listy</button>
|
||||
</div>
|
||||
<div class="card-body p-3">
|
||||
<div class="mb-2">
|
||||
<label class="form-label small text-muted mb-1">Nazwa Odbiorcy</label>
|
||||
<input type="text" class="form-control form-control-sm" value="ABC Logistics - Oddział Magazynowy Stalowa Wola">
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-8">
|
||||
<label class="form-label small text-muted mb-1">Adres Odbiorcy</label>
|
||||
<input type="text" class="form-control form-control-sm" value="ul. Przemysłowa 12, 37-450 Stalowa Wola">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label class="form-label small text-muted mb-1">NIP Odbiorcy (opcja)</label>
|
||||
<input type="text" class="form-control form-control-sm" placeholder="Opcjonalny NIP">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-uppercase fw-bold text-muted">Miejsce wystawienia</label>
|
||||
<input type="text" class="form-control" value="Stalowa Wola">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-uppercase fw-bold text-muted">Osoba wystawiająca</label>
|
||||
<input type="text" class="form-control" value="Bartłomiej Banaczyk">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kontakt i powiadomienia -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title text-primary mb-3">Kontakt i powiadomienia</h6>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-uppercase text-muted fw-bold">Email kontaktowy</label>
|
||||
<input type="email" class="form-control" value="ksiegowosc@abclogistics.pl">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-uppercase text-muted fw-bold">Wysyłka faktur e-mail</label>
|
||||
<div class="form-check form-switch mb-2">
|
||||
<input class="form-check-input" type="checkbox" id="autoEmail" checked>
|
||||
<label class="form-check-label" for="autoEmail">Automatyczna wysyłka wg profilu:</label>
|
||||
</div>
|
||||
<select class="form-select form-select-sm">
|
||||
<option value="1">Profil: Standardowy (Termin 30 dni)</option>
|
||||
<option value="2">Profil: Szybki (Termin 3 dni)</option>
|
||||
<option value="3">Profil: Tylko przypomnienia po terminie</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label small text-uppercase text-muted fw-bold">Numer SMS</label>
|
||||
<input type="text" class="form-control" placeholder="+48 ...">
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label class="form-label small text-uppercase text-muted fw-bold">Powiadomienia SMS</label>
|
||||
<select class="form-select">
|
||||
<option value="" selected>Wybierz opcję</option>
|
||||
<option value="1">Wyślij powiadomienie SMS po wygenerowaniu</option>
|
||||
<option value="0">Brak powiadomień</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ostatni dokument -->
|
||||
<div class="card mb-4 mb-lg-0">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title text-primary mb-3">Ostatni dokument</h6>
|
||||
<p class="text-muted mb-0 small">Brak dokumentów</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Section 2: Document Settings & Variables -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom py-3">
|
||||
<h6 class="card-title m-0"><i class="bx bx-slider-alt me-2 text-primary"></i>Ustawienia Dokumentów Generowanych</h6>
|
||||
</div>
|
||||
<div class="card-body pt-3">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">Rodzaj dokumentu</label>
|
||||
<select class="form-select border-primary text-primary fw-bold">
|
||||
<option value="faktura" selected>Faktura VAT</option>
|
||||
<option value="proforma">Proforma</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">Waluta & Język</label>
|
||||
<div class="input-group">
|
||||
<select class="form-select">
|
||||
<option value="PLN" selected>PLN (zł)</option>
|
||||
<option value="EUR">EUR (€)</option>
|
||||
<option value="USD">USD ($)</option>
|
||||
</select>
|
||||
<select class="form-select">
|
||||
<option value="PL" selected>PL</option>
|
||||
<option value="EN">EN</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">Forma płatności</label>
|
||||
<select class="form-select">
|
||||
<option value="przelew" selected>Przelew bankowy</option>
|
||||
<option value="gotowka">Gotówka</option>
|
||||
<option value="split">Split Payment (MPP)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">Termin płatności</label>
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" value="14">
|
||||
<span class="input-group-text">dni</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mt-1">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold">Konto bankowe</label>
|
||||
<select class="form-select">
|
||||
<option value="1">Main PLN: 89 1050 ... 4491</option>
|
||||
<option value="2">EUR IBAN: PL 12 1050 ... 9901</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Data sprzedaży</label>
|
||||
<select class="form-select">
|
||||
<option value="issue_date" selected>Zgodna z datą wystawienia</option>
|
||||
<option value="last_day_prev_month">Ostatni dzień poprzedniego miesiąca</option>
|
||||
<option value="first_day_curr_month">Pierwszy dzień bieżącego miesiąca</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<label class="form-label fw-bold">Komentarz / Uwagi na fakturze (dla klienta)</label>
|
||||
<input type="text" class="form-control" value="Opłata abonamentowa za miesiąc {MIESIAC} {ROK}. Dziękujemy za współpracę!">
|
||||
<div class="mt-1">
|
||||
<span class="badge bg-label-secondary me-1" style="cursor:pointer;">+ {MIESIAC}</span>
|
||||
<span class="badge bg-label-secondary me-1" style="cursor:pointer;">+ {ROK}</span>
|
||||
<span class="badge bg-label-secondary me-1" style="cursor:pointer;">+ {POPRZEDNI_MIESIAC}</span>
|
||||
<span class="badge bg-label-secondary" style="cursor:pointer;">+ {KWARTAL}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section 3: Items Configurator with Dynamic Tags -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-label-primary py-2 d-flex justify-content-between align-items-center">
|
||||
<span class="fw-bold text-primary"><i class="bx bx-list-plus me-2"></i>Pozycje na fakturze cyklicznej</span>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="text-muted small me-2 text-nowrap">Licz od:</label>
|
||||
<select class="form-select form-select-sm">
|
||||
<option value="netto" selected>Cen netto</option>
|
||||
<option value="brutto">Cen brutto</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary btn-sm"><i class="bx bx-plus me-1"></i> Dodaj pozycję</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered m-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 35%;">Nazwa towaru / usługi (oraz zmienne okresu)</th>
|
||||
<th style="width: 10%;">Ilość</th>
|
||||
<th style="width: 10%;">J.m.</th>
|
||||
<th style="width: 12%;">Cena netto</th>
|
||||
<th style="width: 10%;">VAT</th>
|
||||
<th style="width: 13%;">Wartość brutto</th>
|
||||
<th style="width: 5%;" class="text-center">Usuń</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Item row 1 -->
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" class="form-control mb-1 fw-medium" value="Abonament za opiekę serwerową IT - okres {MIESIAC} {ROK}">
|
||||
</td>
|
||||
<td><input type="number" class="form-control" value="1"></td>
|
||||
<td>
|
||||
<select class="form-select">
|
||||
<option value="usluga" selected>usł.</option>
|
||||
<option value="szt">szt.</option>
|
||||
<option value="msc">m-c</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><input type="text" class="form-control" value="1 200,00"></td>
|
||||
<td>
|
||||
<select class="form-select">
|
||||
<option value="23" selected>23%</option>
|
||||
<option value="8">8%</option>
|
||||
<option value="0">0%</option>
|
||||
<option value="zw">zw.</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><input type="text" class="form-control fw-bold" value="1 476,00" readonly></td>
|
||||
<td class="text-center align-middle">
|
||||
<button type="button" class="btn btn-icon btn-sm btn-label-danger"><i class="bx bx-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Item row 2 -->
|
||||
<tr>
|
||||
<td>
|
||||
<input type="text" class="form-control mb-1 fw-medium" value="Hosting Chmurowy Magico Cloud (Kwartalnie)">
|
||||
</td>
|
||||
<td><input type="number" class="form-control" value="1"></td>
|
||||
<td>
|
||||
<select class="form-select">
|
||||
<option value="usluga" selected>usł.</option>
|
||||
<option value="szt">szt.</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><input type="text" class="form-control" value="300,00"></td>
|
||||
<td>
|
||||
<select class="form-select">
|
||||
<option value="23" selected>23%</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><input type="text" class="form-control fw-bold" value="369,00" readonly></td>
|
||||
<td class="text-center align-middle">
|
||||
<button type="button" class="btn btn-icon btn-sm btn-label-danger"><i class="bx bx-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Dynamic Tag Guide below table -->
|
||||
<div class="p-3 border-top bg-lighter">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<small class="text-muted fw-bold">Dostępne zmienne dla pozycji (kliknij aby skopiować):</small>
|
||||
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{MIESIAC}</span>
|
||||
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{ROK}</span>
|
||||
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{POPRZEDNI_MIESIAC}</span>
|
||||
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{KWARTAL}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-lighter d-flex justify-content-end py-3 border-top">
|
||||
<div class="d-flex flex-column align-items-end me-3">
|
||||
<span class="text-muted small">Suma netto: <strong>1 500,00 PLN</strong></span>
|
||||
<span class="text-muted small">Suma VAT (23%): <strong>345,00 PLN</strong></span>
|
||||
<h5 class="mb-0 text-primary mt-1">Razem brutto: <strong>1 845,00 PLN</strong></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Bottom Bar -->
|
||||
<div class="d-flex justify-content-end gap-2 mb-4">
|
||||
<a href="app-invoice-recurring-list.php" class="btn btn-label-secondary">Anuluj</a>
|
||||
<button type="submit" class="btn btn-primary"><i class="bx bx-save me-1"></i> Zapisz szablon cyklu</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const toggle = document.getElementById('masterStatusToggle');
|
||||
const label = document.getElementById('statusLabelText');
|
||||
const unitSelect = document.getElementById('cycleUnitSelect');
|
||||
const intervalText = document.getElementById('intervalUnitText');
|
||||
|
||||
if (toggle && label) {
|
||||
toggle.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
label.textContent = 'AKTYWNY (ON)';
|
||||
label.className = 'badge bg-label-success';
|
||||
} else {
|
||||
label.textContent = 'WYŁĄCZONY (OFF)';
|
||||
label.className = 'badge bg-label-danger';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const intervalInput = document.getElementById('intervalInput');
|
||||
const summaryDesc = document.getElementById('summaryDescription');
|
||||
const startDateInput = document.getElementById('startDateInput');
|
||||
const endDateInput = document.getElementById('endDateInput');
|
||||
|
||||
function updateUnitsAndSummary() {
|
||||
if (!unitSelect || !intervalInput || !intervalText) return;
|
||||
const val = unitSelect.value;
|
||||
const num = parseInt(intervalInput.value) || 1;
|
||||
|
||||
let unitLabel = '';
|
||||
let unitGenitive = '';
|
||||
|
||||
if (val === 'miesiac') {
|
||||
if (num === 1) unitLabel = 'miesiąc';
|
||||
else if (num >= 2 && num <= 4) unitLabel = 'miesiące';
|
||||
else unitLabel = 'miesięcy';
|
||||
unitGenitive = unitLabel;
|
||||
} else if (val === 'rok') {
|
||||
if (num === 1) unitLabel = 'rok';
|
||||
else if (num >= 2 && num <= 4) unitLabel = 'lata';
|
||||
else unitLabel = 'lat';
|
||||
unitGenitive = unitLabel;
|
||||
} else if (val === 'dzien') {
|
||||
if (num === 1) unitLabel = 'dzień';
|
||||
else unitLabel = 'dni';
|
||||
unitGenitive = unitLabel;
|
||||
}
|
||||
|
||||
intervalText.textContent = unitLabel;
|
||||
|
||||
if (summaryDesc) {
|
||||
const startDate = startDateInput ? startDateInput.value || 'dzisiaj' : 'dzisiaj';
|
||||
const endDate = endDateInput && endDateInput.value ? ` do dnia <strong>${endDateInput.value}</strong>` : ' bezterminowo';
|
||||
summaryDesc.innerHTML = `Faktura będzie generowana <strong>co ${num} ${unitGenitive}</strong>, rozpoczynając od dnia <strong>${startDate}</strong>${endDate}.`;
|
||||
}
|
||||
}
|
||||
|
||||
if (unitSelect) unitSelect.addEventListener('change', updateUnitsAndSummary);
|
||||
if (intervalInput) intervalInput.addEventListener('input', updateUnitsAndSummary);
|
||||
if (startDateInput) startDateInput.addEventListener('change', updateUnitsAndSummary);
|
||||
if (endDateInput) endDateInput.addEventListener('change', updateUnitsAndSummary);
|
||||
|
||||
const recipientToggle = document.getElementById('recipientToggle');
|
||||
const recipientBox = document.getElementById('recipientBox');
|
||||
|
||||
if (recipientToggle && recipientBox) {
|
||||
recipientToggle.addEventListener('change', function () {
|
||||
if (this.checked) {
|
||||
recipientBox.classList.remove('d-none');
|
||||
} else {
|
||||
recipientBox.classList.add('d-none');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,510 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-invoice.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid flex-grow-1 container-p-y">
|
||||
|
||||
<h4 class="py-3 mb-4">
|
||||
<span class="text-muted fw-light">Sprzedaż /</span> Faktury cykliczne
|
||||
</h4>
|
||||
|
||||
<!-- Summary KPI Cards -->
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Aktywne cykle</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2">18</h4>
|
||||
<span class="text-success small fw-medium">nowe w tym roku</span>
|
||||
</div>
|
||||
<small class="text-muted">Szablonów zlecających wysyłkę</small>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-primary">
|
||||
<i class="bx bx-repeat bx-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Szacowany MRR</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2">42 850,00 zł</h4>
|
||||
</div>
|
||||
<small class="text-muted">Przychód powtarzalny / m-c</small>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-success">
|
||||
<i class="bx bx-trending-up bx-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Szacowany ARR</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2">514 200,00 zł</h4>
|
||||
</div>
|
||||
<small class="text-muted">Przychód powtarzalny / rok</small>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-info">
|
||||
<i class="bx bx-calendar-event bx-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<span class="text-heading">Wyłączone (Nieaktywne)</span>
|
||||
<div class="d-flex align-items-center my-1">
|
||||
<h4 class="mb-0 me-2">3</h4>
|
||||
</div>
|
||||
<small class="text-muted">Cykle obecnie wyłączone</small>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-warning">
|
||||
<i class="bx bx-pause-circle bx-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Grid: Table Left (9 cols), Filter Panel Right (3 cols) -->
|
||||
<div class="row">
|
||||
|
||||
<!-- Table Column -->
|
||||
<div class="col-lg-9" id="invoice-list-col">
|
||||
<div class="card">
|
||||
<div
|
||||
class="card-header border-bottom d-flex justify-content-between align-items-center flex-wrap gap-2">
|
||||
|
||||
<div class="me-2">
|
||||
<div class="input-group input-group-merge">
|
||||
<span class="input-group-text" id="basic-addon-search31"><i class="bx bx-search"></i></span>
|
||||
<input type="text" class="form-control" placeholder="Wpisz aby wyszukać cykl..."
|
||||
aria-label="Search..." aria-describedby="basic-addon-search31">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn btn-label-secondary p-2" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<i class="bx bx-cog"></i>
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li>
|
||||
<h6 class="dropdown-header">Widoczność kolumn</h6>
|
||||
</li>
|
||||
<li>
|
||||
<div class="dropdown-item">
|
||||
<div class="form-check"><input class="form-check-input" type="checkbox" checked>
|
||||
<label class="form-check-label">Nazwa cyklu</label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="dropdown-item">
|
||||
<div class="form-check"><input class="form-check-input" type="checkbox" checked>
|
||||
<label class="form-check-label">Kontrahent</label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="dropdown-item">
|
||||
<div class="form-check"><input class="form-check-input" type="checkbox" checked>
|
||||
<label class="form-check-label">Wartość brutto</label>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-label-secondary d-flex align-items-center gap-2"
|
||||
id="filter-toggle-btn">
|
||||
<i class="bx bx-filter-alt"></i> Filtry
|
||||
</button>
|
||||
|
||||
<select class="form-select" style="width: 80px;">
|
||||
<option value="40">40</option>
|
||||
<option value="60">60</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
|
||||
<a href="app-invoice-recurring-add.php" class="btn btn-primary">
|
||||
<i class="bx bx-plus me-1"></i> <span class="d-none d-sm-inline-block">Utwórz fakturę
|
||||
cykliczną</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive text-nowrap" style="min-height: 400px;">
|
||||
<table class="table table-hover table-striped">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 50px;">#</th>
|
||||
<th>Nazwa cyklu i rodzaj</th>
|
||||
<th>Nabywca / Odbiorca</th>
|
||||
<th>Wartość netto</th>
|
||||
<th>Wartość brutto</th>
|
||||
<th>Harmonogram</th>
|
||||
<th>Najbliższa emisja</th>
|
||||
<th>Status</th>
|
||||
<th class="text-center">Akcje</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-border-bottom-0">
|
||||
<!-- Item 1 -->
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="app-invoice-recurring-add.php" class="fw-bold text-body">Abonament
|
||||
Serwis IT i Hosting</a>
|
||||
<small class="text-muted">Faktura VAT</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-semibold">ABC Logistics Sp. z o.o.</span>
|
||||
<small class="text-muted">NIP: 865-223-11-90</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-heading">1 500,00 PLN</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-bold text-heading">1 845,00 PLN</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-label-info"><i class="bx bx-calendar me-1"></i> Co 1 miesiąc</span>
|
||||
<br><small class="text-muted">Bezterminowo</small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-medium text-primary">01.08.2026</span>
|
||||
<br><small class="text-muted">Ostatnio: 01.07.2026</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="form-check form-switch m-0" data-bs-toggle="tooltip" title="Włącz / Wyłącz cykl">
|
||||
<input class="form-check-input" type="checkbox" checked style="cursor: pointer;">
|
||||
<span class="badge bg-label-success ms-1"><i class="bx bx-power-off me-1"></i> ON</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="d-flex justify-content-center align-items-center gap-1">
|
||||
<a href="app-invoice-recurring-add.php"
|
||||
class="btn btn-icon btn-sm text-secondary" data-bs-toggle="tooltip"
|
||||
title="Edytuj szablon">
|
||||
<i class="bx bx-edit-alt fs-5"></i>
|
||||
</a>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow"
|
||||
data-bs-toggle="dropdown">
|
||||
<i class="bx bx-dots-vertical-rounded fs-5"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end">
|
||||
<a class="dropdown-item" href="javascript:void(0);"><i
|
||||
class="bx bx-power-off me-1"></i> Wyłącz cykl</a>
|
||||
<a class="dropdown-item" href="app-invoice-list.php"><i
|
||||
class="bx bx-history me-1"></i> Historia wygenerowanych
|
||||
faktur</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="javascript:void(0);"><i
|
||||
class="bx bx-archive-in me-1"></i> Archiwizuj cykl</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Item 2 -->
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="app-invoice-recurring-add.php" class="fw-bold text-body">Obsługa
|
||||
Księgowa i Kadrowa</a>
|
||||
<small class="text-muted">Faktura VAT</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-semibold">Bud-Spec Budownictwo S.A.</span>
|
||||
<small class="text-muted">NIP: 111-222-33-44 • Odbiorca: Oddział Warszawa</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-heading">3 500,00 PLN</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-bold text-heading">4 305,00 PLN</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-label-info"><i class="bx bx-calendar me-1"></i> Co 1 miesiąc</span>
|
||||
<br><small class="text-muted">Do: 31.12.2026</small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-medium text-primary">10.08.2026</span>
|
||||
<br><small class="text-muted">Ostatnio: 10.07.2026</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="form-check form-switch m-0" data-bs-toggle="tooltip" title="Włącz / Wyłącz cykl">
|
||||
<input class="form-check-input" type="checkbox" checked style="cursor: pointer;">
|
||||
<span class="badge bg-label-success ms-1"><i class="bx bx-power-off me-1"></i> ON</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="d-flex justify-content-center align-items-center gap-1">
|
||||
<a href="app-invoice-recurring-add.php"
|
||||
class="btn btn-icon btn-sm text-secondary" data-bs-toggle="tooltip"
|
||||
title="Edytuj szablon">
|
||||
<i class="bx bx-edit-alt fs-5"></i>
|
||||
</a>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow"
|
||||
data-bs-toggle="dropdown">
|
||||
<i class="bx bx-dots-vertical-rounded fs-5"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end">
|
||||
<a class="dropdown-item" href="javascript:void(0);"><i
|
||||
class="bx bx-power-off me-1"></i> Wyłącz cykl</a>
|
||||
<a class="dropdown-item" href="app-invoice-list.php"><i
|
||||
class="bx bx-history me-1"></i> Historia wygenerowanych
|
||||
faktur</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="javascript:void(0);"><i
|
||||
class="bx bx-archive-in me-1"></i> Archiwizuj cykl</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Item 3 -->
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<a href="app-invoice-recurring-add.php" class="fw-bold text-body">Licencja
|
||||
Oprogramowania Magico ERP</a>
|
||||
<small class="text-muted">Proforma</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-semibold">Klinika Stomatologiczna DentaMed</span>
|
||||
<small class="text-muted">NIP: 554-190-88-21</small>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="text-heading">12 000,00 PLN</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-bold text-heading">14 760,00 PLN</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-label-warning"><i class="bx bx-calendar me-1"></i> Co 1 rok</span>
|
||||
<br><small class="text-muted">Bezterminowo</small>
|
||||
</td>
|
||||
<td>
|
||||
<span class="fw-medium text-muted">15.01.2027</span>
|
||||
<br><small class="text-muted">Ostatnio: 15.01.2026</small>
|
||||
</td>
|
||||
<td>
|
||||
<div class="form-check form-switch m-0" data-bs-toggle="tooltip" title="Włącz / Wyłącz cykl">
|
||||
<input class="form-check-input" type="checkbox" style="cursor: pointer;">
|
||||
<span class="badge bg-label-danger ms-1"><i class="bx bx-power-off me-1"></i> OFF</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="d-flex justify-content-center align-items-center gap-1">
|
||||
<a href="app-invoice-recurring-add.php"
|
||||
class="btn btn-icon btn-sm text-secondary" data-bs-toggle="tooltip"
|
||||
title="Edytuj szablon">
|
||||
<i class="bx bx-edit-alt fs-5"></i>
|
||||
</a>
|
||||
<div class="dropdown">
|
||||
<button type="button" class="btn p-0 dropdown-toggle hide-arrow"
|
||||
data-bs-toggle="dropdown">
|
||||
<i class="bx bx-dots-vertical-rounded fs-5"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end">
|
||||
<a class="dropdown-item text-success" href="javascript:void(0);"><i
|
||||
class="bx bx-power-off me-1"></i> Włącz cykl</a>
|
||||
<a class="dropdown-item" href="app-invoice-list.php"><i
|
||||
class="bx bx-history me-1"></i> Historia wygenerowanych
|
||||
faktur</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="javascript:void(0);"><i
|
||||
class="bx bx-archive-in me-1"></i> Archiwizuj cykl</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card-footer d-flex justify-content-between align-items-center">
|
||||
<span class="text-muted small">Wyświetlono 1-3 z 21 szablonów</span>
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination pagination-sm mb-0">
|
||||
<li class="page-item disabled"><a class="page-link" href="#"><i
|
||||
class="bx bx-chevron-left"></i></a></li>
|
||||
<li class="page-item active"><a class="page-link" href="#">1</a></li>
|
||||
<li class="page-item"><a class="page-link" href="#">2</a></li>
|
||||
<li class="page-item"><a class="page-link" href="#">3</a></li>
|
||||
<li class="page-item"><a class="page-link" href="#"><i class="bx bx-chevron-right"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Column Right (Expandable / Collapsible) -->
|
||||
<div class="col-lg-3" id="invoice-filters-col">
|
||||
<div class="card sticky-top" style="top: 20px;">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center py-3">
|
||||
<h5 class="card-title mb-0">Filtry cykli</h5>
|
||||
<button type="button" class="btn-close text-reset small" aria-label="Close" id="close-filter-btn"
|
||||
style="display:none;"></button>
|
||||
</div>
|
||||
<div class="card-body pt-4">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Kontrahent (Nabywca)</label>
|
||||
<select class="select2 form-select" data-allow-clear="true">
|
||||
<option value="">Wszyscy kontrahenci</option>
|
||||
<option value="1">ABC Logistics Sp. z o.o.</option>
|
||||
<option value="2">Bud-Spec Budownictwo S.A.</option>
|
||||
<option value="3">Klinika Stomatologiczna DentaMed</option>
|
||||
<option value="4">MCreo Mateusz Łada</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Status cyklu</label>
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<div class="form-check">
|
||||
<input name="status-radio" class="form-check-input" type="radio" value="" id="statusAll"
|
||||
checked>
|
||||
<label class="form-check-label" for="statusAll"> Wszystkie </label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input name="status-radio" class="form-check-input" type="radio" value=""
|
||||
id="statusActive">
|
||||
<label class="form-check-label" for="statusActive"> tylko Aktywne </label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input name="status-radio" class="form-check-input" type="radio" value=""
|
||||
id="statusPaused">
|
||||
<label class="form-check-label" for="statusPaused"> Wstrzymane (Pauza) </label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Częstotliwość wystawiania</label>
|
||||
<select class="form-select">
|
||||
<option value="">Wszystkie częstotliwości</option>
|
||||
<option value="1M">Co 1 miesiąc</option>
|
||||
<option value="3M">Co 3 miesiące (Kwartalnie)</option>
|
||||
<option value="12M">Co 1 rok (Rocznie)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Zakres dat najbliższej emisji</label>
|
||||
<input type="text" class="form-control flatpickr-range"
|
||||
placeholder="RRRR-MM-DD do RRRR-MM-DD" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Tryb automatyzacji</label>
|
||||
<select class="form-select">
|
||||
<option value="">Wszystkie tryby</option>
|
||||
<option value="auto">Automatyczne wystawianie i wysyłka</option>
|
||||
<option value="draft">Tworzenie jako Szkic</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end gap-2 pt-2">
|
||||
<button class="btn btn-outline-secondary btn-sm">Wyczyść filtry</button>
|
||||
<button class="btn btn-primary btn-sm">Filtruj</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Obsługa przełącznika panelu filtrów po prawej stronie
|
||||
const filterBtn = document.getElementById('filter-toggle-btn');
|
||||
const filtersCol = document.getElementById('invoice-filters-col');
|
||||
const listCol = document.getElementById('invoice-list-col');
|
||||
|
||||
if (filterBtn && filtersCol && listCol) {
|
||||
filterBtn.addEventListener('click', function () {
|
||||
filtersCol.classList.toggle('d-none');
|
||||
|
||||
if (filtersCol.classList.contains('d-none')) {
|
||||
listCol.classList.remove('col-lg-9');
|
||||
listCol.classList.add('col-lg-12');
|
||||
} else {
|
||||
listCol.classList.remove('col-lg-12');
|
||||
listCol.classList.add('col-lg-9');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Flatpickr range jeśli obecny
|
||||
if (typeof flatpickr !== 'undefined') {
|
||||
document.querySelectorAll('.flatpickr-range').forEach(function (element) {
|
||||
flatpickr(element, {
|
||||
mode: 'range',
|
||||
dateFormat: 'Y-m-d'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-invoice.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid flex-grow-1 container-p-y">
|
||||
<h4 class="py-3 mb-4">
|
||||
<span class="text-muted fw-light">Sprzedaż / Ustawienia /</span> Powiadomienia e-mail (Faktury cykliczne)
|
||||
</h4>
|
||||
|
||||
<div class="row">
|
||||
<!-- Lewa Kolumna: Konfigurator -->
|
||||
<div class="col-lg-5 mb-4 mb-lg-0">
|
||||
|
||||
<!-- Wybór Profilu -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">Wybierz Profil Powiadomień</h5>
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn btn-sm btn-label-danger"><i class="bx bx-trash me-1"></i> Usuń profil</button>
|
||||
<button class="btn btn-sm btn-primary"><i class="bx bx-plus me-1"></i> Nowy profil</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Aktualny profil</label>
|
||||
<select class="form-select select2" id="profile-select">
|
||||
<option value="1">Standardowy (Termin 30 dni)</option>
|
||||
<option value="2">Szybki (Termin 3 dni)</option>
|
||||
<option value="3">Tylko przypomnienia po terminie</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="alert alert-info d-flex mb-0" role="alert">
|
||||
<span class="badge badge-center rounded-pill bg-info border-label-info p-3 me-2"><i class="bx bx-info-circle fs-6"></i></span>
|
||||
<div class="d-flex flex-column ps-1">
|
||||
<h6 class="alert-heading d-flex align-items-center mb-1">Czym są profile wysyłki?</h6>
|
||||
<span class="mb-0 fs-6">Profile pozwalają na zgrupowanie reguł wysyłki e-mail. Możesz stworzyć profil "Długi termin" z wieloma przypomnieniami i przypisać go do wybranych faktur cyklicznych, a dla innych użyć profilu "Szybki" tylko z jednym mailem po terminie.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Harmonogram wysyłki -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">Harmonogram wysyłki</h5>
|
||||
<button class="btn btn-sm btn-label-primary" data-bs-toggle="modal" data-bs-target="#modalRule"><i class="bx bx-plus me-1"></i> Dodaj regułę</button>
|
||||
</div>
|
||||
<div class="card-body pt-4">
|
||||
<ul class="list-group list-group-flush mb-0">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center px-0 pt-0 pb-3" style="cursor: pointer;">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge bg-label-success p-2"><i class="bx bx-check"></i></span>
|
||||
<div>
|
||||
<h6 class="mb-0">Wystawienie faktury</h6>
|
||||
<small class="text-muted">Natychmiast (W dniu dokumentu)</small>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-icon btn-sm text-secondary" data-bs-toggle="modal" data-bs-target="#modalRule"><i class="bx bx-edit"></i></button>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center px-3 py-3 rounded border border-primary bg-label-primary mb-2 mt-2" style="cursor: pointer;">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge bg-primary p-2 text-white"><i class="bx bx-time"></i></span>
|
||||
<div>
|
||||
<h6 class="mb-0 text-primary fw-bold">Przypomnienie przed terminem</h6>
|
||||
<small class="text-primary">14 dni przed upływem terminu</small>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-icon btn-sm text-primary" data-bs-toggle="modal" data-bs-target="#modalRule"><i class="bx bx-edit"></i></button>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center px-0 py-3" style="cursor: pointer;">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge bg-label-warning p-2"><i class="bx bx-error"></i></span>
|
||||
<div>
|
||||
<h6 class="mb-0">Przypomnienie przed terminem</h6>
|
||||
<small class="text-muted">3 dni przed upływem terminu</small>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-icon btn-sm text-secondary" data-bs-toggle="modal" data-bs-target="#modalRule"><i class="bx bx-edit"></i></button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Treść wiadomości -->
|
||||
<div class="card border border-primary">
|
||||
<div class="card-header border-bottom bg-label-primary">
|
||||
<h5 class="card-title mb-0 text-primary">Treść wiadomości <span class="fw-normal fs-6 d-block mt-1">Edytujesz: <strong>Przypomnienie przed terminem (14 dni)</strong></span></h5>
|
||||
</div>
|
||||
<div class="card-body pt-4">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Temat e-maila</label>
|
||||
<input type="text" id="email-subject" class="form-control" value="Przypomnienie: Zbliża się termin płatności faktury {NUMER_FAKTURY}">
|
||||
<div class="form-text">Zmienne: {NUMER_FAKTURY}, {NAZWA_KLIENTA}</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Nagłówek powitania</label>
|
||||
<input type="text" id="email-heading" class="form-control" value="Cześć {IMIE_NABYWCY},">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Główna treść wiadomości</label>
|
||||
<textarea id="email-body" class="form-control" rows="4">Przypominamy, że za 14 dni upływa termin płatności za Twoją ostatnią fakturę. W załączniku przesyłamy plik PDF z dokumentem. Będziemy wdzięczni za terminową wpłatę.</textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-0">
|
||||
<label class="form-label">Podpis / Stopka</label>
|
||||
<input type="text" id="email-footer" class="form-control" value="Pozdrawiamy serdecznie,\nZespół TwojaFirma">
|
||||
</div>
|
||||
|
||||
<!-- Zmienne do kliknięcia -->
|
||||
<div class="mt-4 pt-3 border-top">
|
||||
<small class="text-muted text-uppercase fw-bold d-block mb-2">Dostępne zmienne (kliknij, aby wstawić)</small>
|
||||
<div class="d-flex flex-wrap gap-2" id="variable-badges">
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{NUMER_FAKTURY}">+ {NUMER_FAKTURY}</span>
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{NAZWA_KLIENTA}">+ {NAZWA_KLIENTA}</span>
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{IMIE_NABYWCY}">+ {IMIE_NABYWCY}</span>
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{KWOTA_BRUTTO}">+ {KWOTA_BRUTTO}</span>
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{TERMIN_PLATNOSCI}">+ {TERMIN_PLATNOSCI}</span>
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{POZOSTALO_DNI_DO_TERMINU}">+ {POZOSTALO_DNI_DO_TERMINU}</span>
|
||||
<span class="badge bg-label-primary" style="cursor: pointer;" data-var="{LINK_DO_OPLATY}">+ {LINK_DO_OPLATY}</span>
|
||||
</div>
|
||||
<div class="form-text mt-2">Tag zostanie wstawiony w polu, w którym ostatnio pisałeś.</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Prawa Kolumna: Podgląd Live -->
|
||||
<div class="col-lg-7">
|
||||
<div class="card h-100" style="background-color: #f8f9fa;">
|
||||
<div class="card-header border-bottom bg-white d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<small class="text-muted d-block mb-1">Podgląd na żywo</small>
|
||||
<h6 class="mb-0">Temat: <span id="preview-subject" class="fw-normal">Przypomnienie: Zbliża się termin płatności faktury FV/2026/08/12</span></h6>
|
||||
</div>
|
||||
<span class="badge bg-label-secondary">Wersja Desktop</span>
|
||||
</div>
|
||||
|
||||
<!-- Email Canvas -->
|
||||
<div class="card-body d-flex justify-content-center align-items-start pt-5 pb-5 overflow-auto" style="min-height: 600px;">
|
||||
|
||||
<div class="email-container bg-white rounded shadow-sm" style="width: 100%; max-width: 600px; overflow: hidden; font-family: Arial, sans-serif;">
|
||||
|
||||
<!-- Email Header Logo (Image based on screenshot) -->
|
||||
<div class="text-center pt-5 pb-3 bg-white">
|
||||
<div style="background-color: #8ed689; width: 120px; height: 75px; border-radius: 8px; margin: 0 auto; position: relative; display: flex; align-items: center; justify-content: center;">
|
||||
<!-- Simple illustration placeholder for the green money/face -->
|
||||
<div style="width: 10px; height: 10px; background-color: #333; border-radius: 50%; position: absolute; left: 35px;"></div>
|
||||
<div style="width: 10px; height: 10px; background-color: #333; border-radius: 50%; position: absolute; right: 35px;"></div>
|
||||
<div style="width: 16px; height: 8px; border-bottom: 3px solid #333; border-radius: 50%; position: absolute; top: 40px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email Content Container -->
|
||||
<div class="p-4 p-md-5 pt-0 bg-white">
|
||||
|
||||
<h3 id="preview-heading" class="fw-light mb-4" style="color: #2b5c8f; font-size: 26px;">Szanowni Państwo</h3>
|
||||
|
||||
<p id="preview-body" style="color: #4a5568; line-height: 1.6; margin-bottom: 40px; font-size: 15px;">
|
||||
Dziękujemy za skorzystanie z naszych usług.<br><br>
|
||||
Uprzejmie informujemy, że w dniu 22 lipca 2026 została wystawiona dla Państwa Faktura nr FV/31/07/2026 na kwotę 160,00 zł. Plik PDF znajduje się w załączniku.
|
||||
</p>
|
||||
|
||||
<!-- ZABLOKOWANY MODUŁ Z FAKTURĄ (LOCKED SUMMARY TABLE) -->
|
||||
<div class="invoice-summary border-0 rounded bg-lighter p-4 mb-4 text-center" style="border-left: 4px solid #2b5c8f !important;">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2 text-start">
|
||||
<span class="text-muted">Typ faktury:</span>
|
||||
<span class="text-dark">Faktura</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2 text-start">
|
||||
<span class="text-muted">Termin płatności:</span>
|
||||
<span class="text-dark fw-medium">29 lipca 2026</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 text-start">
|
||||
<span class="text-muted">Kwota do zapłaty:</span>
|
||||
<span class="fw-bold text-dark">160,00 PLN</span>
|
||||
</div>
|
||||
|
||||
<a href="#" class="btn btn-primary w-100 mt-2" style="background-color: #2b5c8f; border-color: #2b5c8f; padding: 10px 20px; text-decoration: none; display: inline-block;">
|
||||
Zobacz dokument i opłać online
|
||||
</a>
|
||||
</div>
|
||||
<!-- END LOCKED MODULE -->
|
||||
|
||||
<p id="preview-footer" style="color: #777; margin-top: 30px; font-size: 0.95em;">
|
||||
Pozdrawiamy serdecznie,<br>Zespół TwojaFirma
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Email Footer App Info -->
|
||||
<div class="bg-light text-center py-4 px-3 border-top">
|
||||
<small class="text-muted d-block mb-1" style="font-size: 11px;">Wiadomość wygenerowana automatycznie. Prosimy nie odpowiadać.</small>
|
||||
<small class="text-muted d-block mb-3" style="font-size: 11px;">Wiadomość wysłana przez firmę TwojaFirma, z siedzibą w Stalowej Woli, al. Jana Pawła II 60F,<br>NIP: 865 256 70 62, REGON: 368428365.</small>
|
||||
|
||||
<small class="text-dark fw-bold d-block" style="font-size: 12px;">Magico Software</small>
|
||||
<small class="text-muted d-block" style="font-size: 11px;">support@magico.pl | +48 665 408 808</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Modal: Dodaj Regułę -->
|
||||
<div class="modal fade" id="modalRule" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalRuleTitle">Konfiguracja reguły wysyłki</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col mb-3">
|
||||
<label class="form-label">Wydarzenie początkowe (Wyzwalacz)</label>
|
||||
<select class="form-select">
|
||||
<option value="issue">Wystawienie nowej faktury</option>
|
||||
<option value="due">Termin płatności faktury</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col mb-0">
|
||||
<label class="form-label">Kiedy wysłać e-mail?</label>
|
||||
<select class="form-select">
|
||||
<option value="0">Dokładnie w tym dniu</option>
|
||||
<option value="before">Przed wydarzeniem</option>
|
||||
<option value="after">Po wydarzeniu</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col mb-0">
|
||||
<label class="form-label">Ile dni?</label>
|
||||
<input type="number" class="form-control" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-label-secondary" data-bs-dismiss="modal">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Zapisz regułę</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Inputs
|
||||
const inputSubject = document.getElementById('email-subject');
|
||||
const inputHeading = document.getElementById('email-heading');
|
||||
const inputBody = document.getElementById('email-body');
|
||||
const inputFooter = document.getElementById('email-footer');
|
||||
|
||||
// Previews
|
||||
const previewSubject = document.getElementById('preview-subject');
|
||||
const previewHeading = document.getElementById('preview-heading');
|
||||
const previewBody = document.getElementById('preview-body');
|
||||
const previewFooter = document.getElementById('preview-footer');
|
||||
|
||||
// Mocks for variables
|
||||
const mockVars = {
|
||||
'{NUMER_FAKTURY}': 'FV/2026/08/12',
|
||||
'{NAZWA_KLIENTA}': 'ABC Logistics',
|
||||
'{IMIE_NABYWCY}': 'Jan',
|
||||
'{KWOTA_BRUTTO}': '1 845,00 PLN',
|
||||
'{TERMIN_PLATNOSCI}': '15.08.2026',
|
||||
'{POZOSTALO_DNI_DO_TERMINU}': '14',
|
||||
'{LINK_DO_OPLATY}': 'https://magico.pl/pay/123'
|
||||
};
|
||||
|
||||
function replaceVariables(text) {
|
||||
let result = text;
|
||||
for (const [key, value] of Object.entries(mockVars)) {
|
||||
result = result.replace(new RegExp(key, 'g'), value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function updatePreview() {
|
||||
previewSubject.innerText = replaceVariables(inputSubject.value);
|
||||
previewHeading.innerText = replaceVariables(inputHeading.value);
|
||||
|
||||
// Preserve line breaks in body
|
||||
const bodyText = replaceVariables(inputBody.value);
|
||||
previewBody.innerHTML = bodyText.replace(/\n/g, '<br>');
|
||||
|
||||
// Preserve line breaks in footer
|
||||
const footerText = replaceVariables(inputFooter.value);
|
||||
previewFooter.innerHTML = footerText.replace(/\n/g, '<br>');
|
||||
}
|
||||
|
||||
// Event Listeners
|
||||
inputSubject.addEventListener('input', updatePreview);
|
||||
inputHeading.addEventListener('input', updatePreview);
|
||||
inputBody.addEventListener('input', updatePreview);
|
||||
inputFooter.addEventListener('input', updatePreview);
|
||||
|
||||
// Initial render
|
||||
updatePreview();
|
||||
|
||||
// Variable insertion logic
|
||||
let lastFocusedInput = inputBody; // default
|
||||
const allInputs = [inputSubject, inputHeading, inputBody, inputFooter];
|
||||
|
||||
allInputs.forEach(input => {
|
||||
input.addEventListener('focus', function() {
|
||||
lastFocusedInput = this;
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('#variable-badges .badge').forEach(badge => {
|
||||
badge.addEventListener('click', function() {
|
||||
const varText = this.getAttribute('data-var');
|
||||
if (lastFocusedInput) {
|
||||
const start = lastFocusedInput.selectionStart;
|
||||
const end = lastFocusedInput.selectionEnd;
|
||||
const text = lastFocusedInput.value;
|
||||
lastFocusedInput.value = text.substring(0, start) + varText + text.substring(end);
|
||||
lastFocusedInput.selectionStart = lastFocusedInput.selectionEnd = start + varText.length;
|
||||
lastFocusedInput.focus();
|
||||
updatePreview();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
@@ -108,7 +108,7 @@ $currentPage = basename($_SERVER['PHP_SELF']);
|
||||
</li>
|
||||
|
||||
<li
|
||||
class="menu-item <?php echo ($currentPage == 'app-invoice-list.php' || $currentPage == 'app-purchase-list.php' || $currentPage == 'app-purchase-calendar.php' || $currentPage == 'app-products.php') ? 'active open' : ''; ?>">
|
||||
class="menu-item <?php echo ($currentPage == 'app-invoice-list.php' || $currentPage == 'app-invoice-recurring-list.php' || $currentPage == 'app-invoice-recurring-add.php' || $currentPage == 'app-purchase-list.php' || $currentPage == 'app-purchase-calendar.php' || $currentPage == 'app-products.php') ? 'active open' : ''; ?>">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon tf-icons bx bx-cart-alt"></i>
|
||||
<div class="text-truncate" data-i18n="Faktury i sprzedaż">Faktury i sprzedaż</div>
|
||||
@@ -119,6 +119,11 @@ $currentPage = basename($_SERVER['PHP_SELF']);
|
||||
<div class="text-truncate" data-i18n="Faktury sprzedaż">Faktury sprzedaż</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-invoice-recurring-list.php' || $currentPage == 'app-invoice-recurring-add.php') ? 'active' : ''; ?>">
|
||||
<a href="app-invoice-recurring-list.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Faktury cykliczne">Faktury cykliczne</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-purchase-list.php') ? 'active' : ''; ?>">
|
||||
<a href="app-purchase-list.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Faktury zakupy">Faktury zakupy</div>
|
||||
@@ -151,7 +156,7 @@ $currentPage = basename($_SERVER['PHP_SELF']);
|
||||
</li>
|
||||
|
||||
<li
|
||||
class="menu-item <?php echo ($currentPage == 'sys-export.php' || $currentPage == 'sys-dictionaries.php' || $currentPage == 'sys-settings.php' || $currentPage == 'sys-logs.php') ? 'active open' : ''; ?>">
|
||||
class="menu-item <?php echo ($currentPage == 'sys-export.php' || $currentPage == 'sys-dictionaries.php' || $currentPage == 'sys-settings.php' || $currentPage == 'app-settings-notifications.php' || $currentPage == 'sys-logs.php') ? 'active open' : ''; ?>">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon tf-icons bx bx-cog"></i>
|
||||
<div class="text-truncate" data-i18n="System">System</div>
|
||||
@@ -172,6 +177,11 @@ $currentPage = basename($_SERVER['PHP_SELF']);
|
||||
<div class="text-truncate" data-i18n="Ustawienia">Ustawienia</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-settings-notifications.php') ? 'active' : ''; ?>">
|
||||
<a href="app-settings-notifications.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Powiadomienia (Cykliczne)">Powiadomienia (Cykliczne)</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'sys-logs.php') ? 'active' : ''; ?>">
|
||||
<a href="sys-logs.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Logi zdarzeń">Logi zdarzeń</div>
|
||||
|
||||
@@ -295,3 +295,48 @@ html {
|
||||
color: #8592a3 !important;
|
||||
}
|
||||
|
||||
/* Custom Nav Pills */
|
||||
.nav-pills .nav-link {
|
||||
background-color: var(--white);
|
||||
color: var(--text-muted);
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||
background-color: var(--primary-color) !important;
|
||||
color: var(--white) !important;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(105, 108, 255, 0.4) !important;
|
||||
}
|
||||
|
||||
/* Floating Action Button (FAB) */
|
||||
.fab-wrapper {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 100%;
|
||||
max-width: 500px; /* same as body max-width */
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 20px;
|
||||
z-index: 1050;
|
||||
pointer-events: none; /* Allows clicking through the wrapper */
|
||||
}
|
||||
|
||||
.fab-btn {
|
||||
pointer-events: auto;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2rem;
|
||||
box-shadow: 0 0.5rem 1rem rgba(105, 108, 255, 0.4);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.fab-btn:active {
|
||||
transform: scale(0.92);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,67 @@ include 'header.php';
|
||||
|
||||
<div class="app-topbar">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="d-flex justify-content-center align-items-center bg-primary-custom rounded-circle me-2"
|
||||
style="width: 32px; height: 32px;">
|
||||
<div class="d-flex justify-content-center align-items-center bg-primary-custom rounded-circle me-2" style="width: 32px; height: 32px;">
|
||||
<i class='bx bx-cube-alt text-white'></i>
|
||||
</div>
|
||||
<h1 class="app-title">Acme Corp</h1>
|
||||
</div>
|
||||
<div class="user-avatar shadow-sm">
|
||||
<i class='bx bx-user'></i>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<!-- Powiadomienia -->
|
||||
<div class="dropdown">
|
||||
<div class="position-relative" style="cursor: pointer;" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class='bx bx-bell fs-4 text-muted'></i>
|
||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger border border-white" style="font-size: 0.65rem; padding: 0.3em 0.45em;">
|
||||
1
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-end p-0 border-0 mt-2" style="border-radius: 16px; width: 340px; box-shadow: 0 0.5rem 1.5rem rgba(105, 108, 255, 0.15); overflow: hidden; z-index: 1050; margin-right: -40px;">
|
||||
<div class="p-3 border-bottom d-flex justify-content-between align-items-center" style="background-color: #fcfcfd;">
|
||||
<h6 class="mb-0 fw-bold" style="color: #566A7F;">Powiadomienia</h6>
|
||||
<span class="badge bg-label-danger rounded-pill">1 nowe</span>
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush" style="max-height: 350px; overflow-y: auto;">
|
||||
|
||||
<!-- Nieprzeczytane -->
|
||||
<a href="vacations.php" class="list-group-item list-group-item-action d-flex align-items-start p-3 border-0" style="background-color: rgba(105, 108, 255, 0.03); border-bottom: 1px solid rgba(0,0,0,0.03) !important;">
|
||||
<div class="d-flex justify-content-center align-items-center rounded-circle flex-shrink-0 me-3" style="width: 40px; height: 40px; background-color: rgba(255, 62, 29, 0.1); color: #ff3e1d;">
|
||||
<i class='bx bx-x-circle fs-5'></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1 fw-bold" style="font-size: 0.9rem; color: #566A7F;">Wniosek odrzucony</h6>
|
||||
<p class="mb-1 small text-muted" style="line-height: 1.4;">Kierownik odrzucił Twój wniosek o urlop na żądanie (05 Wrz).</p>
|
||||
<small class="text-primary-custom fw-semibold" style="font-size: 0.75rem;">10 min temu</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0 ms-2 mt-2">
|
||||
<div style="width: 8px; height: 8px; background-color: #696cff; border-radius: 50%;"></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Przeczytane -->
|
||||
<a href="vacations.php" class="list-group-item list-group-item-action d-flex align-items-start p-3 border-0">
|
||||
<div class="d-flex justify-content-center align-items-center rounded-circle flex-shrink-0 me-3" style="width: 40px; height: 40px; background-color: rgba(113, 221, 55, 0.1); color: #71dd37;">
|
||||
<i class='bx bx-check-circle fs-5'></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1 fw-semibold" style="font-size: 0.9rem; color: #566A7F;">Wniosek zaakceptowany</h6>
|
||||
<p class="mb-1 small text-muted" style="line-height: 1.4;">Twój urlop wypoczynkowy (12-16 Sie) został pomyślnie zatwierdzony.</p>
|
||||
<small class="text-muted" style="font-size: 0.75rem;">Wczoraj</small>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="p-3 border-top text-center" style="background-color: #fcfcfd;">
|
||||
<button class="btn btn-primary btn-sm w-100 fw-bold" style="border-radius: 8px;">Zobacz wszystkie</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-avatar shadow-sm">
|
||||
<i class='bx bx-user'></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,23 +11,216 @@ include 'header.php';
|
||||
</div>
|
||||
<h1 class="app-title">Acme Corp</h1>
|
||||
</div>
|
||||
<div class="user-avatar shadow-sm">
|
||||
<i class='bx bx-user'></i>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<!-- Powiadomienia -->
|
||||
<div class="dropdown">
|
||||
<div class="position-relative" style="cursor: pointer;" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class='bx bx-bell fs-4 text-muted'></i>
|
||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger border border-white" style="font-size: 0.65rem; padding: 0.3em 0.45em;">
|
||||
1
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-end p-0 border-0 mt-2" style="border-radius: 16px; width: 340px; box-shadow: 0 0.5rem 1.5rem rgba(105, 108, 255, 0.15); overflow: hidden; z-index: 1050; margin-right: -40px;">
|
||||
<div class="p-3 border-bottom d-flex justify-content-between align-items-center" style="background-color: #fcfcfd;">
|
||||
<h6 class="mb-0 fw-bold" style="color: #566A7F;">Powiadomienia</h6>
|
||||
<span class="badge bg-label-danger rounded-pill">1 nowe</span>
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush" style="max-height: 350px; overflow-y: auto;">
|
||||
|
||||
<!-- Nieprzeczytane -->
|
||||
<a href="vacations.php" class="list-group-item list-group-item-action d-flex align-items-start p-3 border-0" style="background-color: rgba(105, 108, 255, 0.03); border-bottom: 1px solid rgba(0,0,0,0.03) !important;">
|
||||
<div class="d-flex justify-content-center align-items-center rounded-circle flex-shrink-0 me-3" style="width: 40px; height: 40px; background-color: rgba(255, 62, 29, 0.1); color: #ff3e1d;">
|
||||
<i class='bx bx-x-circle fs-5'></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1 fw-bold" style="font-size: 0.9rem; color: #566A7F;">Wniosek odrzucony</h6>
|
||||
<p class="mb-1 small text-muted" style="line-height: 1.4;">Kierownik odrzucił Twój wniosek o urlop na żądanie (05 Wrz).</p>
|
||||
<small class="text-primary-custom fw-semibold" style="font-size: 0.75rem;">10 min temu</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0 ms-2 mt-2">
|
||||
<div style="width: 8px; height: 8px; background-color: #696cff; border-radius: 50%;"></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Przeczytane -->
|
||||
<a href="vacations.php" class="list-group-item list-group-item-action d-flex align-items-start p-3 border-0">
|
||||
<div class="d-flex justify-content-center align-items-center rounded-circle flex-shrink-0 me-3" style="width: 40px; height: 40px; background-color: rgba(113, 221, 55, 0.1); color: #71dd37;">
|
||||
<i class='bx bx-check-circle fs-5'></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1 fw-semibold" style="font-size: 0.9rem; color: #566A7F;">Wniosek zaakceptowany</h6>
|
||||
<p class="mb-1 small text-muted" style="line-height: 1.4;">Twój urlop wypoczynkowy (12-16 Sie) został pomyślnie zatwierdzony.</p>
|
||||
<small class="text-muted" style="font-size: 0.75rem;">Wczoraj</small>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="p-3 border-top text-center" style="background-color: #fcfcfd;">
|
||||
<button class="btn btn-primary btn-sm w-100 fw-bold" style="border-radius: 8px;">Zobacz wszystkie</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-avatar shadow-sm">
|
||||
<i class='bx bx-user'></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pasek tytułowy sekcji -->
|
||||
<div class="container pt-4">
|
||||
<div class="d-flex justify-content-between align-items-center pb-3 mb-4" style="border-bottom: 1px solid var(--border-color);">
|
||||
<div class="d-flex justify-content-between align-items-center pb-3" style="border-bottom: 1px solid var(--border-color);">
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="home.php" class="text-dark me-2 d-flex align-items-center justify-content-center" style="width: 32px; height: 32px; background: rgba(0,0,0,0.05); border-radius: 50%;">
|
||||
<i class='bx bx-arrow-back fs-4'></i>
|
||||
</a>
|
||||
<h2 class="fw-bold mb-0" style="font-size: 1.25rem;">Mój Grafik</h2>
|
||||
</div>
|
||||
<a href="schedule-calendar.php" class="text-primary-custom d-flex align-items-center justify-content-center" style="width: 36px; height: 36px; background: rgba(105, 108, 255, 0.1); border-radius: 8px;">
|
||||
<i class='bx bx-calendar fs-4'></i>
|
||||
</a>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<!-- Ikona filtrowania (Toggle zaawansowanych) -->
|
||||
<button class="btn btn-sm text-primary-custom d-flex align-items-center justify-content-center p-0" style="width: 36px; height: 36px; background: rgba(105, 108, 255, 0.1); border-radius: 8px; border: none;" data-bs-toggle="collapse" data-bs-target="#advancedFilters" aria-expanded="false">
|
||||
<i class='bx bx-filter fs-4'></i>
|
||||
</button>
|
||||
<a href="schedule-calendar.php" class="text-primary-custom d-flex align-items-center justify-content-center p-0 text-decoration-none" style="width: 36px; height: 36px; background: rgba(105, 108, 255, 0.1); border-radius: 8px;">
|
||||
<i class='bx bx-calendar fs-4'></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Szybki wybór okresu pod spodem -->
|
||||
<div class="mb-4 pt-3 d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0 text-muted small text-uppercase fw-bold">Wybierz okres</h6>
|
||||
<select class="form-select form-select-sm border-0 bg-white shadow-sm fw-semibold text-primary-custom" style="border-radius: 8px; cursor: pointer; width: auto; padding: 0.4rem 2rem 0.4rem 0.8rem; box-shadow: 0 0.125rem 0.25rem rgba(161, 172, 184, 0.15) !important;">
|
||||
<optgroup label="Tygodnie">
|
||||
<option value="week_current">Bieżący tydzień</option>
|
||||
<option value="week_next">Następny tydzień</option>
|
||||
<option value="week_prev">Poprzedni tydzień</option>
|
||||
</optgroup>
|
||||
<optgroup label="Miesiące">
|
||||
<option value="month_current" selected>Bieżący miesiąc</option>
|
||||
<option value="month_next">Następny miesiąc</option>
|
||||
<option value="month_prev">Poprzedni miesiąc</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Zaawansowane filtry (ukryte domyślnie, otwierane przez ikonkę filtra) -->
|
||||
<div class="collapse mb-4" id="advancedFilters">
|
||||
<div class="card border-0 shadow-sm" style="border-radius: 16px; border: 1px solid rgba(105, 108, 255, 0.2) !important;">
|
||||
<div class="card-body p-3 pb-1">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h6 class="mb-0 fw-bold d-flex align-items-center" style="color: #696cff; font-size: 0.95rem;">
|
||||
<i class='bx bx-slider-alt me-1 fs-5'></i> Własny zakres dat
|
||||
</h6>
|
||||
<button type="button" class="btn-close" style="font-size: 0.7rem; box-shadow: none;" data-bs-toggle="collapse" data-bs-target="#advancedFilters" aria-label="Zamknij"></button>
|
||||
</div>
|
||||
|
||||
<!-- Data od -->
|
||||
<label class="form-label fw-medium" style="font-size: 0.85rem; color: #566A7F;">Data od</label>
|
||||
<div class="input-group mb-3 dropdown">
|
||||
<span class="input-group-text bg-white text-muted" style="border-radius: 8px 0 0 8px; border-color: #d9dee3;"><i class='bx bx-calendar'></i></span>
|
||||
<input type="text" class="form-control bg-white dropdown-toggle" value="2024-08-12" readonly data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" style="border-radius: 0 8px 8px 0; border-color: #d9dee3; cursor: pointer;">
|
||||
|
||||
<!-- SneatDatePicker Mock -->
|
||||
<div class="dropdown-menu p-3 shadow border-0" style="border-radius: 8px; min-width: 300px; z-index: 1050; margin-top: 4px !important;">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<a href="#" class="btn btn-sm btn-icon text-secondary" style="padding: 4px;"><i class='bx bx-chevron-left fs-4'></i></a>
|
||||
<div class="fw-bold d-flex align-items-center gap-1" style="color: #566A7F; font-size: 1rem;">
|
||||
Sierpień 2024
|
||||
<div class="d-flex flex-column ms-1">
|
||||
<i class='bx bx-chevron-up' style="font-size: 1rem; line-height: 0.5; cursor: pointer; color: #566a7f;"></i>
|
||||
<i class='bx bx-chevron-down' style="font-size: 1rem; line-height: 0.5; cursor: pointer; color: #566a7f;"></i>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="btn btn-sm btn-icon text-secondary" style="padding: 4px;"><i class='bx bx-chevron-right fs-4'></i></a>
|
||||
</div>
|
||||
<div class="d-flex mb-2">
|
||||
<div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Pn</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Wt</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Śr</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Cz</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Pt</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Sb</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Nd</div>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap" style="row-gap: 8px;">
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #c7cdd4; text-align: center;">29</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #c7cdd4; text-align: center;">30</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #c7cdd4; text-align: center;">31</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">1</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">2</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">3</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">4</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">5</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">6</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">7</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">8</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">9</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">10</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">11</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; background-color: #696cff; color: #fff; text-align: center; border-radius: 6px; font-weight: 600; box-shadow: 0 2px 4px rgba(105, 108, 255, 0.4);">12</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 30px; border: 1px solid #696cff; color: #566A7F; text-align: center; border-radius: 6px;">13</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">14</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">15</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">16</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">17</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">18</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Data do -->
|
||||
<label class="form-label fw-medium" style="font-size: 0.85rem; color: #566A7F;">Data do</label>
|
||||
<div class="input-group mb-4 dropdown">
|
||||
<span class="input-group-text bg-white text-muted" style="border-radius: 8px 0 0 8px; border-color: #d9dee3;"><i class='bx bx-calendar'></i></span>
|
||||
<input type="text" class="form-control bg-white dropdown-toggle" value="2024-08-18" readonly data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" style="border-radius: 0 8px 8px 0; border-color: #d9dee3; cursor: pointer;">
|
||||
|
||||
<!-- SneatDatePicker Mock -->
|
||||
<div class="dropdown-menu p-3 shadow border-0" style="border-radius: 8px; min-width: 300px; z-index: 1050; margin-top: 4px !important;">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<a href="#" class="btn btn-sm btn-icon text-secondary" style="padding: 4px;"><i class='bx bx-chevron-left fs-4'></i></a>
|
||||
<div class="fw-bold d-flex align-items-center gap-1" style="color: #566A7F; font-size: 1rem;">
|
||||
Sierpień 2024
|
||||
<div class="d-flex flex-column ms-1">
|
||||
<i class='bx bx-chevron-up' style="font-size: 1rem; line-height: 0.5; cursor: pointer; color: #566a7f;"></i>
|
||||
<i class='bx bx-chevron-down' style="font-size: 1rem; line-height: 0.5; cursor: pointer; color: #566a7f;"></i>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="btn btn-sm btn-icon text-secondary" style="padding: 4px;"><i class='bx bx-chevron-right fs-4'></i></a>
|
||||
</div>
|
||||
<div class="d-flex mb-2">
|
||||
<div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Pn</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Wt</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Śr</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Cz</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Pt</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Sb</div><div class="text-center fw-semibold" style="width: 14.28%; font-size: 0.75rem; color: #a1acb8;">Nd</div>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap" style="row-gap: 8px;">
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #c7cdd4; text-align: center;">29</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #c7cdd4; text-align: center;">30</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #c7cdd4; text-align: center;">31</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">1</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">2</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">3</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">4</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">5</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">6</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">7</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">8</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">9</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">10</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">11</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">12</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 30px; border: 1px solid #696cff; color: #566A7F; text-align: center; border-radius: 6px;">13</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">14</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">15</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">16</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; color: #566A7F; text-align: center;">17</div></div>
|
||||
<div class="d-flex justify-content-center align-items-center" style="width: 14.28%;"><div style="width: 32px; height: 32px; line-height: 32px; background-color: #696cff; color: #fff; text-align: center; border-radius: 6px; font-weight: 600; box-shadow: 0 2px 4px rgba(105, 108, 255, 0.4);">18</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn w-100 mb-3 fw-medium text-white" style="border-radius: 8px; background-color: #696cff; border-color: #696cff;">Szukaj</button>
|
||||
|
||||
<div class="text-start">
|
||||
<a href="#" class="text-decoration-none fw-medium" style="font-size: 0.85rem; color: #566A7F;">Wyczyść filtry i daty</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,8 +11,62 @@ include 'header.php';
|
||||
</div>
|
||||
<h1 class="app-title">Acme Corp</h1>
|
||||
</div>
|
||||
<div class="user-avatar shadow-sm">
|
||||
<i class='bx bx-user'></i>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<!-- Powiadomienia -->
|
||||
<div class="dropdown">
|
||||
<div class="position-relative" style="cursor: pointer;" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class='bx bx-bell fs-4 text-muted'></i>
|
||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger border border-white" style="font-size: 0.65rem; padding: 0.3em 0.45em;">
|
||||
1
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-end p-0 border-0 mt-2" style="border-radius: 16px; width: 340px; box-shadow: 0 0.5rem 1.5rem rgba(105, 108, 255, 0.15); overflow: hidden; z-index: 1050; margin-right: -40px;">
|
||||
<div class="p-3 border-bottom d-flex justify-content-between align-items-center" style="background-color: #fcfcfd;">
|
||||
<h6 class="mb-0 fw-bold" style="color: #566A7F;">Powiadomienia</h6>
|
||||
<span class="badge bg-label-danger rounded-pill">1 nowe</span>
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush" style="max-height: 350px; overflow-y: auto;">
|
||||
|
||||
<!-- Nieprzeczytane -->
|
||||
<a href="vacations.php" class="list-group-item list-group-item-action d-flex align-items-start p-3 border-0" style="background-color: rgba(105, 108, 255, 0.03); border-bottom: 1px solid rgba(0,0,0,0.03) !important;">
|
||||
<div class="d-flex justify-content-center align-items-center rounded-circle flex-shrink-0 me-3" style="width: 40px; height: 40px; background-color: rgba(255, 62, 29, 0.1); color: #ff3e1d;">
|
||||
<i class='bx bx-x-circle fs-5'></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1 fw-bold" style="font-size: 0.9rem; color: #566A7F;">Wniosek odrzucony</h6>
|
||||
<p class="mb-1 small text-muted" style="line-height: 1.4;">Kierownik odrzucił Twój wniosek o urlop na żądanie (05 Wrz).</p>
|
||||
<small class="text-primary-custom fw-semibold" style="font-size: 0.75rem;">10 min temu</small>
|
||||
</div>
|
||||
<div class="flex-shrink-0 ms-2 mt-2">
|
||||
<div style="width: 8px; height: 8px; background-color: #696cff; border-radius: 50%;"></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- Przeczytane -->
|
||||
<a href="vacations.php" class="list-group-item list-group-item-action d-flex align-items-start p-3 border-0">
|
||||
<div class="d-flex justify-content-center align-items-center rounded-circle flex-shrink-0 me-3" style="width: 40px; height: 40px; background-color: rgba(113, 221, 55, 0.1); color: #71dd37;">
|
||||
<i class='bx bx-check-circle fs-5'></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1 fw-semibold" style="font-size: 0.9rem; color: #566A7F;">Wniosek zaakceptowany</h6>
|
||||
<p class="mb-1 small text-muted" style="line-height: 1.4;">Twój urlop wypoczynkowy (12-16 Sie) został pomyślnie zatwierdzony.</p>
|
||||
<small class="text-muted" style="font-size: 0.75rem;">Wczoraj</small>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="p-3 border-top text-center" style="background-color: #fcfcfd;">
|
||||
<button class="btn btn-primary btn-sm w-100 fw-bold" style="border-radius: 8px;">Zobacz wszystkie</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-avatar shadow-sm">
|
||||
<i class='bx bx-user'></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,83 +84,186 @@ include 'header.php';
|
||||
|
||||
<div class="container pb-4">
|
||||
|
||||
<!-- Akcja Główna: Wniosek o urlop -->
|
||||
<div class="mb-4">
|
||||
<button class="btn btn-primary w-100 py-3 fw-bold shadow-sm" data-bs-toggle="modal" data-bs-target="#vacationModal" style="border-radius: var(--radius-md);">
|
||||
<i class='bx bx-plus-circle fs-5 me-1 align-middle'></i> Nowy wniosek o urlop
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Lista Nadchodzących Urlopów -->
|
||||
<h6 class="fw-bold mb-3 text-muted text-uppercase small">Nadchodzące wnioski</h6>
|
||||
|
||||
<!-- Wniosek 1: Zaakceptowany -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #71dd37 !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-success mb-1">Zaakceptowany</span>
|
||||
<h5 class="fw-bold mb-0" style="font-size: 1.1rem;">Urlop wypoczynkowy</h5>
|
||||
<!-- Statystyki Urlopowe (Dashboard Widget) -->
|
||||
<div class="card border-0 shadow-sm mb-4" style="border-radius: 16px;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="d-flex justify-content-center align-items-center me-2" style="width: 32px; height: 32px; border-radius: 8px; background-color: rgba(105, 108, 255, 0.1);">
|
||||
<i class='bx bx-pie-chart-alt-2' style="color: #696cff; font-size: 1.2rem;"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold mb-0" style="color: #566A7F; font-size: 1.05rem;">Pula urlopowa</h6>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="fw-bold text-dark fs-5">5</span>
|
||||
<span class="text-muted small d-block" style="margin-top: -5px;">dni</span>
|
||||
<select class="form-select form-select-sm border-0 bg-light text-muted fw-semibold" style="width: auto; border-radius: 8px; cursor: pointer;">
|
||||
<option value="2024" selected>Rok: 2024</option>
|
||||
<option value="2023">Rok: 2023</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-end mb-2 mt-1">
|
||||
<div>
|
||||
<span class="text-muted small d-block mb-1">Dostępne do wykorzystania</span>
|
||||
<h3 class="mb-0 fw-bold" style="color: #696cff;">14 <span class="fs-6 fw-semibold text-muted">z 26 dni</span></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3">
|
||||
<i class='bx bx-calendar me-2 fs-5 text-primary-custom'></i>
|
||||
<span class="fw-semibold">12 Sierpnia 2026 - 16 Sierpnia 2026</span>
|
||||
<!-- Progress Bar -->
|
||||
<div class="progress mb-2 mt-3" style="height: 10px; border-radius: 10px; background-color: rgba(105, 108, 255, 0.15);">
|
||||
<div class="progress-bar" role="progressbar" style="width: 46%; background-color: #696cff; border-radius: 10px;" aria-valuenow="12" aria-valuemin="0" aria-valuemax="26"></div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between text-muted" style="font-size: 0.8rem;">
|
||||
<span class="fw-medium">Wykorzystano: 12 dni</span>
|
||||
<span class="fw-medium">Zaległy: 0 dni</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Wniosek 2: Oczekujący -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #8592a3 !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-secondary mb-1">Oczekuje na akceptację</span>
|
||||
<h5 class="fw-bold mb-0" style="font-size: 1.1rem;">Urlop wypoczynkowy</h5>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="fw-bold text-dark fs-5">2</span>
|
||||
<span class="text-muted small d-block" style="margin-top: -5px;">dni</span>
|
||||
|
||||
<!-- Tabs: Nadchodzące / Historia -->
|
||||
<ul class="nav nav-pills nav-justified mb-4" id="vacationTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active fw-bold shadow-sm" id="upcoming-tab" data-bs-toggle="pill" data-bs-target="#upcoming" type="button" role="tab" aria-controls="upcoming" aria-selected="true" style="border-radius: 8px;">Nadchodzące</button>
|
||||
</li>
|
||||
<li class="nav-item ms-2" role="presentation">
|
||||
<button class="nav-link fw-bold shadow-sm" id="history-tab" data-bs-toggle="pill" data-bs-target="#history" type="button" role="tab" aria-controls="history" aria-selected="false" style="border-radius: 8px;">Historia</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content p-0 m-0 border-0" id="vacationTabsContent">
|
||||
<!-- ZAKŁADKA 1: Nadchodzące -->
|
||||
<div class="tab-pane fade show active" id="upcoming" role="tabpanel" aria-labelledby="upcoming-tab">
|
||||
|
||||
<!-- Wniosek 1: Zaakceptowany -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #71dd37 !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-success mb-1">Zaakceptowany</span>
|
||||
<h5 class="fw-bold mb-0" style="font-size: 1.1rem;">Urlop wypoczynkowy</h5>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="fw-bold text-dark fs-5">5</span>
|
||||
<span class="text-muted small d-block" style="margin-top: -5px;">dni</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3">
|
||||
<i class='bx bx-calendar me-2 fs-5 text-primary-custom'></i>
|
||||
<span class="fw-semibold">12 Sierpnia 2026 - 16 Sierpnia 2026</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3">
|
||||
<i class='bx bx-calendar me-2 fs-5 text-primary-custom'></i>
|
||||
<span class="fw-semibold">27 Sierpnia 2026 - 28 Sierpnia 2026</span>
|
||||
|
||||
<!-- Wniosek 2: Oczekujący -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #8592a3 !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-secondary mb-1">Oczekuje na akceptację</span>
|
||||
<h5 class="fw-bold mb-0" style="font-size: 1.1rem;">Urlop wypoczynkowy</h5>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="fw-bold text-dark fs-5">2</span>
|
||||
<span class="text-muted small d-block" style="margin-top: -5px;">dni</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3">
|
||||
<i class='bx bx-calendar me-2 fs-5 text-primary-custom'></i>
|
||||
<span class="fw-semibold">27 Sierpnia 2026 - 28 Sierpnia 2026</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Wniosek 3: Odrzucony -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #ff3e1d !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-danger mb-1">Odrzucony</span>
|
||||
<h5 class="fw-bold mb-0" style="font-size: 1.1rem;">Urlop na żądanie</h5>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="fw-bold text-dark fs-5">1</span>
|
||||
<span class="text-muted small d-block" style="margin-top: -5px;">dzień</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3 mb-2">
|
||||
<i class='bx bx-calendar me-2 fs-5 text-primary-custom'></i>
|
||||
<span class="fw-semibold">05 Września 2026</span>
|
||||
</div>
|
||||
|
||||
<div class="bg-light p-2 rounded text-muted small d-flex align-items-start gap-2 mt-2">
|
||||
<i class='bx bx-info-circle text-danger mt-1'></i>
|
||||
<div>
|
||||
<strong class="text-dark">Kierownik:</strong> Niestety w tym terminie mamy inwentaryzację, brak możliwości udzielenia urlopu.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Wniosek 3: Odrzucony -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #ff3e1d !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-danger mb-1">Odrzucony</span>
|
||||
<h5 class="fw-bold mb-0" style="font-size: 1.1rem;">Urlop na żądanie</h5>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<span class="fw-bold text-dark fs-5">1</span>
|
||||
<span class="text-muted small d-block" style="margin-top: -5px;">dzień</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ZAKŁADKA 2: Historia -->
|
||||
<div class="tab-pane fade" id="history" role="tabpanel" aria-labelledby="history-tab">
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3 mb-2">
|
||||
<i class='bx bx-calendar me-2 fs-5 text-primary-custom'></i>
|
||||
<span class="fw-semibold">05 Września 2026</span>
|
||||
<!-- FILTRY HISTORII -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 gap-2">
|
||||
<select class="form-select bg-white shadow-sm border-0" style="border-radius: 8px; color: #566A7F; font-weight: 500;">
|
||||
<option value="2024" selected>Rok: 2024</option>
|
||||
<option value="2023">Rok: 2023</option>
|
||||
<option value="2022">Rok: 2022</option>
|
||||
</select>
|
||||
<select class="form-select bg-white shadow-sm border-0" style="border-radius: 8px; color: #566A7F; font-weight: 500;">
|
||||
<option value="all" selected>Status: Wszystkie</option>
|
||||
<option value="accepted">Wykorzystane</option>
|
||||
<option value="rejected">Odrzucone</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="bg-light p-2 rounded text-muted small d-flex align-items-start gap-2 mt-2">
|
||||
<i class='bx bx-info-circle text-danger mt-1'></i>
|
||||
<div>
|
||||
<strong class="text-dark">Kierownik:</strong> Niestety w tym terminie mamy inwentaryzację, brak możliwości udzielenia urlopu.
|
||||
|
||||
<!-- Historia: Wykorzystany -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #d9dee3 !important;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-secondary mb-1">Wykorzystany</span>
|
||||
<h5 class="fw-bold mb-0 text-muted" style="font-size: 1.1rem;">Urlop wypoczynkowy</h5>
|
||||
</div>
|
||||
<div class="text-end text-muted">
|
||||
<span class="fw-bold fs-5">14</span>
|
||||
<span class="small d-block" style="margin-top: -5px;">dni</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3">
|
||||
<i class='bx bx-calendar me-2 fs-5'></i>
|
||||
<span>01 Lipca 2024 - 14 Lipca 2024</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Historia: Odrzucony -->
|
||||
<div class="card-custom mb-3 border-0 shadow-sm" style="border-left: 4px solid #d9dee3 !important; opacity: 0.8;">
|
||||
<div class="p-3">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<span class="badge bg-label-danger mb-1 opacity-75">Odrzucony</span>
|
||||
<h5 class="fw-bold mb-0 text-muted" style="font-size: 1.1rem;">Urlop na żądanie</h5>
|
||||
</div>
|
||||
<div class="text-end text-muted">
|
||||
<span class="fw-bold fs-5">1</span>
|
||||
<span class="small d-block" style="margin-top: -5px;">dzień</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center text-muted small mt-3">
|
||||
<i class='bx bx-calendar me-2 fs-5'></i>
|
||||
<span>15 Maja 2024</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -171,6 +328,13 @@ include 'header.php';
|
||||
<!-- Flatpickr Theme (optional, fits well) -->
|
||||
<link rel="stylesheet" type="text/css" href="https://npmcdn.com/flatpickr/dist/themes/airbnb.css">
|
||||
|
||||
<!-- Floating Action Button (FAB) dla nowego wniosku -->
|
||||
<div class="fab-wrapper">
|
||||
<button class="btn btn-primary fab-btn" data-bs-toggle="modal" data-bs-target="#vacationModal" aria-label="Nowy wniosek o urlop">
|
||||
<i class='bx bx-plus'></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
|
||||
<!-- Flatpickr JS -->
|
||||
|
||||
@@ -0,0 +1,455 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-telemetria.php';
|
||||
?>
|
||||
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/libs/leaflet/leaflet.css" />
|
||||
|
||||
<style>
|
||||
#installationsMap {
|
||||
height: calc(100vh - 220px);
|
||||
min-height: 480px;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.map-sidebar-list {
|
||||
max-height: calc(100vh - 420px);
|
||||
min-height: 220px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.map-marker-pin {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50% 50% 50% 0;
|
||||
transform: rotate(-45deg);
|
||||
border: 2px solid #fff;
|
||||
box-shadow: 0 2px 6px rgba(67, 89, 113, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #696cff;
|
||||
}
|
||||
|
||||
.map-marker-pin i {
|
||||
transform: rotate(45deg);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.map-marker-pin.is-alert {
|
||||
background-color: #ff3e1d;
|
||||
}
|
||||
|
||||
.map-list-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.map-list-item:hover,
|
||||
.map-list-item.is-focused {
|
||||
background-color: rgba(105, 108, 255, 0.08);
|
||||
}
|
||||
|
||||
.map-list-item.is-hidden-on-map {
|
||||
opacity: 0.55;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid flex-grow-1 container-p-y">
|
||||
<h4 class="fw-bold py-3 mb-4">
|
||||
Telemetria <span class="text-muted fw-light">/ Mapa instalacji</span>
|
||||
</h4>
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-8 col-xl-9">
|
||||
<div class="card shadow-sm border-0 overflow-hidden">
|
||||
<div id="installationsMap"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-xl-3">
|
||||
<div class="card shadow-sm border-0 h-100">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">Instalacje na mapie</h5>
|
||||
<small class="text-muted">Wyszukaj, filtruj i zarządzaj widocznością</small>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3 mt-3">
|
||||
<label class="form-label" for="mapSearchInput">Szukaj</label>
|
||||
<div class="input-group input-group-merge">
|
||||
<span class="input-group-text"><i class="bx bx-search"></i></span>
|
||||
<input type="text" id="mapSearchInput" class="form-control" placeholder="Nazwa lub lokalizacja...">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="mapTypeFilter">Typ</label>
|
||||
<select id="mapTypeFilter" class="form-select">
|
||||
<option value="">Wszystkie typy</option>
|
||||
<option value="gas">Zbiornik Gazu</option>
|
||||
<option value="farm">Kurnik / Farma</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="mapStatusFilter">Status</label>
|
||||
<select id="mapStatusFilter" class="form-select">
|
||||
<option value="">Każdy status</option>
|
||||
<option value="online">Online</option>
|
||||
<option value="alert">Alert</option>
|
||||
<option value="offline">Offline</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="fw-medium">Widoczność</span>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-primary" id="showAllInstallationsBtn">Wszystkie</button>
|
||||
<button type="button" class="btn btn-outline-secondary" id="hideAllInstallationsBtn">Ukryj</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="mapInstallationsList" class="map-sidebar-list border rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
<script src="<?= $basePath ?>/assets/vendor/libs/leaflet/leaflet.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
const installations = [
|
||||
{
|
||||
id: 'inst-1',
|
||||
name: 'Zbiornik LPG #1',
|
||||
location: 'Stalowa Wola, ul. Przemysłowa 5',
|
||||
type: 'gas',
|
||||
typeLabel: 'Zbiornik Gazu',
|
||||
status: 'online',
|
||||
statusLabel: 'Online',
|
||||
lat: 50.5826,
|
||||
lng: 22.0534,
|
||||
alert: null,
|
||||
url: 'installation-live.php'
|
||||
},
|
||||
{
|
||||
id: 'inst-2',
|
||||
name: 'Kurnik B (Sektor 2)',
|
||||
location: 'Farma Wola, Obiekt Główny',
|
||||
type: 'farm',
|
||||
typeLabel: 'Sterownik Kurnika',
|
||||
status: 'online',
|
||||
statusLabel: 'Online',
|
||||
lat: 50.6012,
|
||||
lng: 22.0918,
|
||||
alert: null,
|
||||
url: 'installation-live.php'
|
||||
},
|
||||
{
|
||||
id: 'inst-3',
|
||||
name: 'Zbiornik LPG #2',
|
||||
location: 'Rzeszów, Baza Północ',
|
||||
type: 'gas',
|
||||
typeLabel: 'Zbiornik Gazu',
|
||||
status: 'offline',
|
||||
statusLabel: 'Offline',
|
||||
lat: 50.0578,
|
||||
lng: 22.0048,
|
||||
alert: 'Brak łączności — brak sygnału od ponad 3 dni.',
|
||||
url: 'installation-live.php'
|
||||
},
|
||||
{
|
||||
id: 'inst-4',
|
||||
name: 'Zbiornik LPG #3',
|
||||
location: 'Lublin, ul. Metalurgiczna 12',
|
||||
type: 'gas',
|
||||
typeLabel: 'Zbiornik Gazu',
|
||||
status: 'alert',
|
||||
statusLabel: 'Alert',
|
||||
lat: 51.2354,
|
||||
lng: 22.5489,
|
||||
alert: 'Niski poziom gazu — poziom poniżej 15%.',
|
||||
url: 'installation-live.php'
|
||||
},
|
||||
{
|
||||
id: 'inst-5',
|
||||
name: 'Zbiornik LPG #4',
|
||||
location: 'Tarnobrzeg, Stacja Przeładunkowa',
|
||||
type: 'gas',
|
||||
typeLabel: 'Zbiornik Gazu',
|
||||
status: 'online',
|
||||
statusLabel: 'Online',
|
||||
lat: 50.5731,
|
||||
lng: 21.6794,
|
||||
alert: null,
|
||||
url: 'installation-live.php'
|
||||
},
|
||||
{
|
||||
id: 'inst-6',
|
||||
name: 'Sterownik Farma Alpha',
|
||||
location: 'Nisko, Sektor A',
|
||||
type: 'farm',
|
||||
typeLabel: 'Sterownik Kurnika',
|
||||
status: 'online',
|
||||
statusLabel: 'Online',
|
||||
lat: 50.5198,
|
||||
lng: 22.1396,
|
||||
alert: null,
|
||||
url: 'installation-live.php'
|
||||
},
|
||||
{
|
||||
id: 'inst-7',
|
||||
name: 'Zbiornik LPG #5',
|
||||
location: 'Przemyśl, Baza Południe',
|
||||
type: 'gas',
|
||||
typeLabel: 'Zbiornik Gazu',
|
||||
status: 'online',
|
||||
statusLabel: 'Online',
|
||||
lat: 49.7837,
|
||||
lng: 22.7673,
|
||||
alert: null,
|
||||
url: 'installation-live.php'
|
||||
}
|
||||
];
|
||||
|
||||
const mapEl = document.getElementById('installationsMap');
|
||||
if (!mapEl || typeof L === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const map = L.map(mapEl).setView([50.45, 22.15], 8);
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||
maxZoom: 18
|
||||
}).addTo(map);
|
||||
|
||||
const markersById = {};
|
||||
let closePopupTimer = null;
|
||||
|
||||
function createMarkerIcon(hasAlert) {
|
||||
const pinClass = hasAlert ? ' is-alert' : '';
|
||||
const iconHtml = hasAlert
|
||||
? '<i class="bx bx-error"></i>'
|
||||
: '<i class="bx bx-buildings"></i>';
|
||||
|
||||
return L.divIcon({
|
||||
className: '',
|
||||
html: '<div class="map-marker-pin' + pinClass + '">' + iconHtml + '</div>',
|
||||
iconSize: [32, 32],
|
||||
iconAnchor: [16, 32],
|
||||
popupAnchor: [0, -28]
|
||||
});
|
||||
}
|
||||
|
||||
function buildPopupHtml(item) {
|
||||
const alertBlock = item.alert
|
||||
? '<div class="alert alert-danger py-2 px-3 mb-2 small">' +
|
||||
'<i class="bx bx-error-circle me-1"></i>' + item.alert +
|
||||
'</div>'
|
||||
: '<p class="text-muted small mb-2">Brak aktywnych alertów</p>';
|
||||
|
||||
return (
|
||||
'<div>' +
|
||||
'<h6 class="mb-1 fw-bold">' + item.name + '</h6>' +
|
||||
'<small class="text-muted d-block mb-2"><i class="bx bx-map me-1"></i>' + item.location + '</small>' +
|
||||
alertBlock +
|
||||
'<button type="button" class="btn btn-sm btn-primary w-100" onclick="window.location.href=\'' + item.url + '\'">' +
|
||||
'<i class="bx bx-right-arrow-alt me-1"></i> Przejdź do instalacji' +
|
||||
'</button>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function statusBadgeClass(status) {
|
||||
if (status === 'online') return 'bg-success';
|
||||
if (status === 'alert') return 'bg-danger';
|
||||
return 'bg-secondary';
|
||||
}
|
||||
|
||||
installations.forEach(function (item) {
|
||||
const marker = L.marker([item.lat, item.lng], {
|
||||
icon: createMarkerIcon(Boolean(item.alert)),
|
||||
title: item.name
|
||||
});
|
||||
|
||||
marker.bindPopup(buildPopupHtml(item));
|
||||
|
||||
marker.on('mouseover', function () {
|
||||
if (closePopupTimer) {
|
||||
clearTimeout(closePopupTimer);
|
||||
closePopupTimer = null;
|
||||
}
|
||||
marker.openPopup();
|
||||
});
|
||||
|
||||
marker.on('mouseout', function () {
|
||||
closePopupTimer = setTimeout(function () {
|
||||
marker.closePopup();
|
||||
}, 280);
|
||||
});
|
||||
|
||||
marker.on('popupopen', function () {
|
||||
const popupEl = marker.getPopup().getElement();
|
||||
if (!popupEl) return;
|
||||
|
||||
popupEl.addEventListener('mouseenter', function () {
|
||||
if (closePopupTimer) {
|
||||
clearTimeout(closePopupTimer);
|
||||
closePopupTimer = null;
|
||||
}
|
||||
});
|
||||
|
||||
popupEl.addEventListener('mouseleave', function () {
|
||||
closePopupTimer = setTimeout(function () {
|
||||
marker.closePopup();
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
|
||||
markersById[item.id] = {
|
||||
item: item,
|
||||
marker: marker,
|
||||
visible: true,
|
||||
matchesFilter: true
|
||||
};
|
||||
|
||||
marker.addTo(map);
|
||||
});
|
||||
|
||||
const listEl = document.getElementById('mapInstallationsList');
|
||||
const searchInput = document.getElementById('mapSearchInput');
|
||||
const typeFilter = document.getElementById('mapTypeFilter');
|
||||
const statusFilter = document.getElementById('mapStatusFilter');
|
||||
|
||||
function renderList() {
|
||||
const fragments = installations.map(function (item) {
|
||||
const state = markersById[item.id];
|
||||
if (!state.matchesFilter) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const hiddenClass = state.visible ? '' : ' is-hidden-on-map';
|
||||
const alertIcon = item.alert
|
||||
? '<i class="bx bx-error-circle text-danger ms-1" title="Alert"></i>'
|
||||
: '';
|
||||
|
||||
return (
|
||||
'<div class="map-list-item border-bottom px-3 py-2' + hiddenClass + '" data-id="' + item.id + '">' +
|
||||
'<div class="d-flex align-items-start gap-2">' +
|
||||
'<div class="form-check form-switch mb-0 mt-1">' +
|
||||
'<input class="form-check-input map-visibility-toggle" type="checkbox" role="switch" ' +
|
||||
'data-id="' + item.id + '" ' + (state.visible ? 'checked' : '') + ' ' +
|
||||
'aria-label="Widoczność ' + item.name + '">' +
|
||||
'</div>' +
|
||||
'<div class="flex-grow-1 min-w-0">' +
|
||||
'<div class="d-flex justify-content-between align-items-start gap-2">' +
|
||||
'<div class="min-w-0">' +
|
||||
'<div class="fw-semibold text-truncate">' + item.name + alertIcon + '</div>' +
|
||||
'<small class="text-muted text-truncate d-block">' + item.location + '</small>' +
|
||||
'</div>' +
|
||||
'<span class="badge ' + statusBadgeClass(item.status) + '">' + item.statusLabel + '</span>' +
|
||||
'</div>' +
|
||||
'<small class="text-muted">' + item.typeLabel + '</small>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}).join('');
|
||||
|
||||
listEl.innerHTML = fragments ||
|
||||
'<div class="text-center text-muted py-4 px-3 small">Brak instalacji spełniających kryteria</div>';
|
||||
}
|
||||
|
||||
function applyFilters() {
|
||||
const query = (searchInput.value || '').trim().toLowerCase();
|
||||
const type = typeFilter.value;
|
||||
const status = statusFilter.value;
|
||||
|
||||
installations.forEach(function (item) {
|
||||
const state = markersById[item.id];
|
||||
const haystack = (item.name + ' ' + item.location).toLowerCase();
|
||||
const matchesQuery = !query || haystack.indexOf(query) !== -1;
|
||||
const matchesType = !type || item.type === type;
|
||||
const matchesStatus = !status || item.status === status;
|
||||
state.matchesFilter = matchesQuery && matchesType && matchesStatus;
|
||||
|
||||
const shouldShow = state.matchesFilter && state.visible;
|
||||
if (shouldShow) {
|
||||
if (!map.hasLayer(state.marker)) {
|
||||
state.marker.addTo(map);
|
||||
}
|
||||
} else if (map.hasLayer(state.marker)) {
|
||||
map.removeLayer(state.marker);
|
||||
}
|
||||
});
|
||||
|
||||
renderList();
|
||||
}
|
||||
|
||||
function setAllVisibility(visible) {
|
||||
installations.forEach(function (item) {
|
||||
markersById[item.id].visible = visible;
|
||||
});
|
||||
applyFilters();
|
||||
}
|
||||
|
||||
function focusInstallation(id) {
|
||||
const state = markersById[id];
|
||||
if (!state || !state.matchesFilter) return;
|
||||
|
||||
if (!state.visible) {
|
||||
state.visible = true;
|
||||
applyFilters();
|
||||
}
|
||||
|
||||
map.flyTo([state.item.lat, state.item.lng], 12, { duration: 0.6 });
|
||||
state.marker.openPopup();
|
||||
|
||||
listEl.querySelectorAll('.map-list-item').forEach(function (el) {
|
||||
el.classList.toggle('is-focused', el.getAttribute('data-id') === id);
|
||||
});
|
||||
}
|
||||
|
||||
listEl.addEventListener('change', function (event) {
|
||||
const toggle = event.target.closest('.map-visibility-toggle');
|
||||
if (!toggle) return;
|
||||
|
||||
const id = toggle.getAttribute('data-id');
|
||||
markersById[id].visible = toggle.checked;
|
||||
applyFilters();
|
||||
});
|
||||
|
||||
listEl.addEventListener('click', function (event) {
|
||||
if (event.target.closest('.map-visibility-toggle')) return;
|
||||
const row = event.target.closest('.map-list-item');
|
||||
if (!row) return;
|
||||
focusInstallation(row.getAttribute('data-id'));
|
||||
});
|
||||
|
||||
searchInput.addEventListener('input', applyFilters);
|
||||
typeFilter.addEventListener('change', applyFilters);
|
||||
statusFilter.addEventListener('change', applyFilters);
|
||||
|
||||
document.getElementById('showAllInstallationsBtn').addEventListener('click', function () {
|
||||
setAllVisibility(true);
|
||||
});
|
||||
|
||||
document.getElementById('hideAllInstallationsBtn').addEventListener('click', function () {
|
||||
setAllVisibility(false);
|
||||
});
|
||||
|
||||
applyFilters();
|
||||
|
||||
setTimeout(function () {
|
||||
map.invalidateSize();
|
||||
}, 200);
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-telemetria.php';
|
||||
?>
|
||||
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<h4 class="fw-bold py-3 mb-4">
|
||||
Telemetria <span class="text-muted fw-light">/ Logi systemowe</span>
|
||||
</h4>
|
||||
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">Dziennik zdarzeń (Logi modułu)</h5>
|
||||
</div>
|
||||
<div class="table-responsive text-nowrap">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Data</th>
|
||||
<th>Użytkownik</th>
|
||||
<th>Operacja</th>
|
||||
<th>Szczegóły</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-border-bottom-0">
|
||||
<tr>
|
||||
<td>2026-06-19 16:30</td>
|
||||
<td><span class="badge bg-label-primary"><i class="bx bx-user me-1"></i> Jan Kowalski</span></td>
|
||||
<td><span class="fw-bold text-danger">Usunięcie urządzenia</span></td>
|
||||
<td>ID: 1024</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2026-06-19 16:20</td>
|
||||
<td><span class="badge bg-label-secondary"><i class="bx bx-cog me-1"></i> System</span></td>
|
||||
<td><span class="fw-bold text-warning">Zmiana statusu</span></td>
|
||||
<td>ID: 1024, Status: Online → Offline (utrata łączności)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2026-06-19 16:15</td>
|
||||
<td><span class="badge bg-label-primary"><i class="bx bx-user me-1"></i> Jan Kowalski</span></td>
|
||||
<td><span class="fw-bold text-info">Edycja danych</span></td>
|
||||
<td>ID: 1024, Edycja danych urządzenia.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2026-06-19 16:10</td>
|
||||
<td><span class="badge bg-label-primary"><i class="bx bx-user me-1"></i> Jan Kowalski</span></td>
|
||||
<td><span class="fw-bold text-success">Dodanie urządzenia</span></td>
|
||||
<td>MAC: AA:BB:CC:DD:EE:FF, Nazwa: "Sterownik Klimatu Alpha"</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -42,11 +42,23 @@ $currentPage = basename($_SERVER['PHP_SELF']);
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'installations.php') ? 'active' : ''; ?>">
|
||||
<a href="installations.php" class="menu-link">
|
||||
<li class="menu-item <?php echo in_array($currentPage, ['installations.php', 'installations-map.php'], true) ? 'active open' : ''; ?>">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon tf-icons bx bx-buildings"></i>
|
||||
<div class="text-truncate" data-i18n="Instalacje">Instalacje</div>
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item <?php echo ($currentPage == 'installations.php') ? 'active' : ''; ?>">
|
||||
<a href="installations.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Lista">Lista instalacji</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'installations-map.php') ? 'active' : ''; ?>">
|
||||
<a href="installations-map.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Mapa instalacji">Mapa instalacji</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'devices.php') ? 'active' : ''; ?>">
|
||||
<a href="devices.php" class="menu-link">
|
||||
@@ -60,5 +72,23 @@ $currentPage = basename($_SERVER['PHP_SELF']);
|
||||
<div class="text-truncate" data-i18n="Raporty">Raporty</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'settings.php' || $currentPage == 'logs.php') ? 'active open' : ''; ?>">
|
||||
<a href="javascript:void(0);" class="menu-link menu-toggle">
|
||||
<i class="menu-icon tf-icons bx bx-server"></i>
|
||||
<div class="text-truncate" data-i18n="System">System</div>
|
||||
</a>
|
||||
<ul class="menu-sub">
|
||||
<li class="menu-item <?php echo ($currentPage == 'settings.php') ? 'active' : ''; ?>">
|
||||
<a href="settings.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Ustawienia">Ustawienia</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'logs.php') ? 'active' : ''; ?>">
|
||||
<a href="logs.php" class="menu-link">
|
||||
<div class="text-truncate" data-i18n="Logi">Logi systemowe</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-telemetria.php';
|
||||
?>
|
||||
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
<h4 class="fw-bold py-3 mb-4">
|
||||
Telemetria <span class="text-muted fw-light">/ Ustawienia</span>
|
||||
</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12 mb-4">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header border-bottom">
|
||||
<h5 class="card-title mb-0">Powiadomienia i Alerty</h5>
|
||||
</div>
|
||||
<div class="card-body pt-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div>
|
||||
<h6 class="mb-1">Aktywny moduł alertów</h6>
|
||||
<small class="text-muted">Pozwala na ustawianie zaawansowanych wyzwalaczy i powiadomień SMS/Email po przekroczeniu progów alarmowych w instalacjach.</small>
|
||||
</div>
|
||||
<div class="form-check form-switch form-switch-lg ms-3 mb-0">
|
||||
<input class="form-check-input" type="checkbox" id="alertsModuleSwitch">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-primary mt-3" onclick="saveSettings()">Zapisz ustawienia</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal potwierdzenia włączenia -->
|
||||
<div class="modal fade" id="confirmPaymentModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-warning border-2">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title text-warning"><i class="bx bx-error-circle me-1"></i> Potwierdzenie subskrypcji</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="cancelSwitch()"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Uruchomienie modułu <strong>Powiadomienia i Alerty</strong> wiąże się z dodatkową opłatą abonamentową w wysokości <strong>50 zł / msc</strong> doliczaną do Twojej faktury.</p>
|
||||
<p class="mb-0 text-dark fw-bold">Czy na pewno chcesz włączyć ten moduł?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal" onclick="cancelSwitch()">Anuluj</button>
|
||||
<button type="button" class="btn btn-success" data-bs-dismiss="modal" onclick="confirmSave()">Tak, włączam moduł</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let isCurrentlyEnabled = false; // Zakładamy że na start jest wyłączone
|
||||
|
||||
function saveSettings() {
|
||||
const switchEl = document.getElementById('alertsModuleSwitch');
|
||||
|
||||
// Jeśli chcemy włączyć, a wcześniej było wyłączone
|
||||
if (switchEl.checked && !isCurrentlyEnabled) {
|
||||
var paymentModal = new bootstrap.Modal(document.getElementById('confirmPaymentModal'));
|
||||
paymentModal.show();
|
||||
} else if (!switchEl.checked && isCurrentlyEnabled) {
|
||||
alert('Moduł został pomyślnie wyłączony. Opłata nie będzie naliczana od następnego okresu rozliczeniowego.');
|
||||
isCurrentlyEnabled = false;
|
||||
} else {
|
||||
alert('Ustawienia zapisane bez zmian.');
|
||||
}
|
||||
}
|
||||
|
||||
function confirmSave() {
|
||||
isCurrentlyEnabled = true;
|
||||
document.getElementById('alertsModuleSwitch').checked = true;
|
||||
alert('Moduł został włączony! Doliczono 50 zł/msc do Twojego abonamentu. Możesz teraz konfigurować alerty w instalacjach.');
|
||||
}
|
||||
|
||||
function cancelSwitch() {
|
||||
// Jeśli anulowano modal, przywracamy przełącznik do stanu wylączonego
|
||||
document.getElementById('alertsModuleSwitch').checked = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user