clientSearch) < 2) { return collect(); } return User::query() ->whereIn('user_type', ['individual', 'company']) ->where(fn ($q) => $q ->where('full_name', 'like', "%{$this->clientSearch}%") ->orWhere('email', 'like', "%{$this->clientSearch}%")) ->limit(10) ->get(); } public function selectClient(int $id): void { $this->clientId = $id; $this->clientSearch = User::find($id)?->full_name ?? ''; } public function clearClient(): void { $this->clientId = null; $this->clientSearch = ''; } public function clearFilters(): void { $this->clientId = null; $this->clientSearch = ''; $this->status = 'all'; $this->dateFrom = ''; $this->dateTo = ''; $this->includeUpdates = false; } public function exportCsv(): ?StreamedResponse { $count = $this->getFilteredTimelines()->count(); if ($count === 0) { $this->dispatch('notify', type: 'info', message: __('export.no_timelines_match')); return null; } $locale = auth()->user()->preferred_language ?? 'ar'; return response()->streamDownload(function () use ($locale) { // UTF-8 BOM for Excel Arabic support echo "\xEF\xBB\xBF"; $csv = Writer::createFromString(); // Headers based on admin language $csv->insertOne([ __('export.case_name', [], $locale), __('export.case_reference', [], $locale), __('export.client_name', [], $locale), __('export.status', [], $locale), __('export.created_date', [], $locale), __('export.updates_count', [], $locale), __('export.last_update', [], $locale), ]); $this->getFilteredTimelines()->cursor()->each(function ($timeline) use ($csv, $locale) { $csv->insertOne([ $timeline->case_name, $timeline->case_reference ?? '-', $timeline->user->full_name, __('export.timeline_status_'.$timeline->status->value, [], $locale), $timeline->created_at->format('Y-m-d'), $timeline->updates_count, $timeline->updates_max_created_at ? Carbon::parse($timeline->updates_max_created_at)->format('Y-m-d H:i') : '-', ]); }); echo $csv->toString(); }, 'timelines-export-'.now()->format('Y-m-d').'.csv', [ 'Content-Type' => 'text/csv; charset=UTF-8', ]); } public function exportPdf(): ?StreamedResponse { $query = $this->getFilteredTimelines(); if ($this->includeUpdates) { $query->with(['updates' => fn ($q) => $q->orderBy('created_at', 'desc')]); } $timelines = $query->get(); if ($timelines->isEmpty()) { $this->dispatch('notify', type: 'info', message: __('export.no_timelines_match')); return null; } if ($timelines->count() > 500) { $this->dispatch('notify', type: 'warning', message: __('export.large_export_warning')); } $locale = auth()->user()->preferred_language ?? 'ar'; $pdf = Pdf::loadView('pdf.timelines-export', [ 'timelines' => $timelines, 'includeUpdates' => $this->includeUpdates, 'locale' => $locale, 'generatedAt' => now(), 'filters' => $this->getActiveFilters(), 'totalCount' => $timelines->count(), ]); $pdf->setOption('isHtml5ParserEnabled', true); $pdf->setOption('defaultFont', 'DejaVu Sans'); return response()->streamDownload( fn () => print($pdf->output()), 'timelines-export-'.now()->format('Y-m-d').'.pdf' ); } public function with(): array { return [ 'statuses' => [ 'all' => __('export.all_statuses'), 'active' => __('export.timeline_status_active'), 'archived' => __('export.timeline_status_archived'), ], 'previewCount' => $this->getFilteredTimelines()->count(), ]; } private function getFilteredTimelines() { return Timeline::query() ->with('user:id,full_name') ->withCount('updates') ->withMax('updates', 'created_at') ->when($this->clientId, fn ($q) => $q->where('user_id', $this->clientId)) ->when($this->status !== 'all', fn ($q) => $q->where('status', $this->status)) ->when($this->dateFrom, fn ($q) => $q->whereDate('created_at', '>=', $this->dateFrom)) ->when($this->dateTo, fn ($q) => $q->whereDate('created_at', '<=', $this->dateTo)) ->orderBy('created_at', 'desc'); } private function getActiveFilters(): array { $filters = []; if ($this->clientId) { $filters['client'] = User::find($this->clientId)?->full_name; } if ($this->status !== 'all') { $filters['status'] = __('export.timeline_status_'.$this->status); } if ($this->dateFrom) { $filters['date_from'] = $this->dateFrom; } if ($this->dateTo) { $filters['date_to'] = $this->dateTo; } return $filters; } }; ?>
{{ __('export.export_timelines') }} {{ __('export.export_timelines_description') }}
{{ __('export.filters_applied') }}
{{-- Client Search --}}
@if ($clientId) @endif @if (strlen($clientSearch) >= 2 && ! $clientId && $this->clients->count() > 0)
@foreach ($this->clients as $client) @endforeach
@endif
{{-- Status Filter --}}
@foreach ($statuses as $value => $label) {{ $label }} @endforeach
{{-- Date From --}}
{{-- Date To --}}
{{-- Include Updates Toggle --}}
{{ __('export.include_updates_description') }}
@if ($clientId || $status !== 'all' || $dateFrom || $dateTo || $includeUpdates)
{{ __('export.clear_filters') }}
@endif
{{ __('export.total_records') }}: {{ $previewCount }}
{{ __('export.export_csv') }} {{ __('export.exporting') }} {{ __('export.export_pdf') }} {{ __('export.exporting') }}
@if ($previewCount === 0)
{{ __('export.no_timelines_match') }}
@endif