feat(voucher): membuat halaman voucher

This commit is contained in:
Yoga Pangestu 2025-11-12 14:54:30 +07:00
parent 8e6029eb7e
commit 456e7be055
4 changed files with 123 additions and 3 deletions

View File

@ -0,0 +1,36 @@
<?php
namespace App\Livewire\Member;
use App\Enums\VoucherType;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
#[Title('Voucher')]
#[Layout('components.layouts.member')]
class Voucher extends Component
{
public array $vouchers = [];
public function mount()
{
$this->vouchers = auth()->user()->vouchers()->get()->map(fn ($voucher) => [
'id' => $voucher->id,
'name' => $voucher->name,
'code' => $voucher->code,
'is_percentage' => $voucher->type == VoucherType::PERCENTAGE,
'min_purchase' => $voucher->min_purchase ? currency($voucher->min_purchase, 'Rp') : 'No Min. Belanja',
'discount_amount' => $voucher->type == VoucherType::PERCENTAGE ? $voucher->discount_amount.'%' : currency($voucher->discount_amount, 'Rp'),
'max_discount' => currency($voucher->max_discount, 'Rp'),
'end_date' => $voucher->end_date ? timeAgo($voucher->end_date) : 'Tidak Ada Batas Waktu',
])->toArray();
}
public function render()
{
return view('livewire.member.voucher', [
'pageTitle' => 'Voucher',
]);
}
}

View File

@ -4,8 +4,15 @@ class="bg-zinc-50 dark:bg-zinc-900 border-r rtl:border-r-0 rtl:border-l border-z
<flux:brand logo="{{ asset('assets/images/logo.png') }}" name="Yadi Parfum" class="px-2 dark:hidden" />
<flux:brand logo="{{ asset('assets/images/dark-logo.png') }}" name="Yadi Parfum" class="px-2 hidden dark:flex" />
<flux:navlist variant="outline">
<flux:navlist.item icon="squares-plus" href="{{ route('member.dashboard.overview') }}"
:current="request()->routeIs('member.dashboard.overview')" wire:navigate.hover>
Ringkasan</flux:navlist.item>
<div class="mb-1">
<div class="grid gap-2">
<flux:navlist.item icon="squares-plus" href="{{ route('member.overview') }}"
:current="request()->routeIs('member.overview')" wire:navigate.hover>
Ringkasan</flux:navlist.item>
<flux:navlist.item icon="ticket" href="{{ route('member.voucher') }}"
:current="request()->routeIs('member.voucher')" wire:navigate.hover>
Voucher</flux:navlist.item>
</div>
</div>
</flux:navlist>
</flux:sidebar>

View File

@ -0,0 +1,75 @@
<flux:main>
<flux:heading size="xl" level="1">{{ $pageTitle }}</flux:heading>
<div class="mt-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
@forelse ($vouchers as $voucher)
<flux:card class="p-0 relative dark:bg-zinc-700!">
<flux:text class="text-white p-2 md:p-0 absolute top-2 right-3 z-50">x3</flux:text>
<div class="flex flex-col sm:flex-row items-stretch sm:items-center p-3 sm:p-4 gap-3 sm:gap-0">
<div
class="flex-shrink-0 w-full sm:w-24 md:w-32 h-24 sm:h-24 md:h-32 bg-gradient-to-br from-emerald-600 to-emerald-700 rounded-lg flex flex-col items-center justify-center text-white relative mx-auto sm:mx-0">
<div
class="hidden sm:block absolute -right-3 top-1/2 transform -translate-y-1/2 w-6 h-6 bg-white dark:bg-zinc-700 rounded-full">
</div>
<img src="{{ asset('assets/images/dark-logo.png') }}" alt="logo"
class="h-12 sm:h-16 md:h-20">
<flux:heading class="text-white!">{{ $voucher['name'] }}</flux:heading>
</div>
<div class="flex-1 sm:ml-4 md:ml-4">
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
<div class="flex-1 w-full sm:w-auto">
<flux:heading class="mb-1">
Diskon {{ $voucher['discount_amount'] }}
{{ $voucher['is_percentage'] ? ' s/d ' . $voucher['max_discount'] : '' }}
</flux:heading>
<flux:text class="mb-1">
Min. Belanja {{ $voucher['min_purchase'] }}
</flux:text>
<div x-data="{ textToCopy: '{{ $voucher['code'] }}', copied: false }"
@click="navigator.clipboard.writeText(textToCopy); copied = true; setTimeout(() => copied = false, 2000)"
:class="copied ? 'bg-emerald-100 dark:bg-emerald-800' :
'bg-emerald-50 dark:bg-emerald-900'"
class="inline-block px-2 py-1 border border-emerald-300 dark:border-emerald-700 rounded text-xs text-emerald-600 dark:text-emerald-300 font-medium my-1 cursor-pointer transition-colors">
<span x-text="copied ? 'Copied!' : textToCopy"></span>
</div>
<div class="flex items-center gap-2 text-xs sm:text-sm flex-wrap">
<flux:text size="xs">
Berakhir: {{ $voucher['end_date'] }}
</flux:text>
<flux:separator vertical class="dark:border-gray-700" />
<flux:text size="xs" class="text-blue-400">
S&K
</flux:text>
</div>
</div>
<div class="w-full sm:w-auto sm:ml-2 md:ml-4 flex justify-center sm:justify-end">
<flux:button variant="primary" color="emerald" class="w-full">Pakai</flux:button>
</div>
</div>
</div>
</div>
</flux:card>
@empty
<div class="flex justify-center flex-col">
<dotlottie-wc src="https://lottie.host/4282c234-6d0f-4a8d-ad04-3d82f2783814/FuhTCVgPGi.lottie"
autoplay loop style="width: 200px; height: 200px; margin: 0 auto;">
</dotlottie-wc>
<flux:text class="block text-center italic mt-5">
Yahhh, sepertinya belum ada data yang tersedia.
</flux:text>
</div>
@endforelse
</div>
</div>
</flux:main>
@assets
<script src="https://unpkg.com/@lottiefiles/dotlottie-wc@0.8.5/dist/dotlottie-wc.js" type="module"></script>
@endassets

View File

@ -1,6 +1,7 @@
<?php
use App\Livewire\Member\Overview;
use App\Livewire\Member\Voucher;
use Illuminate\Support\Facades\Route;
Route::middleware('auth')
@ -8,4 +9,5 @@
->name('member.')
->group(function () {
Route::get('overview', Overview::class)->name('overview');
Route::get('vouchers', Voucher::class)->name('voucher');
});