feat(voucher): membuat crud
-menambahkan enum untuk tipe diskon persentase atau fixed -membuat tabel, form, migrasi, model dll sesuai dengan kebutuhan fitur
This commit is contained in:
parent
f701fdc70a
commit
0f7d1a131d
38
app/Enums/VoucherType.php
Normal file
38
app/Enums/VoucherType.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Traits\WithCommentEnum;
|
||||
use App\Traits\WithValueEnum;
|
||||
|
||||
enum VoucherType: int
|
||||
{
|
||||
use WithCommentEnum, WithValueEnum;
|
||||
|
||||
case FIXED = 1;
|
||||
case PERCENTAGE = 2;
|
||||
|
||||
public function label()
|
||||
{
|
||||
return match ($this) {
|
||||
self::FIXED => 'Nominal',
|
||||
self::PERCENTAGE => 'Persentase',
|
||||
};
|
||||
}
|
||||
|
||||
public function color()
|
||||
{
|
||||
return match ($this) {
|
||||
self::FIXED => 'blue',
|
||||
self::PERCENTAGE => 'pink',
|
||||
};
|
||||
}
|
||||
|
||||
public function icon()
|
||||
{
|
||||
return match ($this) {
|
||||
self::FIXED => 'currency-dollar',
|
||||
self::PERCENTAGE => 'percent-badge',
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,7 @@ public function columns(): array
|
||||
return [
|
||||
Column::make('Nama', 'name')->searchable(),
|
||||
|
||||
Column::make('Min. Pembelian', 'min_purchase')
|
||||
Column::make('Min. Belanja', 'min_purchase')
|
||||
->format(fn ($value) => currency($value, 'Rp'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
110
app/Livewire/Datatable/VouchersTable.php
Normal file
110
app/Livewire/Datatable/VouchersTable.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Datatable;
|
||||
|
||||
use App\Models\Voucher;
|
||||
use App\Traits\Datatable\WithAppendColumn;
|
||||
use App\Traits\Datatable\WithConfiguration;
|
||||
use App\Traits\Datatable\WithPrependColumn;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||
|
||||
class VouchersTable extends DataTableComponent
|
||||
{
|
||||
use WithAppendColumn, WithConfiguration, WithPrependColumn;
|
||||
|
||||
protected $model = Voucher::class;
|
||||
|
||||
public function columns(): array
|
||||
{
|
||||
return [
|
||||
Column::make('Nama')
|
||||
->label(function ($row) {
|
||||
return <<<HTML
|
||||
<div>
|
||||
<div>{$row->name}</div>
|
||||
<span class="text-xs text-gray-400">{$row->code}</span>
|
||||
</div>
|
||||
HTML;
|
||||
})
|
||||
->searchable(function ($query, $searchTerm) {
|
||||
$query->where('name', 'like', "%{$searchTerm}%")
|
||||
->orWhere('code', 'like', "%{$searchTerm}%");
|
||||
})
|
||||
->html(),
|
||||
|
||||
Column::make('Min. Belanja', 'min_purchase')
|
||||
->format(fn ($value) => currency($value, 'Rp'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
Column::make('Jumlah Diskon', 'discount_amount')
|
||||
->label(fn ($row, $column) => formatDiscount($row->discount_amount, $row->type))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
Column::make('Maks. Diskon')
|
||||
->label(fn ($row, $column) => currency($row->max_discount, 'Rp'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
Column::make('Kuota', 'quota')->searchable()->sortable(),
|
||||
|
||||
Column::make('Batas Per Pembali', 'limit_per_user')->searchable()->sortable(),
|
||||
|
||||
Column::make('Tanggal')
|
||||
->label(function ($row) {
|
||||
$startDate = formatDate($row->start_date);
|
||||
$startAgo = timeAgo($row->start_date);
|
||||
|
||||
$endDate = formatDate($row->end_date);
|
||||
$endAgo = timeAgo($row->end_date);
|
||||
|
||||
return <<<HTML
|
||||
<div class="flex flex-col text-xs text-gray-700 dark:text-gray-300 gap-0.5">
|
||||
<div>
|
||||
<span class="font-medium text-gray-900 dark:text-white">Tgl Dimulai:</span>
|
||||
<span>{$startDate}</span>
|
||||
<span class="text-gray-500">({$startAgo})</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-medium text-gray-900 dark:text-white">Tgl Berakhir:</span>
|
||||
<span>{$endDate}</span>
|
||||
<span class="text-gray-500">({$endAgo})</span>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
})
|
||||
->html(),
|
||||
|
||||
Column::make('Akitf?', 'is_active')
|
||||
->format(fn ($value) => Blade::render('<flux:badge color="'.$value->color().'">'.$value->label().'</flux:badge>'))
|
||||
->html(),
|
||||
|
||||
Column::make('Aksi')
|
||||
->label(function ($row) {
|
||||
$actions = '';
|
||||
|
||||
$actions .= view('components.datatables.edit', [
|
||||
'id' => $row->id,
|
||||
'editRoute' => route('studio.loyalty.voucher.edit', $row->id),
|
||||
])->render();
|
||||
|
||||
$actions .= view('components.datatables.delete', [
|
||||
'id' => $row->id,
|
||||
'deleteRoute' => route('studio.loyalty.voucher.delete', $row->id),
|
||||
])->render();
|
||||
|
||||
return $actions;
|
||||
})
|
||||
->html(),
|
||||
];
|
||||
}
|
||||
|
||||
public function builder(): Builder
|
||||
{
|
||||
return Voucher::select('id', 'name', 'code', 'min_purchase', 'discount_amount', 'max_discount', 'quota', 'limit_per_user', 'start_date', 'end_date', 'is_active', 'type');
|
||||
}
|
||||
}
|
||||
@ -31,7 +31,7 @@ public function validationAttributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'nama',
|
||||
'min_purchase' => 'min. pembelian',
|
||||
'min_purchase' => 'min. belanja',
|
||||
'discount_percentage' => 'persentase diskon',
|
||||
'terms_conditions' => 'syarat dan ketentuan',
|
||||
];
|
||||
|
||||
147
app/Livewire/Forms/VoucherForm.php
Normal file
147
app/Livewire/Forms/VoucherForm.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Forms;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\VoucherType;
|
||||
use App\Models\Voucher;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Livewire\Form;
|
||||
|
||||
class VoucherForm extends Form
|
||||
{
|
||||
public ?Voucher $voucher = null;
|
||||
|
||||
public string $name = '';
|
||||
|
||||
public string $code = '';
|
||||
|
||||
public string $type = '1';
|
||||
|
||||
public string $discount_amount = '';
|
||||
|
||||
public ?string $min_purchase = null;
|
||||
|
||||
public ?string $max_discount = null;
|
||||
|
||||
public ?string $quota = null;
|
||||
|
||||
public ?string $limit_per_user = null;
|
||||
|
||||
public string $start_date = '';
|
||||
|
||||
public ?string $end_date = null;
|
||||
|
||||
public ?string $terms_conditions = null;
|
||||
|
||||
public string $is_active = '1';
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:50'],
|
||||
'code' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:20',
|
||||
'alpha_num',
|
||||
Rule::unique('vouchers', 'code')->ignore($this->voucher),
|
||||
],
|
||||
'type' => ['required', Rule::in(VoucherType::values())],
|
||||
'discount_amount' => [
|
||||
'required',
|
||||
Rule::when(
|
||||
fn () => $this->type == VoucherType::PERCENTAGE->value,
|
||||
['integer', 'between:0,100'],
|
||||
['numeric'],
|
||||
),
|
||||
],
|
||||
'min_purchase' => ['nullable', 'numeric'],
|
||||
'max_discount' => [
|
||||
Rule::when(
|
||||
fn () => $this->type == VoucherType::PERCENTAGE->value,
|
||||
['required', 'numeric', 'between:0,100'],
|
||||
['nullable'],
|
||||
),
|
||||
],
|
||||
'quota' => ['nullable', 'numeric'],
|
||||
'limit_per_user' => ['nullable', 'numeric'],
|
||||
'start_date' => ['required', 'date'],
|
||||
'end_date' => ['nullable', 'date', 'after_or_equal:start_date'],
|
||||
'terms_conditions' => ['nullable', 'string'],
|
||||
'is_active' => ['required', Rule::in(IsActive::values())],
|
||||
];
|
||||
}
|
||||
|
||||
public function validationAttributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'nama',
|
||||
'code' => 'kode',
|
||||
'min_purchase' => 'min. belanja',
|
||||
'max_discount' => 'maks. diskon',
|
||||
'quota' => 'kuota',
|
||||
'limit_per_user' => 'limit per user',
|
||||
'terms_conditions' => 'syarat dan ketentuan',
|
||||
'type' => 'Tipe',
|
||||
'discount_amount' => 'Jumlah Diskon',
|
||||
'start_date' => 'tanggal mulai',
|
||||
'end_date' => 'tanggal selesai',
|
||||
'is_active' => 'aktif?',
|
||||
];
|
||||
}
|
||||
|
||||
public function setVoucher(Voucher $voucher)
|
||||
{
|
||||
$this->voucher = $voucher;
|
||||
|
||||
$this->name = $this->voucher->name;
|
||||
$this->code = $this->voucher->code;
|
||||
$this->type = $this->voucher->type->value;
|
||||
$this->discount_amount = replaceCurrency($this->voucher->discount_amount);
|
||||
$this->min_purchase = replaceCurrency($this->voucher->min_purchase);
|
||||
$this->max_discount = replaceCurrency($this->voucher->max_discount);
|
||||
$this->quota = $this->voucher->quota;
|
||||
$this->limit_per_user = $this->voucher->limit_per_user;
|
||||
$this->terms_conditions = $this->voucher->terms_conditions;
|
||||
$this->start_date = $this->voucher->start_date;
|
||||
$this->end_date = $this->voucher->end_date;
|
||||
$this->is_active = $this->voucher->is_active->value;
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$data = $this->prepareSavedData();
|
||||
|
||||
Voucher::create($data);
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$data = $this->prepareSavedData();
|
||||
|
||||
$this->voucher->update($data);
|
||||
}
|
||||
|
||||
private function prepareSavedData()
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'code' => $this->code,
|
||||
'type' => $this->type,
|
||||
'discount_amount' => replaceCurrency($this->discount_amount),
|
||||
'min_purchase' => replaceCurrency($this->min_purchase),
|
||||
'max_discount' => $this->type == VoucherType::PERCENTAGE->value ? replaceCurrency($this->max_discount) : null,
|
||||
'quota' => $this->quota,
|
||||
'limit_per_user' => $this->limit_per_user,
|
||||
'terms_conditions' => $this->terms_conditions,
|
||||
'start_date' => $this->start_date,
|
||||
'end_date' => $this->end_date,
|
||||
'is_active' => $this->is_active,
|
||||
];
|
||||
}
|
||||
}
|
||||
40
app/Livewire/Studio/Loyalty/Voucher/Create.php
Normal file
40
app/Livewire/Studio/Loyalty/Voucher/Create.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Studio\Loyalty\Voucher;
|
||||
|
||||
use App\Livewire\Forms\VoucherForm;
|
||||
use App\Traits\WithUpdatedData;
|
||||
use Flux\Flux;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Title('Tambah Voucher')]
|
||||
class Create extends Component
|
||||
{
|
||||
use WithUpdatedData;
|
||||
|
||||
public VoucherForm $form;
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->form->store();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
Flux::toast(
|
||||
heading: 'Berhasil',
|
||||
text: 'Voucher berhasil ditambahkan.',
|
||||
variant: 'success',
|
||||
duration: 3000
|
||||
);
|
||||
|
||||
$this->redirectRoute('studio.loyalty.voucher.index', navigate: true);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.studio.loyalty.voucher.form', [
|
||||
'pageTitle' => 'Tambah Voucher',
|
||||
]);
|
||||
}
|
||||
}
|
||||
46
app/Livewire/Studio/Loyalty/Voucher/Edit.php
Normal file
46
app/Livewire/Studio/Loyalty/Voucher/Edit.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Studio\Loyalty\Voucher;
|
||||
|
||||
use App\Livewire\Forms\VoucherForm;
|
||||
use App\Models\Voucher;
|
||||
use App\Traits\WithUpdatedData;
|
||||
use Flux\Flux;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Title('Ubah Voucher')]
|
||||
class Edit extends Component
|
||||
{
|
||||
use WithUpdatedData;
|
||||
|
||||
public VoucherForm $form;
|
||||
|
||||
public function mount(Voucher $voucher)
|
||||
{
|
||||
$this->form->setVoucher($voucher);
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->form->update();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
Flux::toast(
|
||||
heading: 'Berhasil',
|
||||
text: 'Voucher berhasil diperbarui.',
|
||||
variant: 'success',
|
||||
duration: 3000
|
||||
);
|
||||
|
||||
$this->redirectRoute('studio.loyalty.voucher.index', navigate: true);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.studio.loyalty.voucher.form', [
|
||||
'pageTitle' => 'Ubah Voucher',
|
||||
]);
|
||||
}
|
||||
}
|
||||
37
app/Livewire/Studio/Loyalty/Voucher/Index.php
Normal file
37
app/Livewire/Studio/Loyalty/Voucher/Index.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Studio\Loyalty\Voucher;
|
||||
|
||||
use App\Models\Voucher;
|
||||
use App\Traits\WithConfirmation;
|
||||
use Flux\Flux;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Title('Voucher')]
|
||||
class Index extends Component
|
||||
{
|
||||
use WithConfirmation;
|
||||
|
||||
public function delete(Voucher $voucher)
|
||||
{
|
||||
$voucher->delete();
|
||||
|
||||
$this->dispatch('refreshDatatable');
|
||||
|
||||
Flux::toast(
|
||||
heading: 'Berhasil',
|
||||
text: 'Voucher berhasil dihapus.',
|
||||
variant: 'success',
|
||||
);
|
||||
|
||||
Flux::modals()->close();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.studio.loyalty.voucher.index', [
|
||||
'pageTitle' => 'Voucher',
|
||||
]);
|
||||
}
|
||||
}
|
||||
29
app/Models/Voucher.php
Normal file
29
app/Models/Voucher.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\VoucherType;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Voucher extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'type' => VoucherType::class,
|
||||
'discount_amount' => 'int',
|
||||
'min_purchase' => 'int',
|
||||
'max_discount' => 'int',
|
||||
'quota' => 'int',
|
||||
'limit_per_user' => 'int',
|
||||
'is_active' => IsActive::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\IsActive;
|
||||
use App\Enums\VoucherType;
|
||||
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('vouchers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 50);
|
||||
$table->string('code', 20)->unique();
|
||||
$table->text('terms_conditions')->nullable();
|
||||
$table->enum('type', [VoucherType::values()])->default(VoucherType::PERCENTAGE)->comment(VoucherType::comment());
|
||||
$table->unsignedInteger('discount_amount');
|
||||
$table->unsignedInteger('min_purchase')->nullable();
|
||||
$table->unsignedInteger('max_discount')->nullable();
|
||||
$table->unsignedInteger('quota')->nullable();
|
||||
$table->unsignedInteger('limit_per_user')->nullable();
|
||||
$table->date('start_date');
|
||||
$table->date('end_date')->nullable();
|
||||
$table->enum('is_active', [IsActive::values()])->default(IsActive::ACTIVE)->comment(IsActive::comment());
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('vouchers');
|
||||
}
|
||||
};
|
||||
@ -11,8 +11,7 @@ class="px-2 hidden dark:flex" />
|
||||
Ringkasan</flux:navlist.item>
|
||||
|
||||
<div class="mt-3 mb-1">
|
||||
<div class="text-zinc-500 dark:text-gray-300 text-sm/6">Master
|
||||
</div>
|
||||
<div class="text-zinc-500 dark:text-gray-300 text-sm/6">Master</div>
|
||||
<div class="grid gap-2">
|
||||
<flux:navlist.item icon="home-modern" href="{{ route('studio.master.outlet.index') }}"
|
||||
:current="request()->routeIs('studio.master.outlet.*')" wire:navigate.hover>Outlet
|
||||
@ -25,12 +24,15 @@ class="px-2 hidden dark:flex" />
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-1">
|
||||
<div class="text-zinc-500 dark:text-gray-300 text-sm/6">Loyalty
|
||||
</div>
|
||||
<div class="text-zinc-500 dark:text-gray-300 text-sm/6">Loyalty</div>
|
||||
<div class="grid gap-2">
|
||||
<flux:navlist.item icon="star" href="{{ route('studio.loyalty.membership.index') }}"
|
||||
:current="request()->routeIs('studio.loyalty.membership.*')" wire:navigate.hover>Membership
|
||||
</flux:navlist.item>
|
||||
|
||||
<flux:navlist.item icon="ticket" href="{{ route('studio.loyalty.voucher.index') }}"
|
||||
:current="request()->routeIs('studio.loyalty.voucher.*')" wire:navigate.hover>Voucher
|
||||
</flux:navlist.item>
|
||||
</div>
|
||||
</div>
|
||||
</flux:navlist>
|
||||
|
||||
138
resources/views/livewire/studio/loyalty/voucher/form.blade.php
Normal file
138
resources/views/livewire/studio/loyalty/voucher/form.blade.php
Normal file
@ -0,0 +1,138 @@
|
||||
<flux:main>
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<flux:heading size="xl">{{ $pageTitle }}</flux:heading>
|
||||
</div>
|
||||
<div>
|
||||
<flux:button href="{{ route('studio.loyalty.voucher.index') }}" wire:navigate.hover class="text-sm">
|
||||
Kembali
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-col lg:flex-row gap-4">
|
||||
<div class="w-full lg:w-3/4 space-y-4">
|
||||
<div class="grid grid-cols-1 gap-4 lg:grid-cols-2 items-start">
|
||||
<div class="col-span-1 lg:col-span-2">
|
||||
<flux:card class="space-y-6 p-6">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<flux:input label="Nama" placeholder="Masukkan nama voucher"
|
||||
wire:model.live.debounce.500ms="form.name" autofocus autocomplete="off" />
|
||||
|
||||
<flux:input label="Kode" placeholder="Masukkan kode voucher"
|
||||
wire:model.live.debounce.500ms="form.code" autofocus autocomplete="off"
|
||||
copyable />
|
||||
|
||||
<div class="lg:col-span-2">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<flux:field>
|
||||
<flux:label>Min. Belanja</flux:label>
|
||||
<flux:input.group>
|
||||
<flux:input.group.prefix>Rp</flux:input.group.prefix>
|
||||
<flux:input placeholder="Masukkan minimal belanja"
|
||||
x-mask:dynamic="$money($input, ',')"
|
||||
wire:model.live.debounce.500ms="form.min_purchase"
|
||||
autocomplete="off" />
|
||||
</flux:input.group>
|
||||
<flux:error name="form.min_purchase" />
|
||||
</flux:field>
|
||||
|
||||
<flux:input label="Kuota" placeholder="Masukkan kuota"
|
||||
wire:model.live.debounce.500ms="form.quota"
|
||||
x-mask:dynamic="$money($input, ',')" autocomplete="off" />
|
||||
|
||||
<flux:input label="Batas Per Pembeli"
|
||||
placeholder="Masukkan batas per pembeli"
|
||||
wire:model.live.debounce.500ms="form.limit_per_user"
|
||||
x-mask:dynamic="$money($input, ',')" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<flux:date-picker label="Tanggal Mulai" with-today
|
||||
wire:model.live.debounce.500ms="form.start_date" autocomplete="off"
|
||||
locale="id-ID" />
|
||||
|
||||
<flux:date-picker label="Tanggal Selesai"
|
||||
wire:model.live.debounce.500ms="form.end_date" autocomplete="off"
|
||||
locale="id-ID" />
|
||||
|
||||
<div class="md:col-span-2">
|
||||
<flux:editor label="Syarat dan Ketentuan" wire:model="form.terms_conditions"
|
||||
placeholder="Masukkan syarat dan ketentuan" auotocomplete="off"
|
||||
class="**:data-[slot=content]:min-h-[100px]!" />
|
||||
</div>
|
||||
</div>
|
||||
</flux:card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="w-full lg:w-1/3 space-y-4">
|
||||
<flux:card class="space-y-2 p-6">
|
||||
<flux:radio.group wire:model.live="form.type" variant="buttons" class="w-full *:flex-1"
|
||||
label="Jumlah Diskon">
|
||||
@foreach (\App\Enums\VoucherType::cases() as $item)
|
||||
<flux:radio value="{{ $item->value }}" icon="{{ $item->icon() }}">
|
||||
{{ $item->label() }}
|
||||
</flux:radio>
|
||||
@endforeach
|
||||
</flux:radio.group>
|
||||
|
||||
<flux:field>
|
||||
<flux:input.group>
|
||||
@if ($form->type == \App\Enums\VoucherType::FIXED->value)
|
||||
<flux:input.group.prefix>Rp</flux:input.group.prefix>
|
||||
|
||||
<flux:input placeholder="Masukkan Jumlah Diskon"
|
||||
x-mask:dynamic="$money($input, ',')"
|
||||
wire:model.live.debounce.500ms="form.discount_amount" autocomplete="off" />
|
||||
@else
|
||||
<flux:input placeholder="Masukkan Jumlah Diskon"
|
||||
wire:model.live.debounce.500ms="form.discount_amount" autocomplete="off" />
|
||||
|
||||
<flux:input.group.suffix>%</flux:input.group.suffix>
|
||||
@endif
|
||||
</flux:input.group>
|
||||
|
||||
<flux:error name="form.discount_amount" />
|
||||
</flux:field>
|
||||
|
||||
@if ($form->type == \App\Enums\VoucherType::PERCENTAGE->value)
|
||||
<flux:field>
|
||||
<flux:label>Maks. Diskon</flux:label>
|
||||
<flux:input.group>
|
||||
<flux:input.group.prefix>Rp</flux:input.group.prefix>
|
||||
|
||||
<flux:input placeholder="Masukkan maksimal diskon"
|
||||
x-mask:dynamic="$money($input, ',')"
|
||||
wire:model.live.debounce.500ms="form.max_discount" autocomplete="off" />
|
||||
</flux:input.group>
|
||||
|
||||
<flux:error name="form.max_discount" />
|
||||
</flux:field>
|
||||
@endif
|
||||
</flux:card>
|
||||
|
||||
<flux:card class="space-y-6 p-6">
|
||||
<flux:radio.group wire:model.live="form.is_active" variant="buttons" class="w-full *:flex-1"
|
||||
label="Aktif?">
|
||||
@foreach (\App\Enums\IsActive::cases() as $item)
|
||||
<flux:radio value="{{ $item->value }}" icon="{{ $item->icon() }}">
|
||||
{{ $item->label() }}
|
||||
</flux:radio>
|
||||
@endforeach
|
||||
</flux:radio.group>
|
||||
</flux:card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-start">
|
||||
<flux:button variant="primary" class="sm:w-auto cursor-pointer" wire:click="save">
|
||||
Simpan
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</flux:main>
|
||||
@ -0,0 +1,19 @@
|
||||
<flux:main>
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<flux:heading size="xl">{{ $pageTitle }}</flux:heading>
|
||||
</div>
|
||||
<div>
|
||||
<flux:button href="{{ route('studio.loyalty.voucher.create') }}" variant="primary" wire:navigate.hover
|
||||
class="text-sm">
|
||||
Tambah
|
||||
</flux:button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<livewire:datatable.vouchers-table />
|
||||
</div>
|
||||
|
||||
@include('components.confirmation.delete')
|
||||
</flux:main>
|
||||
@ -4,6 +4,9 @@
|
||||
use App\Livewire\Auth\Logout;
|
||||
use App\Livewire\Studio\Dashboard\Overview;
|
||||
use App\Livewire\Studio\Loyalty\Membership as MembershipComponent;
|
||||
use App\Livewire\Studio\Loyalty\Voucher\Create as VoucherCreate;
|
||||
use App\Livewire\Studio\Loyalty\Voucher\Edit as VoucherEdit;
|
||||
use App\Livewire\Studio\Loyalty\Voucher\Index as VoucherIndex;
|
||||
use App\Livewire\Studio\Master\Outlet\Create as OutletCreate;
|
||||
use App\Livewire\Studio\Master\Outlet\Edit as OutletEdit;
|
||||
use App\Livewire\Studio\Master\Outlet\Index as OutletIndex;
|
||||
@ -56,4 +59,13 @@
|
||||
Route::get('memberships', MembershipComponent::class)->name('index');
|
||||
Route::delete('memberships/{membership}/delete', MembershipComponent::class)->name('delete');
|
||||
});
|
||||
|
||||
Route::prefix('loyalty')
|
||||
->as('studio.loyalty.voucher.')
|
||||
->group(function () {
|
||||
Route::get('vouchers', VoucherIndex::class)->name('index');
|
||||
Route::get('vouchers/create', VoucherCreate::class)->name('create');
|
||||
Route::get('vouchers/{voucher}/edit', VoucherEdit::class)->name('edit');
|
||||
Route::get('vouchers/{voucher}/delete', VoucherCreate::class)->name('delete');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user