+ {/* 3. Applied the specific titleColor here */}
+
+ {title}
+
+ {/* This summary
will inherit colorWay.text from the parent */}
+
{summary}
+
+
+
+ {/* This
will also inherit colorWay.text */}
+
+ Tracks
+
+ {tracks.map((track) => (
+
+ {track}
+
+ ))}
+
+
+ );
+
+};
+
+export default SwipeCards;
\ No newline at end of file
diff --git a/app/components/ProtectedNavButton.tsx b/app/components/ProtectedNavButton.tsx
new file mode 100644
index 0000000..5a5c48b
--- /dev/null
+++ b/app/components/ProtectedNavButton.tsx
@@ -0,0 +1,35 @@
+"use client";
+
+import React from "react";
+import { useRouter } from "next/navigation";
+
+export default function ProtectedNavButton({
+ children = "Go to Dashboard",
+ className = "mt-4 inline-block w-fit px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md shadow-md transition-colors",
+}: {
+ children?: React.ReactNode;
+ className?: string;
+}) {
+ const router = useRouter();
+
+ const handleClick = () => {
+ // Simple client-side auth check.
+ // Assumption: if localStorage has 'token' (or 'auth'), user is signed in.
+ // Adjust key to match your real auth storage (cookie, localStorage key, etc.).
+ const token = typeof window !== "undefined" ? localStorage.getItem("token") : null;
+
+ if (token) {
+ // The app route folder is named `Dashboard` (capital D).
+ // Use the same path casing to avoid 404s on Next.js routes.
+ router.push("/Dashboard");
+ } else {
+ router.push("/auth/login");
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/app/exportType/types.ts b/app/exportType/types.ts
index 7281483..d60f588 100644
--- a/app/exportType/types.ts
+++ b/app/exportType/types.ts
@@ -14,7 +14,10 @@ export interface GenerateConfig {
temperature: number;
topP: number;
responseMimeType: string;
+<<<<<<< HEAD
maxOutputTokens?: number;
+=======
+>>>>>>> 44b5a4dc49ea757e9790ba8309edc6b37d764105
}
export interface ChatSetting {
diff --git a/app/formfile/page.tsx b/app/formfile/page.tsx
index 613c7b3..a4abdf2 100644
--- a/app/formfile/page.tsx
+++ b/app/formfile/page.tsx
@@ -1,42 +1,54 @@
-// File: Home.tsx (Renamed from form.tsx for export consistency)
-
"use client";
import React, { useState, useEffect, useCallback } from "react";
import FormPage from './FormPage';
-import { ChatSetting, CardData } from "@/app/exportType/types";
+import { ChatSetting } from "../exportType/types";
import { FormData, PROFICIENCY_LEVELS } from './formTypes';
-import SwipeCards from '../cards/page';
-export default function Home() {
- const [showForm, setShowForm] = useState(true);
- const [formData, setFormData] = useState(() => {
- if (typeof window !== 'undefined') {
- const storedFormData = localStorage.getItem('formData');
- if (storedFormData) {
- const parsedData: FormData = JSON.parse(storedFormData);
- return parsedData;
- }
- }
+// --- Helper function to get default form data ---
+const getDefaultFormData = (): FormData => ({
+ Hackathon: '',
+ mainTheme: '',
+ tracksStack: [''],
+ students: [{
+ studentName: '',
+ skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }]
+ }],
+});
+
+// --- New Initializer Function ---
+const getInitialState = () => {
+ if (typeof window === 'undefined') {
return {
- Hackathon: '',
- mainTheme: '',
- tracksStack: [''],
- students: [{
- studentName: '',
- skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }]
- }],
+ data: getDefaultFormData(),
+ showForm: true,
+ runEffect: false
};
- });
+ }
+ const storedFormData = localStorage.getItem('formData');
+ if (storedFormData) {
+ localStorage.removeItem('formData');
+ return {
+ data: JSON.parse(storedFormData) as FormData,
+ showForm: false,
+ runEffect: true,
+ };
+ }
+ return {
+ data: getDefaultFormData(),
+ showForm: true,
+ runEffect: false
+ };
+};
- const [ideaResponse, setIdeaResponse] = useState("");
- const [generatedCards, setGeneratedCards] = useState([]); // New state for parsed cards
-
- const [settings] = useState({
- temperature: 1,
- model: "gemini-2.5-flash-lite",
- sysTemInstructions: `You are an elite hackathon idea generator. Your task is to choose at lease two track and generate five different creative, feasible, and relevant project idea.
+// FIX 1 (Memoization): Moved settings OUTSIDE the component.
+// This makes it a true constant.
+const AI_SETTINGS: ChatSetting = {
+ temperature: 1,
+ model: "gemini-2.5-pro",
+ sysTemInstructions: `You are an elite hackathon idea generator. Your task is to generate five different creative, feasible, and relevant project idea.
The output MUST be in Markdown format and strictly follow this structure:
### Project Idea Title
+<<<<<<< HEAD
**Track** [print out the track you used]
**Concept:** [A concise, single paragraph description of the product and its primary function.]`,
});
@@ -70,6 +82,25 @@ The output MUST be in Markdown format and strictly follow this structure:
console.log("Parsed Cards:", ideas);
return ideas;
};
+=======
+**Relevance to Theme:** [Explain briefly]
+**Core Technology:** [List 3-5 primary technologies]
+**Team Fit:** [How the team's skills apply]
+**Concept:** [A concise, single paragraph description of the product and its primary function.]
+**Bonus Feature:** [A single, ambitious feature to impress judges.]`,
+};
+>>>>>>> 44b5a4dc49ea757e9790ba8309edc6b37d764105
+
+// ------------------------------------------------
+
+export default function Home() {
+
+ const [initialState] = useState(getInitialState);
+ const [showForm, setShowForm] = useState(initialState.showForm);
+ const [formData, setFormData] = useState(initialState.data);
+ const [ideaResponse, setIdeaResponse] = useState("");
+
+ // The 'settings' state [useState] is now removed from here.
const handleFormSubmitFromFormPage = (submittedData: FormData) => {
setFormData(submittedData);
@@ -77,8 +108,9 @@ The output MUST be in Markdown format and strictly follow this structure:
generateIdeas(submittedData);
};
- // eslint-disable-next-line react-hooks/preserve-manual-memoization
+ // Wrapped generateIdeas in useCallback
const generateIdeas = useCallback(async (dataToProcess: FormData) => {
+ // 1. Data Cleaning
const submissionData: FormData = {
...dataToProcess,
tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''),
@@ -90,6 +122,7 @@ The output MUST be in Markdown format and strictly follow this structure:
.filter(student => student.studentName.trim() !== '' || student.skills.length > 0),
};
+ // 2. Prompt Construction
const prompt = `
Hackathon: ${submissionData.Hackathon}
Main Theme: ${submissionData.mainTheme}
@@ -97,11 +130,13 @@ The output MUST be in Markdown format and strictly follow this structure:
Team Members and Skills: ${submissionData.students.map(s =>
`${s.studentName || 'Unamed Member'} (Skills: ${s.skills.map(sk => `${sk.skillName} - ${sk.proficiency}`).join(', ')})`
).join('; ')}
-
+
Using the SYSTEM INSTRUCTIONS, generate 5 project ideas based on the data above.`;
+ // 3. API Call
try {
setIdeaResponse("Generating ideas... Please wait.");
+<<<<<<< HEAD
setGeneratedCards([]); // Clear previous cards
const response = await fetch("/api/generate-idea", {
method: "POST",
@@ -116,10 +151,24 @@ The output MUST be in Markdown format and strictly follow this structure:
const data = await response.json();
+=======
+
+ const response = await fetch("/api/generate-idea", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({
+ prompt: prompt,
+ settings: AI_SETTINGS, // Use the constant
+ }),
+ });
+
+ const data = await response.json();
+>>>>>>> 44b5a4dc49ea757e9790ba8309edc6b37d764105
if (data.error || !response.ok) {
console.error("AI Error:", data.error);
setIdeaResponse(`Error: Failed to generate idea. ${data.error || response.statusText}`);
return;
+<<<<<<< HEAD
}
setIdeaResponse(data.response);
@@ -146,10 +195,33 @@ The output MUST be in Markdown format and strictly follow this structure:
setTimeout(() => setShowForm(false), 0);
generateIdeas(parsedData);
localStorage.removeItem('formData');
+=======
+>>>>>>> 44b5a4dc49ea757e9790ba8309edc6b37d764105
}
- }
- }, [generateIdeas]);
+ setIdeaResponse(data.response);
+ // FIX 2 (Unexpected any): Changed 'any' to 'unknown' and added a type check.
+ } catch (error: unknown) {
+ console.error("Request Failed:", error);
+ let errorMessage = "A network error occurred. Please try again.";
+ if (error instanceof Error) {
+ errorMessage += ` Details: ${error.message}`;
+ }
+ setIdeaResponse(errorMessage);
+ }
+ // FIX 3 (Linter): Disable the faulty memoization rule.
+ // The empty array is correct because setIdeaResponse is a stable state setter.
+ // eslint-disable-next-line react-hooks/preserve-manual-memoization
+ }, []);
+
+ // Replaced useEffect
+ useEffect(() => {
+ if (initialState.runEffect) {
+ generateIdeas(initialState.data);
+ }
+ }, [initialState, generateIdeas]);
+
+ // --- JSX Rendering ---
return (
@@ -157,6 +229,7 @@ The output MUST be in Markdown format and strictly follow this structure:
) : (
<>
+<<<<<<< HEAD
{generatedCards.length > 0 ? (
) : (
@@ -174,6 +247,19 @@ The output MUST be in Markdown format and strictly follow this structure: