+
+
0 || rating ? 'bg-white/95 backdrop-blur-sm rounded-2xl shadow-2xl' : ''}`}>
+ {step === 0 && !rating && (
+
+ Rating Umur Game
+
+ )}
+
+ {step > 0 && step <= questions.length && (
+
{step > 1 && (
+ {
+ setAnswers(answers.slice(0, -1));
+ setStep(step - 1);
+ }}
+ aria-label="Kembali"
+ className="w-8 h-8 bg-yellow-500 rounded-full hover:bg-yellow-600 transition-transform duration-200 flex items-center justify-center focus:outline-none focus:ring-2 focus:ring-yellow-300 border-2 border-white shadow-md hover:scale-110"
+ />
+ )}
{
- setAnswers(answers.slice(0, -1));
- setStep(step - 1);
+ setStep(0);
+ setAnswers([]);
+ setGameName("");
}}
- className="w-6 h-6 bg-yellow-500 rounded-full hover:bg-yellow-700"
- />
- )}
-
- {
- setStep(0);
- setAnswers([]);
- setGameName("");
- }}
- className="w-6 h-6 bg-red-500 rounded-full hover:bg-red-700"
+ aria-label="Reset"
+ className="w-8 h-8 bg-red-500 rounded-full hover:bg-red-600 transition-transform duration-200 flex items-center justify-center focus:outline-none focus:ring-2 focus:ring-red-300 border-2 border-white shadow-md hover:scale-110"
/>
- )}
- {!rating && step === 0 && (
- <>
-
Masukkan nama game:
-
setGameName(e.target.value)}
- className="border border-gray-600 bg-gray-100 p-2 w-full mt-2 focus:bg-gray-200 focus:border-black rounded mt-1"
- />
- {suggestions.length > 0 && (
-
- {suggestions.map((suggestion, index) => (
- handleSelectGame(suggestion)}
- >
- {suggestion}
-
- ))}
-
- )}
+ )}
+
+ {!rating && step === 0 && (
+
+
Masukkan nama game:
+
+
setGameName(e.target.value)}
+ className="w-full px-4 py-3 rounded-xl border-2 border-gray-300 focus:border-yellow-500 focus:ring-2 focus:ring-yellow-200 transition-all duration-300 bg-white/90 backdrop-blur-sm"
+ placeholder="Ketik nama game..."
+ />
+ {suggestions.length > 0 && (
+
+ {suggestions.map((suggestion, index) => (
+ handleSelectGame(suggestion)}
+ >
+ {suggestion}
+
+ ))}
+
+ )}
+
- Cek
+ Cek Rating
- {/* Daftar 5 game terbaru */}
- {latestGames.length > 0 && (
-
-
Game Terbaru:
-
+
+ {latestGames.length > 0 && (
+
+
Game Terbaru:
+
{latestGames.map((game, index) => (
fetchGameRating(game)}
>
{game}
))}
{latestGames.length >= 4 && (
-
+
Selengkapnya
)}
)}
- >
- )}
- {!rating && step > 0 && step <= questions.length && (
- <>
-
{questions[step - 1]}
- {options.map((option) => (
-
handleOptionClick(option)}
- className="block bg-gray-300 text-black px-4 py-2 rounded mt-2 hover:bg-gray-400 w-full"
- >
- {option}
-
- ))}
- >
- )}
- {!rating && step > questions.length && (
- <>
- {/* Menampilkan tabel hasil jawaban */}
-
-
Hasil Jawaban Anda:
-
-
-
- Pertanyaan
- Jawaban
-
-
-
- {questions.map((question, index) => (
-
- {question}
- {answers[index]}
-
- ))}
-
-
-
- {/* Tombol kembali ke input game */}
-
{
- setStep(0);
- setAnswers([]);
- setGameName("");
- }}
- className="bg-red-500 text-white px-4 py-2 rounded mt-4 w-full"
- >
- Kembali
-
- {/* Tombol untuk konfirmasi hasil */}
-
- Cek Hasil
-
- >
- )}
+
+ )}
- {rating && (
- <>
- {easterEggActive ? (
-
+ {!rating && step > 0 && step <= questions.length && (
+
+
+ {questions[step - 1]}
+
+
+ {options.map((option) => (
+ handleOptionClick(option)}
+ className="w-full px-6 py-4 bg-white hover:bg-yellow-50 text-gray-800 rounded-xl border-2 border-gray-200 hover:border-yellow-500 transition-all duration-300 text-left"
+ >
+ {option}
+
+ ))}
+
+
+ )}
+
+ {!rating && step > questions.length && (
+
+
Hasil Jawaban Anda:
+
+
+
+
+ Pertanyaan
+ Jawaban
+
+
+
+ {questions.map((question, index) => (
+
+ {question}
+ {answers[index]}
+
+ ))}
+
+
+
+
+ {
+ setStep(0);
+ setAnswers([]);
+ setGameName("");
+ }}
+ className="flex-1 bg-red-500 hover:bg-red-600 text-white font-semibold px-6 py-3 rounded-xl transition-all duration-300"
+ >
+ Kembali
+
+
+ Cek Hasil
+
+
+
+ )}
+
+ {rating && (
+
+ {easterEggActive ? (
+
+
🎉 BISMILLAH LULUS 2025 DENGAN SEDIKIT REVISI 🎓
- ) : (
- <>
-
- Game {gameName} memiliki rating
- {rating}
-
-
Penjelasan: {ratingDescriptions[rating]}
- >
- )}
-
-
{
- setStep(0);
- setAnswers([]);
- setRating(null);
- setGameName("");
- setEasterEggActive(false);
- window.location.reload();
- }}
- className="bg-red-500 text-white px-4 py-2 rounded mt-4 w-full"
- >
- Coba Lagi
-
- >
- )}
-
-
- {/* Pop-up konfirmasi pilihan jawaban */}
-
setIsPopUpOpen(false)}
- onConfirm={confirmSelection}
- selectedOption={selectedOption}
- />
-
- {/* Pop-up konfirmasi cek hasil */}
- setIsConfirmPopupOpen(false)}
- onConfirm={confirmSubmit}
- selectedOption="Apakah Anda yakin ingin melihat hasil rating?"
- />
-
-
-
-
+
+ ) : (
+
+
+ Game {gameName} memiliki rating
+ {rating}
+
+
+ Penjelasan: {ratingDescriptions[rating]}
+
+
+ )}
+ {
+ setStep(0);
+ setAnswers([]);
+ setRating(null);
+ setGameName("");
+ setEasterEggActive(false);
+ window.location.reload();
+ }}
+ className="w-full bg-red-500 hover:bg-red-600 text-white font-semibold px-6 py-3 rounded-xl transition-all duration-300"
+ >
+ Coba Lagi
+
+
+ )}
-
-
+
+
+
+
+
+
+
+
+
+
+ {/* Pop-ups */}
+
setIsPopUpOpen(false)}
+ onConfirm={confirmSelection}
+ selectedOption={selectedOption}
+ />
+
+ setIsConfirmPopupOpen(false)}
+ onConfirm={confirmSubmit}
+ selectedOption="Apakah Anda yakin ingin melihat hasil rating?"
+ />
);
};
diff --git a/frontend/src/components/Footer.js b/frontend/src/components/Footer.js
index 8d029ff..cdb3594 100644
--- a/frontend/src/components/Footer.js
+++ b/frontend/src/components/Footer.js
@@ -1,30 +1,35 @@
-import react from "react";
+import React from "react";
const Footer = () => {
return (
-
-
© 2025 Rating Umur Game. All rights reserved.
-
- Developed by Dimas Adi
-
-
-
- );
- };
+
+
+
+
© 2025 Rating Umur Game. All rights reserved.
+
+ Developed by Dimas Adi
+
+
+
+
+
+ );
+};
+
export default Footer;
\ No newline at end of file
diff --git a/frontend/src/components/Header.js b/frontend/src/components/Header.js
index 99af0a3..55907bd 100644
--- a/frontend/src/components/Header.js
+++ b/frontend/src/components/Header.js
@@ -1,46 +1,109 @@
-import react from "react";
+import { useState, useEffect } from "react";
const Header = ({ scrollToSection }) => {
- const handleNavigation = (section) => {
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const [isVisible, setIsVisible] = useState(true);
+ const [lastScrollY, setLastScrollY] = useState(0);
+
+ const handleNavigation = (section) => {
+ setIsMenuOpen(false);
if (scrollToSection) {
scrollToSection(section);
} else {
window.location.href = `/#${section}`;
}
};
+
+ useEffect(() => {
+ const controlNavbar = () => {
+ const currentScrollY = window.scrollY;
+ if (currentScrollY > lastScrollY) {
+ setIsVisible(false);
+ } else {
+ setIsVisible(true);
+ }
+ setLastScrollY(currentScrollY);
+ };
+
+ window.addEventListener('scroll', controlNavbar);
+ return () => {
+ window.removeEventListener('scroll', controlNavbar);
+ };
+ }, [lastScrollY]);
+
return (
-
-
-
-
-
- handleNavigation("home")}
- className="text-white hover:text-gray-300"
+
+
+
+
+
+
+
+ {/* Mobile menu button */}
+
+
setIsMenuOpen(!isMenuOpen)}
+ className="text-white hover:text-gray-200 focus:outline-none"
+ >
+
+ {isMenuOpen ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {/* Desktop menu */}
+
+ handleNavigation("home")}
+ className="text-white hover:text-gray-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
>
Beranda
-
-
- handleNavigation("tentang")}
- className="text-white hover:text-gray-300"
+ handleNavigation("tentang")}
+ className="text-white hover:text-gray-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
>
Tentang
-
-
- handleNavigation("kontak")}
- className="text-white hover:text-gray-300"
+ handleNavigation("kontak")}
+ className="text-white hover:text-gray-200 px-3 py-2 rounded-md text-sm font-medium transition-colors duration-200"
>
Kontak
-
-
-
-
- );
- };
-
+
+
+
+
+ {/* Mobile menu */}
+
+
+ handleNavigation("home")}
+ className="block w-full text-left text-white hover:text-gray-200 px-3 py-2 rounded-md text-base font-medium"
+ >
+ Beranda
+
+ handleNavigation("tentang")}
+ className="block w-full text-left text-white hover:text-gray-200 px-3 py-2 rounded-md text-base font-medium"
+ >
+ Tentang
+
+ handleNavigation("kontak")}
+ className="block w-full text-left text-white hover:text-gray-200 px-3 py-2 rounded-md text-base font-medium"
+ >
+ Kontak
+
+
+
+
+ );
+};
+
export default Header;
\ No newline at end of file
diff --git a/frontend/src/components/KategoriRating.js b/frontend/src/components/KategoriRating.js
index 01b60b4..2f62017 100644
--- a/frontend/src/components/KategoriRating.js
+++ b/frontend/src/components/KategoriRating.js
@@ -2,89 +2,133 @@ import React, { useState } from "react";
const KategoriRating = () => {
const [currentIndex, setCurrentIndex] = useState(0);
- const cards = [
- { imageUrl: "/images/SU.png", text: "Semua Umur - Dapat dimainkan oleh semua orang tanpa batasan konten." },
- { imageUrl: "/images/3+.png", text: "Usia 3 Tahun Keatas - Tidak ada konten dewasa, perjudian, atau interaksi online." },
- { imageUrl: "/images/7+.png", text: "Usia 7 Tahun Keatas - Ada unsur ringan seperti kekerasan kartun atau bahasa ringan." },
- { imageUrl: "/images/13+.png", text: "Usia 13 Tahun Keatas - Ada kekerasan moderat, simulasi perjudian, atau tema horor." },
- { imageUrl: "/images/18+.png", text: "Usia 18 Tahun Keatas - Mengandung konten dewasa, kekerasan realistis, atau humor kasar." }
- ];
+ const cards = [
+ { imageUrl: "/images/SU.png", text: "Semua Umur - Dapat dimainkan oleh semua orang tanpa batasan konten." },
+ { imageUrl: "/images/3+.png", text: "Usia 3 Tahun Keatas - Tidak ada konten dewasa, perjudian, atau interaksi online." },
+ { imageUrl: "/images/7+.png", text: "Usia 7 Tahun Keatas - Ada unsur ringan seperti kekerasan kartun atau bahasa ringan." },
+ { imageUrl: "/images/13+.png", text: "Usia 13 Tahun Keatas - Ada kekerasan moderat, simulasi perjudian, atau tema horor." },
+ { imageUrl: "/images/18+.png", text: "Usia 18 Tahun Keatas - Mengandung konten dewasa, kekerasan realistis, atau humor kasar." }
+ ];
- const nextSlide = () => {
- setCurrentIndex((prevIndex) => (prevIndex + 1) % cards.length);
- };
+ const nextSlide = () => {
+ setCurrentIndex((prevIndex) => (prevIndex + 1) % cards.length);
+ };
- const prevSlide = () => {
- setCurrentIndex((prevIndex) => (prevIndex - 1 + cards.length) % cards.length);
- };
- return (
-
-
-
+ const prevSlide = () => {
+ setCurrentIndex((prevIndex) => (prevIndex - 1 + cards.length) % cards.length);
+ };
- {/* Konten utama */}
-
- {/* Teks di sebelah kiri */}
-
-
- Dalam Peraturan Menteri Komunikasi dan Informatika Nomor 2 Tahun 2024,
- gim diklasifikasikan berdasarkan kelompok usia pengguna: 3+, 7+, 13+, dan 18+.
- Setiap kategori ini mempertimbangkan jenis konten yang ditampilkan, seperti kekerasan,
- bahasa, unsur horor, hingga interaksi daring. Semakin tinggi kelompok usia,
- semakin kompleks pula konten yang diizinkan, namun tetap dalam batasan yang
- tidak melanggar norma dan hukum yang berlaku. Klasifikasi ini bertujuan agar
- setiap pengguna dapat memainkan gim yang sesuai dengan tingkat kedewasaan mereka,
- serta membantu orang tua dalam mengawasi pilihan hiburan digital anak-anaknya.
-
-
-
+ return (
+
+
+
-
-
- {cards.slice(currentIndex, currentIndex + 2).map((card, index) => (
-
- ))}
+ {/* Konten utama */}
+
+
+
+ Kategori Rating
+
+
+
+
+
+ {/* Teks di sebelah kiri */}
+
+
+
+ Dalam Peraturan Menteri Komunikasi dan Informatika Nomor 2 Tahun 2024,
+ gim diklasifikasikan berdasarkan kelompok usia pengguna: 3+, 7+, 13+, dan 18+.
+ Setiap kategori ini mempertimbangkan jenis konten yang ditampilkan, seperti kekerasan,
+ bahasa, unsur horor, hingga interaksi daring.
+
+
+ Semakin tinggi kelompok usia, semakin kompleks pula konten yang diizinkan,
+ namun tetap dalam batasan yang tidak melanggar norma dan hukum yang berlaku.
+ Klasifikasi ini bertujuan agar setiap pengguna dapat memainkan gim yang sesuai
+ dengan tingkat kedewasaan mereka, serta membantu orang tua dalam mengawasi
+ pilihan hiburan digital anak-anaknya.
+
+
+
+
+ {/* Cards di sebelah kanan */}
+
+
+ {cards.slice(currentIndex, currentIndex + (window.innerWidth < 1024 ? 1 : 2)).map((card, index) => (
+
+ ))}
+
+
+
+
-
- ◀
- ▶
-
-
-
-
- );
+ );
};
const FlipCard = ({ imageUrl, text }) => {
- const [flipped, setFlipped] = useState(false);
+ const [flipped, setFlipped] = useState(false);
- return (
-
setFlipped(true)}
- onMouseLeave={() => setFlipped(false)}
- >
-
- {/* Depan - Gambar */}
-
-
+ return (
+
setFlipped(true)}
+ onMouseLeave={() => setFlipped(false)}
+ >
+
+ {/* Depan - Gambar */}
+
+
+
+ {/* Belakang - Teks */}
+
+
- {/* Belakang - Teks */}
-
-
-
- );
+ );
};
export default KategoriRating;
diff --git a/frontend/src/components/PopUp.js b/frontend/src/components/PopUp.js
index 0fcfa2b..73c28cb 100644
--- a/frontend/src/components/PopUp.js
+++ b/frontend/src/components/PopUp.js
@@ -1,23 +1,26 @@
import React from "react";
-
const PopUp = ({ isOpen, onClose, onConfirm, selectedOption }) => {
if (!isOpen) return null;
return (
-
-
-
Apakah Anda yakin memilih: {selectedOption} ?
-
+
+
+
+ Apakah Anda yakin memilih:
+
+ {selectedOption}
+
+
Kembali
Lanjut
diff --git a/frontend/src/components/Tentang.js b/frontend/src/components/Tentang.js
index be13968..20ed740 100644
--- a/frontend/src/components/Tentang.js
+++ b/frontend/src/components/Tentang.js
@@ -1,13 +1,50 @@
-import react from "react";
+import React from "react";
const Tentang = () => {
return (
-
-
Tentang
-
Klasifikasi gim itu penting, bukan untuk membatasi, tetapi agar semua orang terutama anak muda dapat bermain dengan aman dan sesuai usia.
- Berdasarkan Peraturan Menteri Komunikasi dan Informatika Nomor 2 Tahun 2024, setiap gim yang beredar di Indonesia perlu melewati proses klasifikasi yang
- mempertimbangkan konten dan nilai-nilai budaya kita. Di sini, kami mendukung langkah ini dengan semangat terbuka, agar para pengembang dan pemain sama-sama
- tahu mana yang pas buat siapa. Soal seru-seruan, tetap jalan, tapi tetap bijak juga.
+
+
+
+
+
+
+ Klasifikasi gim itu penting, bukan untuk membatasi, tetapi agar semua orang terutama anak muda dapat bermain dengan aman dan sesuai usia.
+
+
+
+ Berdasarkan Peraturan Menteri Komunikasi dan Informatika Nomor 2 Tahun 2024, setiap gim yang beredar di Indonesia perlu melewati proses klasifikasi yang
+ mempertimbangkan konten dan nilai-nilai budaya kita.
+
+
+
+ Di sini, kami mendukung langkah ini dengan semangat terbuka, agar para pengembang dan pemain sama-sama
+ tahu mana yang pas buat siapa. Soal seru-seruan, tetap jalan, tapi tetap bijak juga.
+
+
+
+
+
+
🏷️
+
Klasifikasi
+
Sistem penilaian yang tepat untuk setiap gim
+
+
+
🛡️
+
Keamanan
+
Melindungi pemain sesuai usia
+
+
+
🎮
+
Developer Game Indonesia
+
Membantu developer game Indonesia dalam menentukan rating umur pada game yang sedang dibuat.
+
+
+
);
};
diff --git a/frontend/src/pages/ListGame.js b/frontend/src/pages/ListGame.js
index 67706c1..c171161 100644
--- a/frontend/src/pages/ListGame.js
+++ b/frontend/src/pages/ListGame.js
@@ -68,68 +68,69 @@ const ListGames = () => {
};
return (
-
+
-
-
Daftar Game
+ {/* Add top padding to prevent header overlap */}
+
+
Daftar Game
- {/* Grid untuk filter di kiri, search + list game di kanan */}
-
- {/* Bagian 1: Filter Rating */}
-
+ {/* Responsive grid: filter on top on mobile, left on desktop */}
+
+ {/* Filter */}
+
- {/* Bagian 2: Daftar Game */}
-
- {/* Bagian 3: Search Form */}
-
-
-
+ {/* Main Content */}
+
+ {/* Search Bar */}
+
+
+
- {/* Card List Game */}
-
- {filteredGames.length > 0 ? (
- filteredGames.map((game, index) => {
- const ratingInfo = ratingDescriptions[game.rating] || {};
- return (
-
-
{game.name}
-
- Rating: {ratingInfo.label}
-
-
- {ratingInfo.description}
-
-
- );
- })
- ) : (
-
Tidak ada game yang sesuai.
- )}
-
-
-
+ {/* Game Cards */}
+
+ {filteredGames.length > 0 ? (
+ filteredGames.map((game, index) => {
+ const ratingInfo = ratingDescriptions[game.rating] || {};
+ return (
+
+
{game.name}
+
+ Rating: {ratingInfo.label}
+
+
+ {ratingInfo.description}
+
+
+ );
+ })
+ ) : (
+
Tidak ada game yang sesuai.
+ )}
+
+
+