perbaikan

This commit is contained in:
aldo 2025-12-15 23:43:48 +07:00
parent 8ae4f0989a
commit 4f2f7ae38e
4 changed files with 214 additions and 98 deletions

View File

@ -156,7 +156,7 @@ if (!isset($_SESSION['username'])) {
#timer-label {
font-size: 20px;
font-weight: bold;
color: #333;
color: darkslategray;
font-family: monospace;
margin-top: 2px;
}
@ -314,7 +314,7 @@ if (!isset($_SESSION['username'])) {
.modal-title {
font-size: 24px;
font-weight: bold;
color: #333;
color: darkslategray;
margin-bottom: 10px;
}
@ -329,7 +329,7 @@ if (!isset($_SESSION['username'])) {
display: flex;
justify-content: space-around;
margin-bottom: 25px;
background-color: #f0f8ff;
background-color: aliceblue;
padding: 10px;
border-radius: 10px;
}
@ -361,8 +361,8 @@ if (!isset($_SESSION['username'])) {
border: 2px solid var(--primary-color);
}
.btn-grey-modal {
background-color: #e0e0e0;
color: #555;
background-color: gainsboro;
color: dimgray;
}
@keyframes popIn {
@ -370,6 +370,55 @@ if (!isset($_SESSION['username'])) {
to { transform: scale(1); opacity: 1; }
}
/* ... existing styles ... */
.game-layout {
display: flex;
gap: 40px;
align-items: flex-start;
}
.game-main {
display: flex;
flex-direction: column;
align-items: center;
}
.game-sidebar {
width: 250px;
background: rgba(255, 255, 255, 0.9);
border-radius: 12px;
padding: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
display: flex;
flex-direction: column;
}
.mini-leaderboard-title {
text-align: center;
font-weight: bold;
margin-bottom: 10px;
color: darkslategray;
border-bottom: 2px solid lightgray;
padding-bottom: 5px;
}
.mini-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.mini-table th, .mini-table td {
padding: 5px;
text-align: left;
border-bottom: 1px solid whitesmoke;
}
.mini-table th { color: gray; font-weight: bold; }
.mini-table tr:last-child td { border-bottom: none; }
.rank-1 { color: gold; font-weight: bold; }
.rank-2 { color: silver; font-weight: bold; }
.rank-3 { color: chocolate; font-weight: bold; }
</style>
</head>
@ -395,6 +444,9 @@ if (!isset($_SESSION['username'])) {
</div>
<div id="screen-game" class="screen">
<div class="game-layout">
<!-- Main Game Area -->
<div class="game-main">
<div class="game-header">
<button class="btn-back-icon" onclick="backToMenu()">&#8592;</button>
@ -428,6 +480,26 @@ if (!isset($_SESSION['username'])) {
<div class="tool-btn btn-delete" onclick="deleteNumber()"><span>🗑</span> HAPUS</div>
<div id="btn-hint" class="tool-btn btn-hint" onclick="getHint()"><span>💡</span> BANTUAN (3)</div>
</div>
</div>
<!-- Right Sidebar: Leaderboard -->
<div class="game-sidebar">
<div class="mini-leaderboard-title">🏆 Top <span id="lb-diff-name">Easy</span></div>
<table class="mini-table">
<thead>
<tr>
<th width="10%">#</th>
<th>Player</th>
<th>Time</th>
</tr>
</thead>
<tbody id="mini-lb-body">
<!-- Loaded via JS -->
<tr><td colspan="3" align="center">Loading...</td></tr>
</tbody>
</table>
</div>
</div>
<div id="modal-game-over" class="modal-overlay">
<div class="modal-content">
@ -501,8 +573,52 @@ if (!isset($_SESSION['username'])) {
else if (difficulty === 'hard') { holes = 50; label = "SULIT"; }
document.getElementById('difficulty-label').innerText = label;
document.getElementById('lb-diff-name').innerText = label; // Update sidebar title
switchScreen('screen-game');
newGame(holes);
loadLeaderboard(difficulty); // Fetch leaderboard
}
// --- Leaderboard Fetch Logic ---
function loadLeaderboard(diff) {
let tbody = document.getElementById('mini-lb-body');
tbody.innerHTML = '<tr><td colspan="3" align="center">Loading...</td></tr>';
fetch(`leaderboard.php?api=true&difficulty=${diff}`)
.then(res => res.json())
.then(data => {
tbody.innerHTML = '';
if (data.length === 0) {
tbody.innerHTML = '<tr><td colspan="3" align="center">Belum ada data</td></tr>';
return;
}
data.forEach((row, index) => {
let rank = index + 1;
let m = Math.floor(row.time_seconds / 60);
let s = row.time_seconds % 60;
let timeStr = (m < 10 ? "0"+m : m) + ":" + (s < 10 ? "0"+s : s);
let rankClass = '';
if (rank === 1) rankClass = 'rank-1';
else if (rank === 2) rankClass = 'rank-2';
else if (rank === 3) rankClass = 'rank-3';
let tr = `
<tr>
<td class="${rankClass}">#${rank}</td>
<td>${row.username}</td>
<td>${timeStr}</td>
</tr>
`;
tbody.innerHTML += tr;
});
})
.catch(err => {
console.error(err);
tbody.innerHTML = '<tr><td colspan="3" align="center" style="color:red">Error</td></tr>';
});
}
function newGame(holesCount) {
@ -736,6 +852,8 @@ if (!isset($_SESSION['username'])) {
document.getElementById("tools-row").style.display = "none";
document.getElementById("numpad-row").style.display = "none";
loadLeaderboard(currentDifficulty);
return true;
}
@ -799,7 +917,7 @@ function saveScore() {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: 'difficulty=${currentDifficulty}&time=${secondsElapsed}'
body: `difficulty=${currentDifficulty}&time=${secondsElapsed}`
})
.then(res => res.text())
.then(data => console.log("SAVE SCORE:", data))

View File

@ -1,7 +1,7 @@
<?php
require_once 'db.php';
// Auto-create table if it doesn't exist
try {
$checkTable = $conn->query("SHOW TABLES LIKE 'leaderboard_sudoku'");
if ($checkTable->rowCount() == 0) {
@ -16,11 +16,14 @@ try {
$conn->exec($createSql);
}
} catch (PDOException $e) {
// Fail silently or log, but attempting to continue might show empty leaderboard instead of crash
}
// Helper function to get top 10 by difficulty
function getLeaderboard($conn, $difficulty) {
$allowed = ['easy', 'medium', 'hard'];
if (!in_array($difficulty, $allowed)) {
return [];
}
$sql = "
SELECT username, time_seconds, created_at
FROM leaderboard_sudoku
@ -33,7 +36,13 @@ function getLeaderboard($conn, $difficulty) {
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// Fetch data for each level
if (isset($_GET['api']) && isset($_GET['difficulty'])) {
header('Content-Type: application/json');
$data = getLeaderboard($conn, $_GET['difficulty']);
echo json_encode($data);
exit;
}
$easyData = getLeaderboard($conn, 'easy');
$mediumData = getLeaderboard($conn, 'medium');
$hardData = getLeaderboard($conn, 'hard');
@ -48,7 +57,8 @@ $hardData = getLeaderboard($conn, 'hard');
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #121212;
background: url("Background.jpg") no-repeat center center fixed;
background-size: cover;
color: white;
display: flex;
flex-direction: column;
@ -63,13 +73,13 @@ $hardData = getLeaderboard($conn, 'hard');
.leaderboard-container {
width: 100%;
max-width: 500px;
background: #1e1e1e;
background: white;
color: darkslategray;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
/* Tabs Navigation */
.tabs {
display: flex;
width: 100%;
@ -82,37 +92,35 @@ $hardData = getLeaderboard($conn, 'hard');
cursor: pointer;
font-size: 16px;
font-weight: bold;
color: #ccc;
background-color: #2c2c2c;
color: dimgray;
background-color: whitesmoke;
transition: 0.3s;
border-bottom: 4px solid transparent;
border-bottom: 4px solid lightgray;
}
.tab-btn:hover {
background-color: #333;
color: white;
background-color: gainsboro;
color: black;
}
/* Active Tab Styling - Colors requested: Easy=Green, Medium=Yellow, Hard=Blue */
.tab-btn.active.easy {
background-color: #1e1e1e;
color: #4CAF50; /* Green */
border-bottom-color: #4CAF50;
background-color: white;
color: limegreen;
border-bottom-color: limegreen;
}
.tab-btn.active.medium {
background-color: #1e1e1e;
color: #2196F3; /* Blue */
border-bottom-color: #2196F3;
background-color: white;
color: dodgerblue;
border-bottom-color: dodgerblue;
}
.tab-btn.active.hard {
background-color: #1e1e1e;
color: #f44336; /* Red */
border-bottom-color: #f44336;
background-color: white;
color: red;
border-bottom-color: red;
}
/* Content Sections */
.tab-content {
display: none; /* Hidden by default */
display: none;
padding: 20px;
animation: fadeIn 0.4s;
}
@ -130,11 +138,11 @@ $hardData = getLeaderboard($conn, 'hard');
th, td {
text-align: left;
padding: 12px;
border-bottom: 1px solid #333;
border-bottom: 1px solid whitesmoke;
}
th {
color: #888;
color: gray;
font-size: 14px;
text-transform: uppercase;
}
@ -143,25 +151,27 @@ $hardData = getLeaderboard($conn, 'hard');
border-bottom: none;
}
/* Rank Colors */
.rank-1 { color: gold; font-weight: bold; }
.rank-2 { color: silver; font-weight: bold; }
.rank-3 { color: #cd7f32; font-weight: bold; } /* Bronze */
.rank-3 { color: chocolate; font-weight: bold; }
.back-btn {
margin-top: 20px;
padding: 10px 20px;
background-color: #333;
color: white;
background-color: white;
color: darkslategray;
border: none;
border-radius: 20px;
cursor: pointer;
text-decoration: none;
font-weight: bold;
transition: 0.2s;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.back-btn:hover {
background-color: #444;
background-color: whitesmoke;
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(0,0,0,0.15);
}
@keyframes fadeIn {
@ -175,28 +185,23 @@ $hardData = getLeaderboard($conn, 'hard');
<h2>🏆 Leaderboard</h2>
<div class="leaderboard-container">
<!-- Tabs -->
<div class="tabs">
<button class="tab-btn easy active" onclick="openTab('easy')">MUDAH</button>
<button class="tab-btn medium" onclick="openTab('medium')">SEDANG</button>
<button class="tab-btn hard" onclick="openTab('hard')">SULIT</button>
</div>
<!-- Easy Section -->
<div id="easy" class="tab-content active">
<h3 style="color: #4CAF50; margin-top: 0;">Level Mudah</h3>
<h3 style="color: limegreen; margin-top: 0;">Level Mudah</h3>
<?php renderTable($easyData); ?>
</div>
<!-- Medium Section -->
<div id="medium" class="tab-content">
<h3 style="color: #2196F3; margin-top: 0;">Level Sedang</h3>
<h3 style="color: dodgerblue; margin-top: 0;">Level Sedang</h3>
<?php renderTable($mediumData); ?>
</div>
<!-- Hard Section -->
<div id="hard" class="tab-content">
<h3 style="color: #f44336; margin-top: 0;">Level Sulit</h3>
<h3 style="color: red; margin-top: 0;">Level Sulit</h3>
<?php renderTable($hardData); ?>
</div>
</div>
@ -205,19 +210,13 @@ $hardData = getLeaderboard($conn, 'hard');
<script>
function openTab(difficulty) {
// Hide all tab contents
const contents = document.querySelectorAll('.tab-content');
contents.forEach(content => content.classList.remove('active'));
// Deactivate all buttons
const buttons = document.querySelectorAll('.tab-btn');
buttons.forEach(btn => btn.classList.remove('active'));
// Activate specific tab and button
document.getElementById(difficulty).classList.add('active');
// Find the button that calls this function (or match by class) needs logic if I don't pass 'this'
// Using querySelector to find the button with specific class for simplicity in this context
document.querySelector(`.tab-btn.${difficulty}`).classList.add('active');
}
</script>
@ -226,7 +225,6 @@ $hardData = getLeaderboard($conn, 'hard');
</html>
<?php
// Helper to render table
function renderTable($data) {
if (count($data) === 0) {
echo "<p style='color: gray; text-align: center; padding: 20px;'>Belum ada data.</p>";

View File

@ -54,14 +54,14 @@ if (isset($_POST['login'])) {
<title>Login</title>
<style>
/* Style disamakan persis dengan register.php Anda */
body { font-family: Arial; background:#eef2f7; display:flex; height:100vh; justify-content:center; align-items:center; margin:0; }
body { font-family: Arial; background:aliceblue; display:flex; height:100vh; justify-content:center; align-items:center; margin:0; }
.card { width:350px; background:white; padding:20px; border-radius:10px; box-shadow:0 6px 20px rgba(0,0,0,0.1); }
.input { width:100%; padding:10px; margin:8px 0; border:1px solid #ccc; border-radius:8px; box-sizing: border-box; }
.btn { width:100%; padding:12px; background:#007bff; color:white; border:none; border-radius:8px; cursor:pointer; }
.btn:hover { background:#0056b3; }
.err { color:#d00000; margin-bottom:10px; text-align:center; background: #ffe6e6; padding: 5px; border-radius: 5px;}
.input { width:100%; padding:10px; margin:8px 0; border:1px solid lightgray; border-radius:8px; box-sizing: border-box; }
.btn { width:100%; padding:12px; background:dodgerblue; color:white; border:none; border-radius:8px; cursor:pointer; }
.btn:hover { background:mediumblue; }
.err { color:firebrick; margin-bottom:10px; text-align:center; background: mistyrose; padding: 5px; border-radius: 5px;}
.link { text-align:center; margin-top:10px; }
a { text-decoration: none; color: #007bff; }
a { text-decoration: none; color: dodgerblue; }
</style>
</head>
<body>

View File

@ -51,16 +51,16 @@ if (isset($_POST['register'])) {
<head>
<title>Daftar Akun Baru</title>
<style>
body { font-family: Arial; background:#eef2f7; display:flex; height:100vh; justify-content:center; align-items:center; margin:0; }
body { font-family: Arial; background:aliceblue; display:flex; height:100vh; justify-content:center; align-items:center; margin:0; }
.card { width:350px; background:white; padding:20px; border-radius:10px; box-shadow:0 6px 20px rgba(0,0,0,0.1); }
.input { width:100%; padding:10px; margin:8px 0; border:1px solid #ccc; border-radius:8px; box-sizing: border-box; }
.btn { width:100%; padding:12px; background:#28a745; color:white; border:none; border-radius:8px; cursor:pointer; font-weight: bold;}
.btn:hover { background:#218838; }
.err { color:#721c24; margin-bottom:10px; text-align:center; background: #f8d7da; padding: 10px; border-radius: 5px; border: 1px solid #f5c6cb; font-size: 14px;}
.success { color:#155724; margin-bottom:10px; text-align:center; background: #d4edda; padding: 10px; border-radius: 5px; border: 1px solid #c3e6cb;}
.link { text-align:center; margin-top:10px; font-size: 14px; color: #666; }
a { text-decoration: none; color: #007bff; }
h2 { text-align: center; margin-top: 0; color: #333; }
.input { width:100%; padding:10px; margin:8px 0; border:1px solid lightgray; border-radius:8px; box-sizing: border-box; }
.btn { width:100%; padding:12px; background:forestgreen; color:white; border:none; border-radius:8px; cursor:pointer; font-weight: bold;}
.btn:hover { background:darkgreen; }
.err { color:darkred; margin-bottom:10px; text-align:center; background: mistyrose; padding: 10px; border-radius: 5px; border: 1px solid pink; font-size: 14px;}
.success { color:darkgreen; margin-bottom:10px; text-align:center; background: honeydew; padding: 10px; border-radius: 5px; border: 1px solid lightgreen;}
.link { text-align:center; margin-top:10px; font-size: 14px; color: gray; }
a { text-decoration: none; color: dodgerblue; }
h2 { text-align: center; margin-top: 0; color: darkslategray; }
p { text-align:center; color:gray; font-size: 14px; margin-bottom: 20px; }
</style>
</head>