Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 10s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 11s
Gemini PR Review / Gemini PR Review (pull_request) Successful in 14s
Laravel Larastan / larastan (pull_request) Failing after 2m23s
Laravel Pint / pint (pull_request) Failing after 2m30s
206 lines
5.5 KiB
PHP
206 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Widgets;
|
|
|
|
use App\Models\RfqTransporterBid;
|
|
use Filament\Widgets\ChartWidget;
|
|
use Illuminate\Support\Js;
|
|
|
|
class RfqRankChart extends ChartWidget
|
|
{
|
|
protected static ?string $heading = 'Chart';
|
|
|
|
// protected function getData(): array
|
|
// {
|
|
// $rfqId = session('rfq_id');
|
|
|
|
// if (!$rfqId) {
|
|
// return [
|
|
// 'datasets' => [],
|
|
// 'labels' => [],
|
|
// ];
|
|
// }
|
|
|
|
// // Get bids ordered by lowest freight charge
|
|
// $bids = RfqTransporterBid::query()
|
|
// ->where('request_quotation_id', $rfqId)
|
|
// ->orderByRaw('CAST(total_freight_charge AS DECIMAL(10,2)) ASC')
|
|
// ->get();
|
|
|
|
// // $labels = [];
|
|
// // $ranks = [];
|
|
|
|
// // $rank = 1;
|
|
// // foreach ($bids as $bid) {
|
|
// // $labels[] = $bid->transporter_name;
|
|
// // $ranks[] = $rank++;
|
|
// // }
|
|
|
|
// // return [
|
|
// // 'datasets' => [
|
|
// // [
|
|
// // 'label' => 'Rank (Lower is Better)',
|
|
// // 'data' => $ranks,
|
|
// // 'fill' => false,
|
|
// // 'tension' => 0.3,
|
|
// // ],
|
|
// // ],
|
|
// // 'labels' => $labels,
|
|
// // ];
|
|
// $labels = [];
|
|
// $ranks = [];
|
|
// $colors = [];
|
|
|
|
// $rank = 1;
|
|
// foreach ($bids as $bid) {
|
|
// $labels[] = $bid->transporter_name;
|
|
// $ranks[] = $rank;
|
|
|
|
// // Rank-based colors
|
|
// $colors[] = match ($rank) {
|
|
// 1 => '#FFD700', // Gold
|
|
// 2 => '#C0C0C0', // Silver
|
|
// 3 => '#CD7F32', // Bronze
|
|
// default => '#3B82F6', // Blue
|
|
// };
|
|
|
|
// $rank++;
|
|
// }
|
|
|
|
// return [
|
|
// 'datasets' => [
|
|
// [
|
|
// 'label' => 'Rank (1 = Best)',
|
|
// 'data' => $ranks,
|
|
|
|
// // 🎨 Styling
|
|
// 'borderColor' => '#3B82F6',
|
|
// 'backgroundColor' => $colors,
|
|
// 'pointBackgroundColor' => $colors,
|
|
// 'pointBorderColor' => '#000',
|
|
// 'pointRadius' => 7,
|
|
// 'pointHoverRadius' => 10,
|
|
// 'borderWidth' => 3,
|
|
// 'tension' => 0.4,
|
|
// 'fill' => false,
|
|
// ],
|
|
// ],
|
|
// 'labels' => $labels,
|
|
// ];
|
|
// }
|
|
|
|
|
|
|
|
protected function getData(): array
|
|
{
|
|
$rfqId = session('rfq_id');
|
|
|
|
if (!$rfqId) {
|
|
return [
|
|
'datasets' => [],
|
|
'labels' => [],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* STEP 1: Get bids sorted by freight charge (for ranking)
|
|
*/
|
|
$rankedBids = RfqTransporterBid::query()
|
|
->where('request_quotation_id', $rfqId)
|
|
->orderByRaw('CAST(total_freight_charge AS DECIMAL(10,2)) ASC')
|
|
->get();
|
|
|
|
$rankMap = [];
|
|
$rank = 1;
|
|
|
|
foreach ($rankedBids as $bid) {
|
|
$rankMap[$bid->id] = $rank++;
|
|
}
|
|
|
|
/**
|
|
* STEP 2: Get bids in natural order (for wave effect)
|
|
* You can change orderBy to:
|
|
* - created_at
|
|
* - transporter_name
|
|
*/
|
|
$chartBids = RfqTransporterBid::query()
|
|
->where('request_quotation_id', $rfqId)
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
$labels = [];
|
|
$amounts = [];
|
|
$colors = [];
|
|
|
|
$ranks = [];
|
|
|
|
foreach ($chartBids as $bid) {
|
|
$labels[] = $bid->transporter_name;
|
|
$amounts[] = (float) $bid->total_freight_charge;
|
|
|
|
$rank = $rankMap[$bid->id];
|
|
$ranks[] = $rank;
|
|
|
|
$colors[] = match ($rank) {
|
|
1 => '#FFD700',
|
|
2 => '#C0C0C0',
|
|
3 => '#CD7F32',
|
|
default => '#2563EB',
|
|
};
|
|
}
|
|
|
|
|
|
return [
|
|
'datasets' => [
|
|
[
|
|
'label' => 'Freight Charge',
|
|
'data' => $amounts,
|
|
'rankData' => $ranks,
|
|
|
|
'borderColor' => '#2563EB',
|
|
'backgroundColor' => $colors,
|
|
'pointBackgroundColor' => $colors,
|
|
'pointBorderColor' => '#000',
|
|
'pointRadius' => 7,
|
|
'pointHoverRadius' => 11,
|
|
'borderWidth' => 3,
|
|
'tension' => 0.45,
|
|
'fill' => false,
|
|
],
|
|
],
|
|
'labels' => $labels,
|
|
];
|
|
}
|
|
|
|
protected function getOptions(): array
|
|
{
|
|
return [
|
|
'plugins' => [
|
|
'datalabels' => [
|
|
'anchor' => 'start',
|
|
'align' => 'start',
|
|
'offset' => -15,
|
|
'color' => '#000',
|
|
'font' => [
|
|
'weight' => 'bold',
|
|
],
|
|
'formatter' => Js::from("function(value) { return Number(value); }"),
|
|
],
|
|
],
|
|
'scales' => [
|
|
'y' => [
|
|
'beginAtZero' => true,
|
|
'ticks' => [
|
|
'stepSize' => 0.5,
|
|
],
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
protected function getType(): string
|
|
{
|
|
return 'bar';
|
|
}
|
|
}
|