# Low Level Design (LLD)

# ASETQU V.2 - Digital Asset Ecosystem Platform

---

## 📋 Document Information

| Item              | Detail                 |
| ----------------- | ---------------------- |
| **Project Name**  | ASETQU V.2             |
| **Document Type** | Low Level Design (LLD) |
| **Version**       | 1.0.0                  |
| **Created Date**  | January 2026           |
| **Last Updated**  | January 2026           |

---

## 1. Module Structure Detail

### 1.1 Core Module

```
Modules/Core/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   └── BaseController.php
│   │   └── Middleware/
│   │       └── SetLocale.php
│   ├── Providers/
│   │   └── CoreServiceProvider.php
│   ├── Services/
│   │   ├── CacheService.php
│   │   ├── MediaService.php
│   │   └── HelperService.php
│   └── Traits/
│       ├── HasSlug.php
│       ├── HasMedia.php
│       └── Filterable.php
├── config/
│   └── config.php
├── resources/
│   ├── views/
│   │   ├── layouts/
│   │   │   ├── master.blade.php
│   │   │   ├── admin.blade.php
│   │   │   └── auth.blade.php
│   │   ├── components/
│   │   │   ├── navbar.blade.php
│   │   │   ├── footer.blade.php
│   │   │   ├── mega-menu.blade.php
│   │   │   ├── alert.blade.php
│   │   │   └── modal.blade.php
│   │   └── partials/
│   │       ├── head.blade.php
│   │       ├── scripts.blade.php
│   │       └── meta.blade.php
│   ├── css/
│   │   ├── _variables.scss
│   │   ├── _mixins.scss
│   │   └── core.scss
│   └── js/
│       └── core.js
├── routes/
│   └── web.php
└── module.json
```

---

### 1.2 Auth Module

```
Modules/Auth/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── LoginController.php
│   │   │   ├── RegisterController.php
│   │   │   ├── ForgotPasswordController.php
│   │   │   ├── ResetPasswordController.php
│   │   │   └── VerificationController.php
│   │   ├── Middleware/
│   │   │   └── RedirectIfAuthenticated.php
│   │   └── Requests/
│   │       ├── LoginRequest.php
│   │       ├── RegisterRequest.php
│   │       └── ForgotPasswordRequest.php
│   ├── Providers/
│   │   └── AuthServiceProvider.php
│   ├── Services/
│   │   ├── AuthService.php
│   │   └── SocialAuthService.php
│   └── Events/
│       ├── UserLoggedIn.php
│       ├── UserRegistered.php
│       └── PasswordReset.php
├── config/
│   └── config.php
├── database/
│   └── migrations/
├── resources/
│   └── views/
│       ├── login.blade.php
│       ├── register.blade.php
│       ├── forgot-password.blade.php
│       ├── reset-password.blade.php
│       └── verify-email.blade.php
├── routes/
│   └── web.php
└── module.json
```

---

### 1.3 Admin Module

```
Modules/Admin/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── DashboardController.php
│   │   │   ├── UserController.php
│   │   │   ├── RoleController.php
│   │   │   ├── PermissionController.php
│   │   │   ├── SettingController.php
│   │   │   └── ActivityLogController.php
│   │   ├── Middleware/
│   │   │   └── AdminMiddleware.php
│   │   └── Requests/
│   │       ├── UserRequest.php
│   │       ├── RoleRequest.php
│   │       └── SettingRequest.php
│   ├── Providers/
│   │   └── AdminServiceProvider.php
│   └── Services/
│       ├── DashboardService.php
│       ├── ReportService.php
│       └── ActivityLogService.php
├── config/
│   └── config.php
├── resources/
│   └── views/
│       ├── dashboard.blade.php
│       ├── users/
│       │   ├── index.blade.php
│       │   ├── create.blade.php
│       │   ├── edit.blade.php
│       │   └── show.blade.php
│       ├── roles/
│       ├── settings/
│       └── activity-logs/
├── routes/
│   └── web.php
└── module.json
```

---

### 1.4 Page Module (CMS)

> **CMS Features Include:**
>
> -   Header menu management (mega menu text, links, order)
> -   Footer content management (text, copyright, contact)
> -   Social media links management
> -   Static pages, FAQs, testimonials, partners, roadmap

