ifnex/04_Laravel/app/Filament/Widgets/TransactionChartWidget.php
Kazem Alghasi 91984dbde3 feat(ui): redesign admin dashboard with layered grid and custom branding
Implement a comprehensive overhaul of the Filament admin dashboard,
introducing a structured 12-column responsive grid layout and enhanced
visual identity.

Key changes include:
- Redesigned Dashboard layout with a 4-layer progressive disclosure
  architecture (KPIs, Exchange Rates, Data Tables, and Trends).
- Introduced custom IFNEX design tokens via CSS, including branded
  stat cards, status badges, and improved sidebar typography.
- Enhanced FinanceOverviewWidget with real-time trend analysis and
  sparkline-ready data structures.
- Refactored RecentShipments and RecentTransactions widgets to use
  custom Blade templates for a more polished, consistent UI.
- Integrated brand assets including the company logo and custom
  authentication pages.
- Added global number formatting helpers and integrated them into
  financial widgets.
- Updated AdminPanelProvider to support custom login pages and
  brand-specific header/footer hooks.
2026-10-03 11:08:50 +03:30

127 lines
4.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Filament\Widgets;
use App\Models\WalletTransaction;
use Filament\Widgets\ChartWidget;
use Illuminate\Support\Facades\DB;
use Morilog\Jalali\Jalalian;
/**
* Layer 2 (left) — 7-day revenue trend chart, spanning 8/12 of the body grid.
*/
class TransactionChartWidget extends ChartWidget
{
protected static ?int $sort = 8;
protected static ?string $pollingInterval = '60s';
protected static ?string $heading = 'روند تراکنش‌های ۷ روز اخیر';
protected static ?string $maxHeight = '320px';
protected int|string|array $columnSpan = 12;
protected function getData(): array
{
$data = WalletTransaction::select(
DB::raw('DATE(created_at) as date'),
DB::raw('SUM(CASE WHEN type = "deposit" AND status = "completed" THEN amount ELSE 0 END) as deposits'),
DB::raw('SUM(CASE WHEN type IN ("withdrawal", "order_payment") AND status = "completed" THEN amount ELSE 0 END) as withdrawals')
)
->where('created_at', '>=', now()->subDays(7))
->groupBy('date')
->orderBy('date')
->get();
$labels = $data->pluck('date')->map(function ($date) {
return Jalalian::fromCarbon(\Carbon\Carbon::parse($date))->format('l d');
})->toArray();
$deposits = $data->pluck('deposits')->map(fn ($v) => (float) $v)->toArray();
$withdrawals = $data->pluck('withdrawals')->map(fn ($v) => (float) $v)->toArray();
return [
'datasets' => [
[
'label' => 'واریزی‌ها',
'data' => $deposits,
'borderColor' => '#10b981',
'backgroundColor' => 'rgba(16, 185, 129, 0.15)',
'fill' => true,
'tension' => 0.4,
'pointRadius' => 3,
'pointHoverRadius' => 5,
'pointBackgroundColor' => '#10b981',
],
[
'label' => 'برداشت‌ها',
'data' => $withdrawals,
'borderColor' => '#f59e0b',
'backgroundColor' => 'rgba(245, 158, 11, 0.15)',
'fill' => true,
'tension' => 0.4,
'pointRadius' => 3,
'pointHoverRadius' => 5,
'pointBackgroundColor' => '#f59e0b',
],
],
'labels' => $labels,
];
}
protected function getType(): string
{
return 'line';
}
protected function getOptions(): array
{
return [
'plugins' => [
'legend' => [
'position' => 'top',
'align' => 'end',
'labels' => [
'font' => [
'family' => 'Vazirmatn',
'size' => 12,
],
'usePointStyle' => true,
'boxWidth' => 8,
],
],
'tooltip' => [
'callbacks' => [
'label' => 'function(context) {
var v = context.parsed.y;
if (v === null || v === undefined) return "";
return context.dataset.label + ": " + v.toLocaleString("fa-IR") + " ریال";
}',
],
],
],
'scales' => [
'y' => [
'beginAtZero' => true,
'ticks' => [
'callback' => 'function(value) { return value.toLocaleString("fa-IR"); }',
'font' => ['family' => 'Vazirmatn', 'size' => 11],
],
'grid' => [
'color' => 'rgba(0, 0, 0, 0.05)',
],
],
'x' => [
'ticks' => [
'maxRotation' => 0,
'font' => ['family' => 'Vazirmatn', 'size' => 11],
],
'grid' => [
'display' => false,
],
],
],
'maintainAspectRatio' => false,
];
}
}