mirror of
https://github.com/PinkSheep27/SBU-Hackathon.git
synced 2026-10-11 00:40:25 -04:00
merge bunch of files (mostly page.tsx's and Gemini stuff)
This commit is contained in:
+119
-33
@@ -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<FormData>(() => {
|
||||
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<string>("");
|
||||
const [generatedCards, setGeneratedCards] = useState<CardData[]>([]); // New state for parsed cards
|
||||
|
||||
const [settings] = useState<ChatSetting>({
|
||||
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<FormData>(initialState.data);
|
||||
const [ideaResponse, setIdeaResponse] = useState<string>("");
|
||||
|
||||
// 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 (
|
||||
<main className="min-h-screen bg-gray-50 flex items-start justify-center p-4 sm:p-6 font-inter">
|
||||
<div className="w-full max-w-2xl bg-white p-8 shadow-2xl rounded-xl mt-8">
|
||||
@@ -157,6 +229,7 @@ The output MUST be in Markdown format and strictly follow this structure:
|
||||
<FormPage onFormSubmit={handleFormSubmitFromFormPage} />
|
||||
) : (
|
||||
<>
|
||||
<<<<<<< HEAD
|
||||
{generatedCards.length > 0 ? (
|
||||
<SwipeCards initialCards={generatedCards} />
|
||||
) : (
|
||||
@@ -174,6 +247,19 @@ The output MUST be in Markdown format and strictly follow this structure:
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
=======
|
||||
<h1 className="text-3xl font-extrabold text-center text-gray-800 mb-8 tracking-tight">
|
||||
Generated Project Idea 💡
|
||||
</h1>
|
||||
<div className="mt-8 p-4 bg-yellow-50 rounded-lg border border-yellow-200">
|
||||
<h2 className="text-xl font-bold text-gray-700 mb-2">Generated Ideas:</h2>
|
||||
<div
|
||||
className="prose max-w-none"
|
||||
dangerouslySetInnerHTML={{ __html: ideaResponse.replace(/\n/g, '<br/>') }}
|
||||
/>
|
||||
{ideaResponse === "" && <p className="text-gray-500">Submit the form to generate project ideas.</p>}
|
||||
</div>
|
||||
>>>>>>> 44b5a4dc49ea757e9790ba8309edc6b37d764105
|
||||
<button
|
||||
onClick={() => setShowForm(true)}
|
||||
className="mt-6 w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-lg text-lg font-semibold text-white bg-blue-600 hover:bg-blue-700 transition duration-150"
|
||||
|
||||
Reference in New Issue
Block a user