{{--
|--------------------------------------------------------------------------
| Plik Widoku: Panel Główny (Vendor Dashboard)
|--------------------------------------------------------------------------
|
| Lokalizacja: resources/views/home.blade.php
| Autor: Tomasz Kaplanski
| Wersja: 1.0
| Ostatnia modyfikacja: 14 lipca 2025
|
|--------------------------------------------------------------------------
| Opis Przeznaczenia
|--------------------------------------------------------------------------
|
| Ten plik Blade renderuje główny panel informacyjny (dashboard) dla
| zalogowanego użytkownika z rolą "vendor" (sprzedawca/restauracja).
| Pełni on rolę centrum dowodzenia, agregując i wizualizując kluczowe
| dane biznesowe w czasie rzeczywistym. Widok umożliwia szybką ocenę
| bieżącej kondycji finansowej, statusu zamówień oraz przegląd
| najnowszej aktywności w systemie.
|
|--------------------------------------------------------------------------
| Kluczowe Funkcjonalności
|--------------------------------------------------------------------------
|
| - Wyświetlanie dynamicznych kafelków z kluczowymi metrykami (KPIs).
| - Interaktywny wykres słupkowy (Chart.js) prezentujący przegląd sprzedaży.
| - Tabela z listą 5 ostatnich, aktywnych zamówień (z zamaskowanym e-mailem klienta).
| - Warunkowe renderowanie całej sekcji dla sprzedawcy w oparciu o rolę użytkownika.
| - Pełnoekranowy loader informujący o procesie pobierania danych z bazy.
| - Pełna responsywność interfejsu.
|
|--------------------------------------------------------------------------
| Stos Technologiczny i Zależności
|--------------------------------------------------------------------------
|
| - Backend: Laravel (Blade, Auth, i18n)
| - Frontend: JavaScript (ES6+), Chart.js, Moment.js, Tailwind CSS, Font Awesome
| - Baza Danych: Laravel + PostgreSQL (migracja z Firebase)
| - Dane pobierane z /api/dashboard (Eloquent + PostgreSQL).
| - Usunięto wszelkie zależności od Firebase/Firestore.
|
--}}

{{-- Pobranie roli zalogowanego użytkownika i jego uprawnień --}}
@php
    $role = trim(Auth::guard('admin')->user()->getUserRole());
    $merchantEmployee = \App\Models\MerchantEmployee::where('user_id', Auth::id())->first();
    $userPermissions = $merchantEmployee ? $merchantEmployee->permissions : [];
    
    // Funkcja sprawdzająca uprawnienia
    $hasPermission = function($permission) use ($userPermissions, $role) {
        // Główny użytkownik ma wszystkie uprawnienia
        if ($role === 'vendor') return true;
        // Sprawdź czy użytkownik ma konkretne uprawnienie
        return in_array($permission, $userPermissions);
    };
@endphp

@extends('layouts.app')

