Create an Interactive QR Generator with filamentPHP and livewire
zeus zeus
interactive QR generator, unlock the power of FilamentPHP
I created this simple page with coloring options to generate a QR code. and my Twitter account went crazy 😜
Instead of packing it into a plugin, I decided it’s really simple, and I am sure everyone has a different use case for it.
This is more like a demo of how powerful and flexible filament can be.
Also, please note this code is a draft, I am sure there is plenty of improvement and refactoring depending on your app, so I’ll keep that task to you :)
Usage:
You can start with creating a Livewire component, or a filament page.
Notice the mount function to fill the form, you can simply replace it with the ->defualt() method.
QrCode.php
public function mount(): void
{
$defualtData = [
'url' => 'https://filamentphp.com/',
'size' => '300',
'margin' => '1',
'color' => 'rgb(0, 0, 0)',
'back_color' => 'rgb(252, 252, 252)',
'gradient_form' => 'rgb(69, 179, 157)',
'gradient_to' => 'rgb(241, 148, 138)',
'eye_color_inner' => 'rgb(241, 148, 138)',
'eye_color_outer' => 'rgb(69, 179, 157)',
'gradient_type' => 'vertical',
'style' => 'square',
'eye_style' => 'square',
];
$this->form->fill($defualtData);
}
public function form(Form $form): Form
{
return $form
->statePath('data')
->schema([
Section::make()
->id('main-card')
->columns([
'default' => '1',
'lg' => '2',
])
->schema([
TextInput::make('size')->live(),
TextInput::make('url')->live(onBlur: true),
ColorPicker::make('color')
->live()
->rgb(),
ColorPicker::make('back_color')
->live()
->rgb(),
Select::make('margin')
->live()
->options([
'0' => '0',
'1' => '1',
'3' => '3',
'7' => '7',
'9' => '9',
]),
Select::make('style')
->live()
->options([
'square' => __('square'),
'round' => __('round'),
'dot' => __('dot'),
]),
Toggle::make('hasGradient')
->live()
->inline()
->columnSpan([
'sm' => 1,
'lg' => 2,
])
->reactive(),
Grid::make()
->schema([
ColorPicker::make('gradient_form')
->live()
->rgb(),
ColorPicker::make('gradient_to')
->live()
->rgb(),
Select::make('gradient_type')
->live()
->options([
'vertical' => __('vertical'),
'horizontal' => __('horizontal'),
'diagonal' => __('diagonal'),
'inverse_diagonal' => __('inverse_diagonal'),
'radial' => __('radial'),
]),
])
->columns([
'sm' => 1,
'lg' => 3,
])
->columnSpan([
'sm' => 1,
'lg' => 2,
])
->visible(fn(\Filament\Forms\Get $get) => $get('hasGradient')),
Toggle::make('hasEyeColor')
->live()
->inline()
->columnSpan([
'sm' => 1,
'lg' => 2,
]),
Grid::make()->schema([
ColorPicker::make('eye_color_inner')
->live()
->rgb(),
ColorPicker::make('eye_color_outer')
->live()
->rgb(),
Select::make('eye_style')
->live()
->options([
'square' => __('square'),
'circle' => __('circle'),
]),
])
->columns([
'sm' => 1,
'lg' => 3,
])
->columnSpan([
'sm' => 1,
'lg' => 2,
])
->visible(fn(\Filament\Forms\Get $get) => $get('hasEyeColor')),
]),
]);
}
public static function maketheqr($data): string
{
$maker = new \SimpleSoftwareIO\QrCode\Generator();
if ($data['color'] !== null) {
$colorRGB = str_replace(['rgb(', ')'], '', $data['color']);
$colorRGB = explode(',', $colorRGB);
call_user_func_array([$maker, 'color'], $colorRGB);
}
if ($data['back_color'] !== null) {
$back_colorRGB = str_replace(['rgb(', ')'], '', $data['back_color']);
$back_colorRGB = explode(',', $back_colorRGB);
call_user_func_array([$maker, 'backgroundColor'], $back_colorRGB);
}
$maker = $maker->size($data['size']);
if ($data['hasGradient']) {
if ($data['gradient_to'] !== null && $data['gradient_form'] !== null) {
$gradient_form = str_replace(['rgb(', ')'], '', $data['gradient_form']);
$gradient_form = explode(',', $gradient_form);
$gradient_to = str_replace(['rgb(', ')'], '', $data['gradient_to']);
$gradient_to = explode(',', $gradient_to);
$options = array_merge($gradient_to, $gradient_form, [$data['gradient_type']]);
call_user_func_array([$maker, 'gradient'], $options);
}
}
if ($data['hasEyeColor']) {
if ($data['eye_color_inner'] !== null && $data['eye_color_outer'] !== null) {
$eye_color_inner = str_replace(['rgb(', ')'], '', $data['eye_color_inner']);
$eye_color_inner = explode(',', $eye_color_inner);
$eye_color_outer = str_replace(['rgb(', ')'], '', $data['eye_color_outer']);
$eye_color_outer = explode(',', $eye_color_outer);
$options = array_merge([0], $eye_color_inner, $eye_color_outer);
call_user_func_array([$maker, 'eyeColor'], $options);
$options = array_merge([1], $eye_color_inner, $eye_color_outer);
call_user_func_array([$maker, 'eyeColor'], $options);
$options = array_merge([2], $eye_color_inner, $eye_color_outer);
call_user_func_array([$maker, 'eyeColor'], $options);
}
}
if ($data['margin'] !== null) {
$maker = $maker->margin($data['margin']);
}
if ($data['style'] !== null) {
$maker = $maker->style($data['style']);
}
if (isset($data['eye_style']) && filled($data['eye_style'])) {
$maker = $maker->eye($data['eye_style']);
}
return $maker->generate('https://larazeus.com')->toHtml();
}
And here is the Blade file:
QrCode.blade.php
<x-filament::page>
<div class="flex items-stretch justify-center gap-4">
<div class="w-full lg:w-1/2">
{{ $this->form }}
div>
<div class="w-full lg:w-1/2">
<x-filament::section>
<x-slot name="heading">
Preview
x-slot>
<div id="qrcode" class="text-center flex justify-center items-center">
{!! \App\Filament\Pages\QrCode::maketheqr($this->form->getState()) !!}
div>
<x-slot name="headerEnd">
<x-filament::button type="button" @click="download('{{ 'filename' }}')">
Download
x-filament::button>
x-slot>
x-filament::section>
div>
div>
{{--better to use @push...--}}
<script src="{{ asset('js/qrcode.js') }}">script>
x-filament::page>
Finally, to provide the download button for the QR code as an image:
QrCode.blade.php
import domtoimage from 'dom-to-image';
import {saveAs} from 'file-saver';
window.download = function (domain) {
var node = document.querySelector('#qrcode svg');
domtoimage.toBlob(node)
.then(function (blob) {
window.saveAs(blob, domain + '.png');
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
}
Demo
to see it in action, check out the demo page
I hope this is helpful.
Photo by Alba Lantigua on Unsplash