added production line count chart
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Filament\Widgets\CumulativeChart;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
@@ -8,49 +9,51 @@ use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
|
||||
use Filament\Tables\Filters\SelectFilter;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\Plant;
|
||||
|
||||
use Filament\Widgets\Widget;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class Dashboard extends \Filament\Pages\Dashboard
|
||||
{
|
||||
use HasFiltersForm;
|
||||
|
||||
public function filtersForm(Form $form): Form
|
||||
{
|
||||
$selectedPlant = session('selected_plant', request()->input('filters.Plant'));
|
||||
return $form->schema([
|
||||
// Plant Filter
|
||||
Select::make('Plant')
|
||||
->options(Plant::pluck('name', 'id')) // Fetch plant names with their IDs
|
||||
->label('Select Plant')
|
||||
->reactive()
|
||||
->afterStateUpdated(function ($state, callable $set) use ($selectedPlant) {
|
||||
session(['selected_plant' => $state]);
|
||||
session()->forget('selected_line');
|
||||
$set('Plant', $state);
|
||||
$set('Line', null);
|
||||
$this->triggerChartUpdate();
|
||||
}),
|
||||
protected static ?string $navigationGroup = 'Production DashBoard';
|
||||
|
||||
// Line Filter
|
||||
Select::make('Line')
|
||||
->options(function ($get) {
|
||||
$plantId = $get('Plant');
|
||||
return $plantId ? Plant::find($plantId)->getLineNames()->pluck('name', 'id') : [];
|
||||
})
|
||||
->label('Select Line')
|
||||
->reactive()
|
||||
->afterStateUpdated(function ($state) {
|
||||
session(['selected_line' => $state]); // Store in session
|
||||
$this->triggerChartUpdate(); // Notify chart to refresh
|
||||
}),
|
||||
]);
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->filtersForm->fill([
|
||||
'plant' => Plant::first()?->id // Default to first plant
|
||||
]);
|
||||
}
|
||||
|
||||
// Helper to check if both filters are set
|
||||
public function triggerChartUpdate(): void
|
||||
public function filtersForm(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->statePath('filters') // Store form state in 'filters'
|
||||
->schema([
|
||||
Select::make('plant')
|
||||
->options(Plant::pluck('name', 'id'))
|
||||
->label('Select Plant')
|
||||
->reactive()
|
||||
->afterStateUpdated(function ($state) {
|
||||
session(['selected_plant' => $state]); // fixed typo
|
||||
$this->dispatch('cumulativeChart'); // custom Livewire event
|
||||
}),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
if (session()->has('selected_plant') && session()->has('selected_line')) {
|
||||
$this->dispatch('filtersUpdated');
|
||||
}
|
||||
return 'Production Line Count';
|
||||
}
|
||||
|
||||
public function getHeading(): string
|
||||
{
|
||||
return 'Production Line Count';
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
78
app/Filament/Pages/HourlyProduction.php
Normal file
78
app/Filament/Pages/HourlyProduction.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages;
|
||||
|
||||
use App\Models\Plant;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
|
||||
use Filament\Pages\Page;
|
||||
use Filament\Tables\Concerns\HasFilters;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class HourlyProduction extends Page
|
||||
{
|
||||
protected static ?string $navigationIcon = 'heroicon-o-document-text';
|
||||
|
||||
protected static string $view = 'filament.pages.hourly-production';
|
||||
|
||||
protected static ?string $navigationGroup = 'Production DashBoard';
|
||||
|
||||
use HasFiltersForm;
|
||||
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->filtersForm->fill([
|
||||
'plant' => Plant::first()?->id // Default to first plant
|
||||
]);
|
||||
}
|
||||
|
||||
public function filtersForm(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->statePath('filters')
|
||||
->schema([
|
||||
|
||||
Select::make('plant')
|
||||
->options(Plant::pluck('name', 'id'))
|
||||
->label('Select Plant')
|
||||
->reactive()
|
||||
->afterStateUpdated(function ($state) {
|
||||
session(['selected_plant' => $state]);
|
||||
$this->triggerChartUpdate();
|
||||
}),
|
||||
|
||||
// Line Filter
|
||||
Select::make('line')
|
||||
->options(function ($get) {
|
||||
$plantId = $get('plant');
|
||||
return $plantId ? Plant::find($plantId)->getLineNames()->pluck('name', 'id') : [];
|
||||
})
|
||||
->label('Select Line')
|
||||
->reactive()
|
||||
->afterStateUpdated(function ($state) {
|
||||
session(['selected_line' => $state]);
|
||||
$this->triggerChartUpdate();
|
||||
}),
|
||||
])
|
||||
->columns(2);
|
||||
}
|
||||
|
||||
public function triggerChartUpdate(): void
|
||||
{
|
||||
if (session()->has('selected_plant') && session()->has('selected_line')) {
|
||||
$this->dispatch('filtersUpdated');
|
||||
}
|
||||
}
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return 'Hourly Production Count';
|
||||
}
|
||||
|
||||
public static function canAccess(): bool
|
||||
{
|
||||
return Auth::check() && Auth::user()->can('view production dashboard');
|
||||
}
|
||||
}
|
||||
111
app/Filament/Widgets/CumulativeChart.php
Normal file
111
app/Filament/Widgets/CumulativeChart.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Models\Line;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class CumulativeChart extends ChartWidget
|
||||
{
|
||||
protected static ?string $heading = 'Production Line Count';
|
||||
|
||||
protected $listeners = ['cumulativeChart'];
|
||||
|
||||
|
||||
protected int|string|array $columnSpan = 12;
|
||||
protected function getData(): array
|
||||
{
|
||||
$selectedPlant = session('selected_plant') ?? session('select_plant');
|
||||
$activeFilter = $this->filter;
|
||||
|
||||
// Define date range based on filter
|
||||
switch ($activeFilter) {
|
||||
case 'yesterday':
|
||||
$startDate = now()->subDay()->startOfDay();
|
||||
$endDate = now()->subDay()->endOfDay();
|
||||
break;
|
||||
case 'this_week':
|
||||
$startDate = now()->startOfWeek();
|
||||
$endDate = now()->endOfWeek();
|
||||
break;
|
||||
case 'this_month':
|
||||
$startDate = now()->startOfMonth();
|
||||
$endDate = now()->endOfMonth();
|
||||
break;
|
||||
default: // today
|
||||
$startDate = now()->startOfDay();
|
||||
$endDate = now()->endOfDay();
|
||||
break;
|
||||
}
|
||||
|
||||
// Get all lines for selected plant
|
||||
$lines = Line::where('plant_id', $selectedPlant)
|
||||
->pluck('name', 'id')
|
||||
->toArray();
|
||||
|
||||
// Get total production per line in the date range
|
||||
$production = \DB::table('production_quantities')
|
||||
->select('line_id', \DB::raw('COUNT(*) as total_quantity'))
|
||||
->whereBetween('created_at', [$startDate, $endDate])
|
||||
->whereIn('line_id', array_keys($lines))
|
||||
->groupBy('line_id')
|
||||
->pluck('total_quantity', 'line_id')
|
||||
->toArray();
|
||||
|
||||
// Match quantities with lines (fill 0 if missing)
|
||||
$labels = [];
|
||||
$data = [];
|
||||
|
||||
foreach ($lines as $lineId => $lineName) {
|
||||
$labels[] = $lineName;
|
||||
$data[] = $production[$lineId] ?? 0;
|
||||
}
|
||||
|
||||
return [
|
||||
'labels' => $labels,
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => match ($activeFilter) {
|
||||
'yesterday' => "Production Quantity (Yesterday)",
|
||||
'this_week' => "Weekly Production This Month",
|
||||
'this_month' => "Yesterday's Hourly Production",
|
||||
default => "Today's Production",
|
||||
},
|
||||
'data' => $data,
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function getType(): string
|
||||
{
|
||||
return 'bar';
|
||||
}
|
||||
|
||||
protected function getFilters(): ?array
|
||||
{
|
||||
return [
|
||||
'today' => 'Today',
|
||||
'yesterday' => 'Yesterday',
|
||||
'this_week'=> 'This Week',
|
||||
'this_month'=> 'This Month',
|
||||
];
|
||||
}
|
||||
|
||||
protected function getOptions(): array
|
||||
{
|
||||
return [
|
||||
'scales' => [
|
||||
'y' => [
|
||||
'beginAtZero' => true, //Start Y-axis from 0
|
||||
'ticks' => [
|
||||
'stepSize' => 0.5,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,8 +8,7 @@ class ItemOverview extends ChartWidget
|
||||
{
|
||||
protected static ?string $heading = 'Hourly Production';
|
||||
|
||||
// protected int|string|array $columnSpan = 'full';
|
||||
protected int|string|array $columnSpan = 12;
|
||||
protected int|string|array $columnSpan = '12';
|
||||
|
||||
protected static ?string $maxHeight = '350px';
|
||||
|
||||
@@ -146,20 +145,6 @@ class ItemOverview extends ChartWidget
|
||||
return 'line';
|
||||
}
|
||||
|
||||
// protected function getContent(): string
|
||||
// {
|
||||
// return '<div style="height: 100%;">' . $this->chart->render() . '</div>';
|
||||
// }
|
||||
// protected function getContent(): string
|
||||
// {
|
||||
// return <<<HTML
|
||||
// <div id="chart-container" style="height: 100vh; width: 100%;">
|
||||
// {$this->chart->render()}
|
||||
// </div>
|
||||
// HTML;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
protected function getOptions(): array
|
||||
{
|
||||
@@ -173,15 +158,6 @@ class ItemOverview extends ChartWidget
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
// 'scales' => [
|
||||
// 'y' => [
|
||||
// 'beginAtZero' => true, //Start Y-axis from 0
|
||||
// 'ticks' => [
|
||||
// 'stepSize' => 0.5,
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -194,4 +170,10 @@ class ItemOverview extends ChartWidget
|
||||
'this_month'=> 'This Month',
|
||||
];
|
||||
}
|
||||
|
||||
public static function canView(): bool
|
||||
{
|
||||
// Only show on HourlyProduction page
|
||||
return request()->routeIs('filament.pages.hourly-production');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<x-filament-panels::page>
|
||||
<div class="space-y-4">
|
||||
{{-- Filters form --}}
|
||||
{{ $this->filtersForm($this->form) }}
|
||||
|
||||
{{-- Chart Widget --}}
|
||||
@livewire(\App\Filament\Widgets\ItemOverview::class)
|
||||
</div>
|
||||
</x-filament-panels::page>
|
||||
Reference in New Issue
Block a user