Nowa aplikacja: Company - widok informacji o firmie
This commit is contained in:
80
header-company.php
Normal file
80
header-company.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
$basePath = '';
|
||||
if ($_SERVER['HTTP_HOST'] === 'localhost' || $_SERVER['HTTP_HOST'] === '127.0.0.1') {
|
||||
$basePath = '/magico-prototype';
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" class="light-style layout-navbar-fixed layout-menu-fixed layout-compact" dir="ltr"
|
||||
data-theme="theme-default" data-assets-path="<?= $basePath ?>/assets/"
|
||||
data-template="vertical-menu-template-no-customizer-starter">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
|
||||
|
||||
<title>company.magico</title>
|
||||
|
||||
<meta name="description" content="" />
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/x-icon" href="<?= $basePath ?>/assets/img/favicon/favicon.ico" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap"
|
||||
rel="stylesheet" />
|
||||
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/fonts/boxicons.css" />
|
||||
<!-- <link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/fonts/fontawesome.css" /> -->
|
||||
<!-- <link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/fonts/flag-icons.css" /> -->
|
||||
|
||||
<!-- Core CSS -->
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/css/rtl/core.css" />
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/css/rtl/theme-default.css" />
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/css/demo.css" />
|
||||
|
||||
<!-- Vendors CSS -->
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/vendor/libs/perfect-scrollbar/perfect-scrollbar.css" />
|
||||
|
||||
<!-- Page CSS -->
|
||||
|
||||
<!-- Helpers -->
|
||||
<script src="<?= $basePath ?>/assets/vendor/js/helpers.js"></script>
|
||||
<!--! Template customizer & Theme config files MUST be included after core stylesheets and helpers.js in the <head> section -->
|
||||
<!--? Config: Mandatory theme config file contain global vars & default theme options, Set your preferred theme option in this file. -->
|
||||
<script src="<?= $basePath ?>/assets/js/config.js"></script>
|
||||
|
||||
<?php if (!empty($enablePrototypeComments) && $enablePrototypeComments): ?>
|
||||
<link rel="stylesheet" href="<?= $basePath ?>/assets/css/comments.css">
|
||||
<?php endif; ?>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1200px) {
|
||||
|
||||
.layout-menu-fixed .layout-menu,
|
||||
.layout-menu-fixed-offcanvas .layout-menu {
|
||||
padding-top: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Layout wrapper -->
|
||||
<div class="layout-wrapper layout-content-navbar">
|
||||
<div class="layout-container">
|
||||
<!-- Menu -->
|
||||
|
||||
<?php include 'menu.php'; ?>
|
||||
<!-- / Menu -->
|
||||
|
||||
<!-- Layout container -->
|
||||
<div class="layout-page pt-0" style="padding-top: 0 !important;">
|
||||
|
||||
<!-- Content wrapper -->
|
||||
<div class="content-wrapper">
|
||||
291
prototype/company/app-company-info.php
Normal file
291
prototype/company/app-company-info.php
Normal file
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-invoice.php';
|
||||
?>
|
||||
|
||||
<!-- Vendor CSS -->
|
||||
<link rel="stylesheet" href="../../assets/vendor/libs/select2/select2.css" />
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css" />
|
||||
|
||||
<style>
|
||||
/* Obłe krawędzie dla kółka wykadrowania w Cropper JS */
|
||||
.cropper-view-box,
|
||||
.cropper-face {
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-xxl flex-grow-1 container-p-y">
|
||||
|
||||
<h4 class="fw-bold py-3 mb-4">
|
||||
<span class="text-muted fw-light">Zarządzanie firmą /</span> Informacje o firmie
|
||||
</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<div class="card mb-4">
|
||||
<h5 class="card-header border-bottom">Profil firmy</h5>
|
||||
|
||||
<div class="card-body mt-3">
|
||||
<div class="d-flex align-items-start align-items-sm-center gap-4">
|
||||
<img src="https://ui-avatars.com/api/?name=Firma&background=e7e7ff&color=696cff&size=150"
|
||||
alt="Logo firmy" class="d-block rounded-circle" height="100" width="100" id="uploadedLogo"
|
||||
style="object-fit: cover;">
|
||||
<div class="button-wrapper">
|
||||
<label for="upload" class="btn btn-primary me-2 mb-3" tabindex="0">
|
||||
<span class="d-none d-sm-block">Wgraj nowe logo</span>
|
||||
<i class="bx bx-upload d-block d-sm-none"></i>
|
||||
<input type="file" id="upload" class="account-file-input" hidden
|
||||
accept="image/png, image/jpeg, image/jpg">
|
||||
</label>
|
||||
<button type="button" class="btn btn-label-secondary account-image-reset mb-3">
|
||||
<i class="bx bx-reset d-block d-sm-none"></i>
|
||||
<span class="d-none d-sm-block">Usuń</span>
|
||||
</button>
|
||||
<p class="text-muted mb-0">Dozwolone formaty: JPG, GIF lub PNG. Max rozmiar 800K</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-0">
|
||||
|
||||
<div class="card-body">
|
||||
<form id="formCompanyProfile" onsubmit="return false">
|
||||
<div class="row">
|
||||
<div class="mb-3 col-md-6">
|
||||
<label for="companyShortName" class="form-label">
|
||||
Krótka nazwa firmy
|
||||
<i class="bx bx-info-circle text-muted ms-1 cursor-pointer" data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="Nazwa będzie widoczna tylko dla Ciebie i współpracowników. Wykorzystywana w aplikacjach magico."></i>
|
||||
</label>
|
||||
<input class="form-control" type="text" id="companyShortName" name="companyShortName"
|
||||
placeholder="Wpisz krótką nazwę..." value="" autofocus>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<h5 class="card-header border-bottom">Dane rozliczeniowe</h5>
|
||||
<div class="card-body mt-3">
|
||||
<form id="formBillingSettings" onsubmit="return false">
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6">
|
||||
<label for="locationLabel" class="form-label">Kraj</label>
|
||||
<select id="locationLabel" class="form-select select2-country">
|
||||
<option value="pl" selected>Polska</option>
|
||||
<option value="us">Stany Zjednoczone</option>
|
||||
<option value="gb">Wielka Brytania</option>
|
||||
<option value="de">Niemcy</option>
|
||||
<option value="fr">Francja</option>
|
||||
<option value="it">Włochy</option>
|
||||
<option value="es">Hiszpania</option>
|
||||
<option value="ua">Ukraina</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="nipNumber" class="form-label">Numer NIP</label>
|
||||
<input type="text" name="nipNumber" id="nipNumber" placeholder="___-___-__-__"
|
||||
class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="companyFullName" class="form-label">Pełna nazwa firmy</label>
|
||||
<input type="text" name="companyFullName" id="companyFullName"
|
||||
placeholder="Wpisz pełną nazwę podmiotu..." class="form-control">
|
||||
<div class="form-text">Do użytku w rozliczeniach i fakturach</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="zipCode" class="form-label">Kod pocztowy</label>
|
||||
<input type="text" name="zipCode" id="zipCode" placeholder="__-___"
|
||||
class="form-control">
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label for="cityName" class="form-label">Miasto</label>
|
||||
<input type="text" name="cityName" id="cityName" placeholder="Wpisz miasto..."
|
||||
class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="addressDetails" class="form-label">Adres</label>
|
||||
<input type="text" name="addressDetails" id="addressDetails"
|
||||
placeholder="Ulica i numer budynku/lokalu" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mt-4">
|
||||
<div class="border-top pt-4">
|
||||
<label for="billingEmail" class="form-label">Dodatkowy adres e-mail do
|
||||
rozliczeń</label>
|
||||
<input type="email" name="billingEmail" id="billingEmail"
|
||||
placeholder="np. ksiegowosc@twojafirma.pl" class="form-control mb-2">
|
||||
|
||||
<div class="alert alert-primary d-flex align-items-baseline mb-0" role="alert">
|
||||
<span class="alert-icon align-middle me-2">
|
||||
<i class="bx bx-info-circle"></i>
|
||||
</span>
|
||||
<div>
|
||||
Dokumenty rozliczeniowe będą automatycznie wysyłane na powyższy adres
|
||||
(opcjonalnie) oraz do wszystkich użytkowników posiadających rolę
|
||||
<strong>"Właściciel"</strong> ustawioną w sekcji Zespół.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal dla Cropper.js -->
|
||||
<div class="modal fade" id="cropModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="cropModalLabel">Wykadruj logo (koło)</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zamknij"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="img-container"
|
||||
style="max-height: 400px; display: flex; justify-content: center; background-color: #f5f5f9;">
|
||||
<img id="imageToCrop" src="" alt="Obraz do wykadrowania" style="max-width: 100%; display: block;">
|
||||
</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" id="cropButton">Zatwierdź logo</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" class="footer" style="background: #e7e7ff; position: sticky; bottom: 0px; right: 0px;">
|
||||
<footer class="content-footer footer">
|
||||
<div class="container-xxl d-flex py-3 justify-content-center">
|
||||
<button class="btn btn-primary btn-lg">Zapisz</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<div class="content-backdrop fade"></div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="../../assets/vendor/libs/select2/select2.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// --- Inicjalizacja Tooltipów ---
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
|
||||
// --- Inicjalizacja Select2 ---
|
||||
function renderIcons(option) {
|
||||
if (!option.id) { return option.text; }
|
||||
var $icon = $(
|
||||
"<span class='d-flex align-items-center'><img src='https://flagcdn.com/w20/" + option.id.toLowerCase() + ".png' class='me-2' style='width: 20px; border-radius: 2px;' alt='flag' />" + option.text + "</span>"
|
||||
);
|
||||
return $icon;
|
||||
}
|
||||
|
||||
if ($('.select2-country').length) {
|
||||
$('.select2-country').select2({
|
||||
templateResult: renderIcons,
|
||||
templateSelection: renderIcons,
|
||||
escapeMarkup: function (es) { return es; }
|
||||
});
|
||||
}
|
||||
|
||||
// --- Inicjalizacja Cropper JS ---
|
||||
let cropper;
|
||||
const image = document.getElementById('imageToCrop');
|
||||
const input = document.getElementById('upload');
|
||||
const cropModalEl = document.getElementById('cropModal');
|
||||
const uploadedLogo = document.getElementById('uploadedLogo');
|
||||
let cropModal;
|
||||
|
||||
if (cropModalEl) {
|
||||
cropModal = new bootstrap.Modal(cropModalEl);
|
||||
}
|
||||
|
||||
if (input) {
|
||||
input.addEventListener('change', function (e) {
|
||||
const files = e.target.files;
|
||||
if (files && files.length > 0) {
|
||||
const file = files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
image.src = e.target.result;
|
||||
cropModal.show();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
input.value = ''; // reset value to allow choosing the same file again
|
||||
});
|
||||
}
|
||||
|
||||
if (cropModalEl) {
|
||||
cropModalEl.addEventListener('shown.bs.modal', function () {
|
||||
cropper = new Cropper(image, {
|
||||
aspectRatio: 1, // kwadrat = koło po zaokrągleniu
|
||||
viewMode: 1,
|
||||
dragMode: 'move',
|
||||
autoCropArea: 0.8,
|
||||
restore: false,
|
||||
guides: false,
|
||||
center: false,
|
||||
highlight: false,
|
||||
cropBoxMovable: true,
|
||||
cropBoxResizable: true,
|
||||
toggleDragModeOnDblclick: false,
|
||||
});
|
||||
});
|
||||
|
||||
cropModalEl.addEventListener('hidden.bs.modal', function () {
|
||||
if (cropper) {
|
||||
cropper.destroy();
|
||||
cropper = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const cropBtn = document.getElementById('cropButton');
|
||||
if (cropBtn) {
|
||||
cropBtn.addEventListener('click', function () {
|
||||
if (!cropper) return;
|
||||
const canvas = cropper.getCroppedCanvas({
|
||||
width: 300,
|
||||
height: 300
|
||||
});
|
||||
uploadedLogo.src = canvas.toDataURL(); // aktualizacja logo
|
||||
cropModal.hide();
|
||||
});
|
||||
}
|
||||
|
||||
// Reset obrazka
|
||||
const resetBtn = document.querySelector('.account-image-reset');
|
||||
if (resetBtn) {
|
||||
resetBtn.addEventListener('click', () => {
|
||||
uploadedLogo.src = 'https://ui-avatars.com/api/?name=Firma&background=e7e7ff&color=696cff&size=150';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
131
prototype/company/index.php
Normal file
131
prototype/company/index.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-invoice.php';
|
||||
?>
|
||||
|
||||
<div class="container-fluid flex-grow-1 container-p-y">
|
||||
|
||||
<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">Witaj w panelu firmy! 👋</h4>
|
||||
<p class="text-muted mb-0">Oto finansowe podsumowanie Twojego biznesu.</p>
|
||||
</div>
|
||||
<div class="d-flex align-content-center flex-wrap gap-2">
|
||||
<a href="app-invoice-add.php" class="btn btn-primary">
|
||||
<i class="bx bx-plus me-1"></i> Utwórz nową firmę
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<div class="content-backdrop fade"></div>
|
||||
|
||||
<?php include '../../footer.php'; ?>
|
||||
|
||||
<script src="../../assets/vendor/libs/apex-charts/apexcharts.js"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// Konfiguracja i kolory ze stylu szablonu
|
||||
let cardColor = '#fff',
|
||||
headingColor = '#566a7f',
|
||||
axisColor = '#a1acb8',
|
||||
borderColor = '#eceef1',
|
||||
primaryColor = '#696cff',
|
||||
infoColor = '#03c3ec';
|
||||
|
||||
// 1. Wykres Słupkowy - 12 Miesięcy (Przychody)
|
||||
const sales12MonthsEl = document.querySelector('#sales12MonthsChart');
|
||||
if (sales12MonthsEl) {
|
||||
const sales12MonthsOptions = {
|
||||
chart: {
|
||||
height: 300,
|
||||
type: 'bar',
|
||||
toolbar: { show: false }
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 4,
|
||||
columnWidth: '40%',
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded'
|
||||
}
|
||||
},
|
||||
colors: [primaryColor],
|
||||
dataLabels: { enabled: false },
|
||||
series: [{
|
||||
name: 'Sprzedaż Netto (zł)',
|
||||
data: [12000, 15000, 14000, 18000, 22000, 19000, 25000, 21000, 17000, 23000, 21800, 24500]
|
||||
}],
|
||||
xaxis: {
|
||||
categories: ['Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru', 'Sty', 'Lut', 'Mar'],
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
labels: { style: { colors: axisColor } }
|
||||
},
|
||||
yaxis: {
|
||||
labels: { style: { colors: axisColor }, formatter: function (val) { return val / 1000 + "k"; } }
|
||||
},
|
||||
grid: {
|
||||
borderColor: borderColor,
|
||||
strokeDashArray: 4,
|
||||
padding: { top: -20, bottom: -10, left: 10, right: 10 }
|
||||
}
|
||||
};
|
||||
const sales12MonthsChart = new ApexCharts(sales12MonthsEl, sales12MonthsOptions);
|
||||
sales12MonthsChart.render();
|
||||
}
|
||||
|
||||
// 2. Wykres Liniowy - Porównanie Rok do Roku (YoY)
|
||||
const salesYoYEl = document.querySelector('#salesYoYChart');
|
||||
if (salesYoYEl) {
|
||||
const salesYoYOptions = {
|
||||
chart: {
|
||||
height: 300,
|
||||
type: 'line',
|
||||
toolbar: { show: false }
|
||||
},
|
||||
stroke: {
|
||||
width: [2, 2, 2],
|
||||
curve: 'smooth'
|
||||
},
|
||||
colors: [primaryColor, infoColor, '#ffab00'], // Lata 2026, 2025, 2024
|
||||
series: [
|
||||
{ name: '2026', data: [15, 21.8, 24.5, null, null, null, null, null, null, null, null, null] },
|
||||
{ name: '2025', data: [12, 14, 18, 20, 25, 22, 28, 29, 31, 26, 33, 35] },
|
||||
{ name: '2024', data: [10, 11, 13, 14, 17, 16, 20, 21, 23, 22, 25, 28] }
|
||||
],
|
||||
legend: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
horizontalAlign: 'start',
|
||||
labels: { colors: headingColor }
|
||||
},
|
||||
xaxis: {
|
||||
categories: ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII'],
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
labels: { style: { colors: axisColor } }
|
||||
},
|
||||
yaxis: {
|
||||
show: false // Ukrywamy oś Y by wykres był czystszy (trend jest widoczny z tooltipów)
|
||||
},
|
||||
grid: {
|
||||
borderColor: borderColor,
|
||||
strokeDashArray: 4,
|
||||
padding: { top: 0, bottom: -10, left: 10, right: 10 }
|
||||
}
|
||||
};
|
||||
const salesYoYChart = new ApexCharts(salesYoYEl, salesYoYOptions);
|
||||
salesYoYChart.render();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
73
prototype/company/menu.php
Normal file
73
prototype/company/menu.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
$currentPage = basename($_SERVER['PHP_SELF']);
|
||||
?>
|
||||
<aside id="layout-menu" class="layout-menu menu-vertical menu bg-menu-theme">
|
||||
<div class="app-brand demo">
|
||||
<a href="index.php" class="app-brand-link">
|
||||
<span class="app-brand-text demo menu-text fw-bold ms-2">company.magico</span>
|
||||
</a>
|
||||
<a href="javascript:void(0);" class="layout-menu-toggle menu-link text-large ms-auto">
|
||||
<i class="bx bx-chevron-left bx-sm align-middle"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="menu-inner-shadow"></div>
|
||||
|
||||
<ul class="menu-inner py-1">
|
||||
|
||||
<!-- Zarządzanie firmą -->
|
||||
<li class="menu-header small text-uppercase">
|
||||
<span class="menu-header-text" data-i18n="Zarządzanie firmą">Zarządzanie firmą</span>
|
||||
</li>
|
||||
|
||||
<li class="menu-item <?php echo ($currentPage == 'index.php') ? 'active' : ''; ?>">
|
||||
<a href="index.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-home-circle"></i>
|
||||
<div class="text-truncate" data-i18n="Kokpit">Kokpit</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-services.php') ? 'active' : ''; ?>">
|
||||
<a href="app-services.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-grid-alt"></i>
|
||||
<div class="text-truncate" data-i18n="Usługi i aplikacje">Usługi i aplikacje</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-billing.php') ? 'active' : ''; ?>">
|
||||
<a href="app-billing.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-receipt"></i>
|
||||
<div class="text-truncate" data-i18n="Rozliczenia">Rozliczenia</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-company-info.php') ? 'active' : ''; ?>">
|
||||
<a href="app-company-info.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-buildings"></i>
|
||||
<div class="text-truncate" data-i18n="Informacje o firmie">Informacje o firmie</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- Zarządzanie zespołem -->
|
||||
<li class="menu-header small text-uppercase">
|
||||
<span class="menu-header-text" data-i18n="Zarządzanie zespołem">Zarządzanie zespołem</span>
|
||||
</li>
|
||||
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-team.php') ? 'active' : ''; ?>">
|
||||
<a href="app-team.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-group"></i>
|
||||
<div class="text-truncate" data-i18n="Zespół">Zespół</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-groups.php') ? 'active' : ''; ?>">
|
||||
<a href="app-groups.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-sitemap"></i>
|
||||
<div class="text-truncate" data-i18n="Grupy">Grupy</div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item <?php echo ($currentPage == 'app-permissions.php') ? 'active' : ''; ?>">
|
||||
<a href="app-permissions.php" class="menu-link">
|
||||
<i class="menu-icon tf-icons bx bx-shield-quarter"></i>
|
||||
<div class="text-truncate" data-i18n="Uprawnienia">Uprawnienia</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</aside>
|
||||
349
prototype/invoice/app-report-customers.php
Normal file
349
prototype/invoice/app-report-customers.php
Normal file
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
$enablePrototypeComments = true;
|
||||
include '../../header-invoice.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> Ranking klientów
|
||||
</h4>
|
||||
<p class="text-muted mb-0">Zestawienie kontrahentów generujących największy przychód (Top Nabywców).</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-4">
|
||||
<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 (od - do)" value="2026-01-01 do 2026-06-30" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label" for="reportLimit">Zakres danych</label>
|
||||
<select id="reportLimit" class="form-select select2">
|
||||
<option value="10" selected>Top 10</option>
|
||||
<option value="50">Top 50</option>
|
||||
<option value="all">Wszyscy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 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>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Wykres - zajmuje prawą stronę na dużym ekranie, bądź górę -->
|
||||
<div class="col-12">
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title m-0">Wykres Top 10 Odbiorców</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="customersReportChart" style="min-height: 400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tabela -->
|
||||
<div class="col-12">
|
||||
<div class="card h-100">
|
||||
<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 table-sm align-middle">
|
||||
<thead class="table-light sticky-top">
|
||||
<tr>
|
||||
<th class="text-center" style="width: 50px;">Miejsce</th>
|
||||
<th>Kontrahent</th>
|
||||
<th class="text-center">Dokumenty</th>
|
||||
<th class="text-end">Kwota Netto</th>
|
||||
<th style="width: 120px;">Udział %</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<div class="avatar avatar-sm mx-auto">
|
||||
<span
|
||||
class="avatar-initial rounded-circle bg-label-warning fw-bold fs-6">1</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">TechSolutions Sp. z o.o.</span>
|
||||
<small class="text-muted">NIP: 813-345-67-89</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">24</td>
|
||||
<td class="text-end fw-bold">64 500.00 zł</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="progress w-100" style="height: 6px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 35.3%"
|
||||
aria-valuenow="35.3" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="fw-medium">35%</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<div class="avatar avatar-sm mx-auto">
|
||||
<span class="avatar-initial rounded-circle bg-label-secondary fw-bold fs-6"
|
||||
style="color:#788393 !important;">2</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">Gmina Stalowa Wola</span>
|
||||
<small class="text-muted">NIP: 865-123-44-55</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">8</td>
|
||||
<td class="text-end fw-bold">42 800.00 zł</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="progress w-100" style="height: 6px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 23.4%"
|
||||
aria-valuenow="23.4" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="fw-medium">23%</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<div class="avatar avatar-sm mx-auto">
|
||||
<span class="avatar-initial rounded-circle bg-label-danger fw-bold fs-6"
|
||||
style="color:#ffb400 !important; background-color: #fff2d6 !important;">3</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">Kwiaciarnia "Róża"</span>
|
||||
<small class="text-muted">NIP: 734-111-22-33</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">45</td>
|
||||
<td class="text-end fw-bold">31 200.00 zł</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="progress w-100" style="height: 6px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 17.1%"
|
||||
aria-valuenow="17.1" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="fw-medium">17%</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center"><span class="text-muted fw-bold">4</span></td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">F.H.U Jan Kowalski</span>
|
||||
<small class="text-muted">NIP: 555-666-77-88</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">12</td>
|
||||
<td class="text-end fw-bold">18 500.00 zł</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="progress w-100" style="height: 6px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 10.1%"
|
||||
aria-valuenow="10.1" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="fw-medium">10%</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center"><span class="text-muted fw-bold">5</span></td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">Piekarnia "Złoty Kłos"</span>
|
||||
<small class="text-muted">NIP: 123-456-78-90</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">31</td>
|
||||
<td class="text-end fw-bold">15 400.00 zł</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="progress w-100" style="height: 6px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 8.4%"
|
||||
aria-valuenow="8.4" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="fw-medium">8%</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center"><span class="text-muted fw-bold">6</span></td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-medium text-heading">Sklep Rybny "Posejdon"</span>
|
||||
<small class="text-muted">NIP: 987-654-32-10</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">4</td>
|
||||
<td class="text-end fw-bold">10 150.00 zł</td>
|
||||
<td>
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="progress w-100" style="height: 6px;">
|
||||
<div class="progress-bar bg-primary" role="progressbar" style="width: 5.6%"
|
||||
aria-valuenow="5.6" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<small class="fw-medium">6%</small>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot class="table-light fw-bold">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="text-center">124</td>
|
||||
<td class="text-end text-primary">182 550.00 zł</td>
|
||||
<td class="text-center">100%</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</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
|
||||
if (typeof flatpickr !== 'undefined') {
|
||||
const dateRangeEl = document.querySelector('.flatpickr-range');
|
||||
if (dateRangeEl) {
|
||||
flatpickr(dateRangeEl, {
|
||||
mode: 'range',
|
||||
dateFormat: 'Y-m-d',
|
||||
locale: 'pl'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Inicjalizacja Select2
|
||||
if (typeof $ !== 'undefined' && $('.select2').length) {
|
||||
$('.select2').select2({
|
||||
minimumResultsForSearch: Infinity
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Inicjalizacja Wykresu (Horizontal Bar)
|
||||
const chartEl = document.querySelector('#customersReportChart');
|
||||
if (chartEl && typeof ApexCharts !== 'undefined') {
|
||||
const chartConfig = {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 480, // Trochę wyższy by pomieścić wszystkie etykiety
|
||||
parentHeightOffset: 0,
|
||||
toolbar: { show: false }
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 4,
|
||||
horizontal: true, // Kluczowe by wykres był poziomy
|
||||
barHeight: '50%',
|
||||
startingShape: 'rounded',
|
||||
endingShape: 'rounded'
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
textAnchor: 'start',
|
||||
style: {
|
||||
colors: ['#fff']
|
||||
},
|
||||
formatter: function (val, opt) {
|
||||
return val.toLocaleString('pl-PL') + " zł";
|
||||
},
|
||||
offsetX: 0,
|
||||
},
|
||||
series: [{
|
||||
name: 'Przychody netto',
|
||||
data: [64500, 42800, 31200, 18500, 15400, 10150]
|
||||
}],
|
||||
xaxis: {
|
||||
categories: [
|
||||
'TechSolutions Sp.', 'Gmina Stalowa Wola',
|
||||
'Kwiaciarnia "Róża"',
|
||||
'F.H.U Jan Kowalski',
|
||||
'Piekarnia Złoty Kłos',
|
||||
'Sklep Rybny Posejdon'
|
||||
],
|
||||
labels: {
|
||||
formatter: function (val) {
|
||||
return (val / 1000) + "k";
|
||||
},
|
||||
style: { colors: '#a1acb8', fontSize: '13px' }
|
||||
},
|
||||
axisBorder: { show: false },
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: { colors: '#566a7f', fontSize: '13px', fontWeight: 500 }
|
||||
}
|
||||
},
|
||||
colors: ['#696cff'], // Primary color
|
||||
grid: {
|
||||
borderColor: '#e9ecef',
|
||||
strokeDashArray: 4,
|
||||
xaxis: { lines: { show: true } },
|
||||
yaxis: { lines: { show: false } },
|
||||
padding: { top: -20, bottom: -10, left: 10, right: 10 }
|
||||
},
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val) {
|
||||
return val.toLocaleString('pl-PL') + " zł";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const customersChart = new ApexCharts(chartEl, chartConfig);
|
||||
customersChart.render();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -64,6 +64,53 @@ include '../../header-invoice.php';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ranking klientów -->
|
||||
<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-success">Przychody</span>
|
||||
</div>
|
||||
<a href="javascript:void(0);" class="h5 mb-2 fw-semibold">Ranking klientów</a>
|
||||
<p class="mt-1 text-muted mb-4 flex-grow-1">
|
||||
Zbiorcze zestawienie wszystkich kontrahentów ułożonych od generujących największy przychód
|
||||
do najmniejszego.
|
||||
Pomaga szybko zidentyfikować kluczowych nabywców.
|
||||
</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="app-report-customers.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>
|
||||
|
||||
<!-- Analiza kontrahenta -->
|
||||
<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-success">Przychody</span>
|
||||
</div>
|
||||
<a href="javascript:void(0);" class="h5 mb-2 fw-semibold">Historia kontrahenta</a>
|
||||
<p class="mt-1 text-muted mb-4 flex-grow-1">
|
||||
Szczegółowa analiza sprzedaży dla wybranego, pojedynczego klienta.
|
||||
Ukazuje trendy, zestawienie poszczególnych faktur i dokumentów z danym kontrahentem.
|
||||
</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>
|
||||
|
||||
<!-- Raport kwotowy kosztów -->
|
||||
<div class="col-sm-6 col-lg-4 mb-4">
|
||||
<div class="card p-2 h-100 shadow-none border">
|
||||
|
||||
@@ -11,14 +11,7 @@ include '../../header-invoice.php';
|
||||
<h4 class="mb-1 text-body">Witaj w panelu firmy! 👋</h4>
|
||||
<p class="text-muted mb-0">Oto finansowe podsumowanie Twojego biznesu.</p>
|
||||
</div>
|
||||
<div class="d-flex align-content-center flex-wrap gap-2">
|
||||
<a href="app-purchase-add.php" class="btn btn-label-secondary">
|
||||
<i class="bx bx-plus me-1"></i> Dodaj koszt
|
||||
</a>
|
||||
<a href="app-invoice-add.php" class="btn btn-primary">
|
||||
<i class="bx bx-plus me-1"></i> Wystaw fakturę
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-xl-5 g-4 mb-4">
|
||||
|
||||
Reference in New Issue
Block a user