Skip to content

Instantly share code, notes, and snippets.

@trovster
Last active October 11, 2021 14:06
Show Gist options
  • Save trovster/c00d93b3954bc0d4ea70b6fcfb5c7a94 to your computer and use it in GitHub Desktop.
Save trovster/c00d93b3954bc0d4ea70b6fcfb5c7a94 to your computer and use it in GitHub Desktop.
Money View component
@props(['name', 'value' => old($name, $value ?? ''), 'disabled' => false])
<input name="{{ $name }}" value="{{ $value }}" {{ $attributes->merge(['class' => 'form-control']) }}{{ $disabled ? ' disabled' : '' }}>
<?php
namespace App\View\Components\Form;
use App\View\Components\Base as Component;
use Illuminate\Contracts\View\View as Response;
use Money\Money as MoneyObject;
use NumberFormatter;
class Money extends Component
{
public string $name;
public string $currency;
/** @var int|float $value */
public $value;
private ?MoneyObject $money;
private string $format;
public function __construct(string $name, ?MoneyObject $money = null, string $format = 'en_GB')
{
$this->name = $name;
$this->money = $money;
$this->format = $format;
$this->value = $this->value();
$this->currency = $this->currency();
}
public function render(): Response
{
return view('components.form.money');
}
/** @return int|float */
private function value()
{
if (! $this->money) {
return 0;
}
return $this->money->getAmount() / 100;
}
private function currency(): string
{
$numberFormatter = new NumberFormatter($this->locale(), NumberFormatter::CURRENCY);
return $numberFormatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
}
private function locale(): string
{
if (!$this->money) {
return $this->format;
}
return "{$this->format}@currency={$this->money->getCurrency()->getCode()}";
}
}
<?php
namespace Tests\Unit\View\Components\Form;
use App\View\Components\Form\Money as Component;
use Illuminate\View\View;
use Money\Currency;
use Money\Money;
use Tests\Unit\TestCase;
/** @group component */
class MoneyTest extends TestCase
{
protected Component $component;
/** @test */
public function instanceCheck(): void
{
$this->assertInstanceOf(Component::class, $this->component);
}
/** @test */
public function render(): void
{
$this->assertInstanceOf(View::class, $this->component->render());
$this->assertSame('components.form.money', $this->component->render()->name());
}
/** @test */
public function default(): void
{
$this->assertIsString($this->component->name);
$this->assertSame(0, $this->component->value);
$this->assertSame('£', $this->component->currency);
}
/**
* @test
* @dataProvider localesProvider
*/
public function locales(string $locale, string $currency): void
{
$component = new Component($this->faker->word(), null, $locale);
$this->assertSame(0, $component->value);
$this->assertSame($currency, $component->currency);
}
/**
* @test
* @param int|float $value
* @dataProvider valueProvider
*/
public function correctValues(Money $money, string $locale, $value, string $currency): void
{
$component = new Component($this->faker->word(), $money, $locale);
$this->assertIsString($component->name);
$this->assertSame($value, $component->value);
$this->assertSame($currency, $component->currency);
}
public function localesProvider(): iterable
{
return [
yield 'gb as £' => ['en_GB', '£'],
yield 'us as $' => ['en_US', '$'],
yield 'es as euro' => ['es_ES', ''],
yield 'de as euro' => ['de_DE', ''],
];
}
public function valueProvider(): iterable
{
return [
yield 'gbp/gb as £' => [
new Money(500, new Currency('GBP')),
'en_GB',
5,
'£',
],
yield 'gbp/us as £' => [
new Money(500, new Currency('GBP')),
'en_US',
5,
'£',
],
yield 'gbp/es as £' => [
new Money(500, new Currency('GBP')),
'es_ES',
5,
'GBP',
],
yield 'gbp/de as £' => [
new Money(500, new Currency('GBP')),
'de_DE',
5,
'£',
],
yield 'usd/gb as $' => [
new Money(500, new Currency('USD')),
'en_GB',
5,
'US$',
],
yield 'usd/us as $' => [
new Money(500, new Currency('USD')),
'en_US',
5,
'$',
],
yield 'usd/es as $' => [
new Money(500, new Currency('USD')),
'es_ES',
5,
'US$',
],
yield 'usd/de as $' => [
new Money(500, new Currency('USD')),
'de_DE',
5,
'$',
],
yield 'euro/gb as €' => [
new Money(500, new Currency('EUR')),
'en_GB',
5,
'',
],
yield 'euro/us as €' => [
new Money(500, new Currency('EUR')),
'en_US',
5,
'',
],
yield 'euro/es as €' => [
new Money(500, new Currency('EUR')),
'es_ES',
5,
'',
],
yield 'euro/de as €' => [
new Money(500, new Currency('EUR')),
'de_DE',
5,
'',
],
];
}
protected function setUp(): void
{
parent::setUp();
$this->component = new Component($this->faker->word(), null);
}
}
<x-form.money name="rent" :money="$row->rent" class="input-group-sm">
<x-slot name="append">
<x-button class="btn-secondary"><i class="fa fa-check" aria-hidden="true"></i></x-button>
</x-slot>
</x-form.money>
<div {{ $attributes->merge(['class' => 'input-group'])}}>
<div class="input-group-prepend">
<span class="input-group-text">{{ $currency }}</span>
</div>
<x-input type="number" :value="$value" :name="$name" />
@if(isset($append))
<span class="input-group-append">
{!! $append !!}
</span>
@endif
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment