feat(feature): implementasi CRUD fitur keunggulan parfum dan pilih kami
This commit is contained in:
parent
4f09ce32b2
commit
3030c8f6ca
97
app/Livewire/Datatable/Studio/Feature/ChooseUsTable.php
Normal file
97
app/Livewire/Datatable/Studio/Feature/ChooseUsTable.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Datatable\Studio\Feature;
|
||||
|
||||
use App\Models\ChooseUs;
|
||||
use App\Traits\Datatable\WithConfiguration;
|
||||
use App\Traits\Datatable\WithPrependColumn;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
|
||||
class ChooseUsTable extends DataTableComponent
|
||||
{
|
||||
use WithConfiguration, WithPrependColumn;
|
||||
|
||||
protected $model = ChooseUs::class;
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('Nama', 'name')->searchable()->sortable(),
|
||||
|
||||
Column::make('Keterangan', 'description')->searchable()->sortable(),
|
||||
|
||||
Column::make('Aksi')
|
||||
->label(function ($row) {
|
||||
$actions = '';
|
||||
$maxSortOrder = ChooseUs::max('sort_order');
|
||||
|
||||
if (auth()->user()->can('update choose us')) {
|
||||
if ($row->sort_order > 1) {
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'chooseUs',
|
||||
'direction' => 'up',
|
||||
'tooltip' => 'Naik',
|
||||
'color' => 'cyan',
|
||||
'icon' => 'arrow-up',
|
||||
])->render();
|
||||
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'chooseUs',
|
||||
'direction' => 'first',
|
||||
'tooltip' => 'Pertama',
|
||||
'color' => 'emerald',
|
||||
'icon' => 'bars-arrow-up',
|
||||
])->render();
|
||||
}
|
||||
|
||||
if ($row->sort_order < $maxSortOrder) {
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'chooseUs',
|
||||
'direction' => 'down',
|
||||
'tooltip' => 'Turun',
|
||||
'color' => 'orange',
|
||||
'icon' => 'arrow-down',
|
||||
])->render();
|
||||
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'chooseUs',
|
||||
'direction' => 'last',
|
||||
'tooltip' => 'Terakhir',
|
||||
'color' => 'rose',
|
||||
'icon' => 'bars-arrow-down',
|
||||
])->render();
|
||||
}
|
||||
}
|
||||
|
||||
if (auth()->user()->can('update choose us')) {
|
||||
$actions .= view('components.datatables.edit-modal', [
|
||||
'id' => $row->hash,
|
||||
'method' => 'update',
|
||||
'modalTitle' => 'Ubah Kategori',
|
||||
])->render();
|
||||
}
|
||||
|
||||
if (auth()->user()->can('delete choose us')) {
|
||||
$actions .= view('components.datatables.delete', [
|
||||
'id' => $row->hash,
|
||||
'deleteRoute' => route('studio.feature.choose_us.delete', $row->hash),
|
||||
])->render();
|
||||
}
|
||||
|
||||
return $actions;
|
||||
})
|
||||
->html(),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return ChooseUs::select('id', 'name', 'description', 'sort_order')->orderBy('sort_order');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Datatable\Studio\Feature;
|
||||
|
||||
use App\Models\PerfumeFeature;
|
||||
use App\Traits\Datatable\WithConfiguration;
|
||||
use App\Traits\Datatable\WithPrependColumn;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
|
||||
class PerfumeFeaturesTable extends DataTableComponent
|
||||
{
|
||||
use WithConfiguration, WithPrependColumn;
|
||||
|
||||
protected $model = PerfumeFeature::class;
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('Nama', 'name')->searchable()->sortable(),
|
||||
|
||||
Column::make('Keterangan', 'description')->searchable()->sortable(),
|
||||
|
||||
Column::make('Aksi')
|
||||
->label(function ($row) {
|
||||
$actions = '';
|
||||
$maxSortOrder = PerfumeFeature::max('sort_order');
|
||||
|
||||
if (auth()->user()->can('update perfume feature')) {
|
||||
if ($row->sort_order > 1) {
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'perfumeFeature',
|
||||
'direction' => 'up',
|
||||
'tooltip' => 'Naik',
|
||||
'color' => 'cyan',
|
||||
'icon' => 'arrow-up',
|
||||
])->render();
|
||||
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'perfumeFeature',
|
||||
'direction' => 'first',
|
||||
'tooltip' => 'Pertama',
|
||||
'color' => 'emerald',
|
||||
'icon' => 'bars-arrow-up',
|
||||
])->render();
|
||||
}
|
||||
|
||||
if ($row->sort_order < $maxSortOrder) {
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'perfumeFeature',
|
||||
'direction' => 'down',
|
||||
'tooltip' => 'Turun',
|
||||
'color' => 'orange',
|
||||
'icon' => 'arrow-down',
|
||||
])->render();
|
||||
|
||||
$actions .= view('components.datatables.sort-button', [
|
||||
'id' => $row->hash,
|
||||
'module' => 'perfumeFeature',
|
||||
'direction' => 'last',
|
||||
'tooltip' => 'Terakhir',
|
||||
'color' => 'rose',
|
||||
'icon' => 'bars-arrow-down',
|
||||
])->render();
|
||||
}
|
||||
}
|
||||
|
||||
if (auth()->user()->can('update perfume feature')) {
|
||||
$actions .= view('components.datatables.edit-modal', [
|
||||
'id' => $row->hash,
|
||||
'method' => 'update',
|
||||
'modalTitle' => 'Ubah Kategori',
|
||||
])->render();
|
||||
}
|
||||
|
||||
if (auth()->user()->can('delete perfume feature')) {
|
||||
$actions .= view('components.datatables.delete', [
|
||||
'id' => $row->hash,
|
||||
'deleteRoute' => route('studio.feature.perfume_feature.delete', $row->hash),
|
||||
])->render();
|
||||
}
|
||||
|
||||
return $actions;
|
||||
})
|
||||
->html(),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return PerfumeFeature::select('id', 'name', 'description', 'sort_order')->orderBy('sort_order');
|
||||
}
|
||||
}
|
||||
123
app/Livewire/Forms/Studio/Feature/ChooseUsForm.php
Normal file
123
app/Livewire/Forms/Studio/Feature/ChooseUsForm.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Forms\Studio\Feature;
|
||||
|
||||
use App\Models\ChooseUs;
|
||||
use Livewire\Form;
|
||||
|
||||
class ChooseUsForm extends Form
|
||||
{
|
||||
public ?ChooseUs $chooseUs = null;
|
||||
|
||||
public string $name = '';
|
||||
|
||||
public string $description = '';
|
||||
|
||||
public string $color = '';
|
||||
|
||||
public string $icon = '';
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:50'],
|
||||
'description' => ['required', 'string'],
|
||||
'color' => ['required', 'string', 'max:20'],
|
||||
'icon' => ['required', 'string', 'max:20'],
|
||||
];
|
||||
}
|
||||
|
||||
public function validationAttributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'nama',
|
||||
'description' => 'keterangan',
|
||||
'color' => 'warna',
|
||||
'icon' => 'ikon',
|
||||
];
|
||||
}
|
||||
|
||||
public function setChooseUs(ChooseUs $chooseUs)
|
||||
{
|
||||
$this->chooseUs = $chooseUs;
|
||||
|
||||
$this->name = $chooseUs->name;
|
||||
$this->description = $chooseUs->description;
|
||||
$this->color = $chooseUs->color;
|
||||
$this->icon = $chooseUs->icon;
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
ChooseUs::create([
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'color' => $this->color,
|
||||
'icon' => $this->icon,
|
||||
'sort_order' => ChooseUs::count() + 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$this->chooseUs->update([
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'color' => $this->color,
|
||||
'icon' => $this->icon,
|
||||
]);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->chooseUs->delete();
|
||||
|
||||
ChooseUs::where('sort_order', '>', $this->chooseUs->sort_order)
|
||||
->orderBy('sort_order')
|
||||
->get()
|
||||
->each(function ($cat) {
|
||||
$cat->update(['sort_order' => $cat->sort_order - 1]);
|
||||
});
|
||||
}
|
||||
|
||||
public function sortOrder(string $direction)
|
||||
{
|
||||
if (in_array($direction, ['up', 'down'])) {
|
||||
$swap = null;
|
||||
|
||||
if ($direction === 'up') {
|
||||
$swap = ChooseUs::where('sort_order', '<', $this->chooseUs->sort_order)
|
||||
->orderByDesc('sort_order')
|
||||
->first();
|
||||
} else {
|
||||
$swap = ChooseUs::where('sort_order', '>', $this->chooseUs->sort_order)
|
||||
->orderBy('sort_order')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($swap) {
|
||||
$temp = $this->chooseUs->sort_order;
|
||||
$this->chooseUs->update(['sort_order' => $swap->sort_order]);
|
||||
$swap->update(['sort_order' => $temp]);
|
||||
}
|
||||
} elseif ($direction === 'first') {
|
||||
$this->chooseUs->update(['sort_order' => ChooseUs::min('sort_order') - 1]);
|
||||
$this->normalizeSortOrder();
|
||||
} elseif ($direction === 'last') {
|
||||
$this->chooseUs->update(['sort_order' => ChooseUs::max('sort_order') + 1]);
|
||||
$this->normalizeSortOrder();
|
||||
}
|
||||
}
|
||||
|
||||
protected function normalizeSortOrder()
|
||||
{
|
||||
$chooseUss = ChooseUs::orderBy('sort_order')->get();
|
||||
foreach ($chooseUss as $index => $chooseUs) {
|
||||
$chooseUs->update(['sort_order' => $index + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
109
app/Livewire/Forms/Studio/Feature/PerfumeFeatureForm.php
Normal file
109
app/Livewire/Forms/Studio/Feature/PerfumeFeatureForm.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Forms\Studio\Feature;
|
||||
|
||||
use App\Models\PerfumeFeature;
|
||||
use Livewire\Form;
|
||||
|
||||
class PerfumeFeatureForm extends Form
|
||||
{
|
||||
public ?PerfumeFeature $perfumeFeature = null;
|
||||
|
||||
public string $name = '';
|
||||
|
||||
public string $description = '';
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:50'],
|
||||
'description' => ['required', 'string'],
|
||||
];
|
||||
}
|
||||
|
||||
public function validationAttributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'nama',
|
||||
'description' => 'keterangan',
|
||||
];
|
||||
}
|
||||
|
||||
public function setPerfumeFeature(PerfumeFeature $perfumeFeature)
|
||||
{
|
||||
$this->perfumeFeature = $perfumeFeature;
|
||||
|
||||
$this->name = $perfumeFeature->name;
|
||||
$this->description = $perfumeFeature->description;
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
PerfumeFeature::create([
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'sort_order' => PerfumeFeature::count() + 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$this->perfumeFeature->update([
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
]);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->perfumeFeature->delete();
|
||||
|
||||
PerfumeFeature::where('sort_order', '>', $this->perfumeFeature->sort_order)
|
||||
->orderBy('sort_order')
|
||||
->get()
|
||||
->each(function ($cat) {
|
||||
$cat->update(['sort_order' => $cat->sort_order - 1]);
|
||||
});
|
||||
}
|
||||
|
||||
public function sortOrder(string $direction)
|
||||
{
|
||||
if (in_array($direction, ['up', 'down'])) {
|
||||
$swap = null;
|
||||
|
||||
if ($direction === 'up') {
|
||||
$swap = PerfumeFeature::where('sort_order', '<', $this->perfumeFeature->sort_order)
|
||||
->orderByDesc('sort_order')
|
||||
->first();
|
||||
} else {
|
||||
$swap = PerfumeFeature::where('sort_order', '>', $this->perfumeFeature->sort_order)
|
||||
->orderBy('sort_order')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($swap) {
|
||||
$temp = $this->perfumeFeature->sort_order;
|
||||
$this->perfumeFeature->update(['sort_order' => $swap->sort_order]);
|
||||
$swap->update(['sort_order' => $temp]);
|
||||
}
|
||||
} elseif ($direction === 'first') {
|
||||
$this->perfumeFeature->update(['sort_order' => PerfumeFeature::min('sort_order') - 1]);
|
||||
$this->normalizeSortOrder();
|
||||
} elseif ($direction === 'last') {
|
||||
$this->perfumeFeature->update(['sort_order' => PerfumeFeature::max('sort_order') + 1]);
|
||||
$this->normalizeSortOrder();
|
||||
}
|
||||
}
|
||||
|
||||
protected function normalizeSortOrder()
|
||||
{
|
||||
$perfumeFeatures = PerfumeFeature::orderBy('sort_order')->get();
|
||||
foreach ($perfumeFeatures as $index => $perfumeFeature) {
|
||||
$perfumeFeature->update(['sort_order' => $index + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
app/Livewire/Studio/Feature/ChooseUs.php
Normal file
99
app/Livewire/Studio/Feature/ChooseUs.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Studio\Feature;
|
||||
|
||||
use App\Livewire\Forms\Studio\Feature\ChooseUsForm;
|
||||
use App\Models\ChooseUs as ChooseUsModel;
|
||||
use App\Traits\WithAuthorization;
|
||||
use App\Traits\WithCloseModal;
|
||||
use App\Traits\WithConfirmation;
|
||||
use App\Traits\WithToast;
|
||||
use App\Traits\WithUpdatedData;
|
||||
use Flux\Flux;
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Title('Pilih Kami')]
|
||||
class ChooseUs extends Component
|
||||
{
|
||||
use WithAuthorization, WithCloseModal, WithConfirmation, WithToast, WithUpdatedData;
|
||||
|
||||
public ChooseUsForm $form;
|
||||
|
||||
public string $method = 'create';
|
||||
|
||||
public string $modalTitle = '';
|
||||
|
||||
#[On('modal:open')]
|
||||
public function openModal(string $method, string $modalTitle, ?string $id = null)
|
||||
{
|
||||
$this->resetValidation();
|
||||
$this->resetErrorBag();
|
||||
|
||||
$this->method = $method;
|
||||
$this->modalTitle = $modalTitle;
|
||||
|
||||
if ($id) {
|
||||
$this->form->setChooseUs(ChooseUsModel::byHashOrFail($id));
|
||||
}
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$this->canOrAbort('create choose us');
|
||||
|
||||
$this->form->store();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Pilih kami berhasil ditambahkan.');
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$this->canOrAbort('update choose us');
|
||||
|
||||
$this->form->update();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Pilih kami berhasil diperbarui.');
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
public function delete(ChooseUsModel $chooseUs)
|
||||
{
|
||||
$this->form->chooseUs = $chooseUs;
|
||||
|
||||
$this->form->delete();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Pilih kami berhasil dihapus.');
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
#[On('fn:sortOrder')]
|
||||
public function sortOrder(ChooseUsModel $chooseUs, string $direction)
|
||||
{
|
||||
$this->canOrAbort('update choose us');
|
||||
|
||||
$this->form->chooseUs = $chooseUs;
|
||||
|
||||
$this->form->sortOrder($direction);
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.studio.feature.choose-us', [
|
||||
'pageTitle' => 'Pilih Kami',
|
||||
]);
|
||||
}
|
||||
}
|
||||
99
app/Livewire/Studio/Feature/PerfumeFeature.php
Normal file
99
app/Livewire/Studio/Feature/PerfumeFeature.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Studio\Feature;
|
||||
|
||||
use App\Livewire\Forms\Studio\Feature\PerfumeFeatureForm;
|
||||
use App\Models\PerfumeFeature as PerfumeFeatureModel;
|
||||
use App\Traits\WithAuthorization;
|
||||
use App\Traits\WithCloseModal;
|
||||
use App\Traits\WithConfirmation;
|
||||
use App\Traits\WithToast;
|
||||
use App\Traits\WithUpdatedData;
|
||||
use Flux\Flux;
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Title('Keunggulan Parfum')]
|
||||
class PerfumeFeature extends Component
|
||||
{
|
||||
use WithAuthorization, WithCloseModal, WithConfirmation, WithToast, WithUpdatedData;
|
||||
|
||||
public PerfumeFeatureForm $form;
|
||||
|
||||
public string $method = 'create';
|
||||
|
||||
public string $modalTitle = '';
|
||||
|
||||
#[On('modal:open')]
|
||||
public function openModal(string $method, string $modalTitle, ?string $id = null)
|
||||
{
|
||||
$this->resetValidation();
|
||||
$this->resetErrorBag();
|
||||
|
||||
$this->method = $method;
|
||||
$this->modalTitle = $modalTitle;
|
||||
|
||||
if ($id) {
|
||||
$this->form->setPerfumeFeature(PerfumeFeatureModel::byHashOrFail($id));
|
||||
}
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$this->canOrAbort('create perfume feature');
|
||||
|
||||
$this->form->store();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Keunggulan parfum berhasil ditambahkan.');
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$this->canOrAbort('update perfume feature');
|
||||
|
||||
$this->form->update();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Keunggulan parfum berhasil diperbarui.');
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
public function delete(PerfumeFeatureModel $perfumeFeature)
|
||||
{
|
||||
$this->form->perfumeFeature = $perfumeFeature;
|
||||
|
||||
$this->form->delete();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
$this->toast('Keunggulan parfum berhasil dihapus.');
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
#[On('fn:sortOrder')]
|
||||
public function sortOrder(PerfumeFeatureModel $perfumeFeature, string $direction)
|
||||
{
|
||||
$this->canOrAbort('update perfume feature');
|
||||
|
||||
$this->form->perfumeFeature = $perfumeFeature;
|
||||
|
||||
$this->form->sortOrder($direction);
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.studio.feature.perfume-features', [
|
||||
'pageTitle' => 'Keunggulan Parfum',
|
||||
]);
|
||||
}
|
||||
}
|
||||
21
app/Models/ChooseUs.php
Normal file
21
app/Models/ChooseUs.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Veelasky\LaravelHashId\Eloquent\HashableId;
|
||||
|
||||
class ChooseUs extends Model
|
||||
{
|
||||
use HashableId, SoftDeletes;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'sort_order' => 'int',
|
||||
];
|
||||
}
|
||||
}
|
||||
21
app/Models/PerfumeFeature.php
Normal file
21
app/Models/PerfumeFeature.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Veelasky\LaravelHashId\Eloquent\HashableId;
|
||||
|
||||
class PerfumeFeature extends Model
|
||||
{
|
||||
use HashableId, SoftDeletes;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'sort_order' => 'int',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -167,6 +167,25 @@ public function boot(): void
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'heading' => 'Keunggulan',
|
||||
'items' => [
|
||||
[
|
||||
'label' => 'Keunggulan Parfum',
|
||||
'icon' => 'rocket-launch',
|
||||
'route' => 'studio.feature.perfume_feature.index',
|
||||
'match' => 'studio.feature.perfume_feature.*',
|
||||
'can' => 'view perfume feature',
|
||||
],
|
||||
[
|
||||
'label' => 'Pilih Kami',
|
||||
'icon' => 'trophy',
|
||||
'route' => 'studio.feature.choose_us.index',
|
||||
'match' => 'studio.feature.choose_us.*',
|
||||
'can' => 'view choose us',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'heading' => 'Pengaturan',
|
||||
'items' => [
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('perfume_features', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 50);
|
||||
$table->text('description');
|
||||
$table->unsignedInteger('sort_order');
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('perfume_features');
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('choose_us', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 50);
|
||||
$table->text('description');
|
||||
$table->string('icon', 20);
|
||||
$table->string('color', 20);
|
||||
$table->unsignedInteger('sort_order');
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('choose_us');
|
||||
}
|
||||
};
|
||||
@ -120,6 +120,16 @@ public function run(): void
|
||||
'update faq',
|
||||
'delete faq',
|
||||
|
||||
'view perfume feature',
|
||||
'create perfume feature',
|
||||
'update perfume feature',
|
||||
'delete perfume feature',
|
||||
|
||||
'view choose us',
|
||||
'create choose us',
|
||||
'update choose us',
|
||||
'delete choose us',
|
||||
|
||||
'view application settings',
|
||||
|
||||
'view whatsapp settings',
|
||||
|
||||
66
resources/views/livewire/studio/feature/choose-us.blade.php
Normal file
66
resources/views/livewire/studio/feature/choose-us.blade.php
Normal file
@ -0,0 +1,66 @@
|
||||
<flux:main>
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<flux:heading size="xl">{{ $pageTitle }}</flux:heading>
|
||||
</div>
|
||||
@can('create choose us')
|
||||
<div>
|
||||
<flux:modal.trigger name="form-modal">
|
||||
<flux:button variant="primary" class="text-sm"
|
||||
wire:click="$dispatch('modal:open', {method: 'create', 'modalTitle': 'Tambah Pilih Kami'})">
|
||||
Tambah
|
||||
</flux:button>
|
||||
</flux:modal.trigger>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<livewire:datatable.studio.feature.choose-us-table />
|
||||
</div>
|
||||
|
||||
@include('components.confirmation.delete')
|
||||
<flux:modal name="form-modal" class="w-[95%] max-w-sm md:max-w-xl mx-auto" @close="closeModal('form-modal')">
|
||||
<div class="p-4 space-y-6">
|
||||
<flux:heading size="lg">{{ $modalTitle }}</flux:heading>
|
||||
|
||||
<flux:field>
|
||||
<flux:label>Nama <span class="text-red-500 ms-1">*</span></flux:label>
|
||||
<flux:input placeholder="200+ Aroma" wire:model.live.debounce.500ms="form.name" autofocus
|
||||
autocomplete="off" />
|
||||
<flux:error name="form.name" />
|
||||
</flux:field>
|
||||
|
||||
<flux:field>
|
||||
<flux:label>Keterangan <span class="text-red-500 ms-1">*</span></flux:label>
|
||||
<flux:textarea wire:model="form.description" placeholder="Kami punya 200 lebih aroma ..."
|
||||
auotocomplete="off" />
|
||||
</flux:field>
|
||||
|
||||
<div class="lg:col-span-2">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<flux:field>
|
||||
<flux:label>Warna <span class="text-red-500 ms-1">*</span></flux:label>
|
||||
<flux:input type="color" wire:model="form.color" autofocus
|
||||
autocomplete="off" />
|
||||
<flux:error name="form.color" />
|
||||
</flux:field>
|
||||
|
||||
<flux:field>
|
||||
<flux:label>Icon <span class="text-red-500 ms-1">*</span></flux:label>
|
||||
<flux:input type="text" wire:model="form.icon" autofocus
|
||||
autocomplete="off" />
|
||||
<flux:error name="form.icon" />
|
||||
</flux:field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<flux:spacer />
|
||||
<flux:button variant="primary" class="sm:w-auto cursor-pointer" wire:click="{{ $method }}">
|
||||
Simpan
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</flux:modal>
|
||||
</flux:main>
|
||||
@ -0,0 +1,56 @@
|
||||
<flux:main>
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<flux:heading size="xl">{{ $pageTitle }}</flux:heading>
|
||||
</div>
|
||||
@can('create perfume feature')
|
||||
<div>
|
||||
<flux:modal.trigger name="form-modal">
|
||||
<flux:button variant="primary" class="text-sm"
|
||||
wire:click="$dispatch('modal:open', {method: 'create', 'modalTitle': 'Tambah Keunggulan Parfum'})">
|
||||
Tambah
|
||||
</flux:button>
|
||||
</flux:modal.trigger>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<flux:callout icon="megaphone" color="blue" class="mb-6">
|
||||
<flux:callout.heading>Informasi</flux:callout.heading>
|
||||
<flux:callout.text>
|
||||
Untuk tampilan yang lebih bagus dan rapi, disarankan hanya mengisi 4 data saja.
|
||||
</flux:callout.text>
|
||||
</flux:callout>
|
||||
|
||||
<livewire:datatable.studio.feature.perfume-features-table />
|
||||
</div>
|
||||
|
||||
@include('components.confirmation.delete')
|
||||
<flux:modal name="form-modal" class="w-[95%] max-w-sm md:max-w-xl mx-auto" @close="closeModal('form-modal')">
|
||||
<div class="p-4 space-y-6">
|
||||
<flux:heading size="lg">{{ $modalTitle }}</flux:heading>
|
||||
|
||||
<flux:field>
|
||||
<flux:label>Nama <span class="text-red-500 ms-1">*</span></flux:label>
|
||||
<flux:input placeholder="Tahan Lama" wire:model.live.debounce.500ms="form.name" autofocus
|
||||
autocomplete="off" />
|
||||
<flux:error name="form.name" />
|
||||
</flux:field>
|
||||
|
||||
<flux:field>
|
||||
<flux:label>Keterangan <span class="text-red-500 ms-1">*</span></flux:label>
|
||||
<flux:textarea wire:model="form.description"
|
||||
placeholder="Parfum kami diracik secara profesional sehingga memiliki kualitas terbaik."
|
||||
auotocomplete="off" />
|
||||
</flux:field>
|
||||
|
||||
<div class="flex">
|
||||
<flux:spacer />
|
||||
<flux:button variant="primary" class="sm:w-auto cursor-pointer" wire:click="{{ $method }}">
|
||||
Simpan
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</flux:modal>
|
||||
</flux:main>
|
||||
@ -16,6 +16,8 @@
|
||||
use App\Livewire\Studio\Catalog\Product\Edit as ProductEdit;
|
||||
use App\Livewire\Studio\Catalog\Product\Index as ProductIndex;
|
||||
use App\Livewire\Studio\Dashboard\Overview as OverviewComponent;
|
||||
use App\Livewire\Studio\Feature\ChooseUs as ChooseUsComponent;
|
||||
use App\Livewire\Studio\Feature\PerfumeFeature as PerfumeFeatureComponent;
|
||||
use App\Livewire\Studio\Finance\Expense as ExpenseComponent;
|
||||
use App\Livewire\Studio\Finance\Payroll as PayrollComponent;
|
||||
use App\Livewire\Studio\Loyalty\Customer as CustomerComponent;
|
||||
@ -174,6 +176,18 @@
|
||||
});
|
||||
});
|
||||
|
||||
Route::prefix('feature')->name('studio.feature.')->group(function () {
|
||||
Route::prefix('perfume-features')->name('perfume_feature.')->group(function () {
|
||||
Route::get('/', PerfumeFeatureComponent::class)->name('index')->middleware('can:view perfume feature');
|
||||
Route::delete('/{perfume_feature}/delete', PerfumeFeatureComponent::class)->name('delete')->middleware('can:delete perfume feature');
|
||||
});
|
||||
|
||||
Route::prefix('choose-us')->name('choose_us.')->group(function () {
|
||||
Route::get('/', ChooseUsComponent::class)->name('index')->middleware('can:view choose us');
|
||||
Route::delete('/{choose_us}/delete', ChooseUsComponent::class)->name('delete')->middleware('can:delete choose us');
|
||||
});
|
||||
});
|
||||
|
||||
Route::get('/settings/applications', ApplicationComponent::class)->name('studio.setting.application')->middleware('can:view application settings');
|
||||
Route::get('/settings/whatsapp', WhatsappComponent::class)->name('studio.setting.whatsapp')->middleware('can:view whatsapp settings');
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user