Files
timebank-cc-public/resources/views/livewire/single-report.blade.php
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

359 lines
19 KiB
PHP

<div class="relative mb-12 mt-0 w-full min-w-full leading-normal" id="single-report-component">
<!-- Decimal format toggle -->
@if($accountsData && $accountsData->count() > 0)
<div class="mb-6 flex items-center gap-3">
<x-toggle wire:model.live="decimalFormat" id="decimalFormatReport" name="decimalFormatReport" />
<span class="text-xs text-theme-light">{{ __('Show in decimals') }}</span>
</div>
@endif
<!-- Export buttons - always visible but disabled when no period selected -->
<div class="mb-8 mt-0 flex w-full justify-end">
<div class="space-x-2">
@if($this->fromDate && $this->toDate && $accountsData && $accountsData->count() > 0)
<x-jetstream.secondary-button wire:click="$dispatch('export-pdf-with-charts')" wire:loading.attr="disabled">
<span wire:loading.remove wire:target="handleExportPdfWithCharts">
<x-icon class="mr-1 h-4 w-4" name="arrow-down-tray" />
{{ __('PDF') }}
</span>
<span wire:loading wire:target="handleExportPdfWithCharts">
<x-icon class="mr-1 h-4 w-4 animate-spin" name="arrow-path" />
{{ __('Loading...') }}
</span>
</x-jetstream.secondary-button>
@else
<x-jetstream.secondary-button disabled class="cursor-not-allowed opacity-50">
<x-icon class="mr-1 h-4 w-4" name="arrow-down-tray" />
{{ __('PDF') }}
</x-jetstream.secondary-button>
@endif
</div>
</div>
@if($accountsData && $accountsData->count() > 0)
<!-- Account Balances Table -->
<h3 class="text-lg font-medium text-theme-primary">
{{ __('Account Balance') }}
</h3>
<p class="text-sm text-theme-secondary mt-2">
{{ __('Balance overview of your accounts') }}
</p>
<div class="relative mb-24 w-full min-w-full leading-normal">
<table class="w-full" id="account-balances">
<thead>
<tr>
<th class="border-b border-theme-primary py-6 text-left">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Account Name') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Start Balance') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('End Balance') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Difference') }}
</span>
</th>
</tr>
</thead>
<tbody>
@foreach($accountsData as $account)
<tr>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-sm">
<div class="whitespace-no-wrap text-theme-primary font-medium">
{{ $account['name'] }}
</div>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ $account['start_balance_formatted'] }}
</span>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ $account['end_balance_formatted'] }}
</span>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap @if($account['difference'] >= 0) text-theme-primary @else text-red-700 @endif">
{{ $account['difference_formatted'] }}@if($account['difference'] > 0) +@endif
</span>
</td>
</tr>
@endforeach
<!-- Totals Row -->
<tr class="bg-gray-100">
<td class="border-b border-theme-primary bg-gray-100 px-2 py-3 text-sm">
<div class="whitespace-no-wrap text-theme-primary font-bold">
{{ __('TOTALS') }}
</div>
</td>
<td class="border-b border-theme-primary bg-gray-100 px-2 py-3 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary font-bold">
{{ $this->formatAmount($accountsData->sum('start_balance')) }}
</span>
</td>
<td class="border-b border-theme-primary bg-gray-100 px-2 py-3 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary font-bold">
{{ $this->formatAmount($accountsData->sum('end_balance')) }}
</span>
</td>
<td class="border-b border-theme-primary bg-gray-100 px-2 py-3 text-right text-sm">
@php $totalDifference = $accountsData->sum('difference'); @endphp
<span class="whitespace-no-wrap font-bold @if($totalDifference >= 0) text-theme-primary @else text-red-700 @endif">
{{ $this->formatAmount($totalDifference) }}@if($totalDifference > 0) +@endif
</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Transaction Types Breakdown -->
@if($transactionTypesData && $transactionTypesData->count() > 0)
<div class="mb-6">
<h3 class="text-lg font-medium text-theme-primary">
{{ __('Transacion types') }}
</h3>
<p class="text-sm text-theme-secondary mt-2">
{{ __('Overview of the different transaction purposes') }}
</p>
</div>
<div class="relative mb-24 mt-12 w-full min-w-full leading-normal">
<table class="w-full text-left" id="transaction-types">
<thead>
<tr>
<th class="border-b border-theme-primary py-6">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Transaction Type') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Credit') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Debit') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Total') }}
</span>
</th>
</tr>
</thead>
<tbody>
@foreach($transactionTypesData as $transactionType)
<tr>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-sm">
<div class="whitespace-no-wrap text-theme-primary">
{{ $transactionType['type_name'] }}
</div>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ $transactionType['incoming_formatted'] }}
</span>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-red-700">
{{ $transactionType['outgoing_formatted'] }}
</span>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap @if($transactionType['net'] >= 0) text-theme-primary @else text-red-700 @endif">
{{ $transactionType['net_formatted'] }}
</span>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
<!-- Account Balances Chart -->
@if($accountBalancesTimelineData && count($accountBalancesTimelineData) > 4)
<div class="relative mb-24 mt-12 w-full min-w-full leading-normal">
<div class="mb-6">
<h3 class="text-lg font-medium text-theme-primary">
{{ __('Account Balance Over Time') }}
</h3>
<p class="text-sm text-theme-secondary mt-2">
{{ __('Track your account balance over time') }}
</p>
</div>
<div class="bg-white rounded-lg shadow-sm border border-theme-primary p-6"
data-balance-chart-data="{{ json_encode($accountBalancesTimelineData) }}"
data-decimal-format="{{ $decimalFormat ? '1' : '0' }}"
data-date-range="{{ $this->fromDate }} to {{ $this->toDate }}">
<canvas id="accountBalancesChart" width="400" height="200"></canvas>
</div>
</div>
@endif
<!-- Return Ratio Timeline Chart -->
@if($isOrganization && $returnRatioTimelineData && count($returnRatioTimelineData) > 4)
<!-- Loading indicator positioned above chart -->
<div id="chartLoadingIndicator" class="flex items-center justify-center space-x-2 px-3 py-2 rounded-md mb-4" style="display: flex !important; visibility: visible !important;">
<div class="animate-spin rounded-full h-4 w-4 border-2 border-gray-300 border-t-gray-900"></div>
<span class="text-sm font-bold">
{{ __('Loading chart...') }}
</span>
</div>
<div class="relative mb-24 mt-12 w-full min-w-full leading-normal">
<div class="mb-6">
<h3 class="text-lg font-medium text-theme-primary">
{{ __('Reciprocity Rate Timeline') }}
</h3>
<p class="text-sm text-theme-secondary mt-2">
{{ __('Reciprocity rate: the share of your Hours that were also returned by the same people you helped during this period.') }}
</p>
<p class="text-sm text-theme-secondary mt-1">
{{ __('A high rate means you are part of a more closed exchange network with frequent returning exchange partners, while a low rate suggests you are part of a more open network with many different exchange partners.') }}
</p>
</div>
<div class="bg-white rounded-lg shadow-sm border border-theme-primary p-6"
data-chart-data="{{ json_encode($returnRatioTimelineData) }}"
data-trend-data="{{ json_encode($returnRatioTrendData) }}"
data-date-range="{{ $this->fromDate }} to {{ $this->toDate }}">
<canvas id="returnRatioChart" width="400" height="200"></canvas>
</div>
</div>
@endif
<!-- Period Statistics Table -->
<div class="">
<h3 class="text-lg font-medium text-theme-primary">
{{ __('Transaction Relation Statistics') }}
</h3>
<p class="text-sm text-theme-secondary mt-2">
{{ __('Which types of profiles have you transacted with?') }}
</p>
</div>
<div class="relative mb-12 w-full min-w-full leading-normal">
<table class="w-full" id="period-statistics">
<thead>
<tr>
<th class="border-b border-theme-primary text-left">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Period Statistics') }}
</span>
</th>
<th class="border-b border-theme-primary py-6 text-right">
<span class="px-0 py-2 text-sm font-normal text-theme-secondary">
{{ __('Value') }}
</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-sm">
<div class="whitespace-no-wrap text-theme-primary">
{{ __('Number of Transactions') }}
</div>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ number_format($statisticsData['transaction_count']) }}
</span>
</td>
</tr>
@if($statisticsData['profiles_by_type'] && $statisticsData['profiles_by_type']->count() > 0)
@foreach($statisticsData['profiles_by_type'] as $modelType => $count)
<tr>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-sm">
<div class="whitespace-no-wrap text-theme-primary">
{{ __('Unique ' . class_basename($modelType) . 's') }}
</div>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ number_format($count) }}
</span>
</td>
</tr>
@endforeach
@endif
<tr>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-sm">
<div class="whitespace-no-wrap text-theme-primary">
{{ __('Total unique profiles') }}
</div>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ number_format($statisticsData['unique_profiles']) }}
</span>
</td>
</tr>
@if($isOrganization)
<tr>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-sm">
<div class="whitespace-no-wrap text-theme-primary">
{{ __('Average reciprocity rate') }}
</div>
</td>
<td class="border-b border-theme-primary bg-theme-background px-2 py-2 text-right text-sm">
<span class="whitespace-no-wrap text-theme-primary">
{{ number_format($statisticsData['average_return_ratio'], 1) }}%
</span>
</td>
</tr>
@endif
</tbody>
</table>
</div>
@else
<div class="text-left py-8">
<div class="text-theme-secondary">
{{ __('Please select a period to generate the account balance report') }}
</div>
</div>
@endif
<script>
// Register trigger-chart-export listener once globally (guard against re-registration on Livewire morphs)
if (!window._chartExportListenerRegistered) {
window._chartExportListenerRegistered = true;
function registerChartExportListener() {
Livewire.on('trigger-chart-export', () => {
if (typeof window.exportPdfWithChart === 'function') {
window.exportPdfWithChart();
}
});
}
// Livewire may already be initialized (component renders after livewire:init fires)
if (typeof window.Livewire !== 'undefined') {
registerChartExportListener();
} else {
document.addEventListener('livewire:init', registerChartExportListener);
}
}
</script>
</div>