Commit 0402e2b4 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: align remaining modules to actual Supabase column schemas

- ads: remove non-existent columns (advertiser, placement, cpm, title, body, click_url, image_url), use actual schema (campaign_type, target_slots, target_games, budget_daily)
- moderation: resolution→action_taken, resolved_by→reviewed_by (UUID), resolved_at→reviewed_at
- tournaments: el3ab_tournament_players→tournament_registrations, swiss_tournament_id→swiss_api_tournament_id
- players: remove email from insert (not in profiles), banned_at removed, use ban_expires_at
- notifications: remove is_broadcast (not in schema), detect broadcast by null user_id
- settings: is_editable→is_secret, handle JSONB value column
- auth: last_login→last_login_at
- Created el3ab_tournament_rounds table on server
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 367e98e5
...@@ -273,7 +273,7 @@ class Auth ...@@ -273,7 +273,7 @@ class Auth
try { try {
$db = Database::getInstance(); $db = Database::getInstance();
$db->update('admin_users', ['id' => 'eq.' . $userId], [ $db->update('admin_users', ['id' => 'eq.' . $userId], [
'last_login' => date('c'), 'last_login_at' => date('c'),
]); ]);
} catch (\Throwable $e) { } catch (\Throwable $e) {
// Non-critical — don't break login if this fails // Non-critical — don't break login if this fails
......
...@@ -42,9 +42,7 @@ class AdsController ...@@ -42,9 +42,7 @@ class AdsController
Auth::requireCsrf(); Auth::requireCsrf();
$validator = Validator::make($_POST) $validator = Validator::make($_POST)
->required('name', 'اسم الحملة') ->required('name', 'اسم الحملة');
->required('advertiser', 'المعلن')
->required('placement', 'الموضع');
if ($validator->fails()) { if ($validator->fails()) {
Response::error($validator->firstError(), '/ads/create'); Response::error($validator->firstError(), '/ads/create');
...@@ -53,21 +51,17 @@ class AdsController ...@@ -53,21 +51,17 @@ class AdsController
$data = [ $data = [
'name' => trim($_POST['name']), 'name' => trim($_POST['name']),
'advertiser' => trim($_POST['advertiser']), 'name_ar' => trim($_POST['name_ar'] ?? ''),
'placement' => $_POST['placement'], 'campaign_type' => $_POST['campaign_type'] ?? 'cpm',
'status' => 'draft', 'status' => 'draft',
'title' => trim($_POST['title'] ?? ''), 'target_slots' => !empty($_POST['target_slots']) ? '{' . implode(',', (array)$_POST['target_slots']) . '}' : '{}',
'title_ar' => trim($_POST['title_ar'] ?? ''), 'target_games' => !empty($_POST['target_games']) ? '{' . implode(',', (array)$_POST['target_games']) . '}' : '{}',
'body' => trim($_POST['body'] ?? ''), 'target_countries' => !empty($_POST['target_countries']) ? '{' . implode(',', (array)$_POST['target_countries']) . '}' : '{}',
'body_ar' => trim($_POST['body_ar'] ?? ''),
'click_url' => trim($_POST['click_url'] ?? ''),
'image_url' => trim($_POST['image_url'] ?? ''),
'target_countries' => $_POST['target_countries'] ?? '[]',
'target_games' => $_POST['target_games'] ?? '[]',
'starts_at' => $_POST['starts_at'] ?: null, 'starts_at' => $_POST['starts_at'] ?: null,
'ends_at' => $_POST['ends_at'] ?: null, 'ends_at' => $_POST['ends_at'] ?: null,
'budget_total' => (int)($_POST['budget_total'] ?? 0), 'budget_total' => (int)($_POST['budget_total'] ?? 0),
'cpm' => (float)($_POST['cpm'] ?? 0), 'budget_daily' => (int)($_POST['budget_daily'] ?? 0),
'created_by' => Auth::user()['id'] ?? null,
]; ];
$this->db->insert('ad_campaigns', $data); $this->db->insert('ad_campaigns', $data);
...@@ -103,18 +97,15 @@ class AdsController ...@@ -103,18 +97,15 @@ class AdsController
$data = [ $data = [
'name' => trim($_POST['name']), 'name' => trim($_POST['name']),
'advertiser' => trim($_POST['advertiser']), 'name_ar' => trim($_POST['name_ar'] ?? ''),
'placement' => $_POST['placement'], 'campaign_type' => $_POST['campaign_type'] ?? 'cpm',
'title' => trim($_POST['title'] ?? ''), 'target_slots' => !empty($_POST['target_slots']) ? '{' . implode(',', (array)$_POST['target_slots']) . '}' : '{}',
'title_ar' => trim($_POST['title_ar'] ?? ''), 'target_games' => !empty($_POST['target_games']) ? '{' . implode(',', (array)$_POST['target_games']) . '}' : '{}',
'body' => trim($_POST['body'] ?? ''), 'target_countries' => !empty($_POST['target_countries']) ? '{' . implode(',', (array)$_POST['target_countries']) . '}' : '{}',
'body_ar' => trim($_POST['body_ar'] ?? ''),
'click_url' => trim($_POST['click_url'] ?? ''),
'image_url' => trim($_POST['image_url'] ?? ''),
'starts_at' => $_POST['starts_at'] ?: null, 'starts_at' => $_POST['starts_at'] ?: null,
'ends_at' => $_POST['ends_at'] ?: null, 'ends_at' => $_POST['ends_at'] ?: null,
'budget_total' => (int)($_POST['budget_total'] ?? 0), 'budget_total' => (int)($_POST['budget_total'] ?? 0),
'cpm' => (float)($_POST['cpm'] ?? 0), 'budget_daily' => (int)($_POST['budget_daily'] ?? 0),
'updated_at' => date('c'), 'updated_at' => date('c'),
]; ];
......
...@@ -9,31 +9,47 @@ ...@@ -9,31 +9,47 @@
<form method="POST" action="<?= $isEdit ? "/ads/{$campaign['id']}/update" : '/ads/store' ?>" data-validate> <form method="POST" action="<?= $isEdit ? "/ads/{$campaign['id']}/update" : '/ads/store' ?>" data-validate>
<input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>"> <input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>">
<div class="grid grid-2 gap-4"> <div class="grid grid-2 gap-4">
<div class="form-group"><label class="form-label">اسم الحملة *</label><input type="text" name="name" class="form-input" value="<?= View::e($campaign['name'] ?? '') ?>" required><span class="form-error"></span></div> <div class="form-group"><label class="form-label">اسم الحملة (English) *</label><input type="text" name="name" class="form-input" value="<?= View::e($campaign['name'] ?? '') ?>" required dir="ltr"><span class="form-error"></span></div>
<div class="form-group"><label class="form-label">المعلن *</label><input type="text" name="advertiser" class="form-input" value="<?= View::e($campaign['advertiser'] ?? '') ?>" required></div> <div class="form-group"><label class="form-label">اسم الحملة (عربي)</label><input type="text" name="name_ar" class="form-input" value="<?= View::e($campaign['name_ar'] ?? '') ?>"></div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">الموضع *</label> <label class="form-label">نوع الحملة</label>
<select name="placement" class="form-select" required> <select name="campaign_type" class="form-select">
<?php $placements = ['banner_top' => 'بانر علوي', 'banner_bottom' => 'بانر سفلي', 'interstitial' => 'بيني', 'sidebar' => 'جانبي', 'in_game' => 'داخل اللعبة', 'reward_video' => 'فيديو مكافأة']; ?> <?php $types = ['cpm' => 'CPM - التكلفة لكل 1000 ظهور', 'cpc' => 'CPC - التكلفة لكل نقرة', 'flat' => 'ثابت - سعر ثابت']; ?>
<?php foreach ($placements as $val => $label): ?> <?php foreach ($types as $val => $label): ?>
<option value="<?= $val ?>" <?= ($campaign['placement'] ?? '') === $val ? 'selected' : '' ?>><?= $label ?></option> <option value="<?= $val ?>" <?= ($campaign['campaign_type'] ?? 'cpm') === $val ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
</div> </div>
<div class="grid grid-2 gap-4"> <div class="form-group">
<div class="form-group"><label class="form-label">العنوان (English)</label><input type="text" name="title" class="form-input" value="<?= View::e($campaign['title'] ?? '') ?>" dir="ltr"></div> <label class="form-label">المواضع المستهدفة</label>
<div class="form-group"><label class="form-label">العنوان (عربي)</label><input type="text" name="title_ar" class="form-input" value="<?= View::e($campaign['title_ar'] ?? '') ?>"></div> <select name="target_slots[]" class="form-select" multiple>
<?php
$slots = ['banner_top' => 'بانر علوي', 'banner_bottom' => 'بانر سفلي', 'interstitial' => 'بيني', 'sidebar' => 'جانبي', 'in_game' => 'داخل اللعبة', 'reward_video' => 'فيديو مكافأة'];
$selectedSlots = $campaign['target_slots'] ?? [];
foreach ($slots as $val => $label): ?>
<option value="<?= $val ?>" <?= in_array($val, (array)$selectedSlots) ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
<?php if (!empty($games)): ?>
<div class="form-group">
<label class="form-label">الألعاب المستهدفة</label>
<select name="target_games[]" class="form-select" multiple>
<?php $selectedGames = $campaign['target_games'] ?? []; ?>
<?php foreach ($games as $game): ?>
<option value="<?= View::e($game['game_key']) ?>" <?= in_array($game['game_key'], (array)$selectedGames) ? 'selected' : '' ?>><?= View::e($game['name_ar']) ?></option>
<?php endforeach; ?>
</select>
</div> </div>
<div class="form-group"><label class="form-label">رابط الصورة</label><input type="url" name="image_url" class="form-input" value="<?= View::e($campaign['image_url'] ?? '') ?>" dir="ltr"></div> <?php endif; ?>
<div class="form-group"><label class="form-label">رابط النقر</label><input type="url" name="click_url" class="form-input" value="<?= View::e($campaign['click_url'] ?? '') ?>" dir="ltr"></div>
<div class="grid grid-2 gap-4"> <div class="grid grid-2 gap-4">
<div class="form-group"><label class="form-label">تاريخ البدء</label><input type="datetime-local" name="starts_at" class="form-input" value="<?= $campaign['starts_at'] ? date('Y-m-d\TH:i', strtotime($campaign['starts_at'])) : '' ?>"></div> <div class="form-group"><label class="form-label">تاريخ البدء</label><input type="datetime-local" name="starts_at" class="form-input" value="<?= !empty($campaign['starts_at']) ? date('Y-m-d\TH:i', strtotime($campaign['starts_at'])) : '' ?>"></div>
<div class="form-group"><label class="form-label">تاريخ الانتهاء</label><input type="datetime-local" name="ends_at" class="form-input" value="<?= $campaign['ends_at'] ? date('Y-m-d\TH:i', strtotime($campaign['ends_at'])) : '' ?>"></div> <div class="form-group"><label class="form-label">تاريخ الانتهاء</label><input type="datetime-local" name="ends_at" class="form-input" value="<?= !empty($campaign['ends_at']) ? date('Y-m-d\TH:i', strtotime($campaign['ends_at'])) : '' ?>"></div>
</div> </div>
<div class="grid grid-2 gap-4"> <div class="grid grid-2 gap-4">
<div class="form-group"><label class="form-label">الميزانية الكلية</label><input type="number" name="budget_total" class="form-input" value="<?= $campaign['budget_total'] ?? 0 ?>" min="0"></div> <div class="form-group"><label class="form-label">الميزانية الكلية</label><input type="number" name="budget_total" class="form-input" value="<?= $campaign['budget_total'] ?? 0 ?>" min="0"></div>
<div class="form-group"><label class="form-label">CPM</label><input type="number" name="cpm" class="form-input" value="<?= $campaign['cpm'] ?? 0 ?>" min="0" step="0.01"></div> <div class="form-group"><label class="form-label">الميزانية اليومية</label><input type="number" name="budget_daily" class="form-input" value="<?= $campaign['budget_daily'] ?? 0 ?>" min="0"></div>
</div> </div>
<div class="flex gap-3 mt-6"> <div class="flex gap-3 mt-6">
<button type="submit" class="btn btn-primary"><?= $isEdit ? 'حفظ التعديلات' : 'إنشاء الحملة' ?></button> <button type="submit" class="btn btn-primary"><?= $isEdit ? 'حفظ التعديلات' : 'إنشاء الحملة' ?></button>
......
...@@ -34,16 +34,16 @@ ...@@ -34,16 +34,16 @@
<tbody> <tbody>
<?php foreach ($campaigns as $c): ?> <?php foreach ($campaigns as $c): ?>
<tr> <tr>
<td class="font-medium"><?= View::e($c['name']) ?></td> <td class="font-medium"><?= View::e($c['name'] ?? '') ?></td>
<td class="text-secondary"><?= View::e($c['advertiser']) ?></td> <td class="text-secondary"><?= View::e($c['name_ar'] ?? '') ?></td>
<td><span class="badge badge-info"><?= View::e($c['placement']) ?></span></td> <td><span class="badge badge-info"><?= View::e($c['campaign_type'] ?? 'cpm') ?></span></td>
<td> <td>
<?php $sb = ['active' => 'success', 'paused' => 'warning', 'draft' => 'default', 'completed' => 'info', 'expired' => 'danger']; ?> <?php $sb = ['active' => 'success', 'paused' => 'warning', 'draft' => 'default', 'completed' => 'info', 'expired' => 'danger']; ?>
<span class="badge badge-<?= $sb[$c['status']] ?? 'default' ?> badge-dot"><?= View::e($c['status']) ?></span> <span class="badge badge-<?= $sb[$c['status']] ?? 'default' ?> badge-dot"><?= View::e($c['status']) ?></span>
</td> </td>
<td class="tabular-nums"><?= number_format($c['impressions'] ?? 0) ?></td> <td class="tabular-nums"><?= number_format($c['weight'] ?? 0) ?></td>
<td class="tabular-nums"><?= number_format($c['clicks'] ?? 0) ?></td> <td class="tabular-nums"><?= number_format($c['priority'] ?? 0) ?></td>
<td class="tabular-nums text-xs"><?= number_format($c['budget_spent'] ?? 0) ?> / <?= number_format($c['budget_total'] ?? 0) ?></td> <td class="tabular-nums text-xs"><?= number_format($c['spent_total'] ?? 0) ?> / <?= number_format($c['budget_total'] ?? 0) ?></td>
<td> <td>
<div class="flex gap-2"> <div class="flex gap-2">
<a href="/ads/<?= $c['id'] ?>/edit" class="btn btn-ghost btn-sm">تعديل</a> <a href="/ads/<?= $c['id'] ?>/edit" class="btn btn-ghost btn-sm">تعديل</a>
......
...@@ -72,9 +72,9 @@ class ModerationController ...@@ -72,9 +72,9 @@ class ModerationController
$this->db->update('cheat_reports', ['id' => "eq.{$id}"], [ $this->db->update('cheat_reports', ['id' => "eq.{$id}"], [
'status' => 'resolved', 'status' => 'resolved',
'resolution' => $resolution, 'action_taken' => $resolution,
'resolved_by' => Auth::user()['username'], 'reviewed_by' => Auth::user()['id'],
'resolved_at' => date('c'), 'reviewed_at' => date('c'),
]); ]);
AuditLog::log('resolve', 'report', $id, null, ['resolution' => $resolution]); AuditLog::log('resolve', 'report', $id, null, ['resolution' => $resolution]);
...@@ -89,9 +89,9 @@ class ModerationController ...@@ -89,9 +89,9 @@ class ModerationController
$this->db->update('cheat_reports', ['id' => "eq.{$id}"], [ $this->db->update('cheat_reports', ['id' => "eq.{$id}"], [
'status' => 'dismissed', 'status' => 'dismissed',
'resolution' => $resolution, 'action_taken' => $resolution,
'resolved_by' => Auth::user()['username'], 'reviewed_by' => Auth::user()['id'],
'resolved_at' => date('c'), 'reviewed_at' => date('c'),
]); ]);
AuditLog::log('dismiss', 'report', $id); AuditLog::log('dismiss', 'report', $id);
...@@ -107,9 +107,9 @@ class ModerationController ...@@ -107,9 +107,9 @@ class ModerationController
foreach ($ids as $id) { foreach ($ids as $id) {
$this->db->update('cheat_reports', ['id' => "eq.{$id}"], [ $this->db->update('cheat_reports', ['id' => "eq.{$id}"], [
'status' => 'dismissed', 'status' => 'dismissed',
'resolution' => $reason, 'action_taken' => $reason,
'resolved_by' => Auth::user()['username'], 'reviewed_by' => Auth::user()['id'],
'resolved_at' => date('c'), 'reviewed_at' => date('c'),
]); ]);
} }
......
...@@ -46,7 +46,6 @@ class NotificationsController ...@@ -46,7 +46,6 @@ class NotificationsController
'title_ar' => trim($_POST['title_ar'] ?? ''), 'title_ar' => trim($_POST['title_ar'] ?? ''),
'body' => trim($_POST['body'] ?? ''), 'body' => trim($_POST['body'] ?? ''),
'body_ar' => trim($_POST['body_ar'] ?? ''), 'body_ar' => trim($_POST['body_ar'] ?? ''),
'is_broadcast' => false,
]); ]);
AuditLog::log('send', 'notification', $_POST['user_id']); AuditLog::log('send', 'notification', $_POST['user_id']);
...@@ -74,7 +73,6 @@ class NotificationsController ...@@ -74,7 +73,6 @@ class NotificationsController
'title_ar' => trim($_POST['title_ar'] ?? ''), 'title_ar' => trim($_POST['title_ar'] ?? ''),
'body' => trim($_POST['body'] ?? ''), 'body' => trim($_POST['body'] ?? ''),
'body_ar' => trim($_POST['body_ar'] ?? ''), 'body_ar' => trim($_POST['body_ar'] ?? ''),
'is_broadcast' => true,
]); ]);
AuditLog::log('broadcast', 'notification', null, null, ['title' => $_POST['title']]); AuditLog::log('broadcast', 'notification', null, null, ['title' => $_POST['title']]);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<td><span class="badge badge-info"><?= View::e($n['type']) ?></span></td> <td><span class="badge badge-info"><?= View::e($n['type']) ?></span></td>
<td><?= View::e($n['title_ar'] ?: $n['title']) ?></td> <td><?= View::e($n['title_ar'] ?: $n['title']) ?></td>
<td class="text-xs"><?= $n['user_id'] ? substr($n['user_id'], 0, 8) . '...' : '-' ?></td> <td class="text-xs"><?= $n['user_id'] ? substr($n['user_id'], 0, 8) . '...' : '-' ?></td>
<td><?= $n['is_broadcast'] ? '<span class="badge badge-purple">بث عام</span>' : '' ?></td> <td><?= empty($n['user_id']) ? '<span class="badge badge-purple">بث عام</span>' : '' ?></td>
<td class="text-xs tabular-nums"><?= date('m/d H:i', strtotime($n['created_at'])) ?></td> <td class="text-xs tabular-nums"><?= date('m/d H:i', strtotime($n['created_at'])) ?></td>
<td><button class="btn btn-ghost btn-sm" style="color:var(--danger);" onclick="confirmDelete('/notifications/<?= $n['id'] ?>/delete','إشعار')">حذف</button></td> <td><button class="btn btn-ghost btn-sm" style="color:var(--danger);" onclick="confirmDelete('/notifications/<?= $n['id'] ?>/delete','إشعار')">حذف</button></td>
</tr> </tr>
......
...@@ -109,7 +109,6 @@ class PlayersController ...@@ -109,7 +109,6 @@ class PlayersController
'username' => trim($_POST['username']), 'username' => trim($_POST['username']),
'display_name' => trim($_POST['display_name'] ?? ''), 'display_name' => trim($_POST['display_name'] ?? ''),
'display_name_ar' => trim($_POST['display_name_ar'] ?? ''), 'display_name_ar' => trim($_POST['display_name_ar'] ?? ''),
'email' => trim($_POST['email'] ?? ''),
'country_code' => trim($_POST['country_code'] ?? ''), 'country_code' => trim($_POST['country_code'] ?? ''),
'city' => trim($_POST['city'] ?? ''), 'city' => trim($_POST['city'] ?? ''),
'bio' => trim($_POST['bio'] ?? ''), 'bio' => trim($_POST['bio'] ?? ''),
...@@ -191,8 +190,7 @@ class PlayersController ...@@ -191,8 +190,7 @@ class PlayersController
$this->db->update('profiles', ['id' => "eq.{$id}"], [ $this->db->update('profiles', ['id' => "eq.{$id}"], [
'is_banned' => true, 'is_banned' => true,
'ban_reason' => $reason, 'ban_reason' => $reason,
'banned_at' => date('c'), 'banned_by' => Auth::user()['id'],
'banned_by' => Auth::user()['username'],
]); ]);
AuditLog::log('ban', 'player', $id, null, ['reason' => $reason]); AuditLog::log('ban', 'player', $id, null, ['reason' => $reason]);
...@@ -207,7 +205,7 @@ class PlayersController ...@@ -207,7 +205,7 @@ class PlayersController
$this->db->update('profiles', ['id' => "eq.{$id}"], [ $this->db->update('profiles', ['id' => "eq.{$id}"], [
'is_banned' => false, 'is_banned' => false,
'ban_reason' => null, 'ban_reason' => null,
'banned_at' => null, 'ban_expires_at' => null,
'banned_by' => null, 'banned_by' => null,
]); ]);
......
...@@ -102,7 +102,7 @@ ...@@ -102,7 +102,7 @@
<h3 class="card-title">معلومات</h3> <h3 class="card-title">معلومات</h3>
</div> </div>
<div class="flex flex-col gap-3 text-sm"> <div class="flex flex-col gap-3 text-sm">
<div class="flex justify-between"><span class="text-secondary">البريد</span><span><?= View::e($player['email'] ?? '-') ?></span></div> <div class="flex justify-between"><span class="text-secondary">اللغة</span><span><?= View::e($player['preferred_language'] ?? '-') ?></span></div>
<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['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><?= 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['created_at'] ? date('Y-m-d', strtotime($player['created_at'])) : '-' ?></span></div>
......
...@@ -48,14 +48,14 @@ class SettingsController ...@@ -48,14 +48,14 @@ class SettingsController
return; return;
} }
if (!$setting['is_editable']) { if ($setting['is_secret'] ?? false) {
Response::error('هذا الإعداد غير قابل للتعديل', '/settings'); Response::error('هذا الإعداد محمي', '/settings');
return; return;
} }
$old = $setting['value']; $old = $setting['value'];
$this->db->update('system_config', ['key' => "eq.{$key}"], [ $this->db->update('system_config', ['key' => "eq.{$key}"], [
'value' => $value, 'value' => json_encode($value),
'updated_at' => date('c'), 'updated_at' => date('c'),
]); ]);
......
...@@ -32,13 +32,17 @@ ...@@ -32,13 +32,17 @@
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<?php if ($setting['value_type'] === 'boolean'): ?> <?php
$val = is_array($setting['value']) ? json_encode($setting['value']) : (string)($setting['value'] ?? '');
$editable = !($setting['is_secret'] ?? false);
?>
<?php if ($val === 'true' || $val === 'false'): ?>
<form method="POST" action="/settings/update"> <form method="POST" action="/settings/update">
<input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>"> <input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>">
<input type="hidden" name="key" value="<?= View::e($setting['key']) ?>"> <input type="hidden" name="key" value="<?= View::e($setting['key']) ?>">
<input type="hidden" name="value" value="<?= $setting['value'] === 'true' ? 'false' : 'true' ?>"> <input type="hidden" name="value" value="<?= $val === 'true' ? 'false' : 'true' ?>">
<label class="toggle"> <label class="toggle">
<input type="checkbox" <?= $setting['value'] === 'true' ? 'checked' : '' ?> <?= !$setting['is_editable'] ? 'disabled' : '' ?> onchange="this.closest('form').submit()"> <input type="checkbox" <?= $val === 'true' ? 'checked' : '' ?> <?= !$editable ? 'disabled' : '' ?> onchange="this.closest('form').submit()">
<span class="toggle-track"></span> <span class="toggle-track"></span>
</label> </label>
</form> </form>
...@@ -46,8 +50,8 @@ ...@@ -46,8 +50,8 @@
<form method="POST" action="/settings/update" class="flex items-center gap-2"> <form method="POST" action="/settings/update" class="flex items-center gap-2">
<input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>"> <input type="hidden" name="_csrf" value="<?= Auth::csrfToken() ?>">
<input type="hidden" name="key" value="<?= View::e($setting['key']) ?>"> <input type="hidden" name="key" value="<?= View::e($setting['key']) ?>">
<input type="<?= $setting['value_type'] === 'number' ? 'number' : 'text' ?>" name="value" class="form-input" style="width: 200px; padding: var(--space-2) var(--space-3);" value="<?= View::e($setting['value']) ?>" <?= !$setting['is_editable'] ? 'disabled' : '' ?> dir="ltr"> <input type="text" name="value" class="form-input" style="width: 200px; padding: var(--space-2) var(--space-3);" value="<?= View::e($val) ?>" <?= !$editable ? 'disabled' : '' ?> dir="ltr">
<?php if ($setting['is_editable']): ?> <?php if ($editable): ?>
<button type="submit" class="btn btn-primary btn-sm">حفظ</button> <button type="submit" class="btn btn-primary btn-sm">حفظ</button>
<?php endif; ?> <?php endif; ?>
</form> </form>
......
...@@ -60,15 +60,15 @@ class TournamentsController ...@@ -60,15 +60,15 @@ class TournamentsController
// Fetch standings from Swiss API if tournament is in progress or completed // Fetch standings from Swiss API if tournament is in progress or completed
$standings = []; $standings = [];
if (in_array($tournament['status'], ['in_progress', 'completed']) && !empty($tournament['swiss_tournament_id'])) { if (in_array($tournament['status'], ['in_progress', 'completed']) && !empty($tournament['swiss_api_tournament_id'])) {
$response = ApiProxy::swiss('GET', '/tournaments/' . $tournament['swiss_tournament_id'] . '/standings'); $response = ApiProxy::swiss('GET', '/tournaments/' . $tournament['swiss_api_tournament_id'] . '/standings');
if ($response['status'] === 200 && is_array($response['body'])) { if ($response['status'] === 200 && is_array($response['body'])) {
$standings = $response['body']; $standings = $response['body'];
} }
} }
// Fetch registered players // Fetch registered players
$players = $this->db->select('el3ab_tournament_players', [ $players = $this->db->select('tournament_registrations', [
'tournament_id' => "eq.{$id}", 'tournament_id' => "eq.{$id}",
'order' => 'registered_at.asc', 'order' => 'registered_at.asc',
]); ]);
...@@ -186,7 +186,7 @@ class TournamentsController ...@@ -186,7 +186,7 @@ class TournamentsController
'status' => 'draft', 'status' => 'draft',
'swiss_org_id' => $swissOrgId, 'swiss_org_id' => $swissOrgId,
'swiss_event_id' => $swissEventId, 'swiss_event_id' => $swissEventId,
'swiss_tournament_id' => $swissTournamentId, 'swiss_api_tournament_id' => $swissTournamentId,
'created_by' => $_SESSION['user']['username'] ?? 'system', 'created_by' => $_SESSION['user']['username'] ?? 'system',
]; ];
...@@ -284,16 +284,17 @@ class TournamentsController ...@@ -284,16 +284,17 @@ class TournamentsController
} }
// Register players in Swiss API // Register players in Swiss API
if (!empty($tournament['swiss_tournament_id'])) { if (!empty($tournament['swiss_api_tournament_id'])) {
$players = $this->db->select('el3ab_tournament_players', [ $players = $this->db->select('tournament_registrations', [
'tournament_id' => "eq.{$id}", 'tournament_id' => "eq.{$id}",
]); ]);
foreach ($players as $player) { foreach ($players as $player) {
ApiProxy::swiss('POST', '/tournaments/' . $tournament['swiss_tournament_id'] . '/players', [ $profile = $this->db->selectOne('profiles', ['id' => "eq.{$player['player_id']}"]);
ApiProxy::swiss('POST', '/tournaments/' . $tournament['swiss_api_tournament_id'] . '/players', [
'id' => $player['player_id'], 'id' => $player['player_id'],
'name' => $player['player_name'] ?? $player['player_id'], 'name' => $profile['display_name'] ?? $profile['username'] ?? $player['player_id'],
'rating' => $player['rating'] ?? 1500, 'rating' => $profile['elo_blitz'] ?? 1500,
]); ]);
} }
} }
...@@ -375,13 +376,13 @@ class TournamentsController ...@@ -375,13 +376,13 @@ class TournamentsController
return; return;
} }
if (empty($tournament['swiss_tournament_id'])) { if (empty($tournament['swiss_api_tournament_id'])) {
Response::error('لا يوجد ربط مع نظام السويسري', '/tournaments/' . $id); Response::error('لا يوجد ربط مع نظام السويسري', '/tournaments/' . $id);
return; return;
} }
// Call Swiss API to generate round // Call Swiss API to generate round
$response = ApiProxy::swiss('POST', '/tournaments/' . $tournament['swiss_tournament_id'] . '/rounds/generate'); $response = ApiProxy::swiss('POST', '/tournaments/' . $tournament['swiss_api_tournament_id'] . '/rounds/generate');
if ($response['status'] !== 200 && $response['status'] !== 201) { if ($response['status'] !== 200 && $response['status'] !== 201) {
$errorMsg = $response['body']['message'] ?? 'فشل في إنشاء الجولة'; $errorMsg = $response['body']['message'] ?? 'فشل في إنشاء الجولة';
...@@ -495,12 +496,12 @@ class TournamentsController ...@@ -495,12 +496,12 @@ class TournamentsController
return; return;
} }
if (empty($tournament['swiss_tournament_id'])) { if (empty($tournament['swiss_api_tournament_id'])) {
Response::json(['error' => 'لا يوجد ربط مع نظام السويسري'], 400); Response::json(['error' => 'لا يوجد ربط مع نظام السويسري'], 400);
return; return;
} }
$response = ApiProxy::swiss('GET', '/tournaments/' . $tournament['swiss_tournament_id'] . '/standings'); $response = ApiProxy::swiss('GET', '/tournaments/' . $tournament['swiss_api_tournament_id'] . '/standings');
if ($response['status'] === 200) { if ($response['status'] === 200) {
Response::json([ Response::json([
......
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