Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions app/Filament/Resources/Referrals/Pages/CreateReferral.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Filament\Resources\Referrals\Pages;

use App\Filament\Resources\Referrals\ReferralResource;
use Filament\Resources\Pages\CreateRecord;

class CreateReferral extends CreateRecord
{
protected static string $resource = ReferralResource::class;

protected function mutateFormDataBeforeCreate(array $data): array
{
// Generate unique code if not provided
if (empty($data['code'])) {
$data['code'] = \Wave\Referral::generateUniqueCode();
}

return $data;
}
}
19 changes: 19 additions & 0 deletions app/Filament/Resources/Referrals/Pages/EditReferral.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Filament\Resources\Referrals\Pages;

use App\Filament\Resources\Referrals\ReferralResource;
use Filament\Actions\DeleteAction;
use Filament\Resources\Pages\EditRecord;

class EditReferral extends EditRecord
{
protected static string $resource = ReferralResource::class;

protected function getHeaderActions(): array
{
return [
DeleteAction::make(),
];
}
}
19 changes: 19 additions & 0 deletions app/Filament/Resources/Referrals/Pages/ListReferrals.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Filament\Resources\Referrals\Pages;

use App\Filament\Resources\Referrals\ReferralResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;

class ListReferrals extends ListRecords
{
protected static string $resource = ReferralResource::class;

protected function getHeaderActions(): array
{
return [
CreateAction::make(),
];
}
}
175 changes: 175 additions & 0 deletions app/Filament/Resources/Referrals/ReferralResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php

namespace App\Filament\Resources\Referrals;

use App\Filament\Resources\Referrals\Pages\CreateReferral;
use App\Filament\Resources\Referrals\Pages\EditReferral;
use App\Filament\Resources\Referrals\Pages\ListReferrals;
use BackedEnum;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Wave\Referral;

class ReferralResource extends Resource
{
protected static ?string $model = Referral::class;

protected static BackedEnum|string|null $navigationIcon = 'phosphor-share-network-duotone';

protected static ?int $navigationSort = 4;

public static function form(Schema $schema): Schema
{
return $schema
->columns(2)
->components([
Section::make('Referral Information')
->description('Configure the referral code and status')
->schema([
Select::make('user_id')
->label('Referrer')
->relationship('user', 'name')
->searchable()
->preload()
->required(),

TextInput::make('code')
->label('Referral Code')
->required()
->maxLength(20)
->unique(ignoreRecord: true)
->alphaDash()
->helperText('Leave empty to auto-generate'),

Select::make('status')
->options([
'active' => 'Active',
'inactive' => 'Inactive',
'suspended' => 'Suspended',
])
->default('active')
->required(),
])
->columnSpan(1),

Section::make('Performance Metrics')
->description('Real-time referral statistics')
->schema([
Placeholder::make('clicks')
->label('Total Clicks')
->content(fn (?Referral $record): string => $record ? number_format($record->clicks) : '0'),

Placeholder::make('conversions')
->label('Conversions')
->content(fn (?Referral $record): string => $record ? number_format($record->conversions) : '0'),

Placeholder::make('conversion_rate')
->label('Conversion Rate')
->content(fn (?Referral $record): string => $record && $record->clicks > 0
? number_format(($record->conversions / $record->clicks) * 100, 2).'%'
: 'N/A'),
])
->columnSpan(1),

Section::make('Conversion Details')
->description('Information about the referred user and conversion')
->schema([
Select::make('referred_user_id')
->label('Referred User')
->relationship('referredUser', 'name')
->searchable()
->preload()
->disabled(),

DateTimePicker::make('converted_at')
->label('Conversion Date')
->disabled(),
])
->columnSpan(2)
->columns(2)
->collapsed()
->visible(fn (?Referral $record): bool => $record?->conversions > 0),
]);
}

public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('user.name')
->label('Referrer')
->searchable()
->sortable(),
TextColumn::make('code')
->searchable()
->copyable()
->badge()
->color('primary'),
TextColumn::make('clicks')
->numeric()
->sortable(),
TextColumn::make('conversions')
->numeric()
->sortable()
->badge()
->color(fn (int $state): string => $state > 0 ? 'success' : 'gray'),
TextColumn::make('status')
->badge()
->color(fn (string $state): string => match ($state) {
'active' => 'success',
'inactive' => 'gray',
'suspended' => 'danger',
}),
TextColumn::make('converted_at')
->dateTime()
->sortable()
->toggleable(),
TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->defaultSort('created_at', 'desc')
->filters([
//
])
->recordActions([
ViewAction::make(),
EditAction::make(),
DeleteAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}

public static function getRelations(): array
{
return [
//
];
}

public static function getPages(): array
{
return [
'index' => ListReferrals::route('/'),
'create' => CreateReferral::route('/create'),
'edit' => EditReferral::route('/{record}/edit'),
];
}
}
1 change: 1 addition & 0 deletions bootstrap/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
$middleware->append(\Filament\Http\Middleware\DisableBladeIconComponents::class);

$middleware->web(\RalphJSmit\Livewire\Urls\Middleware\LivewireUrlsMiddleware::class);
$middleware->web(\Wave\Http\Middleware\TrackReferrals::class);

$middleware->throttleApi();
})
Expand Down
1 change: 0 additions & 1 deletion public/build/assets/app-75U0MKBP.css

