Telemetria: Raporty

This commit is contained in:
2026-06-18 08:41:49 +02:00
parent a9327760d0
commit 8ed8d3bb42
5 changed files with 589 additions and 31 deletions

View File

@@ -82,38 +82,101 @@ include '../../header-telemetria.php';
</div>
<hr>
<h6 class="text-muted mb-3">Parametry pomiarowe (<span id="type-label-name">Zbiornik
<h6 class="text-muted mb-3">Moduły i Czujniki (<span id="type-label-name">Zbiornik
Gazu</span>)</h6>
<p class="small text-muted mb-4">Włącz czujniki i moduły, które fizycznie obsługuje ta instalacja.</p>
<!-- Parametry Zbiornik (pokazywane dynamicznie) -->
<div id="form-gas" class="row dynamic-form-part">
<div class="col-md-4 mb-3">
<label class="form-label">Pojemność nominalna (litry)</label>
<input type="number" class="form-control" value="2700">
<div id="form-gas" class="dynamic-form-part">
<div class="row mb-4">
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasLevel" checked onchange="toggleSensorConfig('gasLevel')">
<label class="form-check-label fw-bold" for="sensorGasLevel">Poziom napełnienia</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasPressure" checked onchange="toggleSensorConfig('gasPressure')">
<label class="form-check-label fw-bold" for="sensorGasPressure">Ciśnienie</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasTemp" onchange="toggleSensorConfig('gasTemp')">
<label class="form-check-label fw-bold" for="sensorGasTemp">Temperatura</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasGps" onchange="toggleSensorConfig('gasGps')">
<label class="form-check-label fw-bold" for="sensorGasGps">Moduł GPS</label>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Maks. ciśnienie bezp. (bar)</label>
<input type="number" step="0.1" class="form-control" value="15.5">
<div class="row bg-lighter p-3 rounded mb-3" id="config-gasLevel">
<h6 class="mb-3 text-primary"><i class="bx bx-slider-alt"></i> Konfiguracja: Poziom napełnienia</h6>
<div class="col-md-6 mb-3">
<label class="form-label">Pojemność nominalna (litry)</label>
<input type="number" class="form-control" value="2700">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Offset sondy (mm)</label>
<input type="number" class="form-control" value="0">
</div>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Stały adres IP (Opcjonalnie)</label>
<input type="text" class="form-control" placeholder="192.168.1.x">
<div class="row bg-lighter p-3 rounded mb-3" id="config-gasPressure">
<h6 class="mb-3 text-primary"><i class="bx bx-tachometer"></i> Konfiguracja: Ciśnienie</h6>
<div class="col-md-6 mb-3">
<label class="form-label">Maks. ciśnienie bezpieczne (bar)</label>
<input type="number" step="0.1" class="form-control" value="15.5">
</div>
</div>
<div class="row bg-lighter p-3 rounded mb-3 d-none" id="config-gasTemp">
<h6 class="mb-3 text-primary"><i class="bx bxs-thermometer"></i> Konfiguracja: Temperatura</h6>
<div class="col-md-6 mb-3">
<label class="form-label">Korekta wskazań (°C)</label>
<input type="number" step="0.1" class="form-control" value="0.0">
</div>
</div>
<div class="row bg-lighter p-3 rounded mb-3 d-none" id="config-gasGps">
<h6 class="mb-3 text-primary"><i class="bx bx-map"></i> Konfiguracja: GPS</h6>
<div class="col-md-12">
<p class="small text-muted mb-0">Ten moduł nie wymaga dodatkowej konfiguracji. Raportowanie pozycji odbywa się automatycznie.</p>
</div>
</div>
</div>
<!-- Parametry Kurnik (pokazywane dynamicznie) -->
<div id="form-farm" class="row dynamic-form-part d-none">
<div class="col-md-4 mb-3">
<label class="form-label">Liczba stref grzewczych</label>
<input type="number" class="form-control" value="2">
<div id="form-farm" class="dynamic-form-part d-none">
<div class="row mb-4">
<div class="col-md-4">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorFarmTemp" checked>
<label class="form-check-label fw-bold" for="sensorFarmTemp">Sensory Temp.</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorFarmVent" checked>
<label class="form-check-label fw-bold" for="sensorFarmVent">Sterowanie Wentylacją</label>
</div>
</div>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Liczba wentylatorów</label>
<input type="number" class="form-control" value="4">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Interwał próbkowania (sekundy)</label>
<input type="number" class="form-control" value="60">
<div class="row bg-lighter p-3 rounded mb-3">
<div class="col-md-6 mb-3">
<label class="form-label">Liczba stref grzewczych</label>
<input type="number" class="form-control" value="2">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Interwał próbkowania (sekundy)</label>
<input type="number" class="form-control" value="60">
</div>
</div>
</div>
@@ -262,6 +325,18 @@ include '../../header-telemetria.php';
alert("Token skopiowany do schowka!");
}
function toggleSensorConfig(sensorId) {
const checkbox = document.getElementById('sensor' + sensorId.charAt(0).toUpperCase() + sensorId.slice(1));
const configDiv = document.getElementById('config-' + sensorId);
if (configDiv) {
if (checkbox.checked) {
configDiv.classList.remove('d-none');
} else {
configDiv.classList.add('d-none');
}
}
}
function addAlertRow() {
const container = document.getElementById('alerts-container');
const rowHTML = `

View File

@@ -34,21 +34,69 @@ include '../../header-telemetria.php';
</div>
<hr>
<h6 class="text-muted mb-3">Parametry pomiarowe</h6>
<h6 class="text-muted mb-3">Moduły i Czujniki</h6>
<p class="small text-muted mb-4">Zarządzaj aktywnymi czujnikami, które fizycznie obsługuje ta instalacja.</p>
<!-- Parametry Zbiornik (pokazywane na stałe w edycji dla tego konkretnego obiektu) -->
<div class="row">
<div class="col-md-4 mb-3">
<div class="row mb-4">
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasLevel" checked onchange="toggleSensorConfig('gasLevel')">
<label class="form-check-label fw-bold" for="sensorGasLevel">Poziom napełnienia</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasPressure" checked onchange="toggleSensorConfig('gasPressure')">
<label class="form-check-label fw-bold" for="sensorGasPressure">Ciśnienie</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasTemp" onchange="toggleSensorConfig('gasTemp')">
<label class="form-check-label fw-bold" for="sensorGasTemp">Temperatura</label>
</div>
</div>
<div class="col-md-3">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="sensorGasGps" checked onchange="toggleSensorConfig('gasGps')">
<label class="form-check-label fw-bold" for="sensorGasGps">Moduł GPS</label>
</div>
</div>
</div>
<!-- Parametry Zbiornik -->
<div class="row bg-lighter p-3 rounded mb-3" id="config-gasLevel">
<h6 class="mb-3 text-primary"><i class="bx bx-slider-alt"></i> Konfiguracja: Poziom napełnienia</h6>
<div class="col-md-6 mb-3">
<label class="form-label">Pojemność nominalna (litry)</label>
<input type="number" class="form-control" value="2700">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Maks. ciśnienie bezp. (bar)</label>
<div class="col-md-6 mb-3">
<label class="form-label">Offset sondy (mm)</label>
<input type="number" class="form-control" value="0">
</div>
</div>
<div class="row bg-lighter p-3 rounded mb-3" id="config-gasPressure">
<h6 class="mb-3 text-primary"><i class="bx bx-tachometer"></i> Konfiguracja: Ciśnienie</h6>
<div class="col-md-6 mb-3">
<label class="form-label">Maks. ciśnienie bezpieczne (bar)</label>
<input type="number" step="0.1" class="form-control" value="15.5">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Stały adres IP (Opcjonalnie)</label>
<input type="text" class="form-control" value="192.168.1.100">
</div>
<div class="row bg-lighter p-3 rounded mb-3 d-none" id="config-gasTemp">
<h6 class="mb-3 text-primary"><i class="bx bxs-thermometer"></i> Konfiguracja: Temperatura</h6>
<div class="col-md-6 mb-3">
<label class="form-label">Korekta wskazań (°C)</label>
<input type="number" step="0.1" class="form-control" value="0.0">
</div>
</div>
<div class="row bg-lighter p-3 rounded mb-3" id="config-gasGps">
<h6 class="mb-3 text-primary"><i class="bx bx-map"></i> Konfiguracja: GPS</h6>
<div class="col-md-12">
<p class="small text-muted mb-0">Ten moduł nie wymaga dodatkowej konfiguracji. Raportowanie pozycji odbywa się automatycznie na podstawie satelitów.</p>
</div>
</div>
@@ -204,5 +252,19 @@ include '../../header-telemetria.php';
}
</script>
<script>
function toggleSensorConfig(sensorId) {
const checkbox = document.getElementById('sensor' + sensorId.charAt(0).toUpperCase() + sensorId.slice(1));
const configDiv = document.getElementById('config-' + sensorId);
if (configDiv) {
if (checkbox.checked) {
configDiv.classList.remove('d-none');
} else {
configDiv.classList.add('d-none');
}
}
}
</script>
</body>
</html>

View File

@@ -31,5 +31,11 @@ $currentPage = basename($_SERVER['PHP_SELF']);
<div class="text-truncate" data-i18n="Instalacje">Instalacje</div>
</a>
</li>
<li class="menu-item <?php echo ($currentPage == 'reports.php') ? 'active' : ''; ?>">
<a href="reports.php" class="menu-link">
<i class="menu-icon tf-icons bx bx-bar-chart-alt-2"></i>
<div class="text-truncate" data-i18n="Raporty">Raporty</div>
</a>
</li>
</ul>
</aside>

View File

@@ -0,0 +1,281 @@
<?php
$enablePrototypeComments = true;
include '../../header-telemetria.php';
?>
<div class="container-xxl flex-grow-1 container-p-y">
<!-- Vendors CSS dla Select2 i Flatpickr -->
<link rel="stylesheet" href="../../assets/vendor/libs/select2/select2.css" />
<link rel="stylesheet" href="../../assets/vendor/libs/flatpickr/flatpickr.css" />
<!-- Nagłówek i przyciski akcji -->
<div
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-4 gap-3">
<div>
<h4 class="fw-bold mb-1">
<span class="text-muted fw-light">Raporty /</span> Historia zużycia medium
</h4>
<p class="text-muted mb-0">Zestawienie konsumpcji gazu / ubytków poziomu dla wskazanej instalacji we wskazanym okresie.</p>
</div>
<div class="d-flex gap-2">
<button class="btn btn-label-secondary">
<i class="bx bx-export me-1"></i> Eksportuj CSV
</button>
<button class="btn btn-primary">
<i class="bx bx-printer me-1"></i> Drukuj raport
</button>
</div>
</div>
<!-- Karta filtrów -->
<div class="card mb-4">
<div class="card-body">
<form class="row g-3">
<div class="col-12 col-md-3">
<label class="form-label" for="reportInstallation">Instalacja</label>
<select id="reportInstallation" class="form-select select2">
<option value="all">Wszystkie zebrane razem</option>
<option value="1" selected>Zbiornik LPG #1 (Stalowa Wola)</option>
<option value="2">Zbiornik LPG #2 (Rzeszów)</option>
<option value="3">Kurnik Główny</option>
</select>
</div>
<div class="col-12 col-md-3">
<label class="form-label" for="reportDateRange">Zakres dat</label>
<div class="input-group input-group-merge">
<span class="input-group-text"><i class="bx bx-calendar"></i></span>
<input type="text" id="reportDateRange" class="form-control flatpickr-range"
placeholder="Wybierz okres" value="2026-01-01 do 2026-06-30" />
</div>
</div>
<div class="col-12 col-md-3">
<label class="form-label" for="reportGranularity">Szczegółowość</label>
<select id="reportGranularity" class="form-select select2">
<option value="days">Dni</option>
<option value="weeks">Tygodnie</option>
<option value="months" selected>Miesiące</option>
</select>
<small id="daysLimitInfo" class="text-muted d-none mt-1 d-block">
<i class="bx bx-info-circle fs-6 align-middle me-1"></i>Maksymalny okres wynosi 366 dni.
</small>
</div>
<div class="col-12 col-md-3 d-flex align-items-end">
<button type="button" class="btn btn-primary w-100 w-md-auto">
<i class="bx bx-refresh me-1"></i> Generuj
</button>
</div>
</form>
</div>
</div>
<!-- Karta z wykresem -->
<div class="card mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title m-0">Zużycie medium w czasie (litry)</h5>
</div>
<div class="card-body">
<div id="consumptionReportChart" style="min-height: 350px;"></div>
</div>
</div>
<!-- Karta z tabelą danych -->
<div class="card">
<div class="card-header border-bottom">
<h5 class="card-title m-0">Szczegółowe zestawienie</h5>
</div>
<div class="table-responsive text-nowrap">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>Okres</th>
<th class="text-center">Liczba odczytów</th>
<th class="text-end">Stan początkowy</th>
<th class="text-end">Stan końcowy</th>
<th class="text-end">Całkowite zużycie</th>
</tr>
</thead>
<tbody>
<tr>
<td class="fw-medium">Styczeń 2026</td>
<td class="text-center">744</td>
<td class="text-end">2100 l (77%)</td>
<td class="text-end">1550 l (57%)</td>
<td class="text-end fw-bold text-danger">-550 l</td>
</tr>
<tr>
<td class="fw-medium">Luty 2026</td>
<td class="text-center">672</td>
<td class="text-end">1550 l (57%)</td>
<td class="text-end">850 l (31%)</td>
<td class="text-end fw-bold text-danger">-700 l</td>
</tr>
<tr class="table-primary bg-label-primary">
<td class="fw-medium">Marzec 2026 <i class="bx bx-gas-pump ms-1 text-primary" title="Zarejestrowano tankowanie"></i></td>
<td class="text-center">744</td>
<td class="text-end">850 l (31%)</td>
<td class="text-end">2500 l (92%)</td>
<td class="text-end fw-bold text-success">+1650 l</td>
</tr>
<tr>
<td class="fw-medium">Kwiecień 2026</td>
<td class="text-center">720</td>
<td class="text-end">2500 l (92%)</td>
<td class="text-end">2100 l (77%)</td>
<td class="text-end fw-bold text-danger">-400 l</td>
</tr>
<tr>
<td class="fw-medium">Maj 2026</td>
<td class="text-center">744</td>
<td class="text-end">2100 l (77%)</td>
<td class="text-end">1800 l (66%)</td>
<td class="text-end fw-bold text-danger">-300 l</td>
</tr>
<tr>
<td class="fw-medium">Czerwiec 2026</td>
<td class="text-center">360</td>
<td class="text-end">1800 l (66%)</td>
<td class="text-end">1620 l (60%)</td>
<td class="text-end fw-bold text-danger">-180 l</td>
</tr>
</tbody>
<tfoot class="table-light fw-bold">
<tr>
<td>Podsumowanie</td>
<td class="text-center">3984</td>
<td class="text-end text-muted">-</td>
<td class="text-end text-muted">-</td>
<td class="text-end text-primary fs-5">Zbilansowano: -480 l</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<?php include '../../footer.php'; ?>
<!-- Vendors JS -->
<script src="../../assets/vendor/libs/select2/select2.js"></script>
<script src="../../assets/vendor/libs/flatpickr/flatpickr.js"></script>
<!-- ApexCharts scripts and local chart init -->
<script src="../../assets/vendor/libs/apex-charts/apexcharts.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// 1. Inicjalizacja Flatpickr dla zakresu dat
if (typeof flatpickr !== 'undefined') {
const dateRangeEl = document.querySelector('.flatpickr-range');
if (dateRangeEl) {
const fp = flatpickr(dateRangeEl, {
mode: 'range',
dateFormat: 'Y-m-d',
locale: 'pl'
});
}
}
// 2. Inicjalizacja Select2
if (typeof $ !== 'undefined' && $('.select2').length) {
$('.select2').select2({
minimumResultsForSearch: 5
});
// Obsługa pojawiania się podpowiedzi po wybraniu z selecta
$('#reportGranularity').on('change', function () {
const daysInfo = document.getElementById('daysLimitInfo');
if (this.value === 'days') {
daysInfo.classList.remove('d-none');
} else {
daysInfo.classList.add('d-none');
}
});
}
// 3. Inicjalizacja Wykresu
const chartEl = document.querySelector('#consumptionReportChart');
if (chartEl && typeof ApexCharts !== 'undefined') {
const chartConfig = {
chart: {
height: 350,
type: 'area', // Zmieniono na area, by ładnie pokazywać spadek/wzrost litrów
parentHeightOffset: 0,
toolbar: {
show: false
}
},
dataLabels: {
enabled: false
},
stroke: {
curve: 'smooth',
width: 3
},
series: [{
name: 'Stan początkowy w danym miesiącu (litry)',
data: [2100, 1550, 850, 2500, 2100, 1800]
}],
xaxis: {
categories: ['Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec'],
axisBorder: {
show: false
},
axisTicks: {
show: false
},
labels: {
style: {
colors: '#a1acb8',
fontSize: '13px'
}
}
},
yaxis: {
labels: {
formatter: function (val) {
return val.toLocaleString('pl-PL') + " l";
},
style: {
colors: '#a1acb8',
fontSize: '13px'
}
}
},
colors: ['#00cfdd'], // Kolor np. cyan
fill: {
type: 'gradient',
gradient: {
shadeIntensity: 1,
opacityFrom: 0.5,
opacityTo: 0.1,
stops: [0, 90, 100]
}
},
grid: {
borderColor: '#e9ecef',
strokeDashArray: 4,
padding: {
top: -20,
bottom: -10,
left: 20,
right: 20
}
},
tooltip: {
y: {
formatter: function (val) {
return val.toLocaleString('pl-PL') + " l";
}
}
}
};
const consumptionChart = new ApexCharts(chartEl, chartConfig);
consumptionChart.render();
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,134 @@
<?php
$enablePrototypeComments = true;
include '../../header-telemetria.php';
?>
<div class="container-xxl flex-grow-1 container-p-y">
<!-- Header with description -->
<div class="card p-0 mb-4">
<div class="card-body d-flex flex-column flex-md-row justify-content-between p-0">
<!-- Left image -->
<div class="d-none d-md-flex app-academy-md-25 card-body py-0 pt-3 ps-5 align-items-center">
<img src="../../assets/img/illustrations/bulb-light.png" width="90" class="img-fluid" alt="Bulb"
data-app-light-img="illustrations/bulb-light.png" data-app-dark-img="illustrations/bulb-dark.png">
</div>
<!-- Center context -->
<div class="app-academy-md-50 card-body d-flex align-items-md-center flex-column text-md-center mb-1 py-5">
<h4 class="card-title mb-4 px-md-12 lh-base fw-bold">
Analizuj dane z instalacji<br>
w <span class="text-primary text-nowrap">przejrzystych raportach</span>.
</h4>
<p class="mb-4 col-md-10 text-muted">
Poniżej prezentujemy dostępne raporty telemetryczne. Wybierz zestawienie, aby
przeanalizować historię zużycia medium, zidentyfikować anomalie oraz zweryfikować
stabilność połączeń na Twoich obiektach.
</p>
</div>
<!-- Right image -->
<div class="d-none d-md-flex app-academy-md-25 align-items-end justify-content-end pe-4 pb-2">
<img src="../../assets/img/illustrations/pencil-rocket.png" alt="pencil rocket" height="150"
class="scaleX-n1-rtl">
</div>
</div>
</div>
<!-- Reports Gallery -->
<div class="card p-4">
<div class="row">
<!-- Raport historii zużycia -->
<div class="col-sm-6 col-lg-4 mb-4">
<div class="card p-2 h-100 shadow-none border border-primary">
<div class="card-body p-4 pt-2 d-flex flex-column">
<div class="d-flex justify-content-between align-items-center mb-4">
<span class="badge bg-label-primary">Eksploatacja</span>
</div>
<a href="report-consumption.php" class="h5 mb-2 fw-semibold text-primary">Historia zużycia medium</a>
<p class="mt-1 text-muted mb-4 flex-grow-1">
Wykres i tabela prezentująca ubytki / konsumpcję gazu (lub innego medium) dla wskazanej instalacji w danym przedziale czasowym. Oblicza dzienne i miesięczne zużycie.
</p>
<div class="d-flex flex-column flex-md-row gap-4 mt-auto">
<a class="w-100 btn btn-primary d-flex align-items-center justify-content-center"
href="report-consumption.php">
<span class="me-2">Wygeneruj</span>
<i class="bx bx-chevron-right icon-sm lh-1 scaleX-n1-rtl"></i>
</a>
</div>
</div>
</div>
</div>
<!-- Dziennik alertów i przekroczeń -->
<div class="col-sm-6 col-lg-4 mb-4">
<div class="card p-2 h-100 shadow-none border">
<div class="card-body p-4 pt-2 d-flex flex-column">
<div class="d-flex justify-content-between align-items-center mb-4">
<span class="badge bg-label-danger">Bezpieczeństwo</span>
</div>
<a href="javascript:void(0);" class="h5 mb-2 fw-semibold">Dziennik alertów</a>
<p class="mt-1 text-muted mb-4 flex-grow-1">
Ewidencja wszystkich wygenerowanych alarmów, w tym przekroczeń ciśnienia, krytycznie niskich stanów, z datami ich wystąpienia i powiadomionymi osobami.
</p>
<div class="d-flex flex-column flex-md-row gap-4 mt-auto">
<a class="w-100 btn btn-label-primary d-flex align-items-center justify-content-center"
href="javascript:void(0);">
<span class="me-2">Wygeneruj</span>
<i class="bx bx-chevron-right icon-sm lh-1 scaleX-n1-rtl"></i>
</a>
</div>
</div>
</div>
</div>
<!-- Analiza stabilności infrastruktury -->
<div class="col-sm-6 col-lg-4 mb-4">
<div class="card p-2 h-100 shadow-none border">
<div class="card-body p-4 pt-2 d-flex flex-column">
<div class="d-flex justify-content-between align-items-center mb-4">
<span class="badge bg-label-warning">Serwis i Sprzęt</span>
</div>
<a href="javascript:void(0);" class="h5 mb-2 fw-semibold">Analiza stabilności sieci</a>
<p class="mt-1 text-muted mb-4 flex-grow-1">
Monitorowanie przerw w łączności GSM, skoków napięcia i krzywej rozładowania baterii. Służy do planowania prac serwisowych (Predictive Maintenance).
</p>
<div class="d-flex flex-column flex-md-row gap-4 mt-auto">
<a class="w-100 btn btn-label-primary d-flex align-items-center justify-content-center"
href="javascript:void(0);">
<span class="me-2">Wygeneruj</span>
<i class="bx bx-chevron-right icon-sm lh-1 scaleX-n1-rtl"></i>
</a>
</div>
</div>
</div>
</div>
<!-- Sumaryczny bilans instalacji -->
<div class="col-sm-6 col-lg-4 mb-4">
<div class="card p-2 h-100 shadow-none border">
<div class="card-body p-4 pt-2 d-flex flex-column">
<div class="d-flex justify-content-between align-items-center mb-4">
<span class="badge bg-label-info">Podsumowanie całkowite</span>
</div>
<a href="javascript:void(0);" class="h5 mb-2 fw-semibold">Bilans flotowy</a>
<p class="mt-1 text-muted mb-4 flex-grow-1">
Całkowite zestawienie posiadanych zasobów na dany dzień sumuje dostępne litry gazu we wszystkich połączonych zbiornikach, ułatwiając logistykę tankowania.
</p>
<div class="d-flex flex-column flex-md-row gap-4 mt-auto">
<a class="w-100 btn btn-label-primary d-flex align-items-center justify-content-center"
href="javascript:void(0);">
<span class="me-2">Wygeneruj</span>
<i class="bx bx-chevron-right icon-sm lh-1 scaleX-n1-rtl"></i>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php include '../../footer.php'; ?>