```
Modules/Page/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── PageController.php
│   │   │   ├── SectionController.php
│   │   │   ├── MenuController.php
│   │   │   ├── MenuItemController.php
│   │   │   ├── FooterController.php
│   │   │   ├── SocialMediaController.php
│   │   │   ├── FaqController.php
│   │   │   ├── TestimonialController.php
│   │   │   ├── PartnerController.php
│   │   │   └── RoadmapController.php
│   │   └── Requests/
│   │       ├── PageRequest.php
│   │       ├── SectionRequest.php
│   │       ├── MenuRequest.php
│   │       ├── MenuItemRequest.php
│   │       ├── FooterRequest.php
│   │       ├── SocialMediaRequest.php
│   │       └── FaqRequest.php
│   ├── Models/
│   │   ├── Page.php
│   │   ├── Section.php
│   │   ├── Menu.php
│   │   ├── MenuItem.php
│   │   ├── FooterContent.php
│   │   ├── SocialMediaLink.php
│   │   ├── Faq.php
│   │   ├── Testimonial.php
│   │   ├── Partner.php
│   │   ├── RoadmapPhase.php
│   │   └── RoadmapItem.php
│   ├── Providers/
│   │   └── PageServiceProvider.php
│   ├── Services/
│   │   ├── PageService.php
│   │   ├── MenuService.php
│   │   └── FooterService.php
│   └── Repositories/
│       ├── PageRepository.php
│       └── PageRepositoryInterface.php
├── config/
│   └── config.php
├── database/
│   ├── migrations/
│   │   ├── create_menus_table.php
│   │   ├── create_menu_items_table.php
│   │   ├── create_footer_content_table.php
│   │   ├── create_social_media_links_table.php
│   │   ├── create_pages_table.php
│   │   ├── create_sections_table.php
│   │   ├── create_faqs_table.php
│   │   ├── create_testimonials_table.php
│   │   ├── create_partners_table.php
│   │   ├── create_roadmap_phases_table.php
│   │   └── create_roadmap_items_table.php
│   └── seeders/
│       └── PageSeeder.php
├── resources/
│   └── views/
│       ├── public/
│       │   ├── tokenomics.blade.php
│       │   ├── whitepaper.blade.php
│       │   ├── roadmap.blade.php
│       │   ├── architecture.blade.php
│       │   ├── ecosystem.blade.php
│       │   ├── audit-security.blade.php
│       │   └── achievement.blade.php
│       └── admin/
│           ├── pages/
│           ├── sections/
│           ├── faqs/
│           └── testimonials/
├── routes/
│   └── web.php
└── module.json
```

---

### 1.5 News Module

> **Important Notes:**
>
> -   Events: Admin-created only, 1 event per date, with email reminders
> -   Academy: YouTube video links only, no enrollment system

```
Modules/News/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── EventController.php
│   │   │   ├── NewsletterController.php
│   │   │   └── AcademyController.php
│   │   └── Requests/
│   │       ├── EventRequest.php
│   │       ├── NewsletterRequest.php
│   │       └── VideoRequest.php
│   ├── Models/
│   │   ├── Event.php
│   │   ├── EventRegistration.php
│   │   ├── Newsletter.php
│   │   ├── NewsletterSubscriber.php
│   │   ├── AcademyVideo.php
│   │   └── VideoWatchHistory.php
│   ├── Providers/
│   │   └── NewsServiceProvider.php
│   ├── Services/
│   │   ├── EventService.php
│   │   ├── EventReminderService.php
│   │   ├── NewsletterService.php
│   │   └── AcademyService.php
│   └── Jobs/
│       ├── SendNewsletterJob.php
│       ├── SendEventReminderJob.php
│       └── SendEventDayReminderJob.php
├── config/
│   └── config.php
├── database/
│   ├── migrations/
│   └── seeders/
├── resources/
│   └── views/
│       ├── public/
│       │   ├── events/
│       │   ├── newsletter/
│       │   └── academy/
│       └── admin/
├── routes/
│   └── web.php
└── module.json
```

---

### 1.6 Game Module

```
Modules/Game/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── GameController.php
│   │   │   ├── GameSessionController.php
│   │   │   └── LeaderboardController.php
│   │   └── Requests/
│   │       ├── GameRequest.php
│   │       └── GameSessionRequest.php
│   ├── Models/
│   │   ├── Game.php
│   │   ├── GameSession.php
│   │   └── Leaderboard.php
│   ├── Providers/
│   │   └── GameServiceProvider.php
│   ├── Services/
│   │   ├── GameService.php
│   │   ├── SessionService.php
│   │   └── LeaderboardService.php
│   └── Events/
│       ├── GameStarted.php
│       ├── GameCompleted.php
│       └── HighScoreAchieved.php
├── config/
│   └── config.php
├── database/
│   ├── migrations/
│   └── seeders/
├── resources/
│   ├── views/
│   │   ├── index.blade.php
│   │   ├── play.blade.php
│   │   └── leaderboard.blade.php
│   └── js/
│       └── games/
├── routes/
│   └── web.php
└── module.json
```

