Skip to content
Merged
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
3 changes: 3 additions & 0 deletions src/components/CapstoneAdviser/AdviserDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useNavigate, useLocation, useParams } from "react-router-dom";
import Sidebar from "../Sidebar";
import { useAuthGuard } from "../../components/hooks/useAuthGuard";
import AdviserTeamSummary from "./AdviserTeamsSummary";
import AdviserTermsOfService from "./AdviserTermsOfService";
import AdviserTask from "./AdviserTask/AdviserTask";
import AdviserOralDef from "./AdviserTask/AdviserOralDef";
import AdviserFinalDef from "./AdviserTask/AdviserFinalDef";
Expand Down Expand Up @@ -361,6 +362,8 @@ const AdviserDashboard = ({ activePageFromHeader }) => {
switch (activePage) {
case "TeamsSummary":
return <AdviserTeamSummary />;
case "TermsOfService":
return <TermsOfService />;
case "Tasks":
return <AdviserTask setActivePage={setActivePage} />;
case "Oral Defense":
Expand Down
149 changes: 149 additions & 0 deletions src/components/CapstoneAdviser/AdviserTermsOfService.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// src/pages/Adviser/TermsOfService.jsx
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import Swal from "sweetalert2";
import { supabase } from "../../supabaseClient";
import Header from "../Header";
import Footer from "../Footer";

const AdviserTermsOfService = () => {
const [choice, setChoice] = useState("");
const navigate = useNavigate();

// check if logged in
useEffect(() => {
const storedUser = localStorage.getItem("customUser");
if (!storedUser) {
navigate("/Signin");
}
}, [navigate]);

const handleSave = async () => {
const storedUser = localStorage.getItem("customUser");
if (!storedUser) {
navigate("/Signin");
return;
}

const user = JSON.parse(storedUser);

if (choice === "accept") {
Swal.fire({
icon: "success",
title: "Terms Accepted",
text: "Thank you for accepting the terms of service.",
timer: 1500,
showConfirmButton: false,
});

// OPTIONAL: Update Supabase record (if you track agreement)
await supabase
.from("user_credentials")
.update({ terms_accepted: true })
.eq("id", user.id);

navigate("/Adviser/Dashboard");
}
else if (choice === "decline") {
Swal.fire({
icon: "warning",
title: "Terms Declined",
text: "You must accept the Terms of Service to continue.",
timer: 1500,
showConfirmButton: false,
});

// log out
localStorage.removeItem("customUser");
localStorage.removeItem("user_id");
navigate("/Signin", { replace: true });
}
else {
Swal.fire({
icon: "info",
title: "No Selection",
text: "Please select Accept or Decline before saving.",
});
}
};

return (
<div className="flex flex-col min-h-screen bg-gray-50">
<Header />

<main className="flex-grow flex flex-col items-center justify-center p-6">
<div className="bg-white shadow-lg rounded-lg p-8 max-w-3xl w-full">
<h1 className="text-3xl font-bold mb-4 text-center">
Terms of Service
</h1>

<div className="text-gray-700 leading-relaxed space-y-4 max-h-96 overflow-y-auto p-4 border rounded">
{/* ✳️ Your terms content here */}
<p>
Welcome to the TaskSphere IT platform. By using this system, you
agree to comply with the institutional guidelines for managing,
evaluating, and monitoring IT Capstone projects.
</p>
<p>
Advisers are expected to uphold academic integrity, maintain
confidentiality of student works, and ensure fair evaluation
across all teams.
</p>
<p>
Any misuse of this system, unauthorized sharing of data, or
violation of confidentiality policies may result in account
suspension or disciplinary action.
</p>
<p>
Continued use of the platform signifies your acceptance of these
terms and all future updates communicated through official
channels.
</p>
<p>
Please read carefully and select whether you accept or decline the
Terms of Service below.
</p>
</div>

<div className="mt-6 text-center space-x-6">
<label className="inline-flex items-center">
<input
type="radio"
name="tos"
value="accept"
checked={choice === "accept"}
onChange={(e) => setChoice(e.target.value)}
className="mr-2"
/>
Accept
</label>
<label className="inline-flex items-center">
<input
type="radio"
name="tos"
value="decline"
checked={choice === "decline"}
onChange={(e) => setChoice(e.target.value)}
className="mr-2"
/>
Decline
</label>
</div>

<div className="mt-6 text-center">
<button
onClick={handleSave}
className="bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded"
>
Save
</button>
</div>
</div>
</main>

<Footer />
</div>
);
};

export default AdviserTermsOfService;
87 changes: 47 additions & 40 deletions src/components/Signin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,11 @@ const Signin = () => {
const { setIsLoggedIn } = useOutletContext();
const { login } = UserAuth();

// Hard lock page scroll (belt-and-suspenders)
// Lock scroll on mount
useEffect(() => {
const prevDoc = document.documentElement.style.overflow;
const prevBody = document.body.style.overflow;
document.documentElement.style.overflow = "hidden";
document.body.style.overflow = "hidden";
document.body.style.overflow = 'hidden';
return () => {
document.documentElement.style.overflow = prevDoc;
document.body.style.overflow = prevBody;
document.body.style.overflow = 'unset';
};
}, []);

Expand Down Expand Up @@ -114,94 +110,105 @@ const Signin = () => {
}, [navigate]);

return (
// Lock the page height; no scroll
<div className="h-screen w-full bg-neutral-100 flex flex-col overflow-hidden">
<SigninHead />

{/* Main fills remaining height; internal overflow hidden */}
<main className="flex-1 bg-white flex flex-col overflow-hidden">
<div className="flex-1 overflow-hidden">
<div className="mx-auto h-full w-full max-w-[1200px] px-6 md:px-8 grid grid-cols-1 md:grid-cols-2 gap-10 items-center">
{/* Left: taller login card */}
<div className="flex justify-start">
<div className="w-full max-w-[440px] rounded-xl border border-neutral-200 bg-white p-8 shadow-sm min-h-[640px]">
<h2 className="text-center text-[32px] md:text-[34px] font-extrabold leading-8 text-[#611A11]">
<div className="h-screen w-full bg-white flex flex-col overflow-hidden select-none fixed inset-0">
{/* Fixed Header */}
<div className="flex-none">
<SigninHead />
</div>

{/* Main Content - Completely locked, content scales to fit */}
<main className="flex-1 flex items-center justify-center px-2 sm:px-3 lg:px-4 overflow-hidden">
<div className="w-full max-w-6xl h-full flex items-center justify-center">
<div className="flex flex-col lg:flex-row items-center justify-center gap-3 sm:gap-4 md:gap-6 lg:gap-8 xl:gap-10 w-full max-h-full">

{/* Left: Login Card */}
<div className="w-full lg:w-1/2 flex justify-center lg:justify-end">
<div className="w-full max-w-[300px] xs:max-w-[320px] sm:max-w-[340px] md:max-w-[360px] lg:max-w-[380px] rounded-lg sm:rounded-xl border border-neutral-200 bg-white p-3 sm:p-4 md:p-5 shadow-sm">
<h2 className="text-center text-base sm:text-lg md:text-xl lg:text-2xl font-bold text-[#611A11] mb-0.5">
Welcome to
<br />
<span className="text-[32px] md:text-[34px] font-extrabold">TaskSphere IT</span>
</h2>
<h2 className="text-center text-base sm:text-lg md:text-xl lg:text-2xl font-bold text-[#611A11] mb-2 sm:mb-3 md:mb-4">
TaskSphere IT
</h2>

<img
src={Logo1}
alt="TaskSphere icon"
className="mx-auto mt-5 h-[150px] w-[150px] object-contain"
className="mx-auto h-12 w-12 sm:h-14 sm:w-14 md:h-16 md:w-16 lg:h-18 lg:w-18 object-contain mb-2 sm:mb-3 md:mb-4 pointer-events-none"
draggable="false"
/>

<form onSubmit={handleSignIn} className="mt-8 space-y-6">
<form onSubmit={handleSignIn} className="space-y-2 sm:space-y-2.5 md:space-y-3">
<div>
<label htmlFor="userID" className="mb-1 block text-sm font-semibold text-neutral-700">
<label htmlFor="userID" className="block text-[10px] xs:text-xs sm:text-sm font-semibold text-neutral-700 mb-0.5 sm:mb-1">
Username
</label>
<input
id="userID"
type="text"
value={userID}
onChange={(e) => setUserID(e.target.value)}
className="w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-sm text-black outline-none focus:border-[#611A11] focus:ring-1 focus:ring-[#611A11]"
className="w-full rounded-md sm:rounded-lg border border-neutral-300 bg-white px-2.5 sm:px-3 py-1.5 sm:py-2 text-xs sm:text-sm md:text-base text-black outline-none focus:border-[#611A11] focus:ring-1 sm:focus:ring-2 focus:ring-[#611A11]/20"
required
/>
</div>

<div>
<label htmlFor="password" className="mb-1 block text-sm font-semibold text-neutral-700">
<label htmlFor="password" className="block text-[10px] xs:text-xs sm:text-sm font-semibold text-neutral-700 mb-0.5 sm:mb-1">
Password
</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-sm text-black outline-none focus:border-[#611A11] focus:ring-1 focus:ring-[#611A11]"
className="w-full rounded-md sm:rounded-lg border border-neutral-300 bg-white px-2.5 sm:px-3 py-1.5 sm:py-2 text-xs sm:text-sm md:text-base text-black outline-none focus:border-[#611A11] focus:ring-1 sm:focus:ring-2 focus:ring-[#611A11]/20"
required
/>
<div className="mt-1 text-right">
<div className="mt-0.5 sm:mt-1 text-right">
<button
type="button"
onClick={() => navigate("/ForgotPassword")}
className="text-[11px] font-medium text-black hover:underline focus:outline-none bg-transparent p-0 m-0"
className="text-[10px] xs:text-xs sm:text-sm font-medium text-[#611A11] hover:underline focus:outline-none bg-transparent p-0 m-0 cursor-pointer"
>
Forgot Password
Forgot Password?
</button>
</div>
</div>

<button
type="submit"
disabled={loading}
className="mt-2 w-full rounded-full bg-[#611A11] py-2 text-sm font-semibold text-white shadow hover:opacity-95 active:opacity-90 disabled:opacity-60"
className="w-full rounded-md sm:rounded-lg bg-[#611A11] py-1.5 sm:py-2 md:py-2.5 text-xs sm:text-sm md:text-base font-semibold text-white shadow hover:bg-[#7a2218] active:bg-[#4a140e] disabled:opacity-60 transition-colors mt-1.5 sm:mt-2 md:mt-3 cursor-pointer"
>
{loading ? "Signing in..." : "Sign In"}
</button>
</form>
</div>
</div>

{/* Right: seal + headline */}
<div className="flex flex-col items-center justify-center text-center">
<img src={Logo2} alt="CCS Seal" className="h-32 w-32 md:h-36 md:w-36 object-contain" />
<p className="mt-6 text-[30px] md:text-[34px] font-semibold leading-tight text-neutral-800">
A Task Management System for
<br />
Capstone Project Development
{/* Right: Seal and Description */}
<div className="w-full lg:w-1/2 flex flex-col items-center justify-center text-center mt-2 sm:mt-3 lg:mt-0">
<img
src={Logo2}
alt="CCS Seal"
className="h-14 w-14 sm:h-16 sm:w-16 md:h-20 md:w-20 lg:h-24 lg:w-24 xl:h-28 xl:w-28 object-contain pointer-events-none"
draggable="false"
/>
<p className="mt-1.5 sm:mt-2 md:mt-3 text-xs sm:text-sm md:text-base lg:text-lg xl:text-xl font-semibold text-neutral-800 leading-tight px-3 sm:px-4">
A Task Management System for<br />Capstone Project Development
</p>
</div>
</div>
</div>
</main>

<SigninFoot />
{/* Fixed Footer */}
<div className="flex-none">
<SigninFoot />
</div>
</div>
);
};

export default Signin;
export default Signin;
19 changes: 9 additions & 10 deletions src/components/heade-foot/SigninFoot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@ import React from "react";

const SigninFoot = () => {
return (
// Fixed footer so it doesn't add to page height
<footer className="fixed bottom-0 left-0 right-0 bg-white">
{/* Full-width gradient directly above the red divider */}
<div className="h-24 w-full bg-gradient-to-t from-[#611A11]/30 to-transparent" />

{/* Red divider line (inset like your mock) */}
<div className="mx-[0.3in] h-[2px] bg-[#3B0304]" />

<footer className="fixed bottom-0 left-0 right-0 bg-white z-10">
{/* Reduced gradient height */}
<div className="h-8 sm:h-12 w-full bg-gradient-to-t from-[#611A11]/20 to-transparent" />

{/* Red divider line */}
<div className="mx-4 sm:mx-6 md:mx-8 h-[1px] sm:h-[2px] bg-[#3B0304]" />

{/* Footer content */}
<div className="mx-[0.3in] flex flex-col items-center justify-between gap-2 py-3 text-[14px] text-[#3B0304] md:flex-row">
<div className="mx-4 sm:mx-6 md:mx-8 flex flex-col items-center justify-between gap-1 py-2 text-xs sm:text-sm text-[#3B0304] md:flex-row">
<p>©2025 TaskSphere IT - All Rights Reserved</p>
<a href="#" className="hover:underline">Terms of Service</a>
</div>
</footer>
);
};

export default SigninFoot;
export default SigninFoot;
8 changes: 4 additions & 4 deletions src/components/heade-foot/SigninHead.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import Logo from "../../assets/img/Logo.png";

const SigninHead = () => {
return (
<header className="w-full bg-white border-b border-neutral-200 shadow-sm">
<div className="h-[100px] flex items-center justify-start px-6">
<img src={Logo} alt="TaskSphere IT" className="h-12 md:h-14 w-auto ml-2" />
<header className="fixed top-0 left-0 right-0 bg-white border-b border-neutral-200 shadow-sm z-10">
<div className="h-16 flex items-center justify-start px-4 sm:px-6">
<img src={Logo} alt="TaskSphere IT" className="h-8 w-auto" />
</div>
</header>
);
};

export default SigninHead;
export default SigninHead;