Initial commit for new repo
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 1m4s
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 1m4s
This commit is contained in:
189
app/Filament/Widgets/ProductionLineStopChart.php
Normal file
189
app/Filament/Widgets/ProductionLineStopChart.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class ProductionLineStopChart extends ChartWidget
|
||||
{
|
||||
protected static ?string $heading = 'Production Line Stop Chart';
|
||||
|
||||
protected static ?string $maxHeight = '250px';
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$activeFilter = $this->filter;
|
||||
$selectedPlant = session('selected_plant');
|
||||
$selectedLine = session('selected_line');
|
||||
|
||||
if (!$selectedPlant || !$selectedLine)
|
||||
{
|
||||
return [
|
||||
'datasets' => [],
|
||||
'labels' => [],
|
||||
];
|
||||
}
|
||||
|
||||
// Set time range based on active filter
|
||||
if ($activeFilter === 'yesterday') {
|
||||
$startDate = now()->subDay()->setTime(8, 0, 0);
|
||||
$endDate = now()->setTime(8, 0, 0);
|
||||
} elseif ($activeFilter === 'this_week') {
|
||||
$startDate = now()->startOfWeek()->setTime(8, 0, 0);
|
||||
$endDate = now()->endOfWeek()->addDay()->setTime(8, 0, 0);
|
||||
} elseif ($activeFilter === 'this_month') {
|
||||
$startDate = now()->startOfMonth();
|
||||
$endDate = now()->endOfMonth();
|
||||
} else {
|
||||
$startDate = now()->setTime(8, 0, 0);
|
||||
$endDate = now()->copy()->addDay()->setTime(8, 0, 0);
|
||||
}
|
||||
|
||||
// Fetch stop reason data
|
||||
// treats minutes as a visual decimal (e.g., 15 mins = 0.15)
|
||||
$query = \DB::table('production_line_stops')
|
||||
->join('line_stops as ls', 'production_line_stops.linestop_id', '=', 'ls.id')
|
||||
->join('lines', 'production_line_stops.line_id', '=', 'lines.id')
|
||||
->join('plants', 'production_line_stops.plant_id', '=', 'plants.id')
|
||||
->select(
|
||||
'ls.code',
|
||||
'ls.reason',
|
||||
\DB::raw("
|
||||
SUM(production_line_stops.stop_hour) as total_stop_hours,
|
||||
SUM(production_line_stops.stop_min) as total_stop_minutes
|
||||
")
|
||||
)
|
||||
->when($selectedPlant, fn($q) => $q->where('plants.id', $selectedPlant))
|
||||
->when($selectedLine, fn($q) => $q->where('lines.id', $selectedLine))
|
||||
->whereBetween('production_line_stops.created_at', [$startDate, $endDate])
|
||||
->groupBy('ls.code', 'ls.reason')
|
||||
//->orderByDesc('total_hours')
|
||||
->get();
|
||||
|
||||
// Handle empty data gracefully
|
||||
if ($query->isEmpty()) {
|
||||
return [
|
||||
'datasets' => [[
|
||||
'label' => 'Line Stop Reasons',
|
||||
'data' => [1],
|
||||
'backgroundColor' => ['rgba(200, 200, 200, 0.4)'],
|
||||
'borderColor' => ['rgba(200, 200, 200, 1)'],
|
||||
'borderWidth' => 1,
|
||||
]],
|
||||
'labels' => ['No Data'],
|
||||
];
|
||||
}
|
||||
|
||||
$labels = [];
|
||||
$data = [];
|
||||
$backgroundColors = [];
|
||||
$borderColors = [];
|
||||
|
||||
function generateColor(string $key, float $opacity): string {
|
||||
// Use a stable hash of the key, no randomness
|
||||
$hash = md5($key);
|
||||
|
||||
// Get the RGB components from the hash
|
||||
$r = hexdec(substr($hash, 0, 2)); // Red component
|
||||
$g = hexdec(substr($hash, 2, 2)); // Green component
|
||||
$b = hexdec(substr($hash, 4, 2)); // Blue component
|
||||
|
||||
// Avoid deep green colors for the `code`
|
||||
if ($g > 150 && $g < 255) {
|
||||
// Adjust green component if it's in the deep green range
|
||||
$g = 150; // Assign a fixed, safe value for green
|
||||
}
|
||||
|
||||
// Return the color as rgba with the specified opacity
|
||||
return "rgba($r, $g, $b, $opacity)";
|
||||
}
|
||||
|
||||
$totalStopMinutes = 0;
|
||||
|
||||
foreach ($query as $row) {
|
||||
$code = $row->code;
|
||||
$reason = $row->reason;
|
||||
|
||||
$stopHours = $row->total_stop_hours;
|
||||
$stopMinutes = $row->total_stop_minutes;
|
||||
$visualTotal = $stopHours + ($stopMinutes / 100);
|
||||
|
||||
$codeLabel = "$code - $reason";
|
||||
$labels[] = $codeLabel;
|
||||
$data[] = $visualTotal;
|
||||
$backgroundColors[] = generateColor($code, 0.7); // Unique color for each stop code
|
||||
$borderColors[] = generateColor($code, 1.0);
|
||||
|
||||
// Accumulate total stop time (in minutes)
|
||||
$totalStopMinutes += ($stopHours * 60) + $stopMinutes;
|
||||
}
|
||||
|
||||
// Calculate remaining time (1440 minutes = 24 hours)
|
||||
$remainingMinutes = 1440 - $totalStopMinutes;
|
||||
$runtimeHours = floor($remainingMinutes / 60);
|
||||
$runtimeMinutes = $remainingMinutes % 60;
|
||||
$runtimeVisual = $runtimeHours + ($runtimeMinutes / 100);
|
||||
|
||||
// Add runtime slice with green color (either light or dark green)
|
||||
$labels[] = 'Available Runtime';
|
||||
$data[] = $runtimeVisual;
|
||||
$backgroundColors[] = 'rgba(47, 218, 47, 0.94)'; // Green for runtime
|
||||
$borderColors[] = 'rgba(75, 192, 75, 1)';
|
||||
|
||||
return [
|
||||
'datasets' => [[
|
||||
'label' => 'Line Stop Durations (hrs)',
|
||||
'data' => $data,
|
||||
'backgroundColor' => $backgroundColors,
|
||||
'borderColor' => $borderColors,
|
||||
'borderWidth' => 1,
|
||||
]],
|
||||
'labels' => $labels,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getType(): string
|
||||
{
|
||||
return 'pie';
|
||||
}
|
||||
|
||||
protected function getFilters(): ?array
|
||||
{
|
||||
return [
|
||||
'today' => 'Today',
|
||||
'yesterday' => 'Yesterday',
|
||||
];
|
||||
}
|
||||
|
||||
protected function getOptions(): array
|
||||
{
|
||||
return [
|
||||
// 'responsive' => true,
|
||||
// 'plugins' => [
|
||||
// 'legend' => [
|
||||
// 'position' => 'bottom',
|
||||
// ],
|
||||
// 'tooltip' => [
|
||||
// 'enabled' => true, // Tooltips enabled on hover
|
||||
// ],
|
||||
// ],
|
||||
'plugins' => [
|
||||
'datalabels' => false,
|
||||
],
|
||||
'scales' => [
|
||||
'x' => [
|
||||
'display' => false, // Disable x-axis
|
||||
],
|
||||
'y' => [
|
||||
'display' => false, // Disable y-axis
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public static function canView(): bool
|
||||
{
|
||||
// Only show on HourlyProduction page
|
||||
return request()->routeIs('filament.pages.production-line-stop-count');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user