layer-chicken/app/Filament/Resources/DelayedGoods/Schemas/DelayedGoodForm.php

235 lines
9.3 KiB
PHP

<?php
namespace App\Filament\Resources\DelayedGoods\Schemas;
use App\Models\Warehouse;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Schema;
class DelayedGoodForm
{
public static function configure(Schema $schema): Schema
{
$unmaskQty = function ($state) {
if (blank($state)) {
return 0;
}
if (is_int($state) || is_float($state)) {
return $state;
}
return (float) str($state)
->replace(',', '.')
->toString();
};
$unmaskMoney = function ($state) {
if (blank($state)) {
return 0;
}
if (is_int($state) || is_float($state)) {
return $state;
}
return (float) str($state)
->replace('.', '')
->replace(',', '.')
->toString();
};
$recalculateTotal = function (callable $get, callable $set) use ($unmaskMoney, $unmaskQty): void {
$quantity = $unmaskQty($get('quantity'));
$unitPrice = $unmaskMoney($get('unit_price'));
$totalAmount = $quantity * $unitPrice;
$set('total_amount', number_format($totalAmount, 0, ',', '.'));
};
$recalculateRemaining = function (callable $get, callable $set) use ($unmaskMoney): void {
$paidAmount = $unmaskMoney($get('paid_amount'));
$totalAmount = $unmaskMoney($get('total_amount'));
$remaining = max(0, $totalAmount - $paidAmount);
$set('remaining_amount', number_format($remaining, 0, ',', '.'));
};
return $schema->components([
Grid::make(3)
->schema([
DatePicker::make('stored_date')
->label('Tanggal Penyimpanan')
->default(now())
->required()
->native(false)
->displayFormat('l, d F Y'),
Select::make('warehouse_id')
->label('Ambil Dari Gudang')
->relationship('warehouse', 'name')
->searchable()
->preload()
->native(false)
->required()
->default(fn () => Warehouse::first()?->id),
Select::make('customer_id')
->label('Pelanggan')
->relationship('customer', 'name')
->searchable()
->preload()
->native(false)
->required(),
])
->columnSpanFull(),
Grid::make(3)
->schema([
TextInput::make('quantity')
->label('Jumlah Barang')
->placeholder('0')
->autocomplete(false)
->required()
->live()
->afterStateUpdated(function ($state, callable $get, callable $set) use ($recalculateTotal, $recalculateRemaining): void {
$recalculateTotal($get, $set);
$recalculateRemaining($get, $set);
})
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 2)
->formatStateUsing(fn ($state) => $state === null ? null : (float) $state)
->dehydrateStateUsing($unmaskQty),
TextInput::make('unit_price')
->label('Harga per Satuan')
->placeholder('0')
->autocomplete(false)
->prefix('Rp')
->required()
->live()
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 0)
->dehydrateStateUsing($unmaskMoney)
->afterStateUpdated(function ($state, callable $get, callable $set) use ($recalculateTotal, $recalculateRemaining): void {
$recalculateTotal($get, $set);
$recalculateRemaining($get, $set);
}),
Select::make('unit_id')
->label('Satuan')
->relationship('unit', 'alias')
->searchable()
->preload()
->native(false)
->required(),
]),
Grid::make(3)
->schema([
TextInput::make('total_amount')
->label('Total')
->placeholder('0')
->readOnly()
->prefix('Rp')
->required()
->live()
->formatStateUsing(
fn ($state) => number_format((float) ($state ?? 0), 0, ',', '.')
)
->dehydrateStateUsing($unmaskMoney),
TextInput::make('paid_amount')
->label('Jumlah yang Sudah Dibayar (DP)')
->placeholder('0')
->default(0)
->autocomplete(false)
->required()
->live()
->prefix('Rp')
->readOnly(fn (callable $get) => $get('is_paid'))
->afterStateUpdated(function ($state, callable $get, callable $set) use ($recalculateRemaining, $unmaskMoney): void {
$paidAmount = $unmaskMoney($state);
$totalAmount = $unmaskMoney($get('total_amount'));
$recalculateRemaining($get, $set);
if (! $get('is_paid')) {
$set('is_paid', $paidAmount >= $totalAmount && $totalAmount > 0);
}
if ($paidAmount >= $totalAmount && $totalAmount > 0 && ! $get('payment_date')) {
$set('payment_date', now());
}
if ($paidAmount < $totalAmount) {
$set('payment_date', null);
}
})
->currencyMask(thousandSeparator: '.', decimalSeparator: ',', precision: 0)
->dehydrateStateUsing($unmaskMoney),
TextInput::make('remaining_amount')
->label('Sisa Pembayaran')
->placeholder('0')
->readOnly()
->prefix('Rp')
->default(0)
->live()
->formatStateUsing(function ($state, callable $get) use ($unmaskMoney) {
$paidAmount = $unmaskMoney($get('paid_amount'));
$totalAmount = $unmaskMoney($get('total_amount'));
$remaining = max(0, $totalAmount - $paidAmount);
return number_format($remaining, 0, ',', '.');
})
->dehydrated(false),
Toggle::make('is_paid')
->label('Lunas')
->default(false)
->live()
->afterStateUpdated(function ($state, callable $get, callable $set) use ($recalculateRemaining, $unmaskMoney): void {
$totalAmount = $unmaskMoney($get('total_amount'));
if ($state) {
$set('paid_amount', number_format($totalAmount, 0, ',', '.'));
if (! $get('payment_date')) {
$set('payment_date', now());
}
} else {
$set('paid_amount', 0);
$set('payment_date', null);
}
$recalculateRemaining($get, $set);
}),
DatePicker::make('payment_date')
->label('Tanggal Pembayaran Lunas')
->native(false)
->displayFormat('l, d F Y')
->visible(function (callable $get) use ($unmaskMoney) {
$paidAmount = $unmaskMoney($get('paid_amount'));
$totalAmount = $unmaskMoney($get('total_amount'));
return $paidAmount >= $totalAmount && $totalAmount > 0;
}),
]),
Textarea::make('notes')
->label('Catatan')
->placeholder('...')
->autocomplete(false)
->columnSpanFull(),
])
->columns(1);
}
}