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
130 changes: 127 additions & 3 deletions src/app/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import { getDoc, doc, query, collection, where, getDocs, documentId, updateDoc } from "firebase/firestore";
import { getDoc, doc, query, collection, where, getDocs, documentId, updateDoc, arrayUnion, arrayRemove } from "firebase/firestore";
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import documentId.

Suggested change
import { getDoc, doc, query, collection, where, getDocs, documentId, updateDoc, arrayUnion, arrayRemove } from "firebase/firestore";
import { getDoc, doc, query, collection, where, getDocs, updateDoc, arrayUnion, arrayRemove } from "firebase/firestore";

Copilot uses AI. Check for mistakes.
import { db } from "@/lib/firebase";
import { useAuthContext } from "@/context/AuthContext";
import QRCode from "react-qr-code";
Expand Down Expand Up @@ -34,6 +34,8 @@ export default function Profile() {
const [saving, setSaving] = useState(false);
const [isEditingProblem, setIsEditingProblem] = useState(false);
const [hasProblemStatement, setHasProblemStatement] = useState(false);
const [joinTeamCode, setJoinTeamCode] = useState("");
const [joining, setJoining] = useState(false);

// Check if editing is allowed (until Jan 1st, 2026)
const isEditingAllowed = new Date() < new Date('2026-01-01T00:00:00');
Expand Down Expand Up @@ -147,6 +149,82 @@ export default function Profile() {
setSaving(false);
}
};

const handleJoinTeam = async () => {
if (!user?.uid || !joinTeamCode) return;

setJoining(true);
try {
const teamsRef = collection(db, "teams");
const teamQuery = query(teamsRef, where("referralCode", "==", joinTeamCode.toUpperCase()));
const teamSnapshot = await getDocs(teamQuery);

if (teamSnapshot.empty) {
alert("Invalid referral code. Please check and try again.");
setJoining(false);
return;
}
Comment on lines +153 to +166
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The handleJoinTeam function doesn't verify the current team membership status before attempting to join. Although the UI conditionally renders the Join Team section based on isTeamMember, the function itself should validate userData.isTeamMember to prevent a user from joining if they're already in a team (in case the function is called directly or due to stale state). Consider adding a check like: if (userData?.isTeamMember === 1) { alert("You are already in a team!"); return; }

Copilot uses AI. Check for mistakes.

const teamDoc = teamSnapshot.docs[0];
const teamData = teamDoc.data();

if (teamData.participants && teamData.participants.length >= 5) {
alert("This team is full (maximum 5 members).");
setJoining(false);
return;
}

if (teamData.participants && teamData.participants.includes(user.uid)) {
alert("You are already in this team!");
setJoining(false);
return;
}

await updateDoc(doc(db, "teams", teamDoc.id), {
participants: arrayUnion(user.uid),
});

await updateDoc(doc(db, "registrations", user.uid), {
isTeamMember: 1,
teamName: teamData.teamName,
});

alert("Successfully joined team!");
window.location.reload();
} catch (error) {
console.error("Error joining team:", error);
alert("Failed to join team. Please try again.");
Comment on lines +163 to +196
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using alert() for user feedback is not ideal for modern web applications. Consider replacing with a more user-friendly toast notification system or inline error/success messages that provide a better user experience and don't block the UI.

Copilot uses AI. Check for mistakes.
} finally {
setJoining(false);
}
};

const handleLeaveTeam = async () => {
if (!user?.uid || !teamData?.teamName) return;

if (!confirm("Are you sure you want to leave this team?")) return;

setJoining(true);
try {
await updateDoc(doc(db, "teams", teamData.teamName), {
participants: arrayRemove(user.uid),
});

await updateDoc(doc(db, "registrations", user.uid), {
isTeamMember: 0,
teamName: "",
});

alert("Successfully left the team.");
window.location.reload();
} catch (error) {
console.error("Error leaving team:", error);
alert("Failed to leave team. Please try again.");
Comment on lines +218 to +222
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using alert() for user feedback is not ideal for modern web applications. Consider replacing with a more user-friendly toast notification system or inline error/success messages that provide a better user experience and don't block the UI.

Copilot uses AI. Check for mistakes.
} finally {
setJoining(false);
Comment on lines +207 to +224
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "joining" state variable is being reused for the "Leave Team" operation. This is semantically incorrect and could lead to confusion. Consider renaming this state to something more generic like "isProcessing" or creating a separate state variable for leave operations to improve code clarity.

Copilot uses AI. Check for mistakes.
}
};
Comment on lines +202 to +226
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The handleLeaveTeam function doesn't check if the user is the team lead before allowing them to leave. If a team lead leaves the team, this could result in an orphaned team with no lead, potentially causing issues with team management. Consider either preventing team leads from leaving without transferring leadership, or implementing logic to handle team lead departure (e.g., promoting another member or disbanding the team).

Copilot uses AI. Check for mistakes.

