This commit is contained in:
Evelyn Sucitro 2025-12-17 22:45:09 +07:00
parent dcdc914e25
commit f87ca734de
7 changed files with 38 additions and 97 deletions

View File

@ -92,10 +92,10 @@ function showGameOver() {
const finalScore = currentScore; const finalScore = currentScore;
if (typeof saveScore === 'function') { if (typeof saveScore === 'function') {
console.log("Mengirim skor ke database:", finalScore); console.log("Sending score to the database:", finalScore);
saveScore(finalScore); saveScore(finalScore);
} else { } else {
console.error("Fungsi saveScore tidak ditemukan! Pastikan Score_Request.js sudah diload."); console.error("saveScore function not found! Make sure Score_Request.js is loaded.");
} }
const isNewHighScore = finalScore >= highScore && finalScore > 0; const isNewHighScore = finalScore >= highScore && finalScore > 0;

View File

@ -1,13 +1,11 @@
(function() { (function() {
'use strict'; 'use strict';
// CHECK LOGIN STATUS
function checkLoginStatus() { function checkLoginStatus() {
const loggedInUser = sessionStorage.getItem("loggedInUser"); const loggedInUser = sessionStorage.getItem("loggedInUser");
const loginBtn = document.querySelector('.btn-login'); const loginBtn = document.querySelector('.btn-login');
if (loggedInUser && loginBtn) { if (loggedInUser && loginBtn) {
// Mengubah button login menjadi logout
loginBtn.textContent = 'Logout'; loginBtn.textContent = 'Logout';
loginBtn.classList.remove('btn-login'); loginBtn.classList.remove('btn-login');
loginBtn.classList.add('btn-logout'); loginBtn.classList.add('btn-logout');
@ -25,14 +23,11 @@
} }
} }
// LOGOUT CLICK HANDLER
// Mencegah halaman refresh secara otomatis dan langsung menampilkan jendela pop-up konfirmasi logout
function handleLogoutClick(e) { function handleLogoutClick(e) {
e.preventDefault(); e.preventDefault();
showLogoutModal(); showLogoutModal();
} }
// SHOW LOGOUT CONFIRMATION MODAL
function showLogoutModal() { function showLogoutModal() {
const overlay = document.getElementById('logout-overlay'); const overlay = document.getElementById('logout-overlay');
if (overlay) { if (overlay) {
@ -42,13 +37,11 @@
} }
} }
// SETUP MODAL BUTTONS
function setupModalButtons() { function setupModalButtons() {
const cancelBtn = document.getElementById('btn-logout-cancel'); const cancelBtn = document.getElementById('btn-logout-cancel');
const confirmBtn = document.getElementById('btn-logout-confirm'); const confirmBtn = document.getElementById('btn-logout-confirm');
const overlay = document.getElementById('logout-overlay'); const overlay = document.getElementById('logout-overlay');
// Remove previous listeners (mencegah error double click)
if (cancelBtn) { if (cancelBtn) {
const newCancelBtn = cancelBtn.cloneNode(true); const newCancelBtn = cancelBtn.cloneNode(true);
cancelBtn.replaceWith(newCancelBtn); cancelBtn.replaceWith(newCancelBtn);
@ -61,7 +54,6 @@
newConfirmBtn.onclick = confirmLogout; newConfirmBtn.onclick = confirmLogout;
} }
// Close on overlay click (area gelap)
if (overlay) { if (overlay) {
overlay.onclick = function(e) { overlay.onclick = function(e) {
if (e.target === overlay) { if (e.target === overlay) {
@ -70,12 +62,9 @@
}; };
} }
// Aktifkan tombol escape untuk menutup modal
document.addEventListener('keydown', handleEscapeKey); document.addEventListener('keydown', handleEscapeKey);
} }
// HANDLE ESCAPE KEY
// Menutup jendela pop-up (modal) logout menggunakan tombol keyboard Esc
function handleEscapeKey(e) { function handleEscapeKey(e) {
if (e.key === 'Escape') { if (e.key === 'Escape') {
const overlay = document.getElementById('logout-overlay'); const overlay = document.getElementById('logout-overlay');
@ -85,7 +74,6 @@
} }
} }
// CLOSE LOGOUT MODAL
function closeLogoutModal() { function closeLogoutModal() {
const overlay = document.getElementById('logout-overlay'); const overlay = document.getElementById('logout-overlay');
if (overlay) { if (overlay) {
@ -95,53 +83,45 @@
}, 300); }, 300);
} }
// Remove escape key listener
document.removeEventListener('keydown', handleEscapeKey); document.removeEventListener('keydown', handleEscapeKey);
} }
// CONFIRM LOGOUT
function confirmLogout() { function confirmLogout() {
console.log("Mencoba logout ke server..."); // Debugging console.log("Attempting to log out to the server...");
// Panggil PHP untuk hancurkan sesi server
fetch('Logout.php') fetch('Logout.php')
.then(response => { .then(response => {
console.log("Respon server:", response); console.log("Respon server:", response);
return response.json(); // Ubah ke JSON biar bisa dicek return response.json();
}) })
.then(data => { .then(data => {
console.log("Status Logout:", data); console.log("Status Logout:", data);
// Hapus data di browser (Session Storage)
sessionStorage.removeItem("loggedInUser"); sessionStorage.removeItem("loggedInUser");
sessionStorage.removeItem("authToken"); sessionStorage.removeItem("authToken");
sessionStorage.clear(); // Bersihkan semuanya biar aman sessionStorage.clear();
// Tutup Modal & Redirect
closeLogoutModal(); closeLogoutModal();
showSuccessModal(); showSuccessModal();
setTimeout(() => { setTimeout(() => {
// Redirect ke Homepage
window.location.replace('Homepage.html'); window.location.replace('Homepage.html');
}, 1500); }, 1500);
}) })
.catch(error => { .catch(error => {
console.error('Logout error:', error); console.error('Logout error:', error);
// Fallback: Kalau server error, tetap paksa keluar di tampilan
sessionStorage.clear(); sessionStorage.clear();
window.location.replace('Homepage.html'); window.location.replace('Homepage.html');
}); });
} }
// SHOW SUCCESS MODAL
function showSuccessModal() { function showSuccessModal() {
const successOverlay = document.getElementById('logout-success-overlay'); const successOverlay = document.getElementById('logout-success-overlay');
if (successOverlay) { if (successOverlay) {
successOverlay.style.display = 'flex'; successOverlay.style.display = 'flex';
setTimeout(() => successOverlay.classList.add('active'), 10); setTimeout(() => successOverlay.classList.add('active'), 10);
// Auto close after 1.3 seconds
setTimeout(() => { setTimeout(() => {
successOverlay.classList.remove('active'); successOverlay.classList.remove('active');
setTimeout(() => { setTimeout(() => {
@ -151,9 +131,6 @@
} }
} }
// INITIALIZE
// Menjamin agar kode tidak mencuri start sebelum elemen HTML tersedia.
function init() { function init() {
if (document.readyState === 'loading') { if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', checkLoginStatus); document.addEventListener('DOMContentLoaded', checkLoginStatus);

View File

@ -1,11 +1,10 @@
<?php <?php
session_start(); session_start();
header('Content-Type: application/json'); // Response berupa JSON header('Content-Type: application/json');
session_unset(); // Hapus semua data session session_unset();
session_destroy(); // Hancurkan session login session_destroy();
// Kirim respon logout sukses
echo json_encode([ echo json_encode([
"status" => "success", "status" => "success",
"message" => "Logout berhasil" "message" => "Logout berhasil"

View File

@ -1,7 +1,6 @@
import { showModal, closeModal, setupModalOk, setupOutsideClose } from "./Modal_Register.js"; import { showModal, closeModal, setupModalOk, setupOutsideClose } from "./Modal_Register.js";
import { registerRequest } from "./Register_Request.js"; import { registerRequest } from "./Register_Request.js";
// Aktifkan tombol modal
setupModalOk(); setupModalOk();
setupOutsideClose(); setupOutsideClose();
@ -12,13 +11,11 @@ document.getElementById("registerForm").addEventListener("submit", async functio
const password = document.getElementById("password").value.trim(); const password = document.getElementById("password").value.trim();
const confirmPassword = document.getElementById("confirmPassword").value.trim(); const confirmPassword = document.getElementById("confirmPassword").value.trim();
// Validasi kosong
if (!username || !password || !confirmPassword) { if (!username || !password || !confirmPassword) {
showModal("error", "Register Failed!", "All fields are required."); showModal("error", "Register Failed!", "All fields are required.");
return; return;
} }
// Validasi password tidak sama
if (password !== confirmPassword) { if (password !== confirmPassword) {
showModal("error", "Password Mismatch!", "Password and Confirm Password must match."); showModal("error", "Password Mismatch!", "Password and Confirm Password must match.");
setInputError("password"); setInputError("password");
@ -26,7 +23,6 @@ document.getElementById("registerForm").addEventListener("submit", async functio
return; return;
} }
// Button loading state
const submitBtn = this.querySelector("button[type='submit']"); const submitBtn = this.querySelector("button[type='submit']");
submitBtn.disabled = true; submitBtn.disabled = true;
@ -34,10 +30,9 @@ document.getElementById("registerForm").addEventListener("submit", async functio
const data = await registerRequest(username, password); const data = await registerRequest(username, password);
if (data.status === "success") { if (data.status === "success") {
// 1. Tampilkan modal sukses
showModal("success", "Register Successful!", data.message); showModal("success", "Register Successful!", data.message);
// 2. Simpan Score (Logic Anda)
const pendingScore = localStorage.getItem('lastScore'); const pendingScore = localStorage.getItem('lastScore');
if (pendingScore && typeof saveScore === "function") { if (pendingScore && typeof saveScore === "function") {
console.log("Menyimpan skor pending: " + pendingScore); console.log("Menyimpan skor pending: " + pendingScore);
@ -46,31 +41,21 @@ document.getElementById("registerForm").addEventListener("submit", async functio
saveScore(score); saveScore(score);
} }
// --- 🔥 PERUBAHAN DI SINI 🔥 ---
// Cari tombol OK pada modal.
// PENTING: Pastikan ID ini ("modalOkBtn") sesuai dengan ID tombol OK di HTML/Modal Anda.
// Jika ID-nya beda, ganti string di bawah ini.
// --- 🔥 TAMBAHKAN KODE DI SINI (Bagian Tombol OK) 🔥 ---
const okBtn = document.getElementById("modalOkBtn"); const okBtn = document.getElementById("modalOkBtn");
if (okBtn) { if (okBtn) {
okBtn.addEventListener("click", function() { okBtn.addEventListener("click", function() {
// [BARU] Simpan username ke sessionStorage AGAR TUTORIAL MUNCUL
// Ini penting supaya logic di 2048.js tahu ini user baru
sessionStorage.setItem("loggedInUser", username); sessionStorage.setItem("loggedInUser", username);
// Setelah disimpan, baru pindah ke Homepage
window.location.href = "Homepage.html"; window.location.href = "Homepage.html";
}, { once: true }); }, { once: true });
} else { } else {
// Fallback jika tombol error
console.warn("Tombol OK tidak ditemukan, redirect otomatis."); console.warn("OK button not found, redirecting automatically.");
setTimeout(() => { setTimeout(() => {
// [BARU] Simpan juga disini buat jaga-jaga
sessionStorage.setItem("loggedInUser", username); sessionStorage.setItem("loggedInUser", username);
window.location.href = "Homepage.html"; window.location.href = "Homepage.html";
}, 2000); }, 2000);
@ -95,12 +80,10 @@ document.getElementById("registerForm").addEventListener("submit", async functio
} }
}); });
// Hilangkan efek error saat user mengetik
document.getElementById("username").addEventListener("input", clearInputStyle); document.getElementById("username").addEventListener("input", clearInputStyle);
document.getElementById("password").addEventListener("input", clearInputStyle); document.getElementById("password").addEventListener("input", clearInputStyle);
document.getElementById("confirmPassword").addEventListener("input", clearInputStyle); document.getElementById("confirmPassword").addEventListener("input", clearInputStyle);
// Efek error merah neon
function setInputError(id) { function setInputError(id) {
const el = document.getElementById(id); const el = document.getElementById(id);
if(el) { if(el) {
@ -109,7 +92,6 @@ function setInputError(id) {
} }
} }
// Hilangkan error visual
function clearInputStyle() { function clearInputStyle() {
this.style.borderColor = ""; this.style.borderColor = "";
this.style.boxShadow = ""; this.style.boxShadow = "";

View File

@ -1,5 +1,5 @@
<?php <?php
date_default_timezone_set('Asia/Jakarta'); // Set waktu WIB date_default_timezone_set('Asia/Jakarta');
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
@ -12,33 +12,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
exit(); exit();
} }
// Koneksi Database
include 'Connection.php'; include 'Connection.php';
// Ambil Input
$input = json_decode(file_get_contents('php://input'), true); $input = json_decode(file_get_contents('php://input'), true);
$username = trim($input['username'] ?? $_POST['username'] ?? ''); // Username $username = trim($input['username'] ?? $_POST['username'] ?? '');
$password = $input['password'] ?? $_POST['password'] ?? ''; // Password $password = $input['password'] ?? $_POST['password'] ?? '';
// Validasi Kosong
if (empty($username) || empty($password)) { if (empty($username) || empty($password)) {
echo json_encode(["status" => "error", "message" => "Username and password are required"]); echo json_encode(["status" => "error", "message" => "Username and password are required"]);
exit; exit;
} }
// Validasi Password
if (strlen($password) < 6) { if (strlen($password) < 6) {
echo json_encode(["status" => "error", "message" => "Password must be at least 6 characters"]); echo json_encode(["status" => "error", "message" => "Password must be at least 6 characters"]);
exit; exit;
} }
// Validasi Username
if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) { if (!preg_match('/^[a-zA-Z0-9_]{3,20}$/', $username)) {
echo json_encode(["status" => "error", "message" => "Invalid username format"]); echo json_encode(["status" => "error", "message" => "Invalid username format"]);
exit; exit;
} }
// Cek Username
$check = $conn->prepare("SELECT id FROM users WHERE username = ?"); $check = $conn->prepare("SELECT id FROM users WHERE username = ?");
$check->bind_param("s", $username); $check->bind_param("s", $username);
$check->execute(); $check->execute();
@ -52,9 +46,8 @@ if ($check->num_rows > 0) {
} }
$check->close(); $check->close();
// Simpan User Baru $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$hashedPassword = password_hash($password, PASSWORD_DEFAULT); // Hash password $created_at = date("Y-m-d H:i:s");
$created_at = date("Y-m-d H:i:s"); // Waktu daftar
$stmt = $conn->prepare( $stmt = $conn->prepare(
"INSERT INTO users (username, password, created_at) VALUES (?, ?, ?)" "INSERT INTO users (username, password, created_at) VALUES (?, ?, ?)"
@ -62,11 +55,11 @@ $stmt = $conn->prepare(
$stmt->bind_param("sss", $username, $hashedPassword, $created_at); $stmt->bind_param("sss", $username, $hashedPassword, $created_at);
if ($stmt->execute()) { if ($stmt->execute()) {
$new_user_id = $stmt->insert_id; // Ambil ID user baru $new_user_id = $stmt->insert_id;
session_start(); // Mulai session session_start();
$_SESSION['user_id'] = $new_user_id; // Set session ID $_SESSION['user_id'] = $new_user_id;
$_SESSION['username'] = $username; // Set session username $_SESSION['username'] = $username;
echo json_encode([ echo json_encode([
"status" => "success", "status" => "success",
@ -80,6 +73,6 @@ if ($stmt->execute()) {
]); ]);
} }
$stmt->close(); // Tutup statement $stmt->close();
$conn->close(); // Tutup DB $conn->close();
?> ?>

View File

@ -1,9 +1,8 @@
<?php <?php
session_start(); // Mulai session session_start();
header('Content-Type: application/json'); header('Content-Type: application/json');
require 'Connection.php'; // Koneksi DB require 'Connection.php';
// Cek Login
if (!isset($_SESSION['username']) || !isset($_SESSION['user_id'])) { if (!isset($_SESSION['username']) || !isset($_SESSION['user_id'])) {
echo json_encode([ echo json_encode([
"status" => "error", "status" => "error",
@ -12,12 +11,10 @@ if (!isset($_SESSION['username']) || !isset($_SESSION['user_id'])) {
exit; exit;
} }
// Ambil Data $username = $_SESSION['username'];
$username = $_SESSION['username']; // Username dari session $user_id = $_SESSION['user_id'];
$user_id = $_SESSION['user_id']; // User ID dari session $score = intval($_POST['score'] ?? 0);
$score = intval($_POST['score'] ?? 0); // Score dari client
// Validasi Score
if ($score <= 0) { if ($score <= 0) {
echo json_encode([ echo json_encode([
"status" => "error", "status" => "error",
@ -26,22 +23,17 @@ if ($score <= 0) {
exit; exit;
} }
// Cek Data Leaderboard $checkStmt = $conn->prepare("SELECT score FROM leaderboard WHERE user_id = ?");
$checkStmt = $conn->prepare(
"SELECT score FROM leaderboard WHERE user_id = ?"
); // Cek berdasarkan user_id
$checkStmt->bind_param("i", $user_id); $checkStmt->bind_param("i", $user_id);
$checkStmt->execute(); $checkStmt->execute();
$result = $checkStmt->get_result(); $result = $checkStmt->get_result();
// Jika sudah ada score
if ($result->num_rows > 0) { if ($result->num_rows > 0) {
$row = $result->fetch_assoc(); $row = $result->fetch_assoc();
$oldScore = $row['score']; $oldScore = $row['score'];
if ($score > $oldScore) { if ($score > $oldScore) {
// Update jika score lebih tinggi
$updateStmt = $conn->prepare( $updateStmt = $conn->prepare(
"UPDATE leaderboard SET score = ?, username = ? WHERE user_id = ?" "UPDATE leaderboard SET score = ?, username = ? WHERE user_id = ?"
); );
@ -63,7 +55,6 @@ if ($result->num_rows > 0) {
} else { } else {
// Score lebih rendah dari record lama
echo json_encode([ echo json_encode([
"status" => "success", "status" => "success",
"message" => "Score not higher than previous", "message" => "Score not higher than previous",
@ -73,7 +64,6 @@ if ($result->num_rows > 0) {
} else { } else {
// Jika Belum Ada Score
$insertStmt = $conn->prepare( $insertStmt = $conn->prepare(
"INSERT INTO leaderboard (user_id, username, score) VALUES (?, ?, ?)" "INSERT INTO leaderboard (user_id, username, score) VALUES (?, ?, ?)"
); );

View File

@ -1,15 +1,15 @@
function saveScore(score) { function saveScore(score) {
// Kirim score ke server
fetch('Score.php', { fetch('Score.php', {
method: 'POST', // Method POST method: 'POST',
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded' // Data dikirim dalam format form data 'Content-Type': 'application/x-www-form-urlencoded'
}, },
body: 'score=' + encodeURIComponent(score) // Data score yang dikirim body: 'score=' + encodeURIComponent(score)
}) })
.then(response => response.json()) // Ubah response ke JSON .then(response => response.json())
.then(data => { .then(data => {
// Cek status dari server
if (data.status === "success") { if (data.status === "success") {
console.log("Score saved successfully"); console.log("Score saved successfully");
} else { } else {