This file was deleted.

1 change: 1 addition & 0 deletions public/build/assets/app-BTsxaOG5.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/build/assets/theme-BPZmyZPO.css

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion public/build/assets/theme-DRT1wFy8.css

This file was deleted.

4 changes: 2 additions & 2 deletions public/build/manifest.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"resources/css/filament/admin/theme.css": {
"file": "assets/theme-DRT1wFy8.css",
"file": "assets/theme-BPZmyZPO.css",
"src": "resources/css/filament/admin/theme.css",
"isEntry": true
},
"resources/themes/anchor/assets/css/app.css": {
"file": "assets/app-75U0MKBP.css",
"file": "assets/app-BTsxaOG5.css",
"src": "resources/themes/anchor/assets/css/app.css",
"isEntry": true
},
Expand Down
1 change: 1 addition & 0 deletions resources/themes/anchor/components/app/sidebar.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class="fixed top-0 left-0 flex items-stretch -translate-x-full overflow-hidden l

<div class="flex flex-col justify-start items-center px-4 space-y-1.5 w-full h-full text-slate-600 dark:text-zinc-400">
<x-app.sidebar-link href="/dashboard" icon="phosphor-house" :active="Request::is('dashboard')">Dashboard</x-app.sidebar-link>
<x-app.sidebar-link href="/dashboard/referrals" icon="phosphor-share-network" :active="Request::is('dashboard/referrals')">Referrals</x-app.sidebar-link>
<x-app.sidebar-dropdown text="Projects" icon="phosphor-stack" id="projects_dropdown" :active="(Request::is('projects'))" :open="(Request::is('project_a') || Request::is('project_b') || Request::is('project_c')) ? '1' : '0'">
<x-app.sidebar-link onclick="event.preventDefault(); new FilamentNotification().title('Modify this button inside of sidebar.blade.php').send()" icon="phosphor-cube" :active="(Request::is('project_a'))">Project A</x-app.sidebar-link>
<x-app.sidebar-link onclick="event.preventDefault(); new FilamentNotification().title('Modify this button inside of sidebar.blade.php').send()" icon="phosphor-cube" :active="(Request::is('project_b'))">Project B</x-app.sidebar-link>
Expand Down
24 changes: 24 additions & 0 deletions resources/themes/anchor/pages/dashboard/referrals.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
use function Laravel\Folio\{middleware, name};
middleware('auth');
name('dashboard.referrals');
?>

<x-layouts.app>
<x-app.container x-data class="lg:space-y-6" x-cloak>

<x-app.alert id="referrals_alert" class="hidden lg:flex">
Share your referral link and earn commissions when your friends subscribe!
You'll receive 20% of their subscription fees as rewards.
</x-app.alert>

<x-app.heading
title="Referral Program"
description="Invite friends and earn rewards for every successful subscription"
:border="false"
/>

@livewire('referrals.dashboard')

</x-app.container>
</x-layouts.app>
Loading