Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions client/src/LandingPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ const LandingPage = () => {
return (
<div className="w-full min-h-screen bg-neutral-950 text-white flex flex-col">
{/* Header */}
<header className="w-full flex justify-between items-center px-8 py-4 border-b border-gray-700">
<h1 className="text-2xl font-bold text-blue-400">
<header className="w-full flex flex-col sm:flex-row justify-between items-center px-4 sm:px-8 py-4 border-b border-gray-700 gap-4">
<h1 className="text-xl sm:text-2xl font-bold text-blue-400 text-center sm:text-left">
Bit by Query - SQL Competition Platform
</h1>

{userInfo ? (
<div className="flex items-center bg-blue-800/30 text-white px-4 py-2 rounded-lg shadow-md">
<div className="flex items-center bg-blue-800/30 text-white px-3 sm:px-4 py-2 rounded-lg shadow-md w-full sm:w-auto justify-center">
<Check className="w-4 h-4 mr-2 text-blue-400" />
<span className="text-gray-300">
<span className="text-gray-300 text-sm sm:text-base">
Logged in as{" "}
<span className="text-blue-400 font-semibold">
{userInfo.username}
Expand All @@ -58,31 +58,31 @@ const LandingPage = () => {
) : (
<button
onClick={() => navigate("/register")}
className="bg-blue-600 hover:bg-blue-700 text-white px-5 py-2 rounded-md shadow-md"
className="bg-blue-600 hover:bg-blue-700 text-white px-4 sm:px-5 py-2 rounded-md shadow-md w-full sm:w-auto text-sm sm:text-base"
>
Start Registration
</button>
)}
</header>

{/* Main Content */}
<main className="flex-1 flex flex-col items-center justify-start px-8 py-10">
<main className="flex-1 flex flex-col items-center justify-start px-4 sm:px-8 py-6 sm:py-10">
{/* Project Intro */}
<div className="max-w-4xl text-center">
<h2 className="text-3xl font-semibold text-blue-400 mb-4">
<div className="max-w-4xl w-full text-center">
<h2 className="text-2xl sm:text-3xl font-semibold text-blue-400 mb-4">
Welcome to Bit by Query
</h2>
<p className="text-gray-300 mb-6">
<p className="text-gray-300 mb-6 text-sm sm:text-base px-2">
A full-stack SQL competition platform where participants can test
their SQL knowledge, compete with peers, and rise up the leaderboard.
</p>

{/* Rules Section */}
<div className="bg-gray-900 p-6 rounded-lg shadow-lg text-left">
<h3 className="text-xl font-semibold text-blue-400 mb-3">
<div className="bg-gray-900 p-4 sm:p-6 rounded-lg shadow-lg text-left">
<h3 className="text-lg sm:text-xl font-semibold text-blue-400 mb-3">
Competition Rules & Highlights
</h3>
<ul className="list-disc list-inside text-gray-300 space-y-2">
<ul className="list-disc list-inside text-gray-300 space-y-2 text-sm sm:text-base">
<li>Each user must register before joining the contest.</li>
<li>Contest includes SQL query challenges of varying difficulty.</li>
<li>Leaderboard is updated in real-time based on scores.</li>
Expand All @@ -95,15 +95,15 @@ const LandingPage = () => {
</ul>

{/* Rules Checkbox */}
<div className="mt-6 flex items-center">
<div className="mt-6 flex items-start sm:items-center">
<input
type="checkbox"
id="rules"
checked={rulesAccepted}
onChange={handleCheckbox}
className="w-5 h-5 mr-3 accent-blue-500"
className="w-5 h-5 mr-3 accent-blue-500 mt-1 sm:mt-0 flex-shrink-0"
/>
<label htmlFor="rules" className="text-gray-300">
<label htmlFor="rules" className="text-gray-300 text-sm sm:text-base">
I have read and agree to all the rules & instructions
</label>
</div>
Expand All @@ -113,9 +113,9 @@ const LandingPage = () => {
<button
onClick={handleStartContest}
disabled={!rulesAccepted}
className={`w-full py-3 rounded-md shadow-lg ${
className={`w-full py-3 rounded-md shadow-lg text-sm sm:text-base ${
rulesAccepted
? "bg-blue-600 hover:bg-blue-700 text-white"
? "bg-blue-600 hover:bg-blue-700 text-white transition-colors duration-200"
: "bg-gray-600 text-gray-400 cursor-not-allowed"
}`}
>
Expand All @@ -127,11 +127,11 @@ const LandingPage = () => {
</main>

{/* Footer */}
<footer className="w-full text-center py-4 border-t border-gray-700 text-gray-500 text-sm">
<footer className="w-full text-center py-4 border-t border-gray-700 text-gray-500 text-xs sm:text-sm px-4">
© {new Date().getFullYear()} Bit by Query | MIT Licensed
</footer>
</div>
);
};

export default LandingPage;
export default LandingPage;
68 changes: 48 additions & 20 deletions client/src/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ function Login() {
const [password, setPassword] = useState("");
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const dispatch=useDispatch();
const [showPassword, setShowPassword] = useState(false);
const dispatch = useDispatch();
const navigate = useNavigate();

const handleLogin = async (e) => {
Expand All @@ -30,7 +31,7 @@ function Login() {
password,
});

const user=response.data.user;
const user = response.data.user;
dispatch(login(user));

toast.success("Login successful!");
Expand All @@ -40,12 +41,16 @@ function Login() {
} catch (err) {
const message =
err.response?.data?.error || "Unable to login. Please try again.";
setError(message); // show error in UI
setError(message);
} finally {
setLoading(false);
}
};

const togglePasswordVisibility = () => {
setShowPassword(!showPassword);
};

return (
<div className="w-full h-screen bg-neutral-950 text-white flex items-center justify-center">
<ToastContainer
Expand Down Expand Up @@ -80,7 +85,7 @@ function Login() {
<input
type="text"
id="username"
className="w-full p-3 bg-gray-700 text-white border border-gray-600 rounded-md"
className="w-full p-3 bg-gray-700 text-white border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter ACM ID"
Expand All @@ -94,21 +99,44 @@ function Login() {
</label>
<div className="relative">
<input
type="password"
type={showPassword ? "text" : "password"}
id="password"
className="w-full p-3 bg-gray-700 text-white border border-gray-600 rounded-md"
className="w-full p-3 bg-gray-700 text-white border border-gray-600 rounded-md pr-12 focus:outline-none focus:ring-2 focus:ring-blue-500"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter password"
required
/>
<button
type="button"
className="absolute inset-y-0 right-0 px-3 py-2 text-gray-400"
tabIndex={-1}
>
<i className="fas fa-eye"></i>
</button>
<button
type="button"
className="absolute inset-y-0 right-0 px-4 flex items-center justify-center text-white hover:text-blue-400 transition-colors duration-200"
onClick={togglePasswordVisibility}
tabIndex={-1}
>
{showPassword ? (
// Password is visible → show EYE icon
<svg
className="w-6 h-6"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
<path fillRule="evenodd" d="M1.323 11.447C2.811 6.976 7.028 4 12.001 4c4.97 0 9.185 2.975 10.675 7.552.12.362.12.752 0 1.113-1.487 4.471-5.705 7.447-10.677 7.447-4.97 0-9.186-2.975-10.675-7.552a1.54 1.54 0 0 1 0-1.113ZM17 12a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z" clipRule="evenodd"/>
</svg>
) : (
// Password is hidden → show EYE SLASH icon
<svg
className="w-6 h-6"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/>
<path fillRule="evenodd" d="M1.323 11.447C2.811 6.976 7.028 4 12.001 4c4.97 0 9.185 2.975 10.675 7.552.12.362.12.752 0 1.113-1.487 4.471-5.705 7.447-10.677 7.447-4.97 0-9.186-2.975-10.675-7.552a1.54 1.54 0 0 1 0-1.113ZM17 12a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z" clipRule="evenodd"/>
<path d="m3.707 2.293 18 18 1.414-1.414-18-18-1.414 1.414Z"/>
</svg>
)}
</button>

</div>
<div className="text-right mt-2">
<a
Expand All @@ -122,23 +150,23 @@ function Login() {

<button
type="submit"
className="w-full py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50"
className="w-full py-3 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 transition-colors duration-200 font-medium"
disabled={loading}
>
{loading ? "Logging in..." : "Login"}
</button>

<hr className="my-6" />
<p className="text-center text-gray-400">
<hr className="my-6 border-gray-700" />
<p className="text-center text-gray-400 mb-2">
New user?{" "}
<a href="/register" className="text-blue-400 hover:underline">
<a href="/register" className="text-blue-400 hover:underline font-medium">
Sign up
</a>
</p>
<p className="text-center text-gray-400">
<p className="text-center text-gray-400 text-sm mb-2">
Difficulties logging in? Contact team members.
</p>
<p className="text-center text-gray-400">
<p className="text-center text-gray-400 text-sm">
<span className="text-green-400">Dummy Credentials:</span>
<br />
ACM ID: <strong>test</strong>, Pass: <strong>123</strong>
Expand All @@ -150,4 +178,4 @@ function Login() {
);
}

export default Login;
export default Login;