---

### 1.7 Wallet Module

```
Modules/Wallet/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── WalletController.php
│   │   │   ├── WalletPlatformController.php
│   │   │   └── WalletBalanceController.php
│   │   └── Requests/
│   │       └── WalletRequest.php
│   ├── Models/
│   │   ├── Wallet.php
│   │   ├── WalletPlatform.php
│   │   └── WalletBalance.php
│   ├── Providers/
│   │   └── WalletServiceProvider.php
│   ├── Services/
│   │   ├── WalletService.php
│   │   ├── BalanceService.php
│   │   └── Web3Service.php
│   └── Jobs/
│       └── SyncWalletBalanceJob.php
├── config/
│   └── config.php
├── database/
│   ├── migrations/
│   └── seeders/
│       └── WalletPlatformSeeder.php
├── resources/
│   └── views/
│       ├── index.blade.php
│       ├── create.blade.php
│       └── show.blade.php
├── routes/
│   └── web.php
└── module.json
```

---

### 1.8 Point Module

```
Modules/Point/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── CoinController.php
│   │   │   ├── PointController.php
│   │   │   ├── ConversionController.php
│   │   │   └── DailyRewardController.php
│   │   └── Requests/
│   │       └── ConversionRequest.php
│   ├── Models/
│   │   ├── Coin.php
│   │   ├── Point.php
│   │   ├── CoinConversion.php
│   │   └── DailyReward.php
│   ├── Providers/
│   │   └── PointServiceProvider.php
│   ├── Services/
│   │   ├── CoinService.php
│   │   ├── PointService.php
│   │   ├── ConversionService.php
│   │   └── RewardService.php
│   └── Events/
│       ├── CoinsEarned.php
│       ├── PointsConverted.php
│       └── DailyRewardClaimed.php
├── config/
│   └── config.php
├── database/
│   ├── migrations/
│   └── seeders/
├── resources/
│   └── views/
│       ├── coins/
│       ├── points/
│       └── rewards/
├── routes/
│   └── web.php
└── module.json
```

---

### 1.9 Dashboard Module

```
Modules/Dashboard/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── DashboardController.php
│   │   │   ├── ProfileController.php
│   │   │   └── NotificationController.php
│   │   └── Requests/
│   │       └── ProfileRequest.php
│   ├── Providers/
│   │   └── DashboardServiceProvider.php
│   └── Services/
│       ├── DashboardService.php
│       └── ProfileService.php
├── config/
│   └── config.php
├── resources/
│   └── views/
│       ├── index.blade.php
│       ├── profile/
│       │   ├── show.blade.php
│       │   └── edit.blade.php
│       └── notifications/
├── routes/
│   └── web.php
└── module.json
```

---

### 1.10 Setting Module

```
Modules/Setting/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── SettingController.php
│   │   │   └── MediaController.php
│   │   └── Requests/
│   │       ├── SettingRequest.php
│   │       └── MediaRequest.php
│   ├── Models/
│   │   ├── Setting.php
│   │   └── Media.php
│   ├── Providers/
│   │   └── SettingServiceProvider.php
│   └── Services/
│       ├── SettingService.php
│       └── MediaService.php
├── config/
│   └── config.php
├── database/
│   ├── migrations/
│   └── seeders/
│       └── SettingSeeder.php
├── resources/
│   └── views/
│       ├── index.blade.php
│       └── media/
├── routes/
│   └── web.php
└── module.json
```

---

## 2. Class Diagrams

### 2.1 User & Authentication Classes

```
┌─────────────────────────────────────┐
│              User                   │
├─────────────────────────────────────┤
│ - id: bigint                        │
│ - uuid: string                      │
│ - name: string                      │
│ - email: string                     │
│ - email_verified_at: timestamp      │
│ - password: string                  │
│ - phone: string                     │
│ - avatar: string                    │
│ - status: enum                      │
│ - last_login_at: timestamp          │
│ - coin_balance: integer             │
│ - point_balance: integer            │
│ - remember_token: string            │
│ - deleted_at: timestamp             │
├─────────────────────────────────────┤
│ + wallets(): HasMany                │
│ + roles(): BelongsToMany            │
│ + permissions(): BelongsToMany      │
│ + gameSessions(): HasMany           │
│ + coins(): HasMany                  │
│ + points(): HasMany                 │
│ + videoWatchHistory(): HasMany      │
│ + eventRegistrations(): HasMany     │
│ + activityLogs(): HasMany           │
└─────────────────────────────────────┘
            │
            │ implements
            ▼
┌─────────────────────────────────────┐
│     HasRoles (Spatie Trait)         │
├─────────────────────────────────────┤
│ + assignRole(role)                  │
│ + removeRole(role)                  │
│ + hasRole(role): bool               │
│ + hasPermissionTo(permission): bool │
└─────────────────────────────────────┘
```

