Admin Page With Tailwind Alpine Laravel Livewire + Reusable components
git clone https://github.com/manusiakemos/tall-admin.git
cd tall-admin
cp .env.example .env
#configure .env variables
php artisan key:generate
composer i
npm i
npm run prod
#or npm run dev for development
php artisan migrate
php artisan storage:link
php artisan db:seed
make sure to upload to your hosting to make sure it works
#to seed user data
php artisan db:seed --class=UserSeeder
#to seed laravolt data
php artisan laravolt:indonesia:seed
Alpine JS v3.2.2
$this->emit("showToast", ["message" => "", "type" => "success", "reload"=>false]);
<x-input.form-group label="YourLabel" key="yourid" model="yourmodel">
</x-input.form-group>
<x-input.filepond remove-file-event="removeFile" wire:model="image"></x-input.filepond>
in php add this
use WithFileUploads;
use Intervention\Image\Facades\Image;
public $image;
//with image intervention
if ($this->image){
$basename = Str::random();
$image = $this->image;
$original = $basename . '.' . $image->getClientOriginalExtension();
$thumbnail = 'thumb_'. $basename . '.'.$image->getClientOriginalExtension();
$folderName = "uploads";
$image->storeAs($folderName, $original,"public");
Image::make($image)
->resize(null, 100, function ($constraint){
$constraint->aspectRatio();
})
->save(public_path("/storage/$folderName/" . $thumbnail));
$this->dispatchBrowserEvent('removeFile');
$db->filename = $original;
}
or you can upload the image use this code below
use WithFileUploads;
public $photo;
// Store in the "photos" directory with the filename "avatar.png".
$this->photo->storeAs('photos', 'avatar');
//or
$filename = Str::random() . "." . $this->photo->getClientOriginalExtension();
$this->photo->storeAs('uploads', $filename, 'public');
//or with spatie media library
$user = User::find($id);
$user->addMedia($this->image->getRealPath())->toMediaCollection('collectionName');
//reset filepond
$this->dispatchBrowserEvent('resetFilePond');
More info
https://laravel-livewire.com/docs/2.x/file-uploads#basic-upload
https://github.com/spatie/laravel-medialibrary
<x-input.datepicker wire:model.defer="invitation.place"></x-input.text>
<x-input.text type="text" wire:model.defer="invitation.place"></x-input.text>
<x-input.mask id="" data-mask="" wire:model.lazy=""
data-options="{placeholder: '__/__/____'}"/>
<x-input.textarea wire:model.defer="invitation.place"></x-input.text>
<!--datepicker-->
<x-input.datepicker wire:model=""></x-input.datepicker>
<!--switch-->
<x-input.toggle-switch method="" id="" wire:model=""></x-input.toggle-switch>
<!--radio-->
<x-input.radio method="" wire:model.defer="model.nested"></x-input.radio>
<!--checkbox-->
<x-input.checkbox method="" wire:model.defer="model.nested"></x-input.checkbox>
<!--select2 options should be defer and boolean-->
<!--check method on App\View\Components\Traits\SelectOptionsTrait File-->
<x-input.select method="" wire:model.defer="" :select2="false"></x-input.select>
<x-input.custom-select
id=""
wire:model=""
:options="$options['']"
text=""
value=""/>
<x-input.custom-select2
id=""
wire:model=""
:options="$options['']"
text=""
value=""/>
to set data you should emit from backend (usually on create and update method)
$this->emit("set_summernote_value");
Or in your blade if code above doesnt work
@push("scripts")
<script>
document.addEventListener("DOMContentLoaded", function (){
Livewire.emit("set_summernote_value");
});
</script>
@endpush
add this to your form blade
<x-input.summernote data-event-name="set_summernote_value" id="about" wire:model="user.about"></x-input.summernote>
On your livewire class add property
public $location = [
"search" => "",
"lat" => -2.1746617,
"lng" => 115.39786,
"radius" => 50
];
//on create and edit
$this->location['lat'] = $db->lat;
$this->location['lng'] = $db->lng;
$this->location['radius'] = $db->radius;
$this->emit("set_map", ['location' => $this->location]);
and on your blade add this
<x-input.location-picker :location="$location" class="location-picker"></x-input.location-picker>
Provinces,cities,distritcs, and villages picker
on your blade use this
<livewire:input.laravolt :value="$user['village_id']"
:level="4"
parent-name="user.user-form"
parent-value-listener="setVillageId"/>
<!--
level 1 province,
level 2 province and city
level 3 province, city and district,
level 4 province, city, district and village,
-->
on your parent livewire add listener
protected $listeners = [
'setLaravoltValue'
];
public function setLaravoltValue($value)
{
$this->user['village_id'] = $value;
}
view('')
->layout('layouts.admin');
<x-ui.navigation selector="foo"></x-ui.navigation>
<main class="w-full flex-grow px-3 pb-5" xmlns:wire="http://www.w3.org/1999/xhtml">
<section class="content mx-auto py-5 px-5 min-h-screen">
<div class="pb-3">
<h4 class="heading">Title</h4>
</div>
<div class="grid md:grid-cols-3 lg:grid-cols-4 sm:grid-cols-12 gap-4">
</div>
</section>
</main>
//breadcrumbs
public array $breadcrumbs = [
["link" => "#", "title" => "Admin"],
["link" => "#", "title" => "User Management"],
];
<x-ui.breadcrumb :breadcrumbs="$breadcrumbs"></x-ui.breadcrumb>
<x-ui.widget-card title="Lorem ipsum" :number="2000000">
<div class="fa fa-line-chart"></div>
</x-ui.widget-card>
<!--
public array $tabHeaders = [
['key' => 'foo', 'disabled' => 'false', 'title' => 'Foo', 'icon' => '<i class="fi-rr-pencil"></i>'],
['key' => 'bar', 'disabled'=>'true', 'title' => 'Bar', 'icon'=> '<i class="fi-rr-pencil"></i>'],
];
-->
<x-ui.tabs class="tabs" :headers="$tabHeaders">
<x-slot name="foo">
Foo
</x-slot>
<x-slot name="bar">
Bar
</x-slot>
</x-ui.tabs>
<!--size sm, md, lg, xl, fullscreen-->
<x-ui.modal id="modal_form" wire:model="showModalForm" size="md"
:title="$updateMode ? 'Edit' : 'Create'">
</x-ui.modal>
<!--variant text, circle, normal, link -->
<x-ui.button class="bg-blue-500 text-white hover:bg-blue-400"
variant="circle"
data-bs-toggle="" data-bs-placement="" title="">
</x-ui.button>
<x-ui.alert :auto-close="false" class="bg-red-500">
<x-slot name="icon">
<span class="flex items-center fi-rr-exclamation"></span>
</x-slot>
Lorem Ipsum
</x-ui.alert>
public array $headers = [
['key' => 'step_1', 'step' => 1, 'title' => 'First', 'icon' => '<i class="fi-rr-pencil"></i>'],
['key' => 'step_2', 'step'=> 2, 'title' => 'Mid', 'icon'=> '<i class="fi-rr-pencil"></i>'],
['key' => 'step_3', 'step'=> 3, 'title' => 'Last', 'icon'=> '<i class="fi-rr-pencil"></i>'],
];
<x-ui.wizard-form class="tabs" :headers="$headers">
<x-slot name="step_1">
First
</x-slot>
<x-slot name="step_2">
Mid
</x-slot>
<x-slot name="step_3">
Last
</x-slot>
</x-ui.wizard-form>
to use setting table config change config/app enabled_setting to true
#config/app.php
'enabled_setting' => false,
Use config from setting table like this
#for example if you want to get setting App Name value
config('setting.app_name.value') ?? ''
#name, and value
tailwind css purge
purge: {
content: [
'./resources/**/*.blade.php',
'./resources/**/*.js',
'./resources/**/*.vue',
'./vendor/wire-elements/modal/resources/views/*.blade.php',
'./storage/framework/views/*.php',
],
options: {
safelist: [
'sm:max-w-sm',
'sm:max-w-md',
'sm:max-w-lg',
'sm:max-w-xl',
'sm:max-w-2xl',
'sm:max-w-3xl',
'sm:max-w-4xl',
'sm:max-w-5xl',
'sm:max-w-6xl',
'sm:max-w-7xl'
]
}
}
Include the CDN asset after @livewireScripts
or <livewire:scripts>
in your app's HTML:
...
@livewireScripts
<script src="https://cdn.jsdelivr.net/gh/livewire/turbolinks@v0.1.x/dist/livewire-turbolinks.js" data-turbolinks-eval="false" data-turbo-eval="false"></script>
</body>
Note: You MUST have either the
data-turbolinks-eval="false"
data-turbo-eval="false"
attributes added to the script tag (having both won't hurt).
<script data-turbolinks-eval="false" data-turbo-eval="false">