Skip to content

Commit 45041f7

Browse files
committed
Merged changes from upstream
2 parents 707e91b + 6be934a commit 45041f7

35 files changed

Lines changed: 1008 additions & 398 deletions

package-lock.json

Lines changed: 55 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"next-pwa": "^5.6.0",
2020
"papaparse": "^5.5.3",
2121
"react": "^19.1.0",
22-
"react-dom": "^19.1.0"
22+
"react-dom": "^19.1.0",
23+
"react-router-dom": "^7.6.2"
2324
},
2425
"devDependencies": {
2526
"@fortawesome/fontawesome-svg-core": "^6.7.2",

public/club_image/ieee.jpg

30 KB
Loading

public/club_image/mulearn.png

5.18 KB
Loading

public/images/FingerprintImg.png

222 KB
Loading

public/wave-line.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { NextRequest, NextResponse } from 'next/server';
2+
// import { getAuth } from 'firebase-admin/auth';
3+
// import { initializeApp, getApps, cert } from 'firebase-admin/app';
4+
import { serialize } from 'cookie';
5+
6+
// const serviceAccount = {
7+
// projectId: process.env.FIREBASE_PROJECT_ID,
8+
// privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
9+
// clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
10+
// };
11+
12+
// if (!getApps().length) {
13+
// initializeApp({
14+
// credential: cert(serviceAccount as any),
15+
// });
16+
// }
17+
18+
export async function POST(req: NextRequest) {
19+
try {
20+
const body = await req.json();
21+
const { idToken } = body;
22+
23+
if (!idToken) {
24+
return NextResponse.json({ error: 'ID token required' }, { status: 400 });
25+
}
26+
27+
// Uncomment to verify token:
28+
// await getAuth().verifyIdToken(idToken);
29+
30+
const cookie = serialize('authToken', idToken, {
31+
httpOnly: true,
32+
secure: process.env.NODE_ENV === 'production',
33+
maxAge: 60 * 60 * 24, // 1 day
34+
path: '/',
35+
sameSite: 'lax',
36+
});
37+
38+
const res = NextResponse.json({ success: true });
39+
res.headers.set('Set-Cookie', cookie);
40+
41+
return res;
42+
} catch (error) {
43+
console.error(error);
44+
return NextResponse.json({ error: 'Invalid token' }, { status: 401 });
45+
}
46+
}

src/app/auth/page.tsx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//
2+
"use client";
3+
import { useState } from "react";
4+
import { signInWithGoogle } from "@/lib/firebase/auth";
5+
import { useRouter } from "next/navigation";
6+
import Image from "next/image";
7+
import Link from "next/link";
8+
9+
export default function AuthPage() {
10+
const [error, setError] = useState<string | null>(null);
11+
const [loading, setLoading] = useState(false);
12+
const [agreed, setAgreed] = useState(false);
13+
const router = useRouter();
14+
15+
const handleLoginWithGoogle = async () => {
16+
if (!agreed) {
17+
setError("Please agree to the terms and services.");
18+
return;
19+
}
20+
21+
setLoading(true);
22+
setError(null);
23+
try {
24+
const result = await signInWithGoogle();
25+
if (result?.isAdmin) {
26+
router.push("/admin");
27+
} else {
28+
router.push("/");
29+
}
30+
} catch (err) {
31+
console.error("Failed to log in with Google:", err);
32+
setError(err instanceof Error ? err.message : "Failed to log in with Google");
33+
} finally {
34+
setLoading(false);
35+
}
36+
};
37+
38+
return (
39+
<div className="flex flex-col items-center justify-center min-h-screen bg-white dark:bg-black px-6 py-8 relative">
40+
{/* Back Arrow Button */}
41+
<Link
42+
href="/"
43+
className="absolute top-6 left-6 p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
44+
aria-label="Go back"
45+
>
46+
<svg
47+
xmlns="http://www.w3.org/2000/svg"
48+
className="w-6 h-6"
49+
viewBox="0 0 24 24"
50+
fill="none"
51+
stroke="currentColor"
52+
strokeWidth="2"
53+
strokeLinecap="round"
54+
strokeLinejoin="round"
55+
>
56+
<line x1="19" y1="12" x2="5" y2="12"></line>
57+
<polyline points="12 19 5 12 12 5"></polyline>
58+
</svg>
59+
</Link>
60+
61+
<div className="w-full max-w-md text-center space-y-6">
62+
{/* Title */}
63+
<h1 className="text-2xl md:text-3xl font-semibold text-black dark:text-white">
64+
Create your account
65+
</h1>
66+
67+
{/* Illustration */}
68+
<div className="flex justify-center">
69+
<Image
70+
src={"/images/FingerprintImg.png"}
71+
alt="Fingerprint illustration"
72+
width={240}
73+
height={240}
74+
className="rounded-xl w-[180px] h-[180px] md:w-[220px] md:h-[220px]"
75+
priority
76+
/>
77+
</div>
78+
79+
{/* Google Login Button */}
80+
<button
81+
onClick={handleLoginWithGoogle}
82+
disabled={loading}
83+
aria-label="Continue with Google"
84+
type="button"
85+
className="flex items-center justify-center w-full py-3 px-6 rounded-full shadow-md
86+
bg-white border border-gray-300 hover:bg-gray-100
87+
transition-all disabled:opacity-60 disabled:cursor-not-allowed"
88+
>
89+
{loading ? (
90+
<span className="text-base font-medium text-gray-600">Logging in...</span>
91+
) : (
92+
<>
93+
<Image
94+
src="https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg"
95+
alt="Google logo"
96+
width={24}
97+
height={24}
98+
className="w-5 h-5 md:w-6 md:h-6"
99+
/>
100+
<span className="ml-3 text-base font-medium text-gray-700">
101+
Continue with Google
102+
</span>
103+
</>
104+
)}
105+
</button>
106+
107+
{/* Terms and Services */}
108+
<div className="flex items-center justify-center space-x-3 text-sm md:text-base">
109+
<input
110+
type="checkbox"
111+
id="terms"
112+
checked={agreed}
113+
onChange={() => setAgreed(!agreed)}
114+
className="form-checkbox text-blue-600 w-4 h-4 md:w-5 md:h-5"
115+
/>
116+
<label htmlFor="terms" className="text-gray-600 dark:text-gray-400">
117+
I agree to my <span className="font-semibold underline">terms and services</span>
118+
</label>
119+
</div>
120+
121+
{/* Error Message */}
122+
{error && (
123+
<p className="text-red-500 text-sm md:text-base">
124+
{error}
125+
</p>
126+
)}
127+
</div>
128+
</div>
129+
);
130+
}

src/app/bus/page.tsx

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BusButtons } from "@/components/Bus/busButton";
1+
//import { BusButtons } from "@/components/Bus/busButton";
22