### 2.2 Wallet Classes

```
┌─────────────────────────┐       ┌─────────────────────────┐
│     WalletPlatform      │       │         Wallet          │
├─────────────────────────┤       ├─────────────────────────┤
│ - id: bigint            │       │ - id: bigint            │
│ - name: string          │       │ - user_id: bigint       │
│ - slug: string          │◀──────│ - platform_id: bigint   │
│ - type: enum            │       │ - wallet_address: string│
│ - icon: string          │       │ - label: string         │
│ - description: text     │       │ - is_primary: boolean   │
│ - is_active: boolean    │       │ - is_verified: boolean  │
├─────────────────────────┤       │ - deleted_at: timestamp │
│ + wallets(): HasMany    │       ├─────────────────────────┤
└─────────────────────────┘       │ + user(): BelongsTo     │
                                  │ + platform(): BelongsTo │
                                  │ + balances(): HasMany   │
                                  └─────────────────────────┘
                                            │
                                            │ 1:N
                                            ▼
                                  ┌─────────────────────────┐
                                  │     WalletBalance       │
                                  ├─────────────────────────┤
                                  │ - id: bigint            │
                                  │ - wallet_id: bigint     │
                                  │ - currency: string      │
                                  │ - balance: decimal      │
                                  │ - updated_at: timestamp │
                                  ├─────────────────────────┤
                                  │ + wallet(): BelongsTo   │
                                  └─────────────────────────┘
```

### 2.3 Game & Point Classes

```
┌─────────────────────────┐       ┌─────────────────────────┐
│          Game           │       │       GameSession       │
├─────────────────────────┤       ├─────────────────────────┤
│ - id: bigint            │       │ - id: bigint            │
│ - name: string          │       │ - user_id: bigint       │
│ - slug: string          │◀──────│ - game_id: bigint       │
│ - description: text     │       │ - score: integer        │
│ - instructions: text    │       │ - points_earned: integer │
│ - thumbnail: string     │       │ - started_at: timestamp │
│ - min_score: integer    │       │ - ended_at: timestamp   │
│ - max_score: integer    │       │ - status: enum          │
│ - point_reward: integer  │       ├─────────────────────────┤
│ - daily_limit: integer  │       │ + user(): BelongsTo     │
│ - is_active: boolean    │       │ + game(): BelongsTo     │
├─────────────────────────┤       └─────────────────────────┘
│ + sessions(): HasMany   │
└─────────────────────────┘

┌─────────────────────────┐       ┌─────────────────────────┐
│          Coin           │       │         Point           │
├─────────────────────────┤       ├─────────────────────────┤
│ - id: bigint            │       │ - id: bigint            │
│ - user_id: bigint       │       │ - user_id: bigint       │
│ - type: enum            │       │ - amount: integer       │
│ - amount: integer       │       │ - source: string        │
│ - source: string        │       │ - description: text     │
│ - reference_type: string│       │ - created_at: timestamp │
│ - reference_id: bigint  │       ├─────────────────────────┤
│ - description: text     │       │ + user(): BelongsTo     │
├─────────────────────────┤       └─────────────────────────┘
│ + user(): BelongsTo     │
│ + reference(): MorphTo  │
└─────────────────────────┘

┌─────────────────────────┐       ┌─────────────────────────┐
│     CoinConversion      │       │      DailyReward        │
├─────────────────────────┤       ├─────────────────────────┤
│ - id: bigint            │       │ - id: bigint            │
│ - user_id: bigint       │       │ - user_id: bigint       │
│ - coins_converted: int  │       │ - reward_date: date     │
│ - points_received: int  │       │ - points_earned: integer │
│ - conversion_rate: dec  │       │ - streak_day: integer   │
│ - created_at: timestamp │       ├─────────────────────────┤
├─────────────────────────┤       │ + user(): BelongsTo     │
│ + user(): BelongsTo     │       └─────────────────────────┘
└─────────────────────────┘
```

