From 75712c4f2aa2c3954621986fbbdbe88cbe105b54 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Wed, 25 Feb 2026 22:35:26 +0700 Subject: [PATCH] feat: Refactor egg collection management by consolidating pages and updating form structure --- .../EggCollections/EggCollectionResource.php | 107 +++++++++++++++-- .../Pages/CreateEggCollection.php | 67 ----------- .../Pages/EditEggCollection.php | 76 ------------ .../Pages/ListEggCollections.php | 22 ---- .../Pages/ManageEggCollections.php | 31 +++++ .../Schemas/EggCollectionForm.php | 63 ---------- .../Tables/EggCollectionsTable.php | 108 ------------------ .../Manage/EggCollections/Traits/HasEggs.php | 46 -------- app/Models/EggCollection.php | 7 +- app/Models/EggCollectionItem.php | 31 ----- database/factories/EggCollectionFactory.php | 42 +------ ...17_000001_create_egg_collections_table.php | 1 + ...0002_create_egg_collection_items_table.php | 26 ----- .../chicken-eggs-grid.blade.php | 29 ----- 14 files changed, 132 insertions(+), 524 deletions(-) delete mode 100644 app/Filament/Resources/Manage/EggCollections/Pages/CreateEggCollection.php delete mode 100644 app/Filament/Resources/Manage/EggCollections/Pages/EditEggCollection.php delete mode 100644 app/Filament/Resources/Manage/EggCollections/Pages/ListEggCollections.php create mode 100644 app/Filament/Resources/Manage/EggCollections/Pages/ManageEggCollections.php delete mode 100644 app/Filament/Resources/Manage/EggCollections/Schemas/EggCollectionForm.php delete mode 100644 app/Filament/Resources/Manage/EggCollections/Tables/EggCollectionsTable.php delete mode 100644 app/Filament/Resources/Manage/EggCollections/Traits/HasEggs.php delete mode 100644 app/Models/EggCollectionItem.php delete mode 100644 database/migrations/2026_02_17_000002_create_egg_collection_items_table.php delete mode 100644 resources/views/filament/resources/manage/egg-collections/chicken-eggs-grid.blade.php diff --git a/app/Filament/Resources/Manage/EggCollections/EggCollectionResource.php b/app/Filament/Resources/Manage/EggCollections/EggCollectionResource.php index cf2052e..65debe2 100644 --- a/app/Filament/Resources/Manage/EggCollections/EggCollectionResource.php +++ b/app/Filament/Resources/Manage/EggCollections/EggCollectionResource.php @@ -2,16 +2,26 @@ namespace App\Filament\Resources\Manage\EggCollections; -use App\Filament\Resources\Manage\EggCollections\Pages\CreateEggCollection; -use App\Filament\Resources\Manage\EggCollections\Pages\EditEggCollection; -use App\Filament\Resources\Manage\EggCollections\Pages\ListEggCollections; -use App\Filament\Resources\Manage\EggCollections\Schemas\EggCollectionForm; -use App\Filament\Resources\Manage\EggCollections\Tables\EggCollectionsTable; +use App\Enums\RoleEnum; +use App\Filament\Actions\Cheerful\DeleteAction; +use App\Filament\Actions\Cheerful\EditAction; +use App\Filament\Actions\Cheerful\ForceDeleteAction; +use App\Filament\Actions\Cheerful\RestoreAction; +use App\Filament\Actions\DefaultBulkActions; +use App\Filament\Columns\TimestampColumns; +use App\Filament\Resources\Manage\EggCollections\Pages\ManageEggCollections; use App\Models\EggCollection; use BackedEnum; +use Filament\Actions\BulkActionGroup; +use Filament\Forms\Components\Hidden; +use Filament\Forms\Components\Textarea; +use Filament\Forms\Components\TextInput; use Filament\Resources\Resource; use Filament\Schemas\Schema; +use Filament\Support\Enums\Width; use Filament\Support\Icons\Heroicon; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Filters\TrashedFilter; use Filament\Tables\Table; use UnitEnum; @@ -33,20 +43,97 @@ class EggCollectionResource extends Resource public static function form(Schema $schema): Schema { - return EggCollectionForm::configure($schema); + return $schema + ->components([ + Hidden::make('production_date') + ->default(now()), + + TextInput::make('total_eggs') + ->label('Jumlah Telur') + ->placeholder('0') + ->autocomplete(false) + ->required() + ->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 0) + ->dehydrateStateUsing(fn ($state) => (int) str()->replace(',', '', (string) ($state ?? 0))), + + TextInput::make('total_broken_eggs') + ->label('Jumlah Telur Pecah') + ->placeholder('0') + ->autocomplete(false) + ->required() + ->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 0) + ->dehydrateStateUsing(fn ($state) => (int) str()->replace(',', '', (string) ($state ?? 0))), + + Textarea::make('notes') + ->label('Catatan') + ->placeholder('...') + ->columnSpanFull(), + ]) + ->columns(1); } public static function table(Table $table): Table { - return EggCollectionsTable::configure($table); + return $table + ->columns([ + TextColumn::make('production_date') + ->label('Tanggal Produksi') + ->dateTime('l, d F Y H:i') + ->searchable() + ->sortable(), + + TextColumn::make('total_eggs') + ->label('Total Telur') + ->numeric() + ->searchable() + ->sortable(), + + TextColumn::make('total_broken_eggs') + ->label('Total Telur Pecah') + ->numeric() + ->searchable() + ->sortable(), + + TextColumn::make('notes') + ->label('Catatan') + ->searchable() + ->wrap() + ->toggleable(), + + ...TimestampColumns::make(), + ]) + ->filters([ + TrashedFilter::make() + ->native(false) + ->visible(fn (): bool => auth()->user()->hasRole(RoleEnum::DEVELOPER)), + ]) + ->recordActions([ + EditAction::make() + ->label('Ubah') + ->modalWidth(Width::Large) + ->modalHeading(fn (EggCollection $record): string => 'Ubah '.$record->production_date->translatedFormat('l, d F Y H:i')), + + DeleteAction::make(), + + ForceDeleteAction::make(), + + RestoreAction::make(), + ]) + ->toolbarActions([ + BulkActionGroup::make([ + ...DefaultBulkActions::make('Produksi Telur'), + ]), + ]) + ->emptyStateIcon(Heroicon::RectangleGroup) + ->emptyStateDescription('Setelah Anda membuat data pertama, maka akan muncul disini.') + ->defaultSort('created_at', 'desc') + ->deferFilters(false); } public static function getPages(): array { return [ - 'index' => ListEggCollections::route('/'), - 'create' => CreateEggCollection::route('/create'), - 'edit' => EditEggCollection::route('/{record}/edit'), + 'index' => ManageEggCollections::route('/'), ]; } } diff --git a/app/Filament/Resources/Manage/EggCollections/Pages/CreateEggCollection.php b/app/Filament/Resources/Manage/EggCollections/Pages/CreateEggCollection.php deleted file mode 100644 index 24e1dc8..0000000 --- a/app/Filament/Resources/Manage/EggCollections/Pages/CreateEggCollection.php +++ /dev/null @@ -1,67 +0,0 @@ -url(ListEggCollections::getUrl()), - ]; - } - - protected function getRedirectUrl(): string - { - return $this->getResource()::getUrl('index'); - } - - protected function mutateFormDataBeforeCreate(array $data): array - { - $data['total_eggs'] = array_sum($this->eggs ?? []); - $data['production_date'] = now(); - - return $data; - } - - protected function afterCreate(): void - { - foreach ($this->eggs as $chickenId => $eggsCount) { - if ($eggsCount <= 0) { - continue; - } - - EggCollectionItem::create([ - 'egg_collection_id' => $this->record->id, - 'chicken_id' => $chickenId, - 'eggs_count' => $eggsCount, - ]); - } - - $this->eggs = []; - } - - protected function getCreatedNotification(): ?Notification - { - return Notification::make() - ->title('Data Berhasil Disimpan') - ->body('Data baru telah berhasil ditambahkan dan disimpan oleh sistem.') - ->success(); - } -} diff --git a/app/Filament/Resources/Manage/EggCollections/Pages/EditEggCollection.php b/app/Filament/Resources/Manage/EggCollections/Pages/EditEggCollection.php deleted file mode 100644 index 82e01a9..0000000 --- a/app/Filament/Resources/Manage/EggCollections/Pages/EditEggCollection.php +++ /dev/null @@ -1,76 +0,0 @@ -eggs = $this->record->items() - ->pluck('eggs_count', 'chicken_id') - ->map(fn ($count) => (int) $count) - ->toArray(); - } - - protected function getHeaderActions(): array - { - return [ - BackAction::make() - ->url(ListEggCollections::getUrl()), - ]; - } - - protected function getRedirectUrl(): string - { - return $this->getResource()::getUrl('index'); - } - - protected function mutateFormDataBeforeSave(array $data): array - { - $data['total_eggs'] = array_sum($this->eggs ?? []); - - return $data; - } - - protected function afterSave(): void - { - EggCollectionItem::where('egg_collection_id', $this->record->id)->delete(); - - foreach ($this->eggs as $chickenId => $eggsCount) { - if ($eggsCount <= 0) { - continue; - } - - EggCollectionItem::create([ - 'egg_collection_id' => $this->record->id, - 'chicken_id' => $chickenId, - 'eggs_count' => $eggsCount, - ]); - } - } - - protected function getSavedNotification(): ?Notification - { - return Notification::make() - ->title('Perubahan Berhasil Disimpan') - ->body('Perubahan pada data telah berhasil disimpan dan diperbarui di sistem.') - ->success(); - } -} diff --git a/app/Filament/Resources/Manage/EggCollections/Pages/ListEggCollections.php b/app/Filament/Resources/Manage/EggCollections/Pages/ListEggCollections.php deleted file mode 100644 index f21c861..0000000 --- a/app/Filament/Resources/Manage/EggCollections/Pages/ListEggCollections.php +++ /dev/null @@ -1,22 +0,0 @@ -label('Tambah'), - ]; - } -} diff --git a/app/Filament/Resources/Manage/EggCollections/Pages/ManageEggCollections.php b/app/Filament/Resources/Manage/EggCollections/Pages/ManageEggCollections.php new file mode 100644 index 0000000..abee8e9 --- /dev/null +++ b/app/Filament/Resources/Manage/EggCollections/Pages/ManageEggCollections.php @@ -0,0 +1,31 @@ +label('Tambah') + ->modalHeading('Tambah Produksi Telur') + ->modalSubmitActionLabel('Simpan') + ->modalCancelActionLabel('Batal') + ->extraModalFooterActions(fn (CreateAction $action): array => [ + $action->makeModalSubmitAction('createAnother', arguments: ['another' => true]) + ->label('Simpan dan Tambah Lagi'), + ]) + ->modalWidth(Width::Large), + ]; + } +} diff --git a/app/Filament/Resources/Manage/EggCollections/Schemas/EggCollectionForm.php b/app/Filament/Resources/Manage/EggCollections/Schemas/EggCollectionForm.php deleted file mode 100644 index 3f5666a..0000000 --- a/app/Filament/Resources/Manage/EggCollections/Schemas/EggCollectionForm.php +++ /dev/null @@ -1,63 +0,0 @@ -remember( - 'active_chickens_for_egg_collection_form', - now()->addMinutes(10), - function () { - return Chicken::query() - ->where('status', ChickenStatus::ACTIVE) - ->orderBy('tag_code') - ->get(); - } - ); - - return $schema - ->components([ - Section::make('Informasi Produksi') - ->schema([ - Grid::make(3) - ->schema([ - Textarea::make('notes') - ->label('Catatan') - ->placeholder('...') - ->columnSpanFull(), - ]), - ]) - ->collapsible(), - - Grid::make([ - 'default' => 1, - 'lg' => 3, - ]) - ->schema([ - Section::make('Daftar Ayam') - ->schema([ - View::make('filament.resources.manage.egg-collections.chicken-eggs-grid') - ->viewData([ - 'chickens' => $chickens, - ]), - ]) - ->columnSpan([ - 'default' => 1, - 'lg' => 3, - ]), - ]), - ]) - ->columns(1); - } -} diff --git a/app/Filament/Resources/Manage/EggCollections/Tables/EggCollectionsTable.php b/app/Filament/Resources/Manage/EggCollections/Tables/EggCollectionsTable.php deleted file mode 100644 index b4e2e60..0000000 --- a/app/Filament/Resources/Manage/EggCollections/Tables/EggCollectionsTable.php +++ /dev/null @@ -1,108 +0,0 @@ -columns([ - TextColumn::make('production_date') - ->label('Tanggal Produksi') - ->dateTime('l, d F Y H:i') - ->searchable() - ->sortable(), - - TextColumn::make('total_eggs') - ->label('Total Telur') - ->numeric() - ->searchable() - ->sortable(), - - TextColumn::make('notes') - ->label('Catatan') - ->searchable() - ->wrap() - ->toggleable(), - - ...TimestampColumns::make(), - ]) - ->filters([ - TrashedFilter::make() - ->native(false) - ->visible(fn (): bool => auth()->user()->hasRole(RoleEnum::DEVELOPER)), - ]) - ->recordActions([ - EditAction::make() - ->label('Ubah'), - - ViewAction::make() - ->label('Detail') - ->color('gray') - ->modalHeading('Detail Produksi Telur') - ->modalWidth(Width::Large) - ->schema([ - Section::make('Ringkasan') - ->schema([ - TextEntry::make('production_date') - ->label('Waktu Produksi') - ->dateTime('l, d F Y H:i'), - - TextEntry::make('total_eggs') - ->label('Total Telur'), - - TextEntry::make('notes') - ->label('Catatan') - ->placeholder('-') - ->columnSpanFull(), - - RepeatableEntry::make('items') - ->label('Daftar Ayam') - ->schema([ - TextEntry::make('chicken.tag_code') - ->label('Kode Ayam') - ->placeholder('-'), - - TextEntry::make('eggs_count') - ->label('Jumlah Telur'), - ]) - ->columns(2), - ]), - ]), - - DeleteAction::make(), - - ForceDeleteAction::make(), - - RestoreAction::make(), - ]) - ->toolbarActions([ - BulkActionGroup::make([ - ...DefaultBulkActions::make('Produksi Telur'), - ]), - ]) - ->emptyStateIcon(Heroicon::RectangleGroup) - ->emptyStateDescription('Setelah Anda membuat data pertama, maka akan muncul disini.') - ->defaultSort('created_at', 'desc') - ->deferFilters(false); - } -} diff --git a/app/Filament/Resources/Manage/EggCollections/Traits/HasEggs.php b/app/Filament/Resources/Manage/EggCollections/Traits/HasEggs.php deleted file mode 100644 index 9c2a46d..0000000 --- a/app/Filament/Resources/Manage/EggCollections/Traits/HasEggs.php +++ /dev/null @@ -1,46 +0,0 @@ - eggs_count] - */ - public array $eggs = []; - - public function addEgg(int $chickenId): void - { - $current = $this->eggs[$chickenId] ?? 0; - $this->eggs[$chickenId] = $current + 1; - - $this->syncTotalEggsFromState(); - } - - public function decreaseEgg(int $chickenId): void - { - $current = $this->eggs[$chickenId] ?? 0; - if ($current <= 0) { - return; - } - - $new = $current - 1; - if ($new > 0) { - $this->eggs[$chickenId] = $new; - } else { - unset($this->eggs[$chickenId]); - } - - $this->syncTotalEggsFromState(); - } - - protected function syncTotalEggsFromState(): void - { - $total = array_sum($this->eggs); - - $this->form->fill([ - ...$this->form->getState(), - 'total_eggs' => $total, - ]); - } -} diff --git a/app/Models/EggCollection.php b/app/Models/EggCollection.php index 8a5ffcc..32240c0 100644 --- a/app/Models/EggCollection.php +++ b/app/Models/EggCollection.php @@ -4,7 +4,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; class EggCollection extends Model @@ -18,11 +17,7 @@ protected function casts(): array return [ 'production_date' => 'datetime', 'total_eggs' => 'integer', + 'total_broken_eggs' => 'integer', ]; } - - public function items(): HasMany - { - return $this->hasMany(EggCollectionItem::class); - } } diff --git a/app/Models/EggCollectionItem.php b/app/Models/EggCollectionItem.php deleted file mode 100644 index 29ee9dd..0000000 --- a/app/Models/EggCollectionItem.php +++ /dev/null @@ -1,31 +0,0 @@ - 'integer', - ]; - } - - public function collection(): BelongsTo - { - return $this->belongsTo(EggCollection::class, 'egg_collection_id'); - } - - public function chicken(): BelongsTo - { - return $this->belongsTo(Chicken::class); - } -} diff --git a/database/factories/EggCollectionFactory.php b/database/factories/EggCollectionFactory.php index 1f0bdeb..a22a42f 100644 --- a/database/factories/EggCollectionFactory.php +++ b/database/factories/EggCollectionFactory.php @@ -2,9 +2,7 @@ namespace Database\Factories; -use App\Models\Chicken; use App\Models\EggCollection; -use App\Models\EggCollectionItem; use Illuminate\Database\Eloquent\Factories\Factory; /** @@ -20,45 +18,9 @@ public function definition(): array return [ 'production_date' => $dateTime, - 'total_eggs' => 0, + 'total_eggs' => fake()->numberBetween(500, 1500), + 'total_broken_eggs' => fake()->numberBetween(0, 100), 'notes' => $this->faker->optional(0.4)->sentence(), ]; } - - public function configure() - { - return $this->afterCreating(function (EggCollection $collection) { - $chickens = Chicken::where('status', 'ACTIVE') - ->inRandomOrder() - ->take(20) - ->get(); - - if ($chickens->isEmpty()) { - $chickens = Chicken::factory()->count(20)->create(); - } - - $itemCount = $this->faker->numberBetween(5, min(20, $chickens->count())); - $selectedChickens = $chickens->shuffle()->take($itemCount); - - $totalEggs = 0; - - foreach ($selectedChickens as $chicken) { - $eggsCount = $this->faker->numberBetween(0, 2); - - if ($eggsCount <= 0) { - continue; - } - - EggCollectionItem::create([ - 'egg_collection_id' => $collection->id, - 'chicken_id' => $chicken->id, - 'eggs_count' => $eggsCount, - ]); - - $totalEggs += $eggsCount; - } - - $collection->update(['total_eggs' => $totalEggs]); - }); - } } diff --git a/database/migrations/2026_02_17_000001_create_egg_collections_table.php b/database/migrations/2026_02_17_000001_create_egg_collections_table.php index 3b78f52..cf2f1c1 100644 --- a/database/migrations/2026_02_17_000001_create_egg_collections_table.php +++ b/database/migrations/2026_02_17_000001_create_egg_collections_table.php @@ -12,6 +12,7 @@ public function up(): void $table->id(); $table->dateTime('production_date'); $table->unsignedInteger('total_eggs')->default(0); + $table->unsignedInteger('total_broken_eggs')->default(0); $table->text('notes')->nullable(); $table->timestamp('created_at')->useCurrent(); $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); diff --git a/database/migrations/2026_02_17_000002_create_egg_collection_items_table.php b/database/migrations/2026_02_17_000002_create_egg_collection_items_table.php deleted file mode 100644 index ab1f23e..0000000 --- a/database/migrations/2026_02_17_000002_create_egg_collection_items_table.php +++ /dev/null @@ -1,26 +0,0 @@ -id(); - $table->foreignId('egg_collection_id')->constrained()->cascadeOnDelete(); - $table->foreignId('chicken_id')->constrained()->cascadeOnDelete(); - $table->unsignedInteger('eggs_count'); - $table->timestamp('created_at')->useCurrent(); - $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate(); - $table->softDeletes(); - }); - } - - public function down(): void - { - Schema::dropIfExists('egg_collection_items'); - } -}; diff --git a/resources/views/filament/resources/manage/egg-collections/chicken-eggs-grid.blade.php b/resources/views/filament/resources/manage/egg-collections/chicken-eggs-grid.blade.php deleted file mode 100644 index 69be9a4..0000000 --- a/resources/views/filament/resources/manage/egg-collections/chicken-eggs-grid.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -
- - @foreach ($chickens as $chicken) -
-
-
- {{ $chicken->tag_code }} -
- -
- - - - - - - {{ $this->eggs[$chicken->id] ?? 0 }} - - - - + - -
-
-
- @endforeach - -