@section('content')
{{-- Główny kontener (`wrapper`) całej zawartości strony, stylizowany za pomocą Tailwind CSS. --}}
<div id="main-wrapper" class="p-10">
    {{-- Kontener Flexbox dla głównych sekcji pulpitu, z odstępami (gap) --}}
    <div class="flex flex-col gap-6">

        {{-- Pełnoekranowa nakładka z loaderem (spinner), wyświetlana podczas ładowania danych. --}}
        <div id="homeLoaderOverlay" class="hidden fixed inset-0 bg-black bg-opacity-80 z-50 flex items-center justify-center">
            <div class="text-white text-lg flex flex-col items-center gap-2">
                <i class="fa-solid fa-spinner fa-spin text-4xl"></i>
                <span class="text-base">{{ trans('lang.processing') }}</span>
            </div>
        </div>
        
        {{-- Toast notifications (prawy górny róg) --}}
        @if(session('success'))
        <div x-data="{ show: true }" 
             x-show="show"
             x-init="setTimeout(() => show = false, 5000)"
             x-transition:enter="transition ease-out duration-300"
             x-transition:enter-start="opacity-0 translate-x-4"
             x-transition:enter-end="opacity-100 translate-x-0"
             x-transition:leave="transition ease-in duration-300"
             x-transition:leave-start="opacity-100"
             x-transition:leave-end="opacity-0"
             class="fixed top-5 right-5 z-50 max-w-md bg-green-100 border-l-4 border-green-500 rounded-lg shadow-lg pointer-events-auto"
             style="display: none;">
            <div class="p-4">
                <div class="flex items-center gap-3">
                    <i class="fa-solid fa-check-circle text-green-500 text-xl"></i>
                    <p class="text-sm font-medium text-green-800 flex-1">{{ session('success') }}</p>
                    <button @click="show = false" class="text-green-400 hover:text-green-600">
                        <i class="fa-solid fa-times"></i>
                    </button>
                </div>
            </div>
        </div>
        @endif
        
        @if(session('error'))
        <div x-data="{ show: true }" 
             x-show="show"
             x-init="setTimeout(() => show = false, 6000)"
             x-transition:enter="transition ease-out duration-300"
             x-transition:enter-start="opacity-0 translate-x-4"
             x-transition:enter-end="opacity-100 translate-x-0"
             x-transition:leave="transition ease-in duration-300"
             x-transition:leave-start="opacity-100"
             x-transition:leave-end="opacity-0"
             class="fixed top-5 right-5 z-50 max-w-md bg-red-100 border-l-4 border-red-500 rounded-lg shadow-lg pointer-events-auto"
             style="display: none;">
            <div class="p-4">
                <div class="flex items-center gap-3">
                    <i class="fa-solid fa-times-circle text-red-500 text-xl"></i>
                    <p class="text-sm font-medium text-red-800 flex-1">{{ session('error') }}</p>
                    <button @click="show = false" class="text-red-400 hover:text-red-600">
                        <i class="fa-solid fa-times"></i>
                    </button>
                </div>
            </div>
        </div>
        @endif
        
        @if(session('warning'))
        <div x-data="{ show: true }" 
             x-show="show"
             x-init="setTimeout(() => show = false, 6000)"
             x-transition:enter="transition ease-out duration-300"
             x-transition:enter-start="opacity-0 translate-x-4"
             x-transition:enter-end="opacity-100 translate-x-0"
             x-transition:leave="transition ease-in duration-300"
             x-transition:leave-start="opacity-100"
             x-transition:leave-end="opacity-0"
             class="fixed top-5 right-5 z-50 max-w-md bg-amber-100 border-l-4 border-amber-500 rounded-lg shadow-lg pointer-events-auto"
             style="display: none;">
            <div class="p-4">
                <div class="flex items-center gap-3">
                    <i class="fa-solid fa-exclamation-triangle text-amber-500 text-xl"></i>
                    <p class="text-sm font-medium text-amber-800 flex-1">{{ session('warning') }}</p>
                    <button @click="show = false" class="text-amber-400 hover:text-amber-600">
                        <i class="fa-solid fa-times"></i>
                    </button>
                </div>
            </div>
        </div>
        @endif
        
        @if(session('info'))
        <div x-data="{ show: true }" 
             x-show="show"
             x-init="setTimeout(() => show = false, 5000)"
             x-transition:enter="transition ease-out duration-300"
             x-transition:enter-start="opacity-0 translate-x-4"
             x-transition:enter-end="opacity-100 translate-x-0"
             x-transition:leave="transition ease-in duration-300"
             x-transition:leave-start="opacity-100"
             x-transition:leave-end="opacity-0"
             class="fixed top-5 right-5 z-50 max-w-md bg-blue-100 border-l-4 border-blue-500 rounded-lg shadow-lg pointer-events-auto"
             style="display: none;">
            <div class="p-4">
                <div class="flex items-center gap-3">
                    <i class="fa-solid fa-info-circle text-blue-500 text-xl"></i>
                    <p class="text-sm font-medium text-blue-800 flex-1">{{ session('info') }}</p>
                    <button @click="show = false" class="text-blue-400 hover:text-blue-600">
                        <i class="fa-solid fa-times"></i>
                    </button>
                </div>
            </div>
        </div>
        @endif
 
        {{-- ====================================================================== --}}
        {{-- STRIPE CONNECT STATUS BANNER (Widoczny gdy nie połączony)            --}}
        {{-- Odczyt z Firebase (vendors.stripe_connect_id) z fallback na MySQL    --}}
        {{-- ====================================================================== --}}
        @if ($hasPermission('home'))
            @php
                $stripeStatus = \App\Services\StripeStatusService::getStripeStatus();
                $stripeConnected = $stripeStatus['connected'];
                $stripeOnboardingComplete = $stripeStatus['onboarding_complete'];
            @endphp
            
            @if(!$stripeConnected || !$stripeOnboardingComplete)
            <div class="bg-orange-50 border-l-4 border-orange-500 rounded-lg p-5 mb-6 shadow-sm">
                <div class="flex items-start gap-4">
                    <div class="flex-shrink-0 text-orange-500">
                        <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-triangle-alert">
                            <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/>
                            <path d="M12 9v4"/>
                            <path d="M12 17h.01"/>
                        </svg>
                    </div>
                    <div class="flex-1">
                        @if(!$stripeConnected)
                            <h3 class="font-bold text-orange-900 text-lg mb-2">
                                {{ trans('lang.stripe_account_not_connected') }}
                            </h3>
                            <p class="text-orange-800 mb-3 text-sm">
                                {{ trans('lang.stripe_account_not_connected_desc') }}
                            </p>
                        @else
                            <h3 class="font-bold text-orange-900 text-lg mb-2">
                                {{ trans('lang.stripe_onboarding_incomplete') }}
                            </h3>
                            <p class="text-orange-800 mb-3 text-sm">
                                {{ trans('lang.stripe_onboarding_incomplete_desc') }}
                            </p>
                        @endif
                        
                        <button onclick="openBusinessTypeModal()" 
                                class="inline-flex items-center gap-2 bg-orange-500 text-white px-5 py-2.5 rounded-lg font-semibold hover:bg-orange-600 transition">
                            <i class="fa-brands fa-stripe text-lg"></i>
                            <span>{{ trans('lang.stripe_complete_setup') }}</span>
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right">
                                <path d="m9 18 6-6-6-6"/>
                            </svg>
                        </button>
                    </div>
                    <button onclick="this.closest('div.bg-orange-50').style.display='none'" 
                            class="flex-shrink-0 text-orange-400 hover:text-orange-600 transition">
                        <i class="fa-solid fa-times text-xl"></i>
                    </button>
                </div>
            </div>
            @endif
        @endif

        {{-- ====================================================================== --}}
        {{-- SEKCJA TOTAL EARNINGS (WIDOCZNA DLA UPRAWNIEŃ 'home')                --}}
        {{-- ====================================================================== --}}
        @if ($hasPermission('home'))

        {{-- Nagłówek sekcji "Zarobki" z sumą całkowitą i linkiem do centrum eksportu --}}
        <div class="rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-gradient-to-r from-slate-900 via-blue-800 to-blue-500 flex items-center justify-between">
            <div>
                <h3 class="text-2xl font-bold text-slate-50">{!! trans('lang.earning_plural') !!}</h3>
                <p class="text-sm text-slate-200 mt-1 m-0">{!! trans('lang.earning_desc') !!}</p>
                {{-- Całkowite zarobki wszech czasów (wypełniane przez JavaScript) --}}
                <h1 class="text-2xl font-bold mt-2 text-white" id="earnings_count"></h1>
            </div>
            <a href="{{ route('user.payment_details') }}" class="px-4 py-2 rounded-md bg-white text-slate-600 text-sm transition focus:outline-none flex items-center justify-center gap-2 whitespace-nowrap hover:no-underline hover:bg-slate-100 hover:text-slate-900">
                <span class="flex items-center gap-2">
                    <i class="fa-solid fa-download"></i>
                    <span>{{ trans('lang.export_center_title') }}</span>
                </span>
            </a>
        </div>

        {{-- Kafelki (KPI tiles) z podsumowaniem zarobków w podziale na okresy (roczny, miesięczny, tygodniowy) --}}
        <div class="flex flex-col md:flex-row w-full gap-4">
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm font-medium m-0">{!! trans('lang.yearly_earnings') !!}</p>
                <h3 id="yearly_earnings" class="text-xl font-bold mt-2 text-blue-500"></h3>
            </div>
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm font-medium m-0">{!! trans('lang.monthly_earnings') !!}</p>
                <h3 id="monthly_earnings" class="text-xl font-bold mt-2 text-blue-500"></h3>
            </div>
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm font-medium m-0">{!! trans('lang.weekly_earnings') !!}</p>
                <h3 id="weekly_earnings" class="text-xl font-bold mt-2 text-blue-500"></h3>
            </div>
        </div>

        {{-- Kontener na wykres sprzedaży z filtrami i nawigacją --}}
        <div class="border border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
            <div class="flex flex-col md:flex-row md:justify-between md:items-center gap-4 mb-6">
                {{-- Nagłówek wykresu i suma dla wybranego zakresu --}}
                <div class="flex flex-col">
                    <h3 class="text-xl text-slate-800 font-bold m-0">{{ trans('lang.sales_overview') }}</h3>
                    <p class="text-sm text-stlate-600 m-0" id="salesTotalTitle"></p>
                    <h1 class="text-2xl font-extrabold mt-2 text-blue-500" id="rangeSalesSum"></h1>
                </div>

                {{-- Przyciski do filtrowania i nawigacji po wykresie --}}
                <div class="flex flex-col md:items-end gap-3">
                    <div class="flex gap-3 justify-end">
                        <button id="yearBtn" class="px-4 py-2 rounded-md border !border-slate-300 bg-white text-slate-700 text-sm hover:bg-slate-100 transition focus:outline-none focus:ring-0">{{ trans('lang.year') }}</button>
                        <button id="monthBtn" class="px-4 py-2 rounded-md border !border-slate-300 bg-white text-slate-700 text-sm hover:bg-slate-100 transition focus:outline-none focus:ring-0">{{ trans('lang.month') }}</button>
                        <button id="weekBtn" class="px-4 py-2 rounded-md border !border-slate-300 bg-white text-slate-700 text-sm hover:bg-slate-100 transition focus:outline-none focus:ring-0">{{ trans('lang.week') }}</button>
                    </div>
                    <div class="flex items-center gap-3 justify-end border !border-slate-300 rounded-full p-1">
                        <button id="prevRangeBtn" class="w-8 h-8 flex items-center justify-center rounded-full bg-white text-gray-700 hover:bg-slate-100 transition focus:outline-none focus:ring-0"><i class="fa-solid fa-chevron-left"></i></button>
                        <span id="chartDateTitle" class="text-sm font-medium text-slate-700 min-w-[120px] text-center"></span>
                        <button id="nextRangeBtn" class="w-8 h-8 flex items-center justify-center rounded-full bg-white text-gray-700 hover:bg-slate-100 transition focus:outline-none focus:ring-0"><i class="fa-solid fa-chevron-right"></i></button>
                    </div>
                </div>
            </div>

            {{-- Element <canvas> renderowany przez bibliotekę Chart.js --}}
            <div class="border border-gray-300 rounded-lg overflow-hidden bg-blue-50 bg-opacity-25 p-4">
                <canvas id="sales-chart" height="400"></canvas>
            </div>
        </div>
        @endif {{-- Koniec warunku @if ($hasPermission('home')) --}}

        {{-- Nagłówek sekcji "Zamówienia" z sumą wszystkich zamówień --}}
        <div class="rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 mt-4 bg-gradient-to-r from-slate-900 via-blue-800 to-blue-500 flex items-center justify-between">
            <div>
                <h3 class="text-2xl font-bold text-slate-50">{!! trans('lang.orders') !!}</h3>
                <p class="text-sm text-slate-200 mt-1 m-0">{!! trans('lang.orders_desc') !!}</p>
                <h1 class="text-2xl font-bold mt-2 text-white" id="order_count"></h1>
            </div>
        </div>

        {{-- Kafelki z podsumowaniem liczby zamówień dla kluczowych statusów --}}
        <div class="flex flex-col md:flex-row w-full gap-4">
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm text-slate-800 font-medium m-0">{!! trans('lang.dashboard_order_placed') !!}</p>
                <h4 id="placed_count" class="text-xl font-bold mt-2 text-blue-500"></h4>
            </div>
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm text-slate-800 font-medium m-0">{!! trans('lang.dashboard_order_accepted') !!}</p>
                <h4 id="confirmed_count" class="text-xl font-bold mt-2 text-blue-500"></h4>
            </div>
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm text-slate-800 font-medium m-0">{!! trans('lang.dashboard_order_completed') !!}</p>
                <h4 id="completed_count" class="text-xl font-bold mt-2 text-blue-500"></h4>
            </div>
            <div class="flex-1 min-w-0 border !border-gray-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] p-4 bg-white">
                <p class="text-sm text-slate-800 font-medium m-0">{!! trans('lang.dashboard_payment_failed') !!}</p>
                <h4 id="failed_payment_count" class="text-xl font-bold mt-2 text-red-500"></h4>
            </div>
        </div>

        {{-- Kontener tabeli z 5 ostatnimi aktywnymi zamówieniami --}}
        <div class="bg-white border !border-slate-300 rounded-lg shadow-[1px_1px_4px_0px_#e2e8f0] relative">
            <div class="p-4">
                <h3 class="text-xl text-slate-800 font-bold m-0">{!! trans('lang.last_orders') !!}</h3>
                <p class="text-sm text-slate-600 m-0">{!! trans('lang.last_orders_desc') !!}</p>
            </div>
            <table class="w-full text-sm text-slate-700" id="homeOrderTable">
                <thead class="bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 text-slate-50">
                    <tr>
                        {{-- ID zamówienia --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.order_id') }}
                        </th>
                        {{-- Email klienta --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.customer') }}
                        </th>
                        {{-- Status zamówienia --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.order_order_status_id') }}
                        </th>
                        {{-- Typ zamówienia --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.order_type') }}
                        </th>
                        {{-- Cena zamówienia --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.total_amount') }}
                        </th>
                        {{-- Ilość produktów --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.quantity') }}
                        </th>
                        {{-- Data zamówienia --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative before:absolute before:right-0 before:top-[20%] before:h-[60%] before:border-r before:border-slate-600">
                            {{ trans('lang.date') }}
                        </th>
                        {{-- Akcje --}}
                        <th class="px-4 py-3 uppercase font-semibold text-center align-middle relative">
                            {{ trans('lang.actions') }}
                        </th>
                    </tr>
                </thead>
                {{-- Korpus tabeli, wypełniany dynamicznie przez buildOrderTableHTML() --}}
                <tbody id="append_list_recent_order" class="divide-y divide-slate-200">
                    {{-- Wiersze zostaną wstawione tutaj przez JavaScript --}}
                </tbody>
            </table>
        </div>

    </div>
</div>
@endsection

@section('scripts')
{{-- Dołączenie skryptów specyficznych dla tej strony --}}
<script src="{{ asset('js/chart.js') }}"></script>

{{-- Obiekt globalny do przekazywania tłumaczeń z Laravela (PHP) do JavaScript --}}
<script>
    window.langTranslations = {
        sales_total_for: "{!! trans('lang.sales_total_for') !!}",
        sales_total_for_week: "{!! trans('lang.sales_total_for_week') !!}",
        week: "{!! trans('lang.week') !!}",
        month: "{!! trans('lang.month') !!}",
        year: "{!! trans('lang.year') !!}",
        months_long: {!! json_encode(trans('lang.months_long')) !!},
        months_short: {!! json_encode(trans('lang.months_short')) !!}
    };
</script>

{{-- Główny blok skryptów dla pulpitu --}}
<script>
    document.addEventListener('DOMContentLoaded', function() {
/**
         * ====================================================================
         * INICJALIZACJA I DEKLARACJA ZMIENNYCH
         * ====================================================================
         */

        // Ustawienie aktywnego elementu w menu nawigacyjnym.
        const menuHome = document.getElementById("menu_home");
        if (menuHome) {
            menuHome.classList.add("active");
        }
        // Zmienne globalne przechowujące stan i dane aplikacji.
        const loaderOverlay = document.getElementById("homeLoaderOverlay");
        let currentCurrency = '';
        let currencyAtRight = false;
        let decimal_degits = 0;
        let allCompletedOrders = [];
        const salesTotalTitleEl = document.getElementById('salesTotalTitle');
        const rangeSalesSumEl = document.getElementById('rangeSalesSum');
        const chartDateTitleEl = document.getElementById('chartDateTitle');
        let currentViewMode = 'year';
        let referenceDate = new Date();
        let earliestDate = null;
        const now = new Date();
        // Wyświetlenie nakładki ładowania na czas operacji asynchronicznych.
        if (loaderOverlay) {
            loaderOverlay.classList.remove("hidden");
        }

        /**
         * ====================================================================
         * GŁÓWNA LOGIKA APLIKACJI (Pobieranie danych z /api/dashboard)
         * ====================================================================
         */
        fetch('{{ route("api.dashboard") }}')
            .then(r => r.json())
            .then(async function(data) {
                // Ustawienie waluty
                currentCurrency = data.currency.symbol;
                currencyAtRight = data.currency.symbolAtRight;
                decimal_degits  = data.currency.decimal_degits;

                // Liczniki zamówień i produktów
                const orderCount = document.getElementById('order_count');
                if (orderCount) orderCount.textContent = data.orderCount;

                const productCount = document.getElementById('product_count');
                if (productCount) productCount.textContent = data.productCount;

                // Liczniki wg statusów
                for (const [key, val] of Object.entries(data.statusCounts)) {
                    const el = document.getElementById(key);
                    if (el) el.textContent = val;
                }

                // Zarobki (wykres i kafelki KPI)
                allCompletedOrders = data.completedOrders;
                loadTotalEarnings(allCompletedOrders);
                calculateAndDisplayPeriodicEarnings(allCompletedOrders);
                earliestDate = findEarliestDate(allCompletedOrders);

                // Zakresy dat dla nawigacji po wykresie
                window.earliestWeek  = getMondayOfWeek(earliestDate);
                window.earliestMonth = getStartOfMonth(earliestDate);
                window.earliestYear  = getStartOfYear(earliestDate);
                window.latestWeek    = getMondayOfWeek(now);
                window.latestMonth   = getStartOfMonth(now);
                window.latestYear    = getStartOfYear(now);

                // Inicjalizacja wykresu z widokiem rocznym
                currentViewMode = 'year';
                referenceDate = new Date();
                loadYearlyEarnings(referenceDate);

                // Ostatnie zamówienia
                const appendListEl = document.getElementById('append_list_recent_order');
                if (appendListEl) {
                    const html = await buildOrderTableHTML(data.recentOrders);
                    if (html) {
                        appendListEl.innerHTML = html;
                        attachTooltipListeners();
                    }
                }

                // Ukrycie loadera
                if (loaderOverlay) {
                    loaderOverlay.classList.add('hidden');
                }

                // Przypisanie event listenerów do przycisków zmiany zakresu wykresu
                const weekBtn  = document.getElementById('weekBtn');
                const monthBtn = document.getElementById('monthBtn');
                const yearBtn  = document.getElementById('yearBtn');

                if (weekBtn) {
                    weekBtn.addEventListener('click', () => {
                        currentViewMode = 'week';
                        referenceDate = new Date();
                        loadWeeklyEarnings(referenceDate);
                    });
                }
                if (monthBtn) {
                    monthBtn.addEventListener('click', () => {
                        currentViewMode = 'month';
                        referenceDate = new Date();
                        loadMonthlyEarnings(referenceDate);
                    });
                }
                if (yearBtn) {
                    yearBtn.addEventListener('click', () => {
                        currentViewMode = 'year';
                        referenceDate = new Date();
                        loadYearlyEarnings(referenceDate);
                    });
                }

                // Przypisanie event listenerów do przycisków nawigacji (poprzedni/następny)
                const prevBtn = document.getElementById('prevRangeBtn');
                const nextBtn = document.getElementById('nextRangeBtn');
                if (prevBtn) prevBtn.addEventListener('click', goPrevRange);
                if (nextBtn) nextBtn.addEventListener('click', goNextRange);
            })
            .catch(function(err) {
                console.error('Dashboard API error:', err);
                if (loaderOverlay) loaderOverlay.classList.add('hidden');
            });

        /**
         * ====================================================================
         * NOWA FUNKCJA: Maskuje adres e-mail, pokazując pierwsze 3 znaki nazwy.
         * ====================================================================
         */
        function obfuscatedEmail(email) {
            if (!email) return '-';
            const atIndex = email.indexOf('@');
            if (atIndex === -1) return email;

            const name = email.slice(0, atIndex);
            const domain = email.slice(atIndex);

            return name.length > 3 ?
                name.slice(0, 3) + '...' + domain :
                email;
        }

        /**
         * Oblicza i zwraca datę poniedziałku dla tygodnia, w którym znajduje się podana data.
         * Ustawia godzinę na 00:00:00.
         */
        function getMondayOfWeek(date) {
            const result = new Date(date);
            let day = result.getDay();
            if (day === 0) day = 7;
            result.setDate(result.getDate() - (day - 1));
            result.setHours(0, 0, 0, 0);
            return result;
        }

        /**
         * Zwraca pierwszy dzień miesiąca dla podanej daty.
         */
        function getStartOfMonth(date) {
            return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
        }

        /**
         * Zwraca pierwszy dzień roku dla podanej daty.
         */
        function getStartOfYear(date) {
            return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0);
        }

        /**
         * Tworzy klucz daty w formacie 'YYYY-MM-DD' do grupowania danych.
         */
        function getLocalDateKey(date) {
            const year = date.getFullYear();
            const month = (date.getMonth() + 1).toString().padStart(2, '0');
            const day = date.getDate().toString().padStart(2, '0');
            return `${year}-${month}-${day}`;
        }

         /**
         * Oblicza i wyświetla całkowite zarobki wszech czasów.
         */
        function loadTotalEarnings(orders) {
            let totalSales = 0;
            let totalTips = 0;
            orders.forEach(orderData => {
                const priceInfo = calculateOrderPrice(orderData);
                const salesVal = priceInfo.sales < 0 ? 0 : priceInfo.sales;
                const tipsVal = priceInfo.tips < 0 ? 0 : priceInfo.tips;
                totalSales += salesVal;
                totalTips += tipsVal;
            });

            const total = totalSales + totalTips;
            const earningsCount = document.getElementById('earnings_count');
            if (earningsCount) {
                const salesText = formatCurrency(totalSales, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(totalTips, currentCurrency, currencyAtRight, decimal_degits);
                const totalText = formatCurrency(total, currentCurrency, currencyAtRight, decimal_degits);
                
                // Wyświetl z podziałem na sprzedaż i napiwki
                earningsCount.innerHTML = `
                    <div style="font-size: 1.2em; font-weight: bold;">${totalText}</div>
                    <div style="font-size: 0.8em; color: #666; margin-top: 4px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + 
                        <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
        }

        /**
         * Oblicza i wyświetla zarobki dla bieżącego roku, miesiąca i tygodnia
         * w odpowiednich kafelkach KPI.
         */
        function calculateAndDisplayPeriodicEarnings(orders) {
            const now = new Date();
            const currentYear = now.getFullYear();
            const currentMonth = now.getMonth();
            const monday = getMondayOfWeek(now);
            const sunday = new Date(monday);
            sunday.setDate(sunday.getDate() + 6);
            sunday.setHours(23, 59, 59, 999);

            let yearlyTotal = 0, monthlyTotal = 0, weeklyTotal = 0;
            let yearlySales = 0, monthlySales = 0, weeklySales = 0;
            let yearlyTips = 0, monthlyTips = 0, weeklyTips = 0;

            orders.forEach(order => {
                if (!order.createdAt) return;
                const orderDate = parseCreatedAtSafe(order.createdAt);
                const priceInfo = calculateOrderPrice(order);
                const salesVal = priceInfo.sales < 0 ? 0 : priceInfo.sales;
                const tipsVal = priceInfo.tips < 0 ? 0 : priceInfo.tips;
                const totalVal = salesVal + tipsVal;

                if (orderDate.getFullYear() === currentYear) {
                    yearlyTotal += totalVal;
                    yearlySales += salesVal;
                    yearlyTips += tipsVal;
                }
                if (orderDate.getFullYear() === currentYear && orderDate.getMonth() === currentMonth) {
                    monthlyTotal += totalVal;
                    monthlySales += salesVal;
                    monthlyTips += tipsVal;
                }
                if (orderDate >= monday && orderDate <= sunday) {
                    weeklyTotal += totalVal;
                    weeklySales += salesVal;
                    weeklyTips += tipsVal;
                }
            });

            // Aktualizuj wyświetlanie z podziałem na sprzedaż i napiwki
            const yearlyEl = document.getElementById('yearly_earnings');
            if(yearlyEl) {
                const totalText = formatCurrency(yearlyTotal, currentCurrency, currencyAtRight, decimal_degits);
                const salesText = formatCurrency(yearlySales, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(yearlyTips, currentCurrency, currencyAtRight, decimal_degits);
                yearlyEl.innerHTML = `
                    <div style="font-weight: bold;">${totalText}</div>
                    <div style="font-size: 0.75em; color: #666; margin-top: 2px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
            
            const monthlyEl = document.getElementById('monthly_earnings');
            if(monthlyEl) {
                const totalText = formatCurrency(monthlyTotal, currentCurrency, currencyAtRight, decimal_degits);
                const salesText = formatCurrency(monthlySales, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(monthlyTips, currentCurrency, currencyAtRight, decimal_degits);
                monthlyEl.innerHTML = `
                    <div style="font-weight: bold;">${totalText}</div>
                    <div style="font-size: 0.75em; color: #666; margin-top: 2px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
            
            const weeklyEl = document.getElementById('weekly_earnings');
            if(weeklyEl) {
                const totalText = formatCurrency(weeklyTotal, currentCurrency, currencyAtRight, decimal_degits);
                const salesText = formatCurrency(weeklySales, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(weeklyTips, currentCurrency, currencyAtRight, decimal_degits);
                weeklyEl.innerHTML = `
                    <div style="font-weight: bold;">${totalText}</div>
                    <div style="font-size: 0.75em; color: #666; margin-top: 2px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
        }

        /**
         * Znajduje najwcześniejszą datę utworzenia zamówienia w dostarczonym zbiorze.
         */
        function findEarliestDate(orders) {
            if (!orders || !orders.length) return new Date();
            let minDate = new Date();
            orders.forEach(o => {
                if (o.createdAt) {
                    let d = parseCreatedAtSafe(o.createdAt);
                    if (d < minDate) minDate = d;
                }
            });
            return minDate;
        }

        /**
         * Obsługuje nawigację do poprzedniego zakresu dat na wykresie (tydzień/miesiąc/rok)
         * i odświeża dane.
         */
        function goPrevRange() {
            let newDate = new Date(referenceDate);
            if (currentViewMode === 'week') {
                newDate.setDate(newDate.getDate() - 7);
                if (newDate < window.earliestWeek) newDate = new Date(window.earliestWeek);
                referenceDate = newDate;
                loadWeeklyEarnings(referenceDate);
            } else if (currentViewMode === 'month') {
                newDate.setMonth(newDate.getMonth() - 1);
                if (newDate < window.earliestMonth) newDate = new Date(window.earliestMonth);
                referenceDate = newDate;
                loadMonthlyEarnings(referenceDate);
            } else if (currentViewMode === 'year') {
                newDate.setFullYear(newDate.getFullYear() - 1);
                if (newDate < window.earliestYear) newDate = new Date(window.earliestYear);
                referenceDate = newDate;
                loadYearlyEarnings(referenceDate);
            }
        }

        /**
         * Obsługuje nawigację do następnego zakresu dat na wykresie (tydzień/miesiąc/rok)
         * i odświeża dane.
         */
        function goNextRange() {
            let newDate = new Date(referenceDate);
            if (currentViewMode === 'week') {
                newDate.setDate(newDate.getDate() + 7);
                if (newDate > window.latestWeek) newDate = new Date(window.latestWeek);
                referenceDate = newDate;
                loadWeeklyEarnings(referenceDate);
            } else if (currentViewMode === 'month') {
                newDate.setMonth(newDate.getMonth() + 1);
                if (newDate > window.latestMonth) newDate = new Date(window.latestMonth);
                referenceDate = newDate;
                loadMonthlyEarnings(referenceDate);
            } else if (currentViewMode === 'year') {
                newDate.setFullYear(newDate.getFullYear() + 1);
                if (newDate > window.latestYear) newDate = new Date(window.latestYear);
                referenceDate = newDate;
                loadYearlyEarnings(referenceDate);
            }
        }

        /**
         * Ładuje i renderuje dane o sprzedaży dla wybranego tygodnia.
         * Agreguje dane dzienne i aktualizuje wykres oraz podsumowania.
         */
        function loadWeeklyEarnings(refDate) {
            setActiveChartButton('weekBtn');
            currentViewMode = 'week';
            let refDay = refDate.getDay();
            if (refDay === 0) refDay = 7;
            const monday = new Date(refDate);
            monday.setHours(0, 0, 0, 0);
            monday.setDate(monday.getDate() - (refDay - 1));
            const sunday = new Date(monday);
            sunday.setDate(sunday.getDate() + 6);
            sunday.setHours(23, 59, 59, 999);
            const weekNumber = moment(monday).isoWeek();
            const yearNumber = monday.getFullYear();
            if (salesTotalTitleEl) salesTotalTitleEl.textContent = `${window.langTranslations.sales_total_for_week} ${weekNumber} (${yearNumber})`;
            if (chartDateTitleEl) chartDateTitleEl.textContent = `${window.langTranslations.week} ${weekNumber} (${yearNumber})`;
            let dailySales = {}, dailyTips = {};
            let totalEarning = 0, totalSalesEarning = 0, totalTipsEarning = 0;
            
            allCompletedOrders.forEach(orderData => {
                if (!orderData.createdAt) return;
                let createdTS = parseCreatedAtSafe(orderData.createdAt);
                if (createdTS >= monday && createdTS <= sunday) {
                    let priceInfo = calculateOrderPrice(orderData);
                    let salesVal = priceInfo.sales < 0 ? 0 : priceInfo.sales;
                    let tipsVal = priceInfo.tips < 0 ? 0 : priceInfo.tips;
                    let totalVal = salesVal + tipsVal;
                    
                    totalEarning += totalVal;
                    totalSalesEarning += salesVal;
                    totalTipsEarning += tipsVal;
                    
                    let key = getLocalDateKey(createdTS);
                    dailySales[key] = (dailySales[key] || 0) + salesVal;
                    dailyTips[key] = (dailyTips[key] || 0) + tipsVal;
                }
            });
            
            let labels = [], salesData = [], tipsData = [];
            let loopDate = new Date(monday);
            while (loopDate <= sunday) {
                let key = getLocalDateKey(loopDate);
                let dd = loopDate.getDate().toString().padStart(2, '0');
                let mm = (loopDate.getMonth() + 1).toString().padStart(2, '0');
                labels.push(`${dd}/${mm}`);
                salesData.push(dailySales[key] || 0);
                tipsData.push(dailyTips[key] || 0);
                loopDate.setDate(loopDate.getDate() + 1);
            }
            
            if (rangeSalesSumEl) {
                const totalText = formatCurrency(totalEarning, currentCurrency, currencyAtRight, decimal_degits);
                const salesText = formatCurrency(totalSalesEarning, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(totalTipsEarning, currentCurrency, currencyAtRight, decimal_degits);
                rangeSalesSumEl.innerHTML = `
                    <div style="font-weight: bold; font-size: 1.1em;">${totalText}</div>
                    <div style="font-size: 0.85em; color: #666; margin-top: 4px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
            const salesChartNode = document.getElementById('sales-chart');
            if (salesChartNode) renderChart(salesChartNode, {sales: salesData, tips: tipsData}, labels, currentCurrency, currencyAtRight, decimal_degits);
        }

        /**
         * Ładuje i renderuje dane o sprzedaży dla wybranego miesiąca.
         * Agreguje dane dzienne i aktualizuje wykres oraz podsumowania.
         */
        function loadMonthlyEarnings(refDate) {
            setActiveChartButton('monthBtn');
            currentViewMode = 'month';
            const firstDay = new Date(refDate.getFullYear(), refDate.getMonth(), 1, 0, 0, 0, 0);
            const lastDay = new Date(refDate.getFullYear(), refDate.getMonth() + 1, 0, 23, 59, 59, 999);
            const monthIndex = refDate.getMonth();
            const monthName = window.langTranslations.months_long[monthIndex];
            const yearNumber = refDate.getFullYear();
            if (salesTotalTitleEl) salesTotalTitleEl.textContent = `${window.langTranslations.sales_total_for} ${monthName} ${yearNumber}`;
            if (chartDateTitleEl) chartDateTitleEl.textContent = `${monthName} ${yearNumber}`;
            let dailySales = {}, dailyTips = {};
            let totalEarning = 0, totalSalesEarning = 0, totalTipsEarning = 0;
            
            allCompletedOrders.forEach(orderData => {
                if (!orderData.createdAt) return;
                let createdTS = parseCreatedAtSafe(orderData.createdAt);
                if (createdTS >= firstDay && createdTS <= lastDay) {
                    let priceInfo = calculateOrderPrice(orderData);
                    let salesVal = priceInfo.sales < 0 ? 0 : priceInfo.sales;
                    let tipsVal = priceInfo.tips < 0 ? 0 : priceInfo.tips;
                    let totalVal = salesVal + tipsVal;
                    
                    totalEarning += totalVal;
                    totalSalesEarning += salesVal;
                    totalTipsEarning += tipsVal;
                    
                    let key = getLocalDateKey(createdTS);
                    dailySales[key] = (dailySales[key] || 0) + salesVal;
                    dailyTips[key] = (dailyTips[key] || 0) + tipsVal;
                }
            });
            
            let labels = [], salesData = [], tipsData = [];
            let loopDate = new Date(firstDay);
            while (loopDate <= lastDay) {
                let key = getLocalDateKey(loopDate);
                let dd = loopDate.getDate().toString().padStart(2, '0');
                let mm = (loopDate.getMonth() + 1).toString().padStart(2, '0');
                labels.push(`${dd}/${mm}`);
                salesData.push(dailySales[key] || 0);
                tipsData.push(dailyTips[key] || 0);
                loopDate.setDate(loopDate.getDate() + 1);
            }
            
            if (rangeSalesSumEl) {
                const totalText = formatCurrency(totalEarning, currentCurrency, currencyAtRight, decimal_degits);
                const salesText = formatCurrency(totalSalesEarning, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(totalTipsEarning, currentCurrency, currencyAtRight, decimal_degits);
                rangeSalesSumEl.innerHTML = `
                    <div style="font-weight: bold; font-size: 1.1em;">${totalText}</div>
                    <div style="font-size: 0.85em; color: #666; margin-top: 4px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
            const salesChartNode = document.getElementById('sales-chart');
            if (salesChartNode) renderChart(salesChartNode, {sales: salesData, tips: tipsData}, labels, currentCurrency, currencyAtRight, decimal_degits);
        }

        /**
         * Ładuje i renderuje dane o sprzedaży dla wybranego roku.
         * Agreguje dane miesięczne i aktualizuje wykres oraz podsumowania.
         */
        function loadYearlyEarnings(refDate) {
            setActiveChartButton('yearBtn');
            currentViewMode = 'year';
            const targetYear = refDate.getFullYear();
            if (salesTotalTitleEl) salesTotalTitleEl.textContent = `${window.langTranslations.sales_total_for} ${targetYear}`;
            if (chartDateTitleEl) chartDateTitleEl.textContent = targetYear;
            
            let monthlySales = Array(12).fill(0), monthlyTips = Array(12).fill(0);
            let totalEarning = 0, totalSalesEarning = 0, totalTipsEarning = 0;
            
            allCompletedOrders.forEach(orderData => {
                if (!orderData.createdAt) return;
                let createdTS = parseCreatedAtSafe(orderData.createdAt);
                if (createdTS.getFullYear() === targetYear) {
                    let priceInfo = calculateOrderPrice(orderData);
                    let salesVal = priceInfo.sales < 0 ? 0 : priceInfo.sales;
                    let tipsVal = priceInfo.tips < 0 ? 0 : priceInfo.tips;
                    let totalVal = salesVal + tipsVal;
                    
                    totalEarning += totalVal;
                    totalSalesEarning += salesVal;
                    totalTipsEarning += tipsVal;
                    
                    const orderMonth = createdTS.getMonth();
                    monthlySales[orderMonth] += salesVal;
                    monthlyTips[orderMonth] += tipsVal;
                }
            });
            
            if (rangeSalesSumEl) {
                const totalText = formatCurrency(totalEarning, currentCurrency, currencyAtRight, decimal_degits);
                const salesText = formatCurrency(totalSalesEarning, currentCurrency, currencyAtRight, decimal_degits);
                const tipsText = formatCurrency(totalTipsEarning, currentCurrency, currencyAtRight, decimal_degits);
                rangeSalesSumEl.innerHTML = `
                    <div style="font-weight: bold; font-size: 1.1em;">${totalText}</div>
                    <div style="font-size: 0.85em; color: #666; margin-top: 4px;">
                        <span style="color: #3B82F6;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chart-no-axes-combined-icon lucide-chart-no-axes-combined" style="display: inline; vertical-align: middle;"><path d="M12 16v5"/><path d="M16 14v7"/><path d="M20 10v11"/><path d="m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"/><path d="M4 18v3"/><path d="M8 14v7"/></svg> ${salesText}</span> + <span style="color: #F97316;"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-hand-coins-icon lucide-hand-coins" style="display: inline; vertical-align: middle;"><path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"/><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"/><path d="m2 16 6 6"/><circle cx="16" cy="9" r="2.9"/><circle cx="6" cy="5" r="3"/></svg> ${tipsText}</span>
                    </div>
                `;
            }
            
            let labels = [];
            for (let m = 0; m < 12; m++) {
                labels.push(window.langTranslations.months_short[m]);
            }
            const salesChartNode = document.getElementById('sales-chart');
            if (salesChartNode) renderChart(salesChartNode, {sales: monthlySales, tips: monthlyTips}, labels, currentCurrency, currencyAtRight, decimal_degits);
        }

        /**
         * Zwraca wartości sprzedaży i napiwków z danych zamówienia.
         * API /api/dashboard dostarcza pre-obliczone wartości 'sales' i 'tips'.
         */
        function calculateOrderPrice(orderData) {
            const sales = parseFloat(orderData.sales) || 0;
            const tips  = parseFloat(orderData.tips)  || 0;
            return {
                sales: sales,
                tips:  tips,
                total: sales + tips,
            };
        }

        /**
         * Buduje HTML tabeli ostatnich zamówień z tablicy obiektów z API.
         */
        async function buildOrderTableHTML(orders) {
            let rows = [];
            for (const orderData of orders) {
                if (rows.length >= 5) break;
                const rowHtml = await getListData(orderData);
                if (rowHtml) rows.push(rowHtml);
            }
            return rows.join('');
        }

        function attachTooltipListeners() {
            const tooltipContainers = document.querySelectorAll('.js-tooltip-container');
            tooltipContainers.forEach(container => {
                const tooltip = container.querySelector('.js-tooltip-content');
                if (tooltip) {
                    container.addEventListener('mouseenter', () => {
                        tooltip.classList.remove('opacity-0', 'translate-y-2', 'pointer-events-none');
                        tooltip.classList.add('opacity-100', 'translate-y-0');
                    });
                    container.addEventListener('mouseleave', () => {
                        tooltip.classList.add('opacity-0', 'translate-y-2', 'pointer-events-none');
                        tooltip.classList.remove('opacity-100', 'translate-y-0');
                    });
                }
            });
        }

        /**
         * Generuje kod HTML dla pojedynczego wiersza w tabeli ostatnich zamówień.
         */
        async function getListData(val) {
            // Nie ukrywamy już statusów płatności - wyświetlamy wszystkie zamówienia
            const status = val.status || '';

            // KLUCZOWA ZMIANA: Wywołanie funkcji maskującej e-mail klienta.
            const customerIdentifier = obfuscatedEmail(val.customerEmail);

            let editUrl = `<?php echo route('orders.edit', ':id'); ?>`.replace(':id', val.id);
            const createdAtObj = val.createdAt ? moment(parseCreatedAtSafe(val.createdAt)) : null;
            const datePart = createdAtObj ? createdAtObj.format('DD.MM.YYYY') : '-';
            const timePart = createdAtObj ? createdAtObj.format('HH:mm') : '';
            const statusLabel = transStatus(val.status);
            const badgeClass = statusBadgeClass(val.status);
            const iconClass = statusIconClass(val.status);
            const typeLabel = (val.tableNumber === null) ? `{!! trans('lang.counter_pickup') !!}` : `{!! trans('lang.table_service') !!}`;
            const priceHtml = `${currentCurrency} ${parseFloat(val.checkOutPrice || 0).toFixed(decimal_degits)}`;
            const itemsCount = val.itemsCount || 0;

            return `
            <tr class="hover:bg-gradient-to-r from-blue-50 via-blue-100 to-blue-50 transition-colors delay-50 duration-300 ease-in-out">
                <td class="px-4 py-3 text-center align-middle text-sm text-slate-700">${val.id}</td>
                <td class="px-4 py-3 text-center align-middle text-sm text-slate-700">${customerIdentifier}</td>
                <td class="px-4 py-3 text-center align-middle">
                    <span class="inline-flex items-center px-3 py-2 rounded-md text-xs font-medium ${badgeClass}">
                        <i class="mr-2 text-base ${iconClass}"></i>
                        ${statusLabel}
                    </span>
                </td>
                <td class="px-4 py-3 text-center align-middle text-sm text-slate-700">${typeLabel}</td>
                <td class="px-4 py-3 text-center align-middle text-sm font-bold text-blue-500">${priceHtml}</td>
                <td class="px-4 py-3 text-center align-middle text-sm text-slate-700">
                    <div class="flex justify-center items-center gap-1">
                        <i class="fa fa-shopping-cart text-sm"></i>
                        ${itemsCount}
                    </div>
                </td>
                <td class="px-4 py-3 text-center align-middle text-sm leading-tight">
                    <div class="flex flex-col items-center">
                        <span class="text-slate-700">${datePart}</span>
                        <span class="inline-flex items-center gap-1 text-slate-500">
                            <i class="fa-regular fa-clock text-xs"></i>
                            <span>${timePart}</span>
                        </span>
                    </div>
                </td>
                <td class="px-4 py-3 text-center align-middle text-sm whitespace-nowrap">
                    <div class="js-tooltip-container relative flex justify-center">
                        <a href="${editUrl}" class="flex h-10 w-10 items-center justify-center rounded-lg text-slate-400 hover:bg-blue-100 hover:text-blue-500 transition hover:no-underline">
                            <i class="fa-solid fa-ellipsis text-xl"></i>
                        </a>
                        <div class="js-tooltip-content absolute top-full left-1/2 mt-2 w-max max-w-xs bg-slate-800 text-white text-center text-xs rounded py-2 px-3 z-10 transition-all duration-300 ease-out opacity-0 translate-y-2 pointer-events-none" style="transform: translateX(-50%);">
                            {!! trans('lang.edit') !!}
                            <div class="absolute left-1/2 -translate-x-1/2 bottom-full w-0 h-0 border-x-8 border-x-transparent border-b-8 border-b-slate-800"></div>
                        </div>
                    </div>
                </td>
            </tr>`;
        }

        /**
         * Tłumaczy status zamówienia na język zdefiniowany w plikach `lang` Laravela.
         */
        function transStatus(status) {
            switch (status) {
                case 'Order Placed': return '{!! trans("lang.dashboard_order_placed") !!}';
                case 'Order Accepted': return '{!! trans("lang.dashboard_order_accepted") !!}';
                case 'Order Rejected': return '{!! trans("lang.dashboard_order_canceled") !!}';
                case 'Driver Pending': return '{!! trans("lang.dashboard_order_pending") !!}';
                case 'Order Completed': return '{!! trans("lang.dashboard_order_completed") !!}';
                case 'Finished': return '{!! trans("lang.dashboard_order_finished") !!}';
                case 'Payment Pending':
                case 'pending_payment': return '{!! trans("lang.dashboard_order_pending") !!}';
                case 'Payment Failed': return '{!! trans("lang.dashboard_payment_failed") !!}';
                default: return status;
            }
        }

        /**
         * Zwraca klasy CSS dla "badge'a" statusu na podstawie jego wartości.
         */
        function statusBadgeClass(s) {
            switch (s) {
                case 'Order Placed': return 'bg-amber-50 border !border-amber-500 text-amber-500';
                case 'Order Accepted': return 'bg-blue-50 border !border-blue-600 text-blue-600';
                case 'Order Completed': return 'bg-green-50 border !border-green-600 text-green-600';
                case 'Order Accepted by Bar':
                case 'Order Accepted by Kitchen': return 'bg-green-50 border !border-green-600 text-green-600';
                case 'Finished': return 'bg-green-50 border !border-green-600 text-green-600';
                case 'Order Rejected': return 'bg-red-50 border !border-red-600 text-red-600';
                case 'Payment Pending':
                case 'pending_payment': return 'bg-yellow-50 border !border-yellow-500 text-yellow-600';
                case 'Payment Failed': return 'bg-red-50 border !border-red-600 text-red-600';
                default: return 'bg-slate-100 border !border-slate-600 text-slate-600';
            }
        }

        /**
         * Zwraca klasy CSS dla ikony Font Awesome na podstawie statusu zamówienia.
         */
        function statusIconClass(s) {
            switch (s) {
                case 'Order Placed': return 'fa fa-shopping-bag';
                case 'Order Accepted':
                case 'Order Accepted by Bar':
                case 'Order Accepted by Kitchen':
                case 'Order Completed':
                case 'Finished': return 'fa fa-check-circle';
                case 'Order Rejected':
                case 'Payment Failed': return 'fa fa-times-circle';
                case 'Payment Pending':
                case 'pending_payment': return 'fa fa-clock';
                default: return 'fa fa-info-circle';
            }
        }

        /**
         * Formatuje kwotę pieniężną zgodnie z ustawieniami waluty.
         */
        function formatCurrency(amount, symbol, atRight, decimals = 0) {
            const val = parseFloat(amount).toFixed(decimals);
            return atRight ? (val + ' ' + symbol) : (symbol + ' ' + val);
        }

        /**
         * Renderuje lub aktualizuje wykres sprzedaży za pomocą Chart.js.
         * Niszczy poprzednią instancję wykresu, jeśli istnieje, aby uniknąć problemów.
         */
        function renderChart(chartNode, data, labels, currency, currencyAtRight, decimals) {
            const ctx = chartNode.getContext('2d');
            
            // Gradient dla sprzedaży (niebieski)
            const salesGradient = ctx.createLinearGradient(0, 0, 0, chartNode.height);
            salesGradient.addColorStop(0, 'rgba(59,130,246,0.8)');
            salesGradient.addColorStop(1, 'rgba(29,78,216,0.8)');
            
            // Gradient dla napiwków (pomarańczowy)
            const tipsGradient = ctx.createLinearGradient(0, 0, 0, chartNode.height);
            tipsGradient.addColorStop(0, 'rgba(249,115,22,0.8)');
            tipsGradient.addColorStop(1, 'rgba(234,88,12,0.8)');
            
            const xTicks = { color: '#334155', font: { weight: 'bold' } };
            const yTicks = {
                color: '#334155', font: { weight: 'bold' },
                callback: function(value) {
                    const val = parseFloat(value).toFixed(decimals);
                    return currencyAtRight ? (val + currency) : (currency + val);
                }
            };
            
            if (window.mySalesChart) window.mySalesChart.destroy();
            
            // Sprawdź czy dane mają format z osobnymi sprzedażą i napiwkami
            let datasets;
            if (data && typeof data === 'object' && data.sales && data.tips) {
                // Nowy format z osobnymi danymi dla sprzedaży i napiwków
                datasets = [
                    {
                        label: 'Sprzedaż',
                        data: data.sales,
                        backgroundColor: salesGradient,
                        borderColor: '#3B82F6',
                        borderWidth: 1,
                        borderRadius: 6,
                        borderSkipped: 'bottom'
                    },
                    {
                        label: 'Napiwki',
                        data: data.tips,
                        backgroundColor: tipsGradient,
                        borderColor: '#F97316',
                        borderWidth: 1,
                        borderRadius: 6,
                        borderSkipped: 'bottom'
                    }
                ];
            } else {
                // Stary format - pojedyncza tablica danych
                datasets = [{
                    label: 'Sprzedaż',
                    data: data,
                    backgroundColor: salesGradient,
                    borderColor: '#3B82F6',
                    borderWidth: 1,
                    borderRadius: 8,
                    borderSkipped: 'bottom'
                }];
            }
            
            window.mySalesChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: labels,
                    datasets: datasets
                },
                options: {
                    responsive: true, maintainAspectRatio: false,
                    layout: { padding: { bottom: 10 } },
                    events: ['mousemove', 'touchstart', 'touchmove', 'touchend', 'click'],
                    plugins: {
                        legend: { display: false },
                        tooltip: {
                            mode: 'index', intersect: false, padding: 12,
                            titleFont: { size: 14, weight: 'bold' }, bodyFont: { size: 13 },
                            callbacks: {
                                label: function(context) {
                                    const rawValue = context.parsed.y;
                                    const val = parseFloat(rawValue).toFixed(decimals);
                                    return currencyAtRight ? (val + currency) : (currency + val);
                                }
                            }
                        }
                    },
                    scales: {
                        x: { display: true, grid: { display: true, color: '#e2e8f0' }, ticks: xTicks },
                        y: {
                            display: true, beginAtZero: true, min: 0,
                            grid: { display: true, color: '#e2e8f0', borderColor: 'transparent', lineWidth: 1 },
                            ticks: yTicks
                        }
                    }
                }
            });
        }

        /**
         * Zarządza stylami przycisków (Tydzień, Miesiąc, Rok), aby wizualnie
         * zaznaczyć, który zakres jest aktualnie aktywny.
         */
        function setActiveChartButton(buttonId) {
            const ids = ['weekBtn', 'monthBtn', 'yearBtn'];
            ids.forEach(id => {
                const btn = document.getElementById(id);
                if (!btn) return;
                if (id === buttonId) {
                    btn.classList.remove('bg-white', 'text-slate-700', 'hover:bg-slate-100', 'font-normal', 'border', '!border-slate-300');
                    btn.classList.add('bg-blue-500', 'text-white', 'font-semibold');
                } else {
                    btn.classList.remove('bg-blue-500', 'text-white', 'font-semibold');
                    btn.classList.add('bg-white', 'text-slate-700', 'hover:bg-slate-100', 'font-normal', 'border', '!border-slate-300');
                }
            });
        }

        // Parsowanie daty z ISO stringa (format zwracany przez API)
        function parseCreatedAtSafe(createdAt) {
            if (!createdAt) return null;
            if (createdAt instanceof Date) return createdAt;
            if (typeof createdAt === 'string') return new Date(createdAt);
            return null;
        }

        // Globalny event listener do obsługi przekierowań na podstawie atrybutu `data-url`.
        document.body.addEventListener('click', function(e) {
            if (e.target && e.target.classList.contains('redirecttopage')) {
                const url = e.target.getAttribute('data-url');
                window.location.href = url;
            }
        });
    });
</script>

<script src="https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

@endsection