117 lines
4.5 KiB
PHP
117 lines
4.5 KiB
PHP
<?php
|
|
|
|
use App\Services\MonthlyReportService;
|
|
use Livewire\Volt\Component;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
new class extends Component
|
|
{
|
|
public string $selectedPeriod = '';
|
|
|
|
public bool $generating = false;
|
|
|
|
public function mount(): void
|
|
{
|
|
// Default to previous month
|
|
$previousMonth = now()->subMonth();
|
|
$this->selectedPeriod = $previousMonth->format('Y-m');
|
|
}
|
|
|
|
public function getAvailableMonthsProperty(): array
|
|
{
|
|
$months = [];
|
|
for ($i = 1; $i <= 12; $i++) {
|
|
$date = now()->subMonths($i);
|
|
$months[] = [
|
|
'value' => $date->format('Y-m'),
|
|
'label' => $date->translatedFormat('F Y'),
|
|
];
|
|
}
|
|
|
|
return $months;
|
|
}
|
|
|
|
public function generate(): ?StreamedResponse
|
|
{
|
|
$this->generating = true;
|
|
|
|
try {
|
|
[$year, $month] = explode('-', $this->selectedPeriod);
|
|
|
|
$service = app(MonthlyReportService::class);
|
|
|
|
return $service->generate((int) $year, (int) $month);
|
|
} catch (\Exception $e) {
|
|
$this->dispatch('notify', type: 'error', message: __('report.report_failed'));
|
|
|
|
return null;
|
|
} finally {
|
|
$this->generating = false;
|
|
}
|
|
}
|
|
}; ?>
|
|
|
|
<div>
|
|
<div class="mb-6 flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
<div>
|
|
<flux:heading size="xl">{{ __('report.monthly_report') }}</flux:heading>
|
|
<flux:text class="mt-1 text-zinc-500">{{ __('report.monthly_report_description') }}</flux:text>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rounded-lg border border-zinc-200 bg-white p-6">
|
|
<div class="flex flex-col gap-6 sm:flex-row sm:items-end">
|
|
<div class="w-full sm:w-64">
|
|
<flux:select wire:model="selectedPeriod" :label="__('report.select_period')">
|
|
@foreach ($this->availableMonths as $option)
|
|
<flux:select.option value="{{ $option['value'] }}">
|
|
{{ $option['label'] }}
|
|
</flux:select.option>
|
|
@endforeach
|
|
</flux:select>
|
|
</div>
|
|
|
|
<flux:button
|
|
wire:click="generate"
|
|
wire:loading.attr="disabled"
|
|
wire:target="generate"
|
|
variant="primary"
|
|
icon="document-arrow-down"
|
|
>
|
|
<span wire:loading.remove wire:target="generate">{{ __('report.generate') }}</span>
|
|
<span wire:loading wire:target="generate">{{ __('report.generating') }}</span>
|
|
</flux:button>
|
|
</div>
|
|
|
|
<div class="mt-8 rounded-lg bg-zinc-50 p-6">
|
|
<flux:heading size="sm" class="mb-4">{{ __('report.table_of_contents') }}</flux:heading>
|
|
<div class="space-y-2 text-sm text-zinc-600">
|
|
<div class="flex items-center gap-2">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded-full bg-[#2D3624] text-xs text-white">1</span>
|
|
<span>{{ __('report.executive_summary') }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded-full bg-[#2D3624] text-xs text-white">2</span>
|
|
<span>{{ __('report.user_statistics') }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded-full bg-[#2D3624] text-xs text-white">3</span>
|
|
<span>{{ __('report.consultation_statistics') }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded-full bg-[#2D3624] text-xs text-white">4</span>
|
|
<span>{{ __('report.timeline_statistics') }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded-full bg-[#2D3624] text-xs text-white">5</span>
|
|
<span>{{ __('report.post_statistics') }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="flex h-6 w-6 items-center justify-center rounded-full bg-[#2D3624] text-xs text-white">6</span>
|
|
<span>{{ __('report.trends_chart') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|