return (
<div className="min-h-screen bg-white dark:bg-[#0a0a0a] py-8 px-4">
<div className="max-w-7xl mx-auto">
Expand Down Expand Up @@ -251,7 +329,7 @@ export default function Profile() {
<div className="bg-gray-50 dark:bg-[#141414] rounded-xl p-6 border border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-bold text-gray-900 dark:text-white">Problem Statement</h2>
{hasProblemStatement && !isEditingProblem && isEditingAllowed && (
{hasProblemStatement && !isEditingProblem && isEditingAllowed && userData?.isTeamLead === 1 && (
<button
onClick={() => setIsEditingProblem(true)}
className="px-4 py-2 text-sm bg-blue-500 text-white rounded-lg font-medium hover:bg-blue-600 transition-colors"
Expand All @@ -261,7 +339,7 @@ export default function Profile() {
)}
</div>

{!hasProblemStatement || isEditingProblem ? (
{userData?.isTeamLead === 1 && (!hasProblemStatement || isEditingProblem) ? (
// Edit Mode
<div className="space-y-4">
<div>
Expand Down Expand Up @@ -368,10 +446,46 @@ export default function Profile() {
</p>
</div>
)}

{userData?.isTeamLead !== 1 && userData?.isTeamMember === 1 && (
<div className="mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
<p className="text-sm text-blue-800 dark:text-blue-200">
ℹ️ Only the Team Lead can edit the problem statement.
</p>
</div>
)}
</div>
)}
</div>

{/* Join Team Section */}
{userData?.isTeamMember !== 1 && (
<div className="bg-gray-50 dark:bg-[#141414] rounded-xl p-6 border border-gray-200 dark:border-gray-700">
<h2 className="text-xl font-bold text-gray-900 dark:text-white mb-4">Join a Team</h2>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-900 dark:text-white mb-2">
Enter Referral Code
</label>
<input
type="text"
value={joinTeamCode}
onChange={(e) => setJoinTeamCode(e.target.value)}
placeholder="Enter 6-digit code"
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-[#0a0a0a] text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<button
onClick={handleJoinTeam}
disabled={joining || !joinTeamCode}
Comment on lines +473 to +480
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referral code input lacks validation for format and length. According to the placeholder text, it expects a 6-digit code, but the input doesn't enforce this constraint. Consider adding input validation (e.g., maxLength={6}, pattern matching) and client-side validation to ensure the code format is correct before making the database query.

Suggested change
onChange={(e) => setJoinTeamCode(e.target.value)}
placeholder="Enter 6-digit code"
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-[#0a0a0a] text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<button
onClick={handleJoinTeam}
disabled={joining || !joinTeamCode}
onChange={(e) => {
const numericValue = e.target.value.replace(/\D/g, "").slice(0, 6);
setJoinTeamCode(numericValue);
}}
placeholder="Enter 6-digit code"
maxLength={6}
inputMode="numeric"
pattern="\d{6}"
className="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-[#0a0a0a] text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<button
onClick={handleJoinTeam}
disabled={joining || joinTeamCode.length !== 6}

Copilot uses AI. Check for mistakes.
className="w-full py-3 bg-blue-500 text-white rounded-lg font-medium hover:bg-blue-600 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors"
>
{joining ? "Joining..." : "Join Team"}
</button>
</div>
</div>
)}

{/* Team View Section */}
{userData?.isTeamMember === 1 && teamData && (
<div className="bg-gray-50 dark:bg-[#141414] rounded-xl p-6 border border-gray-200 dark:border-gray-700">
Expand Down Expand Up @@ -426,6 +540,16 @@ export default function Profile() {
Edit Team
</button>
)}

{userData?.isTeamLead !== 1 && (
<button
onClick={handleLeaveTeam}
disabled={joining}
className="w-full mt-4 py-2 text-red-500 dark:text-red-400 rounded-lg border border-red-300 dark:border-red-600 font-medium hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors"
>
{joining ? "Leaving..." : "Leave Team"}
</button>
)}
</div>
)}

Expand Down
5 changes: 3 additions & 2 deletions src/app/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ import {
updateDoc,
arrayUnion,
where,
setDoc,
} from "firebase/firestore";
import { ArrowForwardIos, EmojiEventsOutlined, ContentCopy, CheckCircle } from "@mui/icons-material";
import GetUserProgress from "@/utils/getUserProgress";
import Progress from "@/utils/progress";
import { useSearchParams } from "next/navigation";

const MyForm: React.FC = () => {
const MAX_CODE_GENERATION_ATTEMPTS = 10;
Expand Down Expand Up @@ -92,6 +90,9 @@ const MyForm: React.FC = () => {
const [isTeamLead, setIsTeamLead] = useState<boolean | undefined>(undefined);
const [referralCode, setReferralCode] = useState("");
const [teamName, setTeamName] = useState("");
const [copied, setCopied] = useState(false);
const [generatedReferralCode, setGeneratedReferralCode] = useState("");
const [teamCreated, setTeamCreated] = useState(false);
const router = useRouter();

// Check for referral code in URL
Expand Down
1 change: 0 additions & 1 deletion src/components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ export default function Hero() {
href={"https://maps.google.com?q=Chandrahas%20Bhavan,%20Q9JG+5FF,%20RUSHIKONDA,%20GITAM,%20Rushikonda,%20Visakhapatnam,%20Andhra%20Pradesh%20530045&ftid=0x0:0x6c1c27dfb649611a&entry=gps&lucs=,94297699,94275415,94284508,94231188,94280568,47071704,94218641,94282134,94286869&g_st=ic"}
target="_blank"
rel="noopener noreferrer"
className="text-black"
className="text-black underline-offset-2 dark:text-white"
>
GITAM (Deemed to be University)
Expand Down
2 changes: 1 addition & 1 deletion src/components/Timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function Timeline() {
color: "var(--google-red)"
},
{
date: "Dec 31",
date: "Jan 1",
title: "Registration Deadline",
description: "Last day to register, form teams, and submit pitch decks.",
completed: false,
Expand Down
2 changes: 1 addition & 1 deletion src/data/speakers.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
},
{
"id": "114",
"name": "Aftab Ali",
"name": "Aafthab Ali",
"company": {
"name": "",
"designation": ""
Expand Down