### 2.4 CMS Classes

```
┌─────────────────────────┐
│          Page           │
├─────────────────────────┤
│ - id: bigint            │
│ - title: string         │
│ - slug: string          │
│ - content: longtext     │
│ - meta_title: string    │
│ - meta_description: text│
│ - meta_keywords: string │
│ - featured_image: string│
│ - status: enum          │
│ - published_at: timestamp
│ - created_by: bigint    │
│ - deleted_at: timestamp │
├─────────────────────────┤
│ + author(): BelongsTo   │
│ + sections(): HasMany   │
└─────────────────────────┘

┌─────────────────────────┐       ┌─────────────────────────┐
│        Section          │       │           Faq           │
├─────────────────────────┤       ├─────────────────────────┤
│ - id: bigint            │       │ - id: bigint            │
│ - page_id: bigint       │       │ - question: string      │
│ - title: string         │       │ - answer: text          │
│ - content: longtext     │       │ - category: string      │
│ - type: string          │       │ - sort_order: integer   │
│ - settings: json        │       │ - is_active: boolean    │
│ - sort_order: integer   │       ├─────────────────────────┤
│ - is_active: boolean    │       └─────────────────────────┘
├─────────────────────────┤
│ + page(): BelongsTo     │
└─────────────────────────┘

┌─────────────────────────┐       ┌─────────────────────────┐
│      RoadmapPhase       │       │      RoadmapItem        │
├─────────────────────────┤       ├─────────────────────────┤
│ - id: bigint            │       │ - id: bigint            │
│ - title: string         │◀──────│ - phase_id: bigint      │
│ - description: text     │       │ - title: string         │
│ - phase_number: integer │       │ - is_completed: boolean │
│ - status: enum          │       │ - sort_order: integer   │
│ - sort_order: integer   │       ├─────────────────────────┤
├─────────────────────────┤       │ + phase(): BelongsTo    │
│ + items(): HasMany      │       └─────────────────────────┘
└─────────────────────────┘
```

---

## 3. Service Layer Design

### 3.1 Service Pattern Implementation

```php
// Interface Pattern
namespace Modules\Game\Services;

interface GameServiceInterface
{
    public function getAllGames(): Collection;
    public function getActiveGames(): Collection;
    public function startSession(User $user, Game $game): GameSession;
    public function endSession(GameSession $session, int $score): GameSession;
    public function calculateReward(GameSession $session): int;
}

// Service Implementation
class GameService implements GameServiceInterface
{
    public function __construct(
        private GameRepository $gameRepository,
        private CoinService $coinService,
        private LeaderboardService $leaderboardService
    ) {}

    public function startSession(User $user, Game $game): GameSession
    {
        // Check daily limit
        $todayCount = $this->gameRepository->getUserTodaySessionCount($user, $game);

        if ($todayCount >= $game->daily_limit) {
            throw new DailyLimitExceededException();
        }

        return GameSession::create([
            'user_id' => $user->id,
            'game_id' => $game->id,
            'started_at' => now(),
            'status' => 'playing'
        ]);
    }

    public function endSession(GameSession $session, int $score): GameSession
    {
        $coins = $this->calculateReward($session->game, $score);

        $session->update([
            'score' => $score,
            'points_earned' => $coins,
            'ended_at' => now(),
            'status' => 'completed'
        ]);

        // Award coins
        $this->coinService->addCoins(
            $session->user,
            $coins,
            'game_reward',
            $session
        );

        // Update leaderboard
        $this->leaderboardService->updateScore($session);

        event(new GameCompleted($session));

        return $session;
    }
}
```

### 3.2 Repository Pattern

```php
namespace Modules\Wallet\Repositories;

interface WalletRepositoryInterface
{
    public function findByUser(User $user): Collection;
    public function findById(int $id): ?Wallet;
    public function create(array $data): Wallet;
    public function update(Wallet $wallet, array $data): Wallet;
    public function delete(Wallet $wallet): bool;
    public function findPrimary(User $user): ?Wallet;
}

class WalletRepository implements WalletRepositoryInterface
{
    public function __construct(private Wallet $model) {}

    public function findByUser(User $user): Collection
    {
        return $this->model
            ->where('user_id', $user->id)
            ->with(['platform', 'balances'])
            ->get();
    }

    public function findPrimary(User $user): ?Wallet
    {
        return $this->model
            ->where('user_id', $user->id)
            ->where('is_primary', true)
            ->first();
    }

    public function create(array $data): Wallet
    {
        return DB::transaction(function () use ($data) {
            // If setting as primary, unset other primaries
            if ($data['is_primary'] ?? false) {
                $this->model
                    ->where('user_id', $data['user_id'])
                    ->update(['is_primary' => false]);
            }

            return $this->model->create($data);
        });
    }
}
```

---

## 4. Controller Design

### 4.1 API Controller Example

```php
namespace Modules\Wallet\Http\Controllers;

use App\Http\Controllers\Controller;
use Modules\Wallet\Http\Requests\WalletRequest;
use Modules\Wallet\Services\WalletService;
use Modules\Wallet\Http\Resources\WalletResource;

class WalletController extends Controller
{
    public function __construct(
        private WalletService $walletService
    ) {
        $this->middleware('auth:sanctum');
    }

    public function index()
    {
        $wallets = $this->walletService->getUserWallets(auth()->user());

        return WalletResource::collection($wallets);
    }

    public function store(WalletRequest $request)
    {
        $wallet = $this->walletService->createWallet(
            auth()->user(),
            $request->validated()
        );

        return new WalletResource($wallet);
    }

    public function show(Wallet $wallet)
    {
        $this->authorize('view', $wallet);

        return new WalletResource(
            $wallet->load(['platform', 'balances'])
        );
    }

    public function update(WalletRequest $request, Wallet $wallet)
    {
        $this->authorize('update', $wallet);

        $wallet = $this->walletService->updateWallet(
            $wallet,
            $request->validated()
        );

        return new WalletResource($wallet);
    }

    public function destroy(Wallet $wallet)
    {
        $this->authorize('delete', $wallet);

        $this->walletService->deleteWallet($wallet);

        return response()->noContent();
    }
}
```

### 4.2 Web Controller Example

```php
namespace Modules\Page\Http\Controllers;

use App\Http\Controllers\Controller;
use Modules\Page\Services\PageService;

class PageController extends Controller
{
    public function __construct(
        private PageService $pageService
    ) {}

    public function tokenomics()
    {
        $page = $this->pageService->getPageBySlug('tokenomics');
        $sections = $this->pageService->getPageSections($page);

        return view('page::public.tokenomics', compact('page', 'sections'));
    }

    public function roadmap()
    {
        $phases = $this->pageService->getRoadmapPhases();

        return view('page::public.roadmap', compact('phases'));
    }

    public function whitepaper()
    {
        $page = $this->pageService->getPageBySlug('whitepaper');

        return view('page::public.whitepaper', compact('page'));
    }
}
```

---

## 5. Request Validation

### 5.1 Form Request Classes

```php
namespace Modules\Auth\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class RegisterRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'phone' => ['nullable', 'string', 'max:20'],
            'password' => [
                'required',
                'string',
                'min:8',
                'confirmed',
                'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/'
            ],
            'terms' => ['required', 'accepted'],
        ];
    }

    public function messages(): array
    {
        return [
            'password.regex' => 'Password harus mengandung huruf besar, huruf kecil, dan angka.',
            'terms.accepted' => 'Anda harus menyetujui syarat dan ketentuan.',
        ];
    }
}

namespace Modules\Wallet\Http\Requests;

class WalletRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'platform_id' => ['required', 'exists:wallet_platforms,id'],
            'wallet_address' => [
                'required',
                'string',
                'max:255',
                Rule::unique('wallets')->where(function ($query) {
                    return $query->where('user_id', auth()->id())
                                 ->whereNull('deleted_at');
                })->ignore($this->wallet)
            ],
            'label' => ['nullable', 'string', 'max:100'],
            'is_primary' => ['boolean'],
        ];
    }
}
```

---

## 6. Event & Listener Design

### 6.1 Event Classes

```php
namespace Modules\Game\Events;

use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Modules\Game\Models\GameSession;

class GameCompleted
{
    use Dispatchable, SerializesModels;

    public function __construct(
        public GameSession $session
    ) {}
}

namespace Modules\Point\Events;

class CoinsEarned
{
    use Dispatchable, SerializesModels;

    public function __construct(
        public User $user,
        public int $amount,
        public string $source,
        public ?Model $reference = null
    ) {}
}
```

### 6.2 Listener Classes

```php
namespace Modules\Point\Listeners;

use Modules\Game\Events\GameCompleted;
use Modules\Point\Services\CoinService;

class AwardGameCoins
{
    public function __construct(
        private CoinService $coinService
    ) {}

    public function handle(GameCompleted $event): void
    {
        $this->coinService->recordTransaction(
            $event->session->user,
            'earned',
            $event->session->points_earned,
            'game_reward',
            $event->session
        );
    }
}

namespace Modules\Admin\Listeners;

use Modules\Auth\Events\UserLoggedIn;
use Modules\Admin\Services\ActivityLogService;

class LogUserLogin
{
    public function __construct(
        private ActivityLogService $logService
    ) {}

    public function handle(UserLoggedIn $event): void
    {
        $this->logService->log(
            $event->user,
            'login',
            'User logged in',
            [
                'ip' => request()->ip(),
                'user_agent' => request()->userAgent()
            ]
        );
    }
}
```

---

## 7. Middleware Design

### 7.1 Custom Middleware

```php
namespace Modules\Admin\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class AdminMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        if (!auth()->check()) {
            return redirect()->route('auth.login');
        }

        if (!auth()->user()->hasRole('admin')) {
            abort(403, 'Unauthorized access.');
        }

        return $next($request);
    }
}

namespace Modules\Game\Http\Middleware;

class CheckGameAccess
{
    public function handle(Request $request, Closure $next)
    {
        if (!auth()->check()) {
            return redirect()->route('auth.login')
                ->with('message', 'Silakan login untuk bermain game.');
        }

        if (auth()->user()->status !== 'active') {
            return back()->with('error', 'Akun Anda tidak aktif.');
        }

        return $next($request);
    }
}
```

---

## 8. Job & Queue Design

### 8.1 Queue Jobs

```php
namespace Modules\Wallet\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Modules\Wallet\Models\Wallet;
use Modules\Wallet\Services\Web3Service;

class SyncWalletBalanceJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private Wallet $wallet
    ) {}

    public function handle(Web3Service $web3Service): void
    {
        $balances = $web3Service->getBalances($this->wallet->wallet_address);

        foreach ($balances as $currency => $balance) {
            $this->wallet->balances()->updateOrCreate(
                ['currency' => $currency],
                ['balance' => $balance, 'updated_at' => now()]
            );
        }
    }

    public function failed(\Throwable $exception): void
    {
        Log::error('Failed to sync wallet balance', [
            'wallet_id' => $this->wallet->id,
            'error' => $exception->getMessage()
        ]);
    }
}

namespace Modules\News\Jobs;

class SendNewsletterJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private Newsletter $newsletter,
        private Collection $subscribers
    ) {}

    public function handle(): void
    {
        foreach ($this->subscribers as $subscriber) {
            Mail::to($subscriber->email)
                ->queue(new NewsletterMail($this->newsletter));
        }

        $this->newsletter->update([
            'sent_at' => now(),
            'status' => 'sent'
        ]);
    }
}

namespace Modules\News\Jobs;

/**
 * Send event reminder emails to registered users.
 * This job is triggered by scheduler X days before the event.
 */
class SendEventReminderJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private Event $event
    ) {}

    public function handle(): void
    {
        // Get registrations that haven't received reminder yet
        $registrations = $this->event->registrations()
            ->where('reminder_sent', false)
            ->where('status', 'registered')
            ->with('user')
            ->get();

        foreach ($registrations as $registration) {
            Mail::to($registration->user->email)
                ->queue(new EventReminderMail($this->event, $registration->user));

            $registration->update([
                'reminder_sent' => true,
                'reminder_sent_at' => now()
            ]);
        }
    }
}

namespace Modules\News\Jobs;

/**
 * Send day-of event reminder emails.
 * This job is triggered by scheduler on the event date.
 */
class SendEventDayReminderJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private Event $event
    ) {}

    public function handle(): void
    {
        // Get registrations that haven't received day reminder yet
        $registrations = $this->event->registrations()
            ->where('day_reminder_sent', false)
            ->where('status', 'registered')
            ->with('user')
            ->get();

        foreach ($registrations as $registration) {
            Mail::to($registration->user->email)
                ->queue(new EventDayReminderMail($this->event, $registration->user));

            $registration->update([
                'day_reminder_sent' => true,
                'day_reminder_sent_at' => now()
            ]);
        }
    }
}
```

---

## 9. Resource & Transformation

### 9.1 API Resources

```php
namespace Modules\Wallet\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class WalletResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'platform' => new WalletPlatformResource($this->whenLoaded('platform')),
            'wallet_address' => $this->wallet_address,
            'label' => $this->label,
            'is_primary' => $this->is_primary,
            'is_verified' => $this->is_verified,
            'balances' => WalletBalanceResource::collection($this->whenLoaded('balances')),
            'created_at' => $this->created_at->toIso8601String(),
        ];
    }
}

namespace Modules\Game\Http\Resources;

class LeaderboardResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'rank' => $this->rank,
            'user' => [
                'id' => $this->user->id,
                'name' => $this->user->name,
                'avatar' => $this->user->avatar_url,
            ],
            'score' => $this->score,
            'games_played' => $this->games_played,
            'total_coins' => $this->total_coins,
        ];
    }
}
```

---

## 10. Blade Component Design

### 10.1 Component Classes

```php
namespace Modules\Core\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public function __construct(
        public string $type = 'info',
        public ?string $message = null,
        public bool $dismissible = true
    ) {}

    public function render()
    {
        return view('core::components.alert');
    }

    public function typeClass(): string
    {
        return match($this->type) {
            'success' => 'alert-success',
            'warning' => 'alert-warning',
            'danger', 'error' => 'alert-danger',
            default => 'alert-info',
        };
    }
}

namespace Modules\Core\View\Components;

class Modal extends Component
{
    public function __construct(
        public string $id,
        public ?string $title = null,
        public string $size = 'md',
        public bool $centered = true,
        public bool $scrollable = false
    ) {}

    public function render()
    {
        return view('core::components.modal');
    }

    public function modalClass(): string
    {
        $classes = ['modal-dialog'];

        if ($this->size !== 'md') {
            $classes[] = "modal-{$this->size}";
        }

        if ($this->centered) {
            $classes[] = 'modal-dialog-centered';
        }

        if ($this->scrollable) {
            $classes[] = 'modal-dialog-scrollable';
        }

        return implode(' ', $classes);
    }
}
```

---

## 11. Testing Strategy

### 11.1 Unit Test Example

```php
namespace Modules\Point\Tests\Unit;

use Tests\TestCase;
use Modules\Point\Services\CoinService;
use App\Models\User;

class CoinServiceTest extends TestCase
{
    private CoinService $service;
    private User $user;

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = app(CoinService::class);
        $this->user = User::factory()->create(['coin_balance' => 100]);
    }

    public function test_can_add_coins_to_user()
    {
        $result = $this->service->addCoins($this->user, 50, 'test');

        $this->assertEquals(150, $this->user->fresh()->coin_balance);
        $this->assertDatabaseHas('coins', [
            'user_id' => $this->user->id,
            'type' => 'earned',
            'amount' => 50
        ]);
    }

    public function test_can_deduct_coins_from_user()
    {
        $result = $this->service->deductCoins($this->user, 30, 'test');

        $this->assertEquals(70, $this->user->fresh()->coin_balance);
    }

    public function test_cannot_deduct_more_than_balance()
    {
        $this->expectException(InsufficientBalanceException::class);

        $this->service->deductCoins($this->user, 150, 'test');
    }
}
```

### 11.2 Feature Test Example

```php
namespace Modules\Wallet\Tests\Feature;

use Tests\TestCase;
use App\Models\User;
use Modules\Wallet\Models\WalletPlatform;

class WalletControllerTest extends TestCase
{
    private User $user;
    private WalletPlatform $platform;

    protected function setUp(): void
    {
        parent::setUp();
        $this->user = User::factory()->create();
        $this->platform = WalletPlatform::factory()->create();
    }

    public function test_user_can_create_wallet()
    {
        $response = $this->actingAs($this->user)
            ->postJson('/api/wallets', [
                'platform_id' => $this->platform->id,
                'wallet_address' => '0x1234567890abcdef',
                'label' => 'My Wallet',
                'is_primary' => true
            ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'data' => [
                    'id',
                    'platform',
                    'wallet_address',
                    'label',
                    'is_primary'
                ]
            ]);
    }

    public function test_user_can_view_own_wallets()
    {
        $wallet = $this->user->wallets()->create([
            'platform_id' => $this->platform->id,
            'wallet_address' => '0x1234567890abcdef'
        ]);

        $response = $this->actingAs($this->user)
            ->getJson('/api/wallets');

        $response->assertStatus(200)
            ->assertJsonCount(1, 'data');
    }

    public function test_user_cannot_view_others_wallets()
    {
        $otherUser = User::factory()->create();
        $wallet = $otherUser->wallets()->create([
            'platform_id' => $this->platform->id,
            'wallet_address' => '0x1234567890abcdef'
        ]);

        $response = $this->actingAs($this->user)
            ->getJson("/api/wallets/{$wallet->id}");

        $response->assertStatus(403);
    }
}
```

---

_Document Version: 1.0.0 | Last Updated: January 2026_