33
const busData = [
44
{ slug: 'bus-1', name: 'Bus 1' },
@@ -9,10 +9,45 @@ const busData = [
99
{ slug: 'bus-6', name: 'Bus 6' },
1010
];
1111

12-
export default function BusPage() {
12+
const BusPage: React.FC = () => {
1313
return (
14-
<div>
15-
<BusButtons buses={busData} />
14+
<div className="min-h-screen bg-white">
15+
{/* Header */}
16+
<div className="px-6 py-8">
17+
<div className="text-center mb-8">
18+
<div className="relative">
19+
<h1 className="text-[30px] font-bold text-black">College Bus</h1>
20+
{/* Decorative wave underline */}
21+
<svg
22+
className="absolute -bottom-2 left-1/2 transform -translate-x-1/2 w-24 h-3"
23+
viewBox="0 0 96 12"
24+
fill="none"
25+
>
26+
<path
27+
d="M2 6C8 2, 16 10, 24 6C32 2, 40 10, 48 6C56 2, 64 10, 72 6C80 2, 88 10, 94 6"
28+
stroke="#000000"
29+
strokeWidth="1"
30+
strokeLinecap="round"
31+
/>
32+
</svg>
33+
</div>
34+
</div>
35+
36+
{/* Subject Grid */}
37+
<div className="grid grid-cols-1 md:grid-cols-4 md:gap-y-20 gap-4 px-10">
38+
{busData.map((bus, index) => (
39+
// Use BusButtons
40+
<button
41+
key={index}
42+
className="bg-white border border-black rounded-lg py-7 text-center shadow-md"
43+
>
44+
<span className="text-2xl font-bold text-black">{bus.name}</span>
45+
</button>
46+
))}
47+
</div>
48+
</div>
1649
</div>
1750
);
18-
}
51+
};
52+
53+
export default BusPage;

0 commit comments

Comments
 (0)