mirror of
https://github.com/PinkSheep27/SBU-Hackathon.git
synced 2026-10-10 23:50:26 -04:00
minor tweak to page.tsx
This commit is contained in:
+75
-40
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import React, { useState, useEffect, useCallback } from "react";
|
|
||||||
import FormPage from './FormPage';
|
import FormPage from './FormPage';
|
||||||
import { CardData } from "../exportType/types";
|
import { CardData } from "../exportType/types";
|
||||||
|
import SwipeCards from "../components/Cards";
|
||||||
import { ChatSetting } from "../exportType/types";
|
import { ChatSetting } from "../exportType/types";
|
||||||
import { FormData, PROFICIENCY_LEVELS } from './formTypes';
|
import { FormData, PROFICIENCY_LEVELS } from './formTypes';
|
||||||
import { saveProject } from '../utils/storage';
|
import { saveProject } from '../utils/storage';
|
||||||
@@ -42,35 +42,53 @@ const getInitialState = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
|
||||||
**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.]`
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState<FormData>(getDefaultFormData());
|
||||||
|
const [ideaResponse, setIdeaResponse] = useState<string>("");
|
||||||
|
const [generatedCards, setGeneratedCards] = useState<CardData[]>([]); // New state for parsed cards
|
||||||
const [initialState] = useState(getInitialState);
|
const [initialState] = useState(getInitialState);
|
||||||
const [showForm, setShowForm] = useState(initialState.showForm);
|
const [showForm, setShowForm] = useState(initialState.showForm);
|
||||||
const [formData, setFormData] = useState<FormData>(initialState.data);
|
const initialIdeaGenerationAttempted = useRef(false);
|
||||||
const [ideaResponse, setIdeaResponse] = useState<string>("");
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
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.
|
||||||
|
The output MUST be in Markdown format and strictly follow this structure:
|
||||||
|
### Project Idea Title
|
||||||
|
**Track** [print out the track you used]
|
||||||
|
**Concept:** [A concise, single paragraph description of the product and its primary function.]`,
|
||||||
|
});
|
||||||
|
|
||||||
const handleFormSubmitFromFormPage = (submittedData: FormData) => {
|
const generateIdeas = useCallback(async (dataToProcess: FormData) => {
|
||||||
const savedProject = saveProject(submittedData);
|
const parseAiResponse = (markdownString: string): CardData[] => {
|
||||||
if (typeof window !== 'undefined') localStorage.removeItem('formData');
|
console.log("Raw AI Response:", markdownString);
|
||||||
setFormData(submittedData);
|
const ideas: CardData[] = [];
|
||||||
setShowForm(false);
|
const ideaBlocks = markdownString.split("### ").filter(block => block.trim() !== "");
|
||||||
generateIdeas(submittedData, savedProject.id);
|
|
||||||
};
|
ideaBlocks.forEach((block, index) => {
|
||||||
|
const titleMatch = block.match(/^(.*?)(?=\n\*\*Track\*\*|$)/s);
|
||||||
|
const trackMatch = block.match(/\*\*Track\*\*\s*:\s*(.*?)(?=\n\*\*Concept\*\*|$)/s);
|
||||||
|
const conceptMatch = block.match(/\*\*Concept:\*\*\s*(.*)/s);
|
||||||
|
|
||||||
|
const title = titleMatch ? titleMatch[1].trim() : `Idea ${index + 1}`;
|
||||||
|
const summary = conceptMatch ? conceptMatch[1].trim() : "No concept provided.";
|
||||||
|
const tracksRaw = trackMatch ? trackMatch[1].trim() : "";
|
||||||
|
const tracks = tracksRaw.split(',').map(track => track.trim()).filter(track => track !== '');
|
||||||
|
|
||||||
|
ideas.push({
|
||||||
|
id: index + 1,
|
||||||
|
title,
|
||||||
|
tracks,
|
||||||
|
summary,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
console.log("Parsed Cards:", ideas);
|
||||||
|
return ideas;
|
||||||
|
};
|
||||||
|
|
||||||
const generateIdeas = useCallback(async (dataToProcess: FormData, projectId: string) => {
|
|
||||||
const submissionData: FormData = {
|
const submissionData: FormData = {
|
||||||
...dataToProcess,
|
...dataToProcess,
|
||||||
tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''),
|
tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''),
|
||||||
@@ -94,13 +112,15 @@ export default function Home() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setIdeaResponse("Generating ideas... Please wait.");
|
setIdeaResponse("Generating ideas... Please wait.");
|
||||||
|
setGeneratedCards([]);
|
||||||
const response = await fetch("/api/generate-idea", {
|
const response = await fetch("/api/generate-idea", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
settings: AI_SETTINGS,
|
settings: settings,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -113,6 +133,8 @@ export default function Home() {
|
|||||||
}
|
}
|
||||||
setIdeaResponse(data.response);
|
setIdeaResponse(data.response);
|
||||||
|
|
||||||
|
const projectId = data.projectId ?? `p-${Date.now()}`;
|
||||||
|
|
||||||
if (typeof window !== 'undefined') localStorage.setItem('temp_aiResponse', data.response);
|
if (typeof window !== 'undefined') localStorage.setItem('temp_aiResponse', data.response);
|
||||||
|
|
||||||
router.push(`/cards?projectId=${projectId}&projectTitle=${encodeURIComponent(dataToProcess.Hackathon)}`);
|
router.push(`/cards?projectId=${projectId}&projectTitle=${encodeURIComponent(dataToProcess.Hackathon)}`);
|
||||||
@@ -127,12 +149,19 @@ export default function Home() {
|
|||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
|
// Replaced useEffect
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (initialState.runEffect) {
|
if (initialState.runEffect) {
|
||||||
// generateIdeas(initialState.data, "some-resumed-id");
|
//generateIdeas(initialState.data, "some-resumed-id");
|
||||||
}
|
}
|
||||||
}, [initialState, generateIdeas]);
|
}, [initialState, generateIdeas]);
|
||||||
|
|
||||||
|
const handleFormSubmitFromFormPage = (submittedData: FormData) => {
|
||||||
|
setShowForm(false);
|
||||||
|
generateIdeas(submittedData);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- JSX Rendering ---
|
||||||
return (
|
return (
|
||||||
<main className="min-h-screen bg-gray-50 flex items-start justify-center p-4 sm:p-6 font-inter">
|
<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">
|
<div className="w-full max-w-2xl bg-white p-8 shadow-2xl rounded-xl mt-8">
|
||||||
@@ -140,17 +169,23 @@ export default function Home() {
|
|||||||
<FormPage onFormSubmit={handleFormSubmitFromFormPage} />
|
<FormPage onFormSubmit={handleFormSubmitFromFormPage} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<h1 className="text-3xl font-extrabold text-center text-gray-800 mb-8 tracking-tight">
|
{generatedCards.length > 0 ? (
|
||||||
Generated Project Idea 💡
|
<SwipeCards initialCards={generatedCards} />
|
||||||
</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>
|
<h1 className="text-3xl font-extrabold text-center text-gray-800 mb-8 tracking-tight">
|
||||||
<div
|
Generated Project Idea 💡
|
||||||
className="prose max-w-none"
|
</h1>
|
||||||
dangerouslySetInnerHTML={{ __html: ideaResponse.replace(/\n/g, '<br/>') }}
|
<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>
|
||||||
{ideaResponse === "" && <p className="text-gray-500">Submit the form to generate project ideas.</p>}
|
<div
|
||||||
</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>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowForm(true);
|
setShowForm(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user