Commit 367e98e5 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: align all code to actual Supabase DB schema

Table renames: transactions→economy_transactions, organizations→el3ab_organizations
Column fixes: user_id→player_id, last_active_at→last_seen_at, reported_id→reported_player_id,
organizer_id→created_by, actor→actor_id, entity_type→resource_type, entity_id→resource_id
Schema match: economy_transactions uses type credit/debit + reason + source_id,
audit_log uses actor_id/resource_type/resource_id/details,
org_members uses player_id, ad_campaigns uses spent_total.
Created admin_users, approval_requests, workflow_rules tables on server.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 080ac7e2
......@@ -2,16 +2,19 @@
class AuditLog
{
public static function log(string $action, string $entityType, ?string $entityId = null, ?array $oldValue = null, ?array $newValue = null): void
public static function log(string $action, string $resourceType, ?string $resourceId = null, ?array $oldValue = null, ?array $newValue = null): void
{
$db = Database::getInstance();
$details = [];
if ($oldValue !== null) $details['old'] = $oldValue;
if ($newValue !== null) $details['new'] = $newValue;
$db->insert('audit_log', [
'actor' => Auth::user()['username'] ?? 'system',
'actor_id' => Auth::user()['id'] ?? null,
'action' => $action,
'entity_type' => $entityType,
'entity_id' => $entityId,
'old_value' => $oldValue ? json_encode($oldValue) : null,
'new_value' => $newValue ? json_encode($newValue) : null,
'resource_type' => $resourceType,
'resource_id' => $resourceId,
'details' => !empty($details) ? json_encode($details) : '{}',
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
]);
}
......
......@@ -25,7 +25,11 @@ class Database
$query = http_build_query($params);
$url = "{$this->baseUrl}/{$table}" . ($query ? "?{$query}" : '');
$response = $this->request('GET', $url, null, $headers);
return json_decode($response['body'], true) ?? [];
$result = json_decode($response['body'], true) ?? [];
if (!is_array($result) || (isset($result['message']) && !isset($result[0]))) {
return [];
}
return $result;
}
public function selectOne(string $table, array $params = []): ?array
......@@ -121,6 +125,10 @@ class Database
}
$response = curl_exec($ch);
if ($response === false) {
curl_close($ch);
return ['status' => 0, 'body' => '', 'headers' => []];
}
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$headerStr = substr($response, 0, $headerSize);
......
......@@ -81,12 +81,12 @@ class View
return MODULES_PATH . "/{$view}.php";
}
public static function escape(string $value): string
public static function escape(?string $value): string
{
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8');
}
public static function e(string $value): string
public static function e(?string $value): string
{
return self::escape($value);
}
......
......@@ -16,8 +16,8 @@ $isCharity = ($role === 'charity');
$isViewer = ($role === 'viewer');
$db = Database::getInstance();
$pendingReports = $db->count('cheat_reports', ['status' => 'eq.pending']);
$pendingWorkflows = $isAdmin ? $db->count('approval_requests', ['status' => 'eq.pending']) : 0;
try { $pendingReports = $db->count('cheat_reports', ['status' => 'eq.pending']); } catch (\Throwable $e) { $pendingReports = 0; }
try { $pendingWorkflows = $isAdmin ? $db->count('approval_requests', ['status' => 'eq.pending']) : 0; } catch (\Throwable $e) { $pendingWorkflows = 0; }
?>
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
......
......@@ -24,7 +24,7 @@ class AnalyticsController
$newPlayers = $this->db->count('profiles', ['created_at' => "gte.{$dateFilter}"]);
$newMatches = $this->db->count('matches', ['created_at' => "gte.{$dateFilter}"]);
$totalPlayers = $this->db->count('profiles', []);
$activePlayers = $this->db->count('profiles', ['last_active_at' => "gte." . date('Y-m-d', strtotime('-7 days')) . 'T00:00:00']);
$activePlayers = $this->db->count('profiles', ['last_seen_at' => "gte." . date('Y-m-d', strtotime('-7 days')) . 'T00:00:00']);
$retention = $totalPlayers > 0 ? round(($activePlayers / $totalPlayers) * 100, 1) : 0;
......
......@@ -14,16 +14,16 @@ class AuditLogController
$queryParams = ['select' => '*', 'order' => 'created_at.desc'];
if (!empty($_GET['actor'])) {
$queryParams['actor'] = "eq." . $_GET['actor'];
$queryParams['actor_id'] = "eq." . $_GET['actor'];
}
if (!empty($_GET['action'])) {
$queryParams['action'] = "eq." . $_GET['action'];
}
if (!empty($_GET['entity_type'])) {
$queryParams['entity_type'] = "eq." . $_GET['entity_type'];
if (!empty($_GET['resource_type'])) {
$queryParams['resource_type'] = "eq." . $_GET['resource_type'];
}
if (!empty($_GET['search'])) {
$queryParams['entity_id'] = "eq." . $_GET['search'];
$queryParams['resource_id'] = "eq." . $_GET['search'];
}
$countParams = $queryParams;
......@@ -61,10 +61,10 @@ class AuditLogController
foreach ($logs as $log) {
fputcsv($output, [
$log['created_at'],
$log['actor'],
$log['actor_id'] ?? '',
$log['action'],
$log['entity_type'],
$log['entity_id'] ?? '',
$log['resource_type'],
$log['resource_id'] ?? '',
$log['ip_address'] ?? '',
]);
}
......
......@@ -13,14 +13,14 @@
<input type="text" placeholder="بحث بالمعرف..." value="<?= View::e($_GET['search'] ?? '') ?>" onchange="location.href='/audit-log?search='+this.value">
</div>
<div class="flex gap-2">
<select class="form-select" style="width: auto; font-size: 12px;" onchange="location.href='/audit-log?entity_type='+this.value">
<select class="form-select" style="width: auto; font-size: 12px;" onchange="location.href='/audit-log?resource_type='+this.value">
<option value="">كل الأنواع</option>
<option value="player" <?= ($_GET['entity_type'] ?? '') === 'player' ? 'selected' : '' ?>>لاعب</option>
<option value="game" <?= ($_GET['entity_type'] ?? '') === 'game' ? 'selected' : '' ?>>لعبة</option>
<option value="tournament" <?= ($_GET['entity_type'] ?? '') === 'tournament' ? 'selected' : '' ?>>بطولة</option>
<option value="report" <?= ($_GET['entity_type'] ?? '') === 'report' ? 'selected' : '' ?>>بلاغ</option>
<option value="feature_flag" <?= ($_GET['entity_type'] ?? '') === 'feature_flag' ? 'selected' : '' ?>>ميزة</option>
<option value="system_config" <?= ($_GET['entity_type'] ?? '') === 'system_config' ? 'selected' : '' ?>>إعداد</option>
<option value="player" <?= ($_GET['resource_type'] ?? '') === 'player' ? 'selected' : '' ?>>لاعب</option>
<option value="game" <?= ($_GET['resource_type'] ?? '') === 'game' ? 'selected' : '' ?>>لعبة</option>
<option value="tournament" <?= ($_GET['resource_type'] ?? '') === 'tournament' ? 'selected' : '' ?>>بطولة</option>
<option value="report" <?= ($_GET['resource_type'] ?? '') === 'report' ? 'selected' : '' ?>>بلاغ</option>
<option value="feature_flag" <?= ($_GET['resource_type'] ?? '') === 'feature_flag' ? 'selected' : '' ?>>ميزة</option>
<option value="system_config" <?= ($_GET['resource_type'] ?? '') === 'system_config' ? 'selected' : '' ?>>إعداد</option>
</select>
</div>
</div>
......@@ -44,17 +44,17 @@
<?php foreach ($logs as $log): ?>
<tr>
<td class="text-xs tabular-nums text-muted"><?= date('m/d H:i:s', strtotime($log['created_at'])) ?></td>
<td class="font-medium"><?= View::e($log['actor']) ?></td>
<td class="font-medium"><?= View::e($log['actor_id'] ?? '-') ?></td>
<td>
<?php
$actionColors = ['create' => 'success', 'update' => 'info', 'delete' => 'danger', 'ban' => 'danger', 'unban' => 'success', 'toggle' => 'warning', 'grant' => 'success', 'revoke' => 'danger'];
?>
<span class="badge badge-<?= $actionColors[$log['action']] ?? 'default' ?>"><?= View::e($log['action']) ?></span>
</td>
<td class="text-sm"><?= View::e($log['entity_type']) ?></td>
<td class="text-xs text-muted truncate" style="max-width: 100px;"><?= View::e($log['entity_id'] ?? '-') ?></td>
<td class="text-sm"><?= View::e($log['resource_type'] ?? '') ?></td>
<td class="text-xs text-muted truncate" style="max-width: 100px;"><?= View::e($log['resource_id'] ?? '-') ?></td>
<td>
<?php if ($log['new_value'] || $log['old_value']): ?>
<?php if (!empty($log['details']) && $log['details'] !== '{}'): ?>
<button class="btn btn-ghost btn-sm" onclick='showLogDetail(<?= htmlspecialchars(json_encode($log), ENT_QUOTES) ?>)'>عرض</button>
<?php else: ?>
<span class="text-muted">-</span>
......@@ -69,7 +69,7 @@
<span><?= $pagination->rangeText() ?></span>
<div class="pagination">
<?php foreach ($pagination->pages() as $p): ?>
<a href="?page=<?= $p ?>&entity_type=<?= $_GET['entity_type'] ?? '' ?>&search=<?= $_GET['search'] ?? '' ?>" class="pagination-btn <?= $p === $pagination->page ? 'active' : '' ?>"><?= $p ?></a>
<a href="?page=<?= $p ?>&resource_type=<?= $_GET['resource_type'] ?? '' ?>&search=<?= $_GET['search'] ?? '' ?>" class="pagination-btn <?= $p === $pagination->page ? 'active' : '' ?>"><?= $p ?></a>
<?php endforeach; ?>
</div>
</div>
......
......@@ -61,7 +61,7 @@
<div class="bot-card-header">
<div class="bot-portrait">
<?php if (!empty($bot['portrait_url'])): ?>
<img src="<?= View::e($bot['portrait_url']) ?>" alt="<?= View::e($bot['name']) ?>">
<img src="<?= View::e($bot['portrait_url'] ?? '') ?>" alt="<?= View::e($bot['name'] ?? '') ?>">
<?php else: ?>
<div class="bot-portrait-placeholder">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 2a3 3 0 0 0-3 3v1a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z"/><path d="M19 10H5a2 2 0 0 0-2 2v1a7 7 0 0 0 14 0v-1a2 2 0 0 0-2-2z"/><line x1="12" y1="18" x2="12" y2="22"/></svg>
......@@ -69,8 +69,8 @@
<?php endif; ?>
</div>
<div class="bot-card-info">
<h3 class="bot-card-name"><?= View::e($bot['name_ar'] ?? $bot['name']) ?></h3>
<p class="bot-card-name-en"><?= View::e($bot['name']) ?></p>
<h3 class="bot-card-name"><?= View::e($bot['name_ar'] ?? $bot['name'] ?? 'بوت') ?></h3>
<p class="bot-card-name-en"><?= View::e($bot['name'] ?? $bot['id'] ?? '') ?></p>
<span class="badge badge-info"><?= View::e($bot['style_ar'] ?? $bot['style'] ?? '') ?></span>
</div>
</div>
......
......@@ -62,7 +62,7 @@ class DashboardController
$pendingReports = $db->count('cheat_reports', ['status' => 'eq.pending']);
$totalAdminUsers = $db->count('admin_users', []);
$pendingApprovals = $db->count('admin_users', ['status' => 'eq.pending']);
$pendingApprovals = $db->count('approval_requests', ['status' => 'eq.pending']);
$recentActivity = $db->select('audit_log', [
'select' => '*',
......@@ -99,7 +99,7 @@ class DashboardController
$recentActions = $db->select('audit_log', [
'select' => '*',
'actor' => 'eq.' . Auth::user()['username'],
'actor_id' => 'eq.' . Auth::user()['id'],
'order' => 'created_at.desc',
'limit' => 10,
]);
......@@ -114,14 +114,13 @@ class DashboardController
{
$orgFilters = ['org_id' => 'eq.' . $orgId];
$orgInfo = $db->selectOne('organizations', ['id' => 'eq.' . $orgId]);
$orgInfo = $db->selectOne('el3ab_organizations', ['id' => 'eq.' . $orgId]);
$membersCount = $db->count('org_members', $orgFilters);
$tournamentsCount = $db->count('el3ab_tournaments', $orgFilters);
$activeMatches = $db->count('matches', array_merge($orgFilters, ['status' => 'eq.in_progress']));
$activeMatches = $db->count('matches', ['status' => 'eq.in_progress']);
$recentActivity = $db->select('audit_log', [
'select' => '*',
'org_id' => 'eq.' . $orgId,
'order' => 'created_at.desc',
'limit' => 10,
]);
......@@ -136,29 +135,29 @@ class DashboardController
$userId = Auth::user()['username'];
$activeTournaments = $db->count('el3ab_tournaments', [
'organizer_id' => 'eq.' . $userId,
'created_by' => 'eq.' . $userId,
'status' => 'eq.in_progress',
]);
$completedTournaments = $db->count('el3ab_tournaments', [
'organizer_id' => 'eq.' . $userId,
'created_by' => 'eq.' . $userId,
'status' => 'eq.completed',
]);
$totalTournaments = $db->count('el3ab_tournaments', [
'organizer_id' => 'eq.' . $userId,
'created_by' => 'eq.' . $userId,
]);
$myTournaments = $db->select('el3ab_tournaments', [
'select' => '*',
'organizer_id' => 'eq.' . $userId,
'created_by' => 'eq.' . $userId,
'order' => 'created_at.desc',
'limit' => 5,
]);
$totalParticipants = 0;
foreach ($myTournaments as $t) {
$totalParticipants += (int) ($t['participants_count'] ?? 0);
$totalParticipants += $db->count('tournament_registrations', ['tournament_id' => 'eq.' . $t['id']]);
}
return compact(
......@@ -190,8 +189,8 @@ class DashboardController
$totalImpressions = 0;
$totalSpend = 0;
foreach ($campaigns as $c) {
$totalImpressions += (int) ($c['impressions'] ?? 0);
$totalSpend += (float) ($c['spend'] ?? 0);
$totalImpressions += $db->count('ad_impressions', ['campaign_id' => 'eq.' . $c['id']]);
$totalSpend += (int) ($c['spent_total'] ?? 0);
}
return compact(
......@@ -222,8 +221,8 @@ class DashboardController
$totalDonations = 0;
$totalParticipants = 0;
foreach ($tournaments as $t) {
$totalDonations += (float) ($t['donation_amount'] ?? 0);
$totalParticipants += (int) ($t['participants_count'] ?? 0);
$totalDonations += (float) ($t['charity_percent'] ?? 0);
$totalParticipants += $db->count('tournament_registrations', ['tournament_id' => 'eq.' . $t['id']]);
}
return compact(
......
......@@ -145,10 +145,10 @@
<?php foreach ($recentActivity as $activity): ?>
<tr>
<td class="text-muted text-xs tabular-nums"><?= date('Y-m-d H:i', strtotime($activity['created_at'])) ?></td>
<td><?= View::e($activity['actor']) ?></td>
<td><?= View::e($activity['actor_id'] ?? '-') ?></td>
<td><span class="badge badge-info"><?= View::e($activity['action']) ?></span></td>
<td><?= View::e($activity['entity_type']) ?></td>
<td class="text-xs text-muted truncate" style="max-width: 120px;"><?= View::e($activity['entity_id'] ?? '-') ?></td>
<td><?= View::e($activity['resource_type'] ?? '') ?></td>
<td class="text-xs text-muted truncate" style="max-width: 120px;"><?= View::e($activity['resource_id'] ?? '-') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
......@@ -225,8 +225,8 @@
<?php foreach ($recentReports as $report): ?>
<tr>
<td class="text-muted text-xs tabular-nums"><?= date('Y-m-d H:i', strtotime($report['created_at'])) ?></td>
<td><?= View::e($report['reporter_id'] ?? '-') ?></td>
<td><?= View::e($report['reported_id'] ?? '-') ?></td>
<td><?= View::e($report['reported_by'] ?? '-') ?></td>
<td><?= View::e($report['reported_player_id'] ?? '-') ?></td>
<td><?= View::e($report['reason'] ?? '-') ?></td>
<td><span class="badge badge-<?= $report['status'] === 'pending' ? 'warning' : 'success' ?>"><?= View::e($report['status']) ?></span></td>
</tr>
......@@ -262,8 +262,8 @@
<tr>
<td class="text-muted text-xs tabular-nums"><?= date('Y-m-d H:i', strtotime($action['created_at'])) ?></td>
<td><span class="badge badge-info"><?= View::e($action['action']) ?></span></td>
<td><?= View::e($action['entity_type']) ?></td>
<td class="text-xs text-muted truncate" style="max-width: 120px;"><?= View::e($action['entity_id'] ?? '-') ?></td>
<td><?= View::e($action['resource_type'] ?? '') ?></td>
<td class="text-xs text-muted truncate" style="max-width: 120px;"><?= View::e($action['resource_id'] ?? '-') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
......@@ -340,10 +340,10 @@
<?php foreach ($recentActivity as $activity): ?>
<tr>
<td class="text-muted text-xs tabular-nums"><?= date('Y-m-d H:i', strtotime($activity['created_at'])) ?></td>
<td><?= View::e($activity['actor']) ?></td>
<td><?= View::e($activity['actor_id'] ?? '-') ?></td>
<td><span class="badge badge-info"><?= View::e($activity['action']) ?></span></td>
<td><?= View::e($activity['entity_type']) ?></td>
<td class="text-xs text-muted truncate" style="max-width: 120px;"><?= View::e($activity['entity_id'] ?? '-') ?></td>
<td><?= View::e($activity['resource_type'] ?? '') ?></td>
<td class="text-xs text-muted truncate" style="max-width: 120px;"><?= View::e($activity['resource_id'] ?? '-') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
......
......@@ -20,17 +20,17 @@ class EconomyController
$totalGems += ($p['gems'] ?? 0);
}
$todayEarned = $this->db->count('transactions', [
'type' => 'eq.earn',
$todayEarned = $this->db->count('economy_transactions', [
'type' => 'eq.credit',
'created_at' => 'gte.' . date('Y-m-d') . 'T00:00:00',
]);
$todaySpent = $this->db->count('transactions', [
'type' => 'eq.spend',
$todaySpent = $this->db->count('economy_transactions', [
'type' => 'eq.debit',
'created_at' => 'gte.' . date('Y-m-d') . 'T00:00:00',
]);
$recentTransactions = $this->db->select('transactions', [
$recentTransactions = $this->db->select('economy_transactions', [
'select' => '*',
'order' => 'created_at.desc',
'limit' => 20,
......@@ -52,16 +52,16 @@ class EconomyController
if (!empty($_GET['type'])) {
$queryParams['type'] = 'eq.' . $_GET['type'];
}
if (!empty($_GET['user_id'])) {
$queryParams['user_id'] = 'eq.' . $_GET['user_id'];
if (!empty($_GET['player_id'])) {
$queryParams['player_id'] = 'eq.' . $_GET['player_id'];
}
$total = $this->db->count('transactions', array_diff_key($queryParams, ['select' => 1, 'order' => 1]));
$total = $this->db->count('economy_transactions', array_diff_key($queryParams, ['select' => 1, 'order' => 1]));
$pagination = Pagination::fromRequest($total);
$queryParams['offset'] = $pagination->offset;
$queryParams['limit'] = $pagination->perPage;
$transactions = $this->db->select('transactions', $queryParams);
$transactions = $this->db->select('economy_transactions', $queryParams);
$pageTitle = 'المعاملات';
$moduleCSS = 'economy';
......@@ -93,14 +93,14 @@ class EconomyController
$newBalance = ($player[$currency] ?? 0) + $amount;
$this->db->update('profiles', ['id' => "eq.{$userId}"], [$currency => $newBalance]);
$this->db->insert('transactions', [
'user_id' => $userId,
'type' => 'admin_grant',
$this->db->insert('economy_transactions', [
'player_id' => $userId,
'type' => 'credit',
'currency' => $currency,
'amount' => $amount,
'balance_after' => $newBalance,
'description' => trim($_POST['reason'] ?? 'منح بواسطة الإدارة'),
'created_by' => Auth::user()['username'],
'reason' => trim($_POST['reason'] ?? 'منح بواسطة الإدارة'),
'source_id' => 'admin:' . Auth::user()['username'],
]);
AuditLog::log('grant', 'economy', $userId, null, ['currency' => $currency, 'amount' => $amount]);
......@@ -133,14 +133,14 @@ class EconomyController
$newBalance = $currentBalance - $amount;
$this->db->update('profiles', ['id' => "eq.{$userId}"], [$currency => $newBalance]);
$this->db->insert('transactions', [
'user_id' => $userId,
'type' => 'admin_revoke',
$this->db->insert('economy_transactions', [
'player_id' => $userId,
'type' => 'debit',
'currency' => $currency,
'amount' => -$amount,
'balance_after' => $newBalance,
'description' => trim($_POST['reason'] ?? 'سحب بواسطة الإدارة'),
'created_by' => Auth::user()['username'],
'reason' => trim($_POST['reason'] ?? 'سحب بواسطة الإدارة'),
'source_id' => 'admin:' . Auth::user()['username'],
]);
AuditLog::log('revoke', 'economy', $userId, null, ['currency' => $currency, 'amount' => $amount]);
......@@ -168,14 +168,14 @@ class EconomyController
$newBalance = ($player[$currency] ?? 0) + $amount;
$this->db->update('profiles', ['id' => "eq.{$userId}"], [$currency => $newBalance]);
$this->db->insert('transactions', [
'user_id' => $userId,
'type' => 'admin_grant',
$this->db->insert('economy_transactions', [
'player_id' => $userId,
'type' => 'credit',
'currency' => $currency,
'amount' => $amount,
'balance_after' => $newBalance,
'description' => 'منح جماعي',
'created_by' => Auth::user()['username'],
'reason' => 'منح جماعي',
'source_id' => 'admin:' . Auth::user()['username'],
]);
$count++;
}
......
......@@ -46,8 +46,8 @@ class ModerationController
return;
}
$reported = $this->db->selectOne('profiles', ['id' => "eq.{$report['reported_id']}"]);
$reporter = $report['reporter_id'] ? $this->db->selectOne('profiles', ['id' => "eq.{$report['reporter_id']}"]) : null;
$reported = $this->db->selectOne('profiles', ['id' => "eq.{$report['reported_player_id']}"]);
$reporter = !empty($report['reported_by']) ? $this->db->selectOne('profiles', ['id' => "eq.{$report['reported_by']}"]) : null;
if ($report['status'] === 'pending') {
$this->db->update('cheat_reports', ['id' => "eq.{$id}"], ['status' => 'reviewing']);
......
......@@ -37,7 +37,7 @@
<?php foreach ($reports as $report): ?>
<tr>
<td><input type="checkbox" class="row-check" value="<?= $report['id'] ?>"></td>
<td class="text-xs"><?= View::e(substr($report['reported_id'], 0, 8)) ?>...</td>
<td class="text-xs"><?= View::e(substr($report['reported_player_id'] ?? '', 0, 8)) ?>...</td>
<td>
<?php
$reasons = ['cheating' => 'غش', 'harassment' => 'تحرش', 'inappropriate_name' => 'اسم غير لائق', 'spam' => 'إزعاج', 'other' => 'أخرى'];
......
......@@ -30,25 +30,25 @@ class OrganizationsController
$countParams = $queryParams;
unset($countParams['select'], $countParams['order']);
$total = $this->db->count('organizations', $countParams);
$total = $this->db->count('el3ab_organizations', $countParams);
$pagination = Pagination::fromRequest($total);
$queryParams['offset'] = $pagination->offset;
$queryParams['limit'] = $pagination->perPage;
$organizations = $this->db->select('organizations', $queryParams);
$organizations = $this->db->select('el3ab_organizations', $queryParams);
$pageTitle = 'المنظمات';
$moduleCSS = 'organizations';
$moduleJS = 'organizations';
$moduleCSS = 'el3ab_organizations';
$moduleJS = 'el3ab_organizations';
View::render('organizations/list', compact('organizations', 'pagination', 'search', 'sort', 'dir', 'filter', 'pageTitle', 'moduleCSS', 'moduleJS'));
View::render('organizations/list', compact('el3ab_organizations', 'pagination', 'search', 'sort', 'dir', 'filter', 'pageTitle', 'moduleCSS', 'moduleJS'));
}
public function show(array $params, string $method): void
{
$id = $params['id'];
$org = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$org = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$org) {
http_response_code(404);
......@@ -62,7 +62,7 @@ class OrganizationsController
'order' => 'joined_at.desc',
]);
$tournaments = $this->db->select('tournaments', [
$tournaments = $this->db->select('el3ab_tournaments', [
'select' => '*',
'org_id' => "eq.{$id}",
'order' => 'created_at.desc',
......@@ -70,8 +70,8 @@ class OrganizationsController
]);
$pageTitle = $org['name_ar'] ?? $org['name'];
$moduleCSS = 'organizations';
$moduleJS = 'organizations';
$moduleCSS = 'el3ab_organizations';
$moduleJS = 'el3ab_organizations';
View::render('organizations/show', compact('org', 'members', 'tournaments', 'pageTitle', 'moduleCSS', 'moduleJS'));
}
......@@ -80,7 +80,7 @@ class OrganizationsController
{
$pageTitle = 'إنشاء منظمة';
$org = [];
$moduleCSS = 'organizations';
$moduleCSS = 'el3ab_organizations';
View::render('organizations/form', compact('org', 'pageTitle', 'moduleCSS'));
}
......@@ -118,7 +118,7 @@ class OrganizationsController
$data['logo_url'] = $this->uploadLogo($_FILES['logo']);
}
$result = $this->db->insert('organizations', $data);
$result = $this->db->insert('el3ab_organizations', $data);
AuditLog::log('create', 'organization', $result['id'] ?? null, null, $data);
Response::success('تم إنشاء المنظمة بنجاح', '/organizations');
}
......@@ -126,7 +126,7 @@ class OrganizationsController
public function edit(array $params, string $method): void
{
$id = $params['id'];
$org = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$org = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$org) {
http_response_code(404);
......@@ -135,7 +135,7 @@ class OrganizationsController
}
$pageTitle = 'تعديل المنظمة';
$moduleCSS = 'organizations';
$moduleCSS = 'el3ab_organizations';
View::render('organizations/form', compact('org', 'pageTitle', 'moduleCSS'));
}
......@@ -144,7 +144,7 @@ class OrganizationsController
Auth::requireCsrf();
$id = $params['id'];
$old = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$old = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$old) {
Response::error('المنظمة غير موجودة', '/organizations');
return;
......@@ -167,7 +167,7 @@ class OrganizationsController
$data['logo_url'] = $this->uploadLogo($_FILES['logo']);
}
$this->db->update('organizations', ['id' => "eq.{$id}"], $data);
$this->db->update('el3ab_organizations', ['id' => "eq.{$id}"], $data);
AuditLog::log('update', 'organization', $id, $old, $data);
Response::success('تم تحديث بيانات المنظمة', "/organizations/{$id}");
}
......@@ -177,7 +177,7 @@ class OrganizationsController
Auth::requireCsrf();
$id = $params['id'];
$old = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$old = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$old) {
Response::error('المنظمة غير موجودة', '/organizations');
return;
......@@ -185,11 +185,9 @@ class OrganizationsController
$data = [
'is_verified' => true,
'verified_at' => date('c'),
'verified_by' => Auth::user()['username'],
];
$this->db->update('organizations', ['id' => "eq.{$id}"], $data);
$this->db->update('el3ab_organizations', ['id' => "eq.{$id}"], $data);
AuditLog::log('verify', 'organization', $id, $old, $data);
Response::success('تم توثيق المنظمة بنجاح', "/organizations/{$id}");
}
......@@ -200,15 +198,14 @@ class OrganizationsController
Auth::requireRole('admin');
$id = $params['id'];
$old = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$old = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$old) {
Response::error('المنظمة غير موجودة', '/organizations');
return;
}
$this->db->update('organizations', ['id' => "eq.{$id}"], [
$this->db->update('el3ab_organizations', ['id' => "eq.{$id}"], [
'is_active' => false,
'deleted_at' => date('c'),
]);
AuditLog::log('delete', 'organization', $id, $old);
......@@ -218,7 +215,7 @@ class OrganizationsController
public function members(array $params, string $method): void
{
$id = $params['id'];
$org = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$org = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$org) {
http_response_code(404);
......@@ -233,8 +230,8 @@ class OrganizationsController
]);
$pageTitle = 'أعضاء ' . ($org['name_ar'] ?? $org['name']);
$moduleCSS = 'organizations';
$moduleJS = 'organizations';
$moduleCSS = 'el3ab_organizations';
$moduleJS = 'el3ab_organizations';
View::render('organizations/show', compact('org', 'members', 'pageTitle', 'moduleCSS', 'moduleJS'));
}
......@@ -244,7 +241,7 @@ class OrganizationsController
Auth::requireCsrf();
$id = $params['id'];
$org = $this->db->selectOne('organizations', ['id' => "eq.{$id}"]);
$org = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$id}"]);
if (!$org) {
Response::error('المنظمة غير موجودة', '/organizations');
return;
......@@ -260,7 +257,7 @@ class OrganizationsController
$existing = $this->db->selectOne('org_members', [
'org_id' => "eq.{$id}",
'user_id' => "eq.{$userId}",
'player_id' => "eq.{$userId}",
]);
if ($existing) {
......@@ -270,9 +267,8 @@ class OrganizationsController
$data = [
'org_id' => $id,
'user_id' => $userId,
'player_id' => $userId,
'role' => $role,
'joined_at' => date('c'),
];
$this->db->insert('org_members', $data);
......
......@@ -246,8 +246,8 @@
?>
<span class="badge <?= $statusBadge[$tStatus] ?? 'badge-default' ?>"><?= $statusLabels[$tStatus] ?? $tStatus ?></span>
</td>
<td class="tabular-nums"><?= $tournament['participants_count'] ?? 0 ?></td>
<td class="text-xs tabular-nums"><?= !empty($tournament['start_date']) ? date('Y-m-d', strtotime($tournament['start_date'])) : '-' ?></td>
<td class="tabular-nums"><?= $tournament['max_players'] ?? 0 ?></td>
<td class="text-xs tabular-nums"><?= !empty($tournament['starts_at']) ? date('Y-m-d', strtotime($tournament['starts_at'])) : '-' ?></td>
</tr>
<?php endforeach; ?>
</tbody>
......
......@@ -63,16 +63,16 @@ class PlayersController
'limit' => 20,
]);
$transactions = $this->db->select('transactions', [
$transactions = $this->db->select('economy_transactions', [
'select' => '*',
'user_id' => "eq.{$id}",
'player_id' => "eq.{$id}",
'order' => 'created_at.desc',
'limit' => 20,
]);
$reports = $this->db->select('cheat_reports', [
'select' => '*',
'reported_id' => "eq.{$id}",
'reported_player_id' => "eq.{$id}",
'order' => 'created_at.desc',
]);
......@@ -80,7 +80,7 @@ class PlayersController
$moduleCSS = 'players';
$moduleJS = 'players';
View::render('players/show', compact('player', 'matches', 'transactions', 'reports', 'pageTitle', 'moduleCSS', 'moduleJS'));
View::render('players/show', compact('player', 'matches', 'economy_transactions', 'reports', 'pageTitle', 'moduleCSS', 'moduleJS'));
}
public function create(array $params, string $method): void
......@@ -231,14 +231,14 @@ class PlayersController
$newBalance = ($player[$currency] ?? 0) + $amount;
$this->db->update('profiles', ['id' => "eq.{$id}"], [$currency => $newBalance]);
$this->db->insert('transactions', [
'user_id' => $id,
'type' => 'admin_grant',
$this->db->insert('economy_transactions', [
'player_id' => $id,
'type' => 'credit',
'currency' => $currency,
'amount' => $amount,
'balance_after' => $newBalance,
'description' => trim($_POST['reason'] ?? 'منح بواسطة الإدارة'),
'created_by' => Auth::user()['username'],
'reason' => trim($_POST['reason'] ?? 'منح بواسطة الإدارة'),
'source_id' => 'admin:' . Auth::user()['username'],
]);
AuditLog::log('grant', 'player', $id, null, ['currency' => $currency, 'amount' => $amount]);
......@@ -267,14 +267,14 @@ class PlayersController
$newBalance = $currentBalance - $amount;
$this->db->update('profiles', ['id' => "eq.{$id}"], [$currency => $newBalance]);
$this->db->insert('transactions', [
'user_id' => $id,
'type' => 'admin_revoke',
$this->db->insert('economy_transactions', [
'player_id' => $id,
'type' => 'debit',
'currency' => $currency,
'amount' => -$amount,
'balance_after' => $newBalance,
'description' => trim($_POST['reason'] ?? 'سحب بواسطة الإدارة'),
'created_by' => Auth::user()['username'],
'reason' => trim($_POST['reason'] ?? 'سحب بواسطة الإدارة'),
'source_id' => 'admin:' . Auth::user()['username'],
]);
AuditLog::log('revoke', 'player', $id, null, ['currency' => $currency, 'amount' => $amount]);
......
......@@ -53,7 +53,7 @@
<th data-sort="level">المستوى</th>
<th data-sort="coins">العملات</th>
<th>الحالة</th>
<th data-sort="last_active_at">آخر نشاط</th>
<th data-sort="last_seen_at">آخر نشاط</th>
<th style="width: 60px;">الإجراءات</th>
</tr>
</thead>
......@@ -88,7 +88,7 @@
<?php endif; ?>
</td>
<td class="text-xs text-muted tabular-nums">
<?= $player['last_active_at'] ? date('m/d H:i', strtotime($player['last_active_at'])) : '-' ?>
<?= !empty($player['last_seen_at']) ? date('m/d H:i', strtotime($player['last_seen_at'])) : '-' ?>
</td>
<td>
<div class="dropdown">
......
......@@ -106,7 +106,7 @@
<div class="flex justify-between"><span class="text-secondary">الدولة</span><span><?= View::e($player['country_code'] ?? '-') ?></span></div>
<div class="flex justify-between"><span class="text-secondary">المدينة</span><span><?= View::e($player['city'] ?? '-') ?></span></div>
<div class="flex justify-between"><span class="text-secondary">تاريخ الانضمام</span><span class="tabular-nums"><?= $player['created_at'] ? date('Y-m-d', strtotime($player['created_at'])) : '-' ?></span></div>
<div class="flex justify-between"><span class="text-secondary">آخر نشاط</span><span class="tabular-nums"><?= $player['last_active_at'] ? date('Y-m-d H:i', strtotime($player['last_active_at'])) : '-' ?></span></div>
<div class="flex justify-between"><span class="text-secondary">آخر نشاط</span><span class="tabular-nums"><?= $player['last_seen_at'] ? date('Y-m-d H:i', strtotime($player['last_seen_at'])) : '-' ?></span></div>
</div>
</div>
</div>
......
......@@ -59,7 +59,7 @@ class UsersController
$users = $this->db->select('admin_users', $queryParams);
// Fetch organizations for filter dropdown
$organizations = $this->db->select('organizations', ['select' => 'id,name', 'order' => 'name.asc']);
$organizations = $this->db->select('el3ab_organizations', ['select' => 'id,name', 'order' => 'name.asc']);
$pageTitle = 'المستخدمون';
$moduleCSS = 'users';
......@@ -75,7 +75,7 @@ class UsersController
{
Auth::requireRole('admin');
$organizations = $this->db->select('organizations', ['select' => 'id,name', 'order' => 'name.asc']);
$organizations = $this->db->select('el3ab_organizations', ['select' => 'id,name', 'order' => 'name.asc']);
$user = [];
$pageTitle = 'إضافة مستخدم';
$moduleCSS = 'users';
......@@ -157,19 +157,19 @@ class UsersController
// Fetch organization info if user has one
$organization = null;
if (!empty($user['org_id'])) {
$organization = $this->db->selectOne('organizations', ['id' => "eq.{$user['org_id']}"]);
$organization = $this->db->selectOne('el3ab_organizations', ['id' => "eq.{$user['org_id']}"]);
}
// Activity log for this user
$activities = $this->db->select('audit_log', [
'select' => '*',
'actor' => "eq.{$user['username']}",
'actor_id' => "eq.{$user['id']}",
'order' => 'created_at.desc',
'limit' => 50,
]);
// Count stats
$actionsCount = $this->db->count('audit_log', ['actor' => "eq.{$user['username']}"]);
$actionsCount = $this->db->count('audit_log', ['actor_id' => "eq.{$user['id']}"]);
$pageTitle = $user['display_name'] ?? $user['username'];
$moduleCSS = 'users';
......@@ -194,7 +194,7 @@ class UsersController
return;
}
$organizations = $this->db->select('organizations', ['select' => 'id,name', 'order' => 'name.asc']);
$organizations = $this->db->select('el3ab_organizations', ['select' => 'id,name', 'order' => 'name.asc']);
$pageTitle = 'تعديل المستخدم';
$moduleCSS = 'users';
$moduleJS = 'users';
......
......@@ -168,8 +168,8 @@ $roleBadgeColors = [
<?php foreach ($activities as $activity): ?>
<tr>
<td><span class="badge badge-info"><?= View::e($activity['action']) ?></span></td>
<td class="text-sm"><?= View::e($activity['entity_type'] ?? '-') ?></td>
<td class="text-xs text-muted tabular-nums"><?= View::e(substr($activity['entity_id'] ?? '-', 0, 8)) ?></td>
<td class="text-sm"><?= View::e($activity['resource_type'] ?? '-') ?></td>
<td class="text-xs text-muted tabular-nums"><?= View::e(substr($activity['resource_id'] ?? '-', 0, 8)) ?></td>
<td class="text-xs text-muted tabular-nums" dir="ltr" style="text-align: right;"><?= View::e($activity['ip_address'] ?? '-') ?></td>
<td class="text-xs text-muted tabular-nums"><?= !empty($activity['created_at']) ? date('Y-m-d H:i', strtotime($activity['created_at'])) : '-' ?></td>
</tr>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment