diff --git a/app/Livewire/Datatable/Loyalty/RewardsTable.php b/app/Livewire/Datatable/Loyalty/RewardsTable.php
index 5aa5b09..a09ff22 100644
--- a/app/Livewire/Datatable/Loyalty/RewardsTable.php
+++ b/app/Livewire/Datatable/Loyalty/RewardsTable.php
@@ -10,6 +10,7 @@
use Illuminate\Support\Facades\Blade;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column;
+use Rappasoft\LaravelLivewireTables\Views\Columns\ArrayColumn;
class RewardsTable extends DataTableComponent
{
@@ -42,6 +43,13 @@ public function columns(): array
->label(fn ($row, $column) => Blade::render(''.$row->is_show->label().''))
->html(),
+ ArrayColumn::make('Tier')
+ ->data(
+ fn ($value, $row) => $row->tiers->pluck('name')->toArray() ?: ['Semua Tier']
+ )
+ ->outputFormat(fn ($index, $value) => Blade::render(''.$value.''))
+ ->flexRow(['class' => 'gap-2 flex-wrap']),
+
Column::make('Tanggal')
->label(function ($row) {
$startDate = formatDateLocalized($row->start_date);
@@ -94,6 +102,8 @@ public function columns(): array
public function builder(): Builder
{
- return Reward::select('id', 'name', 'points', 'stock', 'category', 'is_show', 'start_date', 'end_date')->withCount('redemptions');
+ return Reward::select('id', 'name', 'points', 'stock', 'category', 'is_show', 'start_date', 'end_date')
+ ->with('tiers:id,name')
+ ->withCount('redemptions');
}
}
diff --git a/app/Livewire/Forms/Studio/Loyalty/RewardForm.php b/app/Livewire/Forms/Studio/Loyalty/RewardForm.php
index 4e94c24..9a1ca28 100644
--- a/app/Livewire/Forms/Studio/Loyalty/RewardForm.php
+++ b/app/Livewire/Forms/Studio/Loyalty/RewardForm.php
@@ -31,6 +31,8 @@ class RewardForm extends Form
public ?string $end_date = null;
+ public array $tier_ids = [];
+
public array $thumbnail = [];
public function rules(): array
@@ -43,6 +45,8 @@ public function rules(): array
'is_show' => ['required', Rule::in(IsShow::cases())],
'start_date' => ['required', 'date'],
'end_date' => ['nullable', 'date', 'after_or_equal:start_date'],
+ 'tier_ids' => ['required', 'array', 'min:1'],
+ 'tier_ids.*' => Rule::exists('tiers', 'id'),
'thumbnail' => 'array',
];
}
@@ -57,6 +61,8 @@ public function validationAttributes(): array
'is_show' => 'visibilitas',
'start_date' => 'tanggal mulai',
'end_date' => 'tanggal berakhir',
+ 'tier_ids' => 'tier',
+ 'tier_ids.*' => 'tier',
];
}
@@ -71,6 +77,7 @@ public function setReward(Reward $reward): void
$this->is_show = $reward->is_show->value;
$this->start_date = $reward->start_date;
$this->end_date = $reward->end_date;
+ $this->tier_ids = $reward->tiers->pluck('id')->toArray();
$this->thumbnail = $this->mapMediaCollection($reward->getMedia('thumbnail'));
}
@@ -89,6 +96,8 @@ public function store(): void
'end_date' => $this->end_date,
]);
+ $reward->tiers()->sync($this->tier_ids);
+
$this->uploadMedia($this->thumbnail, $reward, 'thumbnail');
});
}
@@ -108,6 +117,8 @@ public function update(): void
'end_date' => $this->end_date,
]);
+ $this->reward->tiers()->sync($this->tier_ids);
+
$this->syncMedia($this->thumbnail, $this->reward, 'thumbnail');
$this->uploadMedia($this->thumbnail, $this->reward, 'thumbnail');
});
diff --git a/app/Livewire/Member/RedeemPoint.php b/app/Livewire/Member/RedeemPoint.php
index 581dfcb..f7d10be 100644
--- a/app/Livewire/Member/RedeemPoint.php
+++ b/app/Livewire/Member/RedeemPoint.php
@@ -28,8 +28,13 @@ class RedeemPoint extends Component
public function mount(): void
{
+ $userTierId = auth()->user()->membership->tier_id;
+
$this->rewards = Reward::show()
->active()
+ ->whereHas('tiers', function ($query) use ($userTierId) {
+ $query->where('id', $userTierId);
+ })
->orderBy('points')
->get()
->map(function (Reward $reward) {
@@ -58,6 +63,14 @@ public function redeem(Reward $reward): void
$user = auth()->user();
$membership = $user->membership;
+ // Check if reward is available for user's tier
+ if (! $reward->tiers()->where('tiers.id', $membership->tier_id)->exists()) {
+ $this->toast('Hadiah ini tidak tersedia untuk tier Anda.', 'Gagal', 'danger');
+ Flux::modals()->close();
+
+ return;
+ }
+
if ($membership->reward_points < $reward->points) {
$this->toast('Poin Anda tidak cukup untuk menukarkan hadiah ini.', 'Gagal', 'danger');
diff --git a/app/Livewire/Studio/Loyalty/Reward.php b/app/Livewire/Studio/Loyalty/Reward.php
index a9503fb..0faef2d 100644
--- a/app/Livewire/Studio/Loyalty/Reward.php
+++ b/app/Livewire/Studio/Loyalty/Reward.php
@@ -4,6 +4,7 @@
use App\Livewire\Forms\Studio\Loyalty\RewardForm;
use App\Models\Reward as RewardModel;
+use App\Models\Tier;
use App\Traits\Authorization\WithAuthorization;
use App\Traits\Components\WithCloseModal;
use App\Traits\Components\WithConfirmation;
@@ -27,6 +28,13 @@ class Reward extends Component
public string $modalTitle = '';
+ public $tiers = [];
+
+ public function mount(): void
+ {
+ $this->tiers = Tier::orderBy('min_spending')->pluck('name', 'id')->toArray();
+ }
+
public function create(): void
{
$this->canOrAbort('create reward');
diff --git a/app/Models/Reward.php b/app/Models/Reward.php
index 4d8bda7..12dc98e 100644
--- a/app/Models/Reward.php
+++ b/app/Models/Reward.php
@@ -8,6 +8,7 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\MediaLibrary\HasMedia;
@@ -52,6 +53,11 @@ protected function active(Builder $query): void
});
}
+ public function tiers(): BelongsToMany
+ {
+ return $this->belongsToMany(Tier::class);
+ }
+
public function redemptions(): HasMany
{
return $this->hasMany(Redemption::class);
diff --git a/app/Models/Tier.php b/app/Models/Tier.php
index 9635490..f53ab53 100644
--- a/app/Models/Tier.php
+++ b/app/Models/Tier.php
@@ -49,6 +49,11 @@ public function vouchers(): BelongsToMany
return $this->belongsToMany(Voucher::class);
}
+ public function rewards(): BelongsToMany
+ {
+ return $this->belongsToMany(Reward::class);
+ }
+
public static function getHighestTier()
{
return self::orderByDesc('min_spending')->first();
diff --git a/database/migrations/2025_12_20_092311_create_reward_tier_table.php b/database/migrations/2025_12_20_092311_create_reward_tier_table.php
new file mode 100644
index 0000000..da54f5c
--- /dev/null
+++ b/database/migrations/2025_12_20_092311_create_reward_tier_table.php
@@ -0,0 +1,29 @@
+foreignId('reward_id')->constrained()->cascadeOnDelete();
+ $table->foreignId('tier_id')->constrained()->cascadeOnDelete();
+ $table->timestamp('created_at')->useCurrent();
+ $table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('reward_tier');
+ }
+};
diff --git a/resources/views/livewire/studio/loyalty/rewards.blade.php b/resources/views/livewire/studio/loyalty/rewards.blade.php
index 9edc4f2..efa4de3 100644
--- a/resources/views/livewire/studio/loyalty/rewards.blade.php
+++ b/resources/views/livewire/studio/loyalty/rewards.blade.php
@@ -88,6 +88,16 @@
placeholder="Pilih Tanggal" autocomplete="off" locale="id-ID" />
+
+ Tier *
+
+ @foreach ($tiers as $key => $value)
+ {{ $value }}
+ @endforeach
+
+
+
+