Skip to content

Instantly share code, notes, and snippets.

@devhammed
Last active October 25, 2024 11:44
Show Gist options
  • Save devhammed/17f28a651fd791b70f7311a00bea2661 to your computer and use it in GitHub Desktop.
Save devhammed/17f28a651fd791b70f7311a00bea2661 to your computer and use it in GitHub Desktop.
Filament Money Input Component (this assumes that you are using the MoneyCast from https://github.com/akaunting/laravel-money package for the field in your model, this package is depended on by default in FilamentPHP so this should work out of the box))
<?php
namespace App\Frontend\Forms\Components;
use Closure;
use Akaunting\Money\Money;
use Filament\Support\RawJs;
use Akaunting\Money\Currency;
use Filament\Forms\Components\TextInput;
class MoneyInput extends TextInput
{
protected bool|Closure|null $masking = null;
protected bool|Closure|null $allowNegative = null;
protected string|Currency|Closure|null $currency = null;
protected function setUp(): void
{
parent::setUp();
$this
->inputMode('decimal')
->extraInputAttributes(['class' => '!text-xl'])
->prefix(fn(MoneyInput $component) => $component->getCurrency()->getPrefix(), isInline: true)
->suffix(fn(MoneyInput $component) => $component->getCurrency()->getSuffix(), isInline: true)
->stripCharacters(fn(MoneyInput $component) => $component->getCurrency()->getDecimalMark())
->formatStateUsing(fn(MoneyInput $component, ?array $state): ?float => $state['value'] ?? null)
->dehydrateStateUsing(fn(MoneyInput $component, ?string $state): Money => money(
amount: floatval(str_replace($component->getCurrency()->getThousandsSeparator(), '', $state ?? '0')),
currency: $component->getCurrency()->getCurrency(),
convert: true,
))
->extraAttributes(['class' => h('[&_.fi-input-wrp-label]:text-3xl [&_.fi-input-wrp-label]:text-primary-700 [&_.fi-input-wrp-label]:select-none dark:[&_.fi-input-wrp-label]:text-primary')])
->rule(fn(MoneyInput $component) => function (string $attribute, ?string $value, Closure $fail) use (
$component
) {
if ( ! $component->getAllowNegative() && floatval($value) < 0) {
$fail(t('Field must be a positive number.'));
}
});
}
public function currency(string|Currency|Closure|null $currency = null): static
{
$this->currency = $currency;
return $this;
}
public function masking(bool|Closure $masking = true): static
{
$this->masking = $masking;
return $this;
}
public function allowNegative(bool|Closure $allowNegative = true): static
{
$this->allowNegative = $allowNegative;
return $this;
}
public function getCurrency(): Currency
{
$currency = $this->evaluate($this->currency);
if ($currency instanceof Currency) {
return $currency;
}
return currency($currency);
}
public function getMasking(): bool
{
return $this->evaluate($this->masking ?? true);
}
public function getAllowNegative(): bool
{
return $this->evaluate($this->allowNegative ?? false);
}
public function getMask(): string|RawJs|null
{
if ( ! $this->getMasking()) {
return null;
}
return RawJs::make(sprintf(
"\$money(\$input, '%s', '%s', %d);",
$this->getCurrency()->getDecimalMark(),
$this->getCurrency()->getThousandsSeparator(),
$this->getCurrency()->getPrecision(),
));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment