# Dashboard Wallet Controller - Data Specification

## File: `Modules/Dashboard/app/Http/Controllers/WalletController.php`

### Method: `index()`

Controller harus mengirimkan data berikut ke view `dashboard::wallet`:

```php
public function index(Request $request)
{
    $user = auth()->user();
    
    // Get connected wallet (primary wallet)
    $connected_wallet = \Modules\Wallet\Models\Wallet::with('platform')
        ->where('user_id', $user->id)
        ->where('is_primary', true)
        ->first();
    
    // If no primary wallet, get first wallet
    if (!$connected_wallet) {
        $connected_wallet = \Modules\Wallet\Models\Wallet::with('platform')
            ->where('user_id', $user->id)
            ->first();
    }
    
    // Get total points from coins
    $total_points = \Modules\Point\Models\Coin::where('user_id', $user->id)
        ->sum('amount');
    
    // Get point history (paginated)
    $point_history = \Modules\Point\Models\Coin::with(['game'])
        ->where('user_id', $user->id)
        ->orderBy('created_at', 'desc')
        ->paginate($request->get('per_page', 10));
    
    return view('dashboard::wallet', [
        'title' => 'Wallet',
        'meta_description' => 'Kelola wallet dan riwayat poin Anda',
        'connected_wallet' => $connected_wallet,
        'total_points' => $total_points,
        'point_history' => $point_history,
    ]);
}
```

---

## Data Variables Required

### 1. **$connected_wallet** (Model Object or Null)
- **Source:** Table `wallets`
- **Relations:** 
  - `platform` (BelongsTo wallet_platforms)
- **Filters:**
  - `user_id` = current logged in user
  - `is_primary` = true (or first wallet if no primary)
- **Fields Used:**
  - `wallets.wallet_address` → displayed as "Address: {wallet_address}"
  - `wallet_platforms.name` → displayed as platform badge (INDODAX, METAMASK, etc.)
- **Display:** Header section "Wallet yang Terhubung"
- **Default:** If null, show "BELUM TERHUBUNG" and "-" for address

### 2. **$total_points** (Integer)
- **Source:** Table `coins`
- **Calculation:** Sum of all `amount` from coins table where:
  - `user_id` = current logged in user
- **Display:** Header section "Total Poin: {total_points} Poin"
- **Default:** 0 if no coins

### 3. **$point_history** (Paginated Collection)
- **Source:** Table `coins`
- **Relations:** 
  - `game` (BelongsTo games) - Optional, only for game rewards
- **Filters:**
  - `user_id` = current logged in user
- **Order:** `created_at` DESC (newest first)
- **Pagination:** 10, 25, 50, or 100 per page (from request)
- **Fields Used:**
  - `coins.source` → converted to label (e.g., 'game_reward' → 'Game Reward')
  - `coins.amount` → displayed with + or - prefix
  - `coins.description` → displayed as subtitle if exists
  - `coins.created_at` → formatted as "d/m/Y"
  - `games.name` → game name (if source is game_reward)
- **Display:** Data table "Data Tabel Riwayat Poin"

---

## Database Tables Reference

### Related Tables:
1. **wallets** - User wallets
   ```
   - id (BIGSERIAL)
   - user_id (BIGINT)
   - platform_id (BIGINT)
   - wallet_address (VARCHAR)
   - label (VARCHAR)
   - is_primary (BOOLEAN)
   - is_verified (BOOLEAN)
   - verified_at (TIMESTAMP)
   - created_at (TIMESTAMP)
   ```

2. **wallet_platforms** - Wallet platforms
   ```
   - id (BIGSERIAL)
   - name (VARCHAR) - 'Indodax', 'MetaMask', 'Trust Wallet', etc.
   - slug (VARCHAR)
   - type (VARCHAR) - 'exchange', 'web3'
   - icon (VARCHAR)
   - is_active (BOOLEAN)
   ```

3. **coins** - Coin/Point transactions
   ```
   - id (BIGSERIAL)
   - user_id (BIGINT)
   - type (VARCHAR) - 'earned', 'spent', 'expired', 'adjusted'
   - amount (INTEGER) - Can be positive or negative
   - balance_after (INTEGER)
   - source (VARCHAR) - 'game_reward', 'daily_bonus', 'referral', etc.
   - reference_type (VARCHAR)
   - reference_id (BIGINT)
   - description (TEXT)
   - created_at (TIMESTAMP)
   ```

4. **games** - Available games
   ```
   - id (BIGSERIAL)
   - name (VARCHAR)
   - slug (VARCHAR)
   - description (TEXT)
   ```

---

## Source Label Mapping

Map `coins.source` to user-friendly labels:

```php
protected function getSourceLabel($source)
{
    $labels = [
        'game_reward' => 'Game Reward',
        'daily_bonus' => 'Bonus Harian',
        'referral' => 'Bonus Referral',
        'admin_adjustment' => 'Penyesuaian Admin',
        'purchase' => 'Pembelian',
        'redeem' => 'Penukaran',
        'expired' => 'Kadaluarsa',
    ];
    
    return $labels[$source] ?? ucwords(str_replace('_', ' ', $source));
}
```

---

## Route Definition

Add to `Modules/Dashboard/routes/web.php`:

```php
Route::middleware(['auth'])->prefix('dashboard')->name('dashboard.')->group(function () {
    Route::get('/wallet', [WalletController::class, 'index'])->name('wallet');
});
```

---

## Sample Controller Implementation

```php
<?php

namespace Modules\Dashboard\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Wallet\Models\Wallet;
use Modules\Point\Models\Coin;

class WalletController extends Controller
{
    public function index(Request $request)
    {
        $user = auth()->user();
        
        // Get connected wallet (primary wallet first)
        $connected_wallet = Wallet::with('platform')
            ->where('user_id', $user->id)
            ->where('is_primary', true)
            ->first();
        
        // If no primary wallet, get first available wallet
        if (!$connected_wallet) {
            $connected_wallet = Wallet::with('platform')
                ->where('user_id', $user->id)
                ->first();
        }
        
        // Get total points
        $total_points = Coin::where('user_id', $user->id)
            ->sum('amount');
        
        // Get point history with pagination and game relation
        $point_history = Coin::where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->paginate($request->get('per_page', 10));
        
        // Add source labels to collection
        $point_history->getCollection()->transform(function ($coin) {
            $coin->source_label = $this->getSourceLabel($coin->source);
            
            // Load game if source is game_reward
            if ($coin->source === 'game_reward' && $coin->reference_type === 'game_sessions') {
                $coin->load('game');
            }
            
            return $coin;
        });
        
        return view('dashboard::wallet', [
            'title' => 'Wallet',
            'meta_description' => 'Kelola wallet dan riwayat poin Anda',
            'connected_wallet' => $connected_wallet,
            'total_points' => $total_points,
            'point_history' => $point_history,
        ]);
    }
    
    protected function getSourceLabel($source)
    {
        $labels = [
            'game_reward' => 'Game Reward',
            'daily_bonus' => 'Bonus Harian',
            'referral' => 'Bonus Referral',
            'admin_adjustment' => 'Penyesuaian Admin',
            'purchase' => 'Pembelian',
            'redeem' => 'Penukaran',
            'expired' => 'Kadaluarsa',
        ];
        
        return $labels[$source] ?? ucwords(str_replace('_', ' ', $source));
    }
}
```

---

## Model Relationships Required

### In `Modules\Point\Models\Coin.php`:

```php
public function game()
{
    // Get game from game_sessions reference
    return $this->hasOneThrough(
        \Modules\Game\Models\Game::class,
        \Modules\Game\Models\GameSession::class,
        'id',           // Foreign key on game_sessions table
        'id',           // Foreign key on games table
        'reference_id', // Local key on coins table
        'game_id'       // Local key on game_sessions table
    )->where('coins.reference_type', 'game_sessions');
}

public function wallet()
{
    // If wallet_id is stored in coins table
    return $this->belongsTo(\Modules\Wallet\Models\Wallet::class);
}
```

### In `Modules\Wallet\Models\Wallet.php`:

```php
public function platform()
{
    return $this->belongsTo(\Modules\Wallet\Models\WalletPlatform::class, 'platform_id');
}

public function user()
{
    return $this->belongsTo(\App\Models\User::class);
}
```

---

## Notes for Backend Developer

1. **Wallet Selection:** The page shows the primary wallet first. If user has multiple wallets, show the one marked as `is_primary = true`
2. **Total Points:** This is the sum of ALL coin transactions (positive and negative). The `balance_after` field in each coin record can also be used.
3. **Point History:** Shows all coin transactions, not just game rewards. Each transaction should have proper source labels.
4. **Search Feature:** Client-side search is implemented in the view for simple filtering
5. **Pagination:** Supports 10, 25, 50, 100 rows per page
6. **Game Relations:** Only load game relation when source is 'game_reward'
7. **Wallet Address Display:** Should show the actual wallet address (e.g., "2109076542" for exchange, or full blockchain address for web3)
8. **Empty States:** View handles empty wallet and empty history gracefully

---

## Sample Database Query Flow

```sql
-- 1. Get connected wallet
SELECT w.*, wp.name as platform_name
FROM wallets w
JOIN wallet_platforms wp ON w.platform_id = wp.id
WHERE w.user_id = :user_id 
  AND w.is_primary = TRUE
  AND w.deleted_at IS NULL
LIMIT 1;

-- 2. Get total points
SELECT SUM(amount) as total_points
FROM coins
WHERE user_id = :user_id;

-- 3. Get point history (paginated)
SELECT c.*, g.name as game_name
FROM coins c
LEFT JOIN game_sessions gs ON c.reference_type = 'game_sessions' 
  AND c.reference_id = gs.id
LEFT JOIN games g ON gs.game_id = g.id
WHERE c.user_id = :user_id
ORDER BY c.created_at DESC
LIMIT 10 OFFSET 0;
```

---

**Last Updated:** January 8, 2026
