generated from spatie/package-skeleton-laravel
-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interactive demo #23
Comments
The interactive demo only demonstrates the capabilities of the It's the following Livewire component: <?php
namespace App\Livewire\LaravelInvoices;
use Brick\Money\Money;
use Carbon\Carbon;
use Finller\Invoice\InvoiceDiscount;
use Finller\Invoice\InvoiceState;
use Finller\Invoice\InvoiceType;
use Finller\Invoice\PdfInvoice;
use Finller\Invoice\PdfInvoiceItem;
use Livewire\Attributes\Url;
use Livewire\Component;
use Symfony\Component\HttpFoundation\StreamedResponse;
class Builder extends Component
{
#[Url]
public InvoiceType $type = InvoiceType::Invoice;
#[Url]
public InvoiceState $state = InvoiceState::Draft;
#[Url]
public ?string $due_at = null;
#[Url]
public ?string $paid_at = null;
#[Url]
public ?string $description = null;
#[Url]
public ?string $serial_number = 'IN24-0001';
#[Url]
public ?string $font = 'Helvetica';
#[Url]
public string $color = '#050038';
/**
* @var array<string, mixed>
*/
public array $seller = [
'name' => 'elegantly',
'address' => [
'street' => "Place de l'Opéra",
'city' => 'Paris',
'postal_code' => '75009',
'country' => 'France',
],
'email' => '[email protected]',
'tax_number' => 'FR123456789',
];
/**
* @var array<string, mixed>
*/
public array $buyer = [
'name' => 'John Doe',
'address' => [
'street' => '8405 Old James St.Rochester',
'city' => 'New York',
'postal_code' => '14609',
'state' => 'New York (NY)',
'country' => 'United States',
],
'email' => '[email protected]',
];
/**
* @var array<int, array<string, mixed>>
*/
public array $items = [
[
'label' => 'Laravel Invoices Package',
'description' => 'An easy way to manage your invoices in Laravel',
'quantity' => 1,
'unit_price' => 100,
],
[
'label' => 'Laravel Money',
'description' => 'Use Brick\Money in Laravel',
'quantity' => 1,
'unit_price' => 1,
],
];
/**
* @var array<int, array<string, mixed>>
*/
public array $discounts = [
[
'name' => 'Discount',
'code' => 'SUMMER',
'percent_off' => 10,
],
];
public function mount(): void
{
//
}
public function download(): StreamedResponse
{
$pdf = $this
->invoice()
->pdf();
return response()->streamDownload(function () use ($pdf) {
echo $pdf->output();
}, 'laravel-invoices-demo.pdf');
}
public function invoice(): PdfInvoice
{
return new PdfInvoice(
name: $this->type->trans(),
state: $this->state->trans(),
serial_number: $this->serial_number,
buyer: $this->buyer,
seller: $this->seller,
created_at: now(),
due_at: $this->due_at ? Carbon::parse($this->due_at) : null,
paid_at: $this->paid_at ? Carbon::parse($this->paid_at) : null,
description: $this->description,
color: $this->color,
font: $this->font,
discounts: array_map(fn ($item) => new InvoiceDiscount(
name: $item['name'] ?? '',
code: $item['code'] ?? null,
percent_off: $item['percent_off'] ?? 0,
), $this->discounts),
items: array_map(fn ($item) => new PdfInvoiceItem(
label: data_get($item, 'label'),
unit_price: data_get($item, 'unit_price') ? Money::of(data_get($item, 'unit_price'), 'USD') : null,
unit_tax: data_get($item, 'unit_tax') ? Money::of(data_get($item, 'unit_tax'), 'USD') : null,
tax_percentage: data_get($item, 'tax_percentage'),
quantity: data_get($item, 'quantity') ?? 1,
description: data_get($item, 'description'),
quantity_unit: data_get($item, 'quantity_unit'),
), $this->items),
);
}
public function render(): \Illuminate\Contracts\View\View
{
return view('livewire.laravel-invoices.builder', [
'types' => InvoiceType::cases(),
'states' => InvoiceState::cases(),
'fonts' => [
'Helvetica',
'DejaVu Sans',
'Courier',
'Times',
'Symbol',
'ZapfDingbats',
],
'invoice' => $this->invoice(),
]);
}
} <div class="flex gap-4">
<div class="w-72 flex-none hidden lg:block">
<form wire:submit.prevent="$refresh" class="flex flex-col gap-3" x-data="{
discounts: $wire.entangle('discounts', true),
items: $wire.entangle('items', true),
addItem() {
this.items.push({
'label': 'Aa',
'quantity': 1,
'unit_price': 100,
});
},
addDiscount() {
this.discounts.push({
'name': '',
'code': '',
'percent_off': 10,
});
}
}">
<x-kit::field label="Font">
<x-kit::select class="rounded-md" color="white" wire:model.live="font">
@foreach ($fonts as $option)
<option value="{{ $option }}">{{ $option }}</option>
@endforeach
</x-kit::select>
</x-kit::field>
<x-kit::field label="Color">
<x-kit::input.base type="color" class="rounded-md" color="white" wire:model.live="color" />
</x-kit::field>
<x-kit::field label="Serial Number">
<x-kit::input class="rounded-md" color="white" wire:model.live="serial_number" />
</x-kit::field>
<div class="grid grid-cols-2 gap-3">
<x-kit::field label="Type">
<x-kit::select class="rounded-md" color="white" wire:model.live="type">
@foreach ($types as $option)
<option value="{{ $option->value }}">{{ $option->trans() }}</option>
@endforeach
</x-kit::select>
</x-kit::field>
<x-kit::field label="State">
<x-kit::select class="rounded-md" color="white" wire:model.live="state">
@foreach ($states as $option)
<option value="{{ $option->value }}">{{ $option->trans() }}</option>
@endforeach
</x-kit::select>
</x-kit::field>
</div>
<div class="grid grid-cols-2 gap-3">
<x-kit::field label="Due At">
<x-kit::input type="date" class="rounded-md" color="white" wire:model.live="due_at" />
</x-kit::field>
<x-kit::field label="Paid At">
<x-kit::input type="date" class="rounded-md" color="white" wire:model.live="paid_at" />
</x-kit::field>
</div>
<x-kit::field label="Description">
<x-kit::input.textarea autosized class="rounded-md" color="white" wire:model.live="description" />
</x-kit::field>
<x-kit::accordion class="rounded-md bg-white shadow">
<x-slot:button>
<x-kit::accordion.button size="lg" class="w-full justify-between rounded-md font-semibold"
icon-right="heroicon-m-chevron-down">
Buyer
</x-kit::accordion.button>
</x-slot:button>
<div class="flex flex-col gap-3 border-t p-3">
<x-kit::field label="Name">
<x-kit::input class="rounded-md" color="white" wire:model.live="buyer.name" />
</x-kit::field>
<x-kit::field label="Email">
<x-kit::input class="rounded-md" color="white" wire:model.live="buyer.email" />
</x-kit::field>
<x-kit::field label="Phone">
<x-kit::input class="rounded-md" color="white" wire:model.live="buyer.phone_number" />
</x-kit::field>
<x-kit::field label="VAT number">
<x-kit::input class="rounded-md" color="white" wire:model.live="buyer.tax_number" />
</x-kit::field>
</div>
</x-kit::accordion>
<x-kit::accordion class="rounded-md bg-white shadow">
<x-slot:button>
<x-kit::accordion.button size="lg" class="w-full justify-between rounded-md font-semibold"
icon-right="heroicon-m-chevron-down">
Seller
</x-kit::accordion.button>
</x-slot:button>
<div class="flex flex-col gap-3 border-t p-3">
<x-kit::field label="Name">
<x-kit::input class="rounded-md" color="white" wire:model.live="seller.name" />
</x-kit::field>
<x-kit::field label="Email">
<x-kit::input class="rounded-md" color="white" wire:model.live="seller.email" />
</x-kit::field>
<x-kit::field label="Phone">
<x-kit::input class="rounded-md" color="white" wire:model.live="seller.phone_number" />
</x-kit::field>
<x-kit::field label="VAT number">
<x-kit::input class="rounded-md" color="white" wire:model.live="seller.tax_number" />
</x-kit::field>
</div>
</x-kit::accordion>
<x-kit::accordion class="rounded-md bg-white shadow">
<x-slot:button>
<x-kit::accordion.button size="lg" class="w-full justify-between rounded-md font-semibold"
icon-right="heroicon-m-chevron-down">
Items
</x-kit::accordion.button>
</x-slot:button>
<div class="flex flex-col gap-3 divide-y">
<template x-for="(item, index) in items" x-bind:key="index">
<div class="flex flex-col gap-3 p-3">
<x-kit::field label="Label">
<x-kit::input class="rounded-md" color="white" x-model="item.label" />
</x-kit::field>
<x-kit::field label="Description">
<x-kit::input.textarea autosized class="rounded-md" color="white"
x-model="item.description" />
</x-kit::field>
<div class="grid grid-cols-2 gap-2">
<x-kit::field label="Quantity">
<x-kit::input type="number" class="rounded-md" color="white"
x-model="item.quantity" />
</x-kit::field>
<x-kit::field label="Unit price">
<x-kit::input type="number" class="rounded-md" color="white"
x-model="item.unit_price" />
</x-kit::field>
</div>
</div>
</template>
</div>
<div class="border-t p-3">
<x-kit::button x-on:click="addItem" color="white"
class="w-full justify-center rounded-md font-semibold">
Add
</x-kit::button>
</div>
</x-kit::accordion>
<x-kit::accordion class="rounded-md bg-white shadow">
<x-slot:button>
<x-kit::accordion.button size="lg" class="w-full justify-between rounded-md font-semibold"
icon-right="heroicon-m-chevron-down">
Discounts
</x-kit::accordion.button>
</x-slot:button>
<div class="flex flex-col gap-3 divide-y">
<template x-for="(discount, index) in discounts" x-bind:key="index">
<div class="flex flex-col gap-3 p-3">
<x-kit::field label="Name">
<x-kit::input class="rounded-md" color="white" x-model="discount.name" />
</x-kit::field>
<div class="grid grid-cols-2 gap-2">
<x-kit::field label="Code">
<x-kit::input type="text" class="rounded-md" color="white"
x-model="discount.code" />
</x-kit::field>
<x-kit::field label="Percent Off">
<x-kit::input type="number" class="rounded-md" color="white"
x-model="discount.percent_off" />
</x-kit::field>
</div>
</div>
</template>
</div>
<div class="border-t p-3">
<x-kit::button x-on:click="addDiscount" color="white"
class="w-full justify-center rounded-md font-semibold">
Add
</x-kit::button>
</div>
</x-kit::accordion>
<x-kit::button wire:click="download" class="justify-between rounded-md font-semibold" color="black"
icon-right="heroicon-m-arrow-down-tray">
Download
</x-kit::button>
</form>
</div>
<div class="grow min-w-0 overflow-auto">
<div class="sticky top-4 flex aspect-[210/297] flex-col bg-white shadow-md min-w-[40rem]"
style="
font-family: '{{ $font }}';
">
@include('invoices::default.invoice', ['invoice' => $invoice])
</div>
</div>
</div> |
Thanks much appreciated ! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Could you publish your "Interactive Demo" source code?
Thanks,
Denis
The text was updated successfully, but these errors were encountered: