From 972df9b70b9bab8588351fcf332c3e8e1ea3e7fa Mon Sep 17 00:00:00 2001 From: PawelC4 Date: Sun, 9 Nov 2025 00:07:25 -0500 Subject: [PATCH 1/4] formatting --- app/Dashboard/page.tsx | 224 ++++---- app/api/chat/route.ts | 42 +- app/api/generate-idea/route.ts | 40 +- app/cards/page.tsx | 378 ++++++------- app/chatbot/page.tsx | 220 ++++---- .../components}/ProtectedNavButton.tsx | 4 +- app/exportType/types.ts | 50 +- app/formfile/FormPage.tsx | 524 +++++++++--------- app/formfile/formTypes.ts | 36 +- app/formfile/generate-idea.ts | 112 ++-- app/formfile/page.tsx | 336 ++++++----- app/globals.css | 26 + app/layout.tsx | 1 + app/page.tsx | 327 ++++++++--- app/utils/geminiHelper.ts | 70 +-- 15 files changed, 1283 insertions(+), 1107 deletions(-) rename {components => app/components}/ProtectedNavButton.tsx (84%) diff --git a/app/Dashboard/page.tsx b/app/Dashboard/page.tsx index a3a4eba..dfe6113 100644 --- a/app/Dashboard/page.tsx +++ b/app/Dashboard/page.tsx @@ -1,121 +1,121 @@ -"use client"; +// "use client"; -import React, { useState } from "react"; -import { useRouter } from "next/navigation"; -import Link from 'next/link'; +// import React, { useState } from "react"; +// import { useRouter } from "next/navigation"; +// import Link from 'next/link'; -export default function Dashboard() { - const router = useRouter(); - const [query, setQuery] = useState(""); - const [sideBarOpen, setSidebarOpen] = useState(true); +// function Dashboard() { // 2. Changed from 'export default function' +// const router = useRouter(); +// const [query, setQuery] = useState(""); +// const [sideBarOpen, setSidebarOpen] = useState(true); - const projects = [ - { name: "Alpha Project", createdAt: "2025-01-01" }, - { name: "Beta Board", createdAt: "2025-02-15" }, - { name: "Gamma Tasl", createdAt: "2025-03-10" }, - ]; - const filtered = projects.filter((p) => - p.name.toLowerCase().includes(query.toLowerCase()) - ); +// const projects = [ +// { name: "Alpha Project", createdAt: "2025-01-01" }, +// { name: "Beta Board", createdAt: "2025-02-15" }, +// { name: "Gamma Tasl", createdAt: "2025-03-10" }, +// ]; +// const filtered = projects.filter((p) => +// p.name.toLowerCase().includes(query.toLowerCase()) +// ); - return ( -
- -
-
-
-
- setQuery(e.target.value)} - placeholder="Search projects, boards or tasks..." - className="w-full max-w-md px-4 py-2 rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-blue-500" - /> -
+//
+//
+//
+//
+// setQuery(e.target.value)} +// placeholder="Search projects, boards or tasks..." +// className="w-full max-w-md px-4 py-2 rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-blue-500" +// /> +//
-
- -
-
-
+//
+// +//
+//
+//
-
-

- Project Names -

+//
+//

+// Project Names +//

-
-
    - {filtered.map((project, index) => ( -
  • - {project.name} - - Created: {project.createdAt} - -
  • - ))} - {filtered.length === 0 && ( -
  • No results found
  • - )} -
-
-
-
-
- ); -} \ No newline at end of file +//
+// +//
+// +// +// +// ); +// } \ No newline at end of file diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index eeb8b31..3c980c0 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,24 +1,24 @@ -import { NextResponse } from "next/server"; -import { chatToGemini } from "@/app/utils/geminiHelper"; -import { ChatHistory, ChatSetting } from "@/app/exportType/types"; +// import { NextResponse } from "next/server"; +// import { chatToGemini } from "@/app/utils/geminiHelper"; +// import { ChatHistory, ChatSetting } from "@/app/exportType/types"; -export async function POST(request: Request) { - try { - const { userMessage, history , settings } = await request.json() as { - userMessage :string; - history : ChatHistory; - settings : ChatSetting; - }; +// export async function POST(request: Request) { +// try { +// const { userMessage, history , settings } = await request.json() as { +// userMessage :string; +// history : ChatHistory; +// settings : ChatSetting; +// }; - const aiResponse = await chatToGemini(userMessage , history, settings); - return NextResponse.json({response : aiResponse}); - } - catch(error){ - console.error(error); - return NextResponse.json( - {error: "Error with the model response "}, - {status : 500} - ); - } -} +// const aiResponse = await chatToGemini(userMessage , history, settings); +// return NextResponse.json({response : aiResponse}); +// } +// catch(error){ +// console.error(error); +// return NextResponse.json( +// {error: "Error with the model response "}, +// {status : 500} +// ); +// } +// } diff --git a/app/api/generate-idea/route.ts b/app/api/generate-idea/route.ts index c135cd4..517ec6c 100644 --- a/app/api/generate-idea/route.ts +++ b/app/api/generate-idea/route.ts @@ -1,23 +1,23 @@ -import { NextResponse } from "next/server"; -import { chatToGemini } from "@/app/utils/geminiHelper"; -import { ChatSetting } from "@/app/exportType/types"; +// import { NextResponse } from "next/server"; +// import { chatToGemini } from "@/app/utils/geminiHelper"; +// import { ChatSetting } from "@/app/exportType/types"; -export async function POST(request: Request) { - try { - const { prompt, settings } = await request.json() as { - prompt :string; - settings : ChatSetting; - }; +// export async function POST(request: Request) { +// try { +// const { prompt, settings } = await request.json() as { +// prompt :string; +// settings : ChatSetting; +// }; - const aiResponse = await chatToGemini(prompt , [], settings); - return NextResponse.json({response : aiResponse}); - } - catch(error){ - console.error(error); - return NextResponse.json( - {error: "Error with the model response "}, - {status : 500} - ); - } -} +// const aiResponse = await chatToGemini(prompt , [], settings); +// return NextResponse.json({response : aiResponse}); +// } +// catch(error){ +// console.error(error); +// return NextResponse.json( +// {error: "Error with the model response "}, +// {status : 500} +// ); +// } +// } diff --git a/app/cards/page.tsx b/app/cards/page.tsx index 0da2c42..5c4858a 100644 --- a/app/cards/page.tsx +++ b/app/cards/page.tsx @@ -1,210 +1,210 @@ -"use client"; +// "use client"; -import React, { useState, useEffect } from "react"; -import { motion, useMotionValue, useTransform, useAnimation } from "framer-motion"; -import { useRouter } from "next/navigation"; +// import React, { useState, useEffect } from "react"; +// import { motion, useMotionValue, useTransform, useAnimation } from "framer-motion"; +// import { useRouter } from "next/navigation"; -// 1. Updated ColorWay interface -interface ColorWay { - card: string; - text: string; - titleColor: string; // Added title color -} +// // 1. Updated ColorWay interface +// interface ColorWay { +// card: string; +// text: string; +// titleColor: string; // Added title color +// } -// 2. Updated COLOR_WAYS array -const COLOR_WAYS: ColorWay[] = [ - { card: "#FEEEDF", text: "#173C46", titleColor: "#173C46" }, - { card: "#FEEEDF", text: "#EA627F", titleColor: "#173C46" }, // Example: Title is dark, text is pink - { card: "#DEE5D4", text: "#173C46", titleColor: "#EA627F" }, - { card: "#DEE5D4", text: "#EA627F", titleColor: "#173C46" }, - { card: "#B8C0AD", text: "#173C46", titleColor: "#173C46" }, - { card: "#B8C0AD", text: "#173C46", titleColor: "#EA627F" }, -]; +// // 2. Updated COLOR_WAYS array +// const COLOR_WAYS: ColorWay[] = [ +// { card: "#FEEEDF", text: "#173C46", titleColor: "#173C46" }, +// { card: "#FEEEDF", text: "#EA627F", titleColor: "#173C46" }, // Example: Title is dark, text is pink +// { card: "#DEE5D4", text: "#173C46", titleColor: "#EA627F" }, +// { card: "#DEE5D4", text: "#EA627F", titleColor: "#173C46" }, +// { card: "#B8C0AD", text: "#173C46", titleColor: "#173C46" }, +// { card: "#B8C0AD", text: "#173C46", titleColor: "#EA627F" }, +// ]; -interface CardData { - id: number; - title: string; - summary: string; - tracks: string[]; -} +// interface CardData { +// id: number; +// title: string; +// summary: string; +// tracks: string[]; +// } -const SwipeCards: React.FC<{ initialCards: CardData[] }> = ({ initialCards }) => { - const [cards, setCards] = useState(initialCards); - const router = useRouter(); +// const SwipeCards: React.FC<{ initialCards: CardData[] }> = ({ initialCards }) => { +// const [cards, setCards] = useState(initialCards); +// const router = useRouter(); - // Update cards state when initialCards prop changes - useEffect(() => { - setCards(initialCards); - }, [initialCards]); +// // Update cards state when initialCards prop changes +// useEffect(() => { +// setCards(initialCards); +// }, [initialCards]); - const removeCard = () => { - setCards((prev) => prev.slice(0, prev.length - 1)); - }; +// const removeCard = () => { +// setCards((prev) => prev.slice(0, prev.length - 1)); +// }; - const handleAccept = (cardData: CardData) => { - removeCard(); - // Redirect to chatbot with card data - router.push(`/chatbot?title=${encodeURIComponent(cardData.title)}&summary=${encodeURIComponent(cardData.summary)}`); - }; +// const handleAccept = (cardData: CardData) => { +// removeCard(); +// // Redirect to chatbot with card data +// router.push(`/chatbot?title=${encodeURIComponent(cardData.title)}&summary=${encodeURIComponent(cardData.summary)}`); +// }; - const handleReject = () => { - removeCard(); - }; +// const handleReject = () => { +// removeCard(); +// }; - const handleReset = () => { - setCards([]); // Reset to initial cards - }; +// const handleReset = () => { +// setCards([]); // Reset to initial cards +// }; - return ( -
- {cards.length > 0 ? ( - cards.map((card, index) => { - const colorWay = COLOR_WAYS[card.id % COLOR_WAYS.length]; - return ( - - ); - }) - ) : ( - // ... (empty state) -
-

- No more cards! -

-

- You've swiped through them all. -

- -
- )} -
- ); -}; +// return ( +//
+// {cards.length > 0 ? ( +// cards.map((card, index) => { +// const colorWay = COLOR_WAYS[card.id % COLOR_WAYS.length]; +// return ( +// +// ); +// }) +// ) : ( +// // ... (empty state) +//
+//

+// No more cards! +//

+//

+// You've swiped through them all. +//

+// +//
+// )} +//
+// ); +// }; -interface CardProps { - cardData: CardData; - colorWay: ColorWay; - isFront: boolean; - onAccept: (cardData: CardData) => void; - onReject: () => void; -} +// interface CardProps { +// cardData: CardData; +// colorWay: ColorWay; +// isFront: boolean; +// onAccept: (cardData: CardData) => void; +// onReject: () => void; +// } -const Card: React.FC = ({ cardData, colorWay, isFront, onAccept, onReject }) => { - const { title, summary, tracks } = cardData; +// const Card: React.FC = ({ cardData, colorWay, isFront, onAccept, onReject }) => { +// const { title, summary, tracks } = cardData; - const x = useMotionValue(0); - const rotate = useTransform(x, [-250, 250], [-25, 25]); - const opacity = useTransform( - x, - [-250, -100, 0, 100, 250], - [0, 1, 1, 1, 0], - ); - const controls = useAnimation(); +// const x = useMotionValue(0); +// const rotate = useTransform(x, [-250, 250], [-25, 25]); +// const opacity = useTransform( +// x, +// [-250, -100, 0, 100, 250], +// [0, 1, 1, 1, 0], +// ); +// const controls = useAnimation(); - const acceptOpacity = useTransform(x, [50, 150], [0, 1]); - const rejectOpacity = useTransform(x, [-150, -50], [1, 0]); - const badgeRotate = useTransform(x, [-150, 150], [-15, 15]); +// const acceptOpacity = useTransform(x, [50, 150], [0, 1]); +// const rejectOpacity = useTransform(x, [-150, -50], [1, 0]); +// const badgeRotate = useTransform(x, [-150, 150], [-15, 15]); - const handleDragEnd = async (event: MouseEvent | TouchEvent | PointerEvent, info: { offset: { x: number } }) => { - if (info.offset.x > 100) { - // Card accepted - await controls.start({ x: 1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly - onAccept(cardData); // Then call onAccept which removes the card and redirects - } else if (info.offset.x < -100) { - // Card rejected - await controls.start({ x: -1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly - onReject(); // Then call onReject which removes the card - } else { - // Card not swiped far enough, snap back to center - controls.start({ x: 0, rotate: 0, opacity: 1, transition: { type: "spring", stiffness: 300, damping: 30 } }); - } - }; +// const handleDragEnd = async (event: MouseEvent | TouchEvent | PointerEvent, info: { offset: { x: number } }) => { +// if (info.offset.x > 100) { +// // Card accepted +// await controls.start({ x: 1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly +// onAccept(cardData); // Then call onAccept which removes the card and redirects +// } else if (info.offset.x < -100) { +// // Card rejected +// await controls.start({ x: -1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly +// onReject(); // Then call onReject which removes the card +// } else { +// // Card not swiped far enough, snap back to center +// controls.start({ x: 0, rotate: 0, opacity: 1, transition: { type: "spring", stiffness: 300, damping: 30 } }); +// } +// }; - return ( - - {/* Accept/Reject Badges */} - -

Accept

-
- -

Reject

-
+// return ( +// +// {/* Accept/Reject Badges */} +// +//

Accept

+//
+// +//

Reject

+//
- {/* Card Content */} -
- {/* 3. Applied the specific titleColor here */} -

- {title} -

- {/* This summary

will inherit colorWay.text from the parent */} -

{summary}

-
+// {/* Card Content */} +//
+// {/* 3. Applied the specific titleColor here */} +//

+// {title} +//

+// {/* This summary

will inherit colorWay.text from the parent */} +//

{summary}

+//
-
- {tracks.slice(0, 2).map((track, index) => ( - - {track} - {index === 0 && tracks.length > 1 && ", "} - - ))} -
-
- ); +//
+// {tracks.slice(0, 2).map((track, index) => ( +// +// {track} +// {index === 0 && tracks.length > 1 && ", "} +// +// ))} +//
+//
+// ); -}; +// }; -export default SwipeCards; +// export default SwipeCards; diff --git a/app/chatbot/page.tsx b/app/chatbot/page.tsx index 363f852..37e8143 100644 --- a/app/chatbot/page.tsx +++ b/app/chatbot/page.tsx @@ -1,135 +1,135 @@ -"use client"; +// "use client"; -import { useState, useEffect, useRef, useCallback } from "react"; -import { useSearchParams } from "next/navigation"; -import ChatInput from "../utils/component/ui/ChatInput"; -import MessageWindow from "../utils/component/ui/MessageWindow"; -import { ChatHistory, ChatSetting, Message , MessageRole } from "@/app/exportType/types"; +// import { useState, useEffect, useRef, useCallback } from "react"; +// import { useSearchParams } from "next/navigation"; +// import ChatInput from "../utils/component/ui/ChatInput"; +// import MessageWindow from "../utils/component/ui/MessageWindow"; +// import { ChatHistory, ChatSetting, Message , MessageRole } from "@/app/exportType/types"; -export default function Home(){ - const [history, setHistory] = useState([]) - const historyRef = useRef([]); // Create a ref for history - const [settings] = useState({ - temperature:1, - model:"gemini-2.5-pro", - sysTemInstructions:"you are a ai helper. Your goal is to expand the project idea and interact with the user on any problem or question they have with the project. You are not allow to code the project for them and stray away from your job" +// export default function Home(){ +// const [history, setHistory] = useState([]) +// const historyRef = useRef([]); // Create a ref for history +// const [settings] = useState({ +// temperature:1, +// model:"gemini-2.5-pro", +// sysTemInstructions:"you are a ai helper. Your goal is to expand the project idea and interact with the user on any problem or question they have with the project. You are not allow to code the project for them and stray away from your job" - }); - const searchParams = useSearchParams(); - const initialMessageSent = useRef(false); +// }); +// const searchParams = useSearchParams(); +// const initialMessageSent = useRef(false); - useEffect(() => { - historyRef.current = history; // Keep the ref updated with the latest history - }, [history]); +// useEffect(() => { +// historyRef.current = history; // Keep the ref updated with the latest history +// }, [history]); - const handleSend = useCallback(async(message:string)=>{ - const newUserMessage:Message = { - role:"user", - parts:[{text:message}], - }; +// const handleSend = useCallback(async(message:string)=>{ +// const newUserMessage:Message = { +// role:"user", +// parts:[{text:message}], +// }; - setHistory(prevHistory => { - const currentHistory = [...prevHistory, newUserMessage]; +// setHistory(prevHistory => { +// const currentHistory = [...prevHistory, newUserMessage]; - const sendApiRequest = async () => { - try{ - const response = await fetch("/api/chat", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - userMessage: message, - history: historyRef.current, // Use the ref for history - settings: settings, - }), - }); +// const sendApiRequest = async () => { +// try{ +// const response = await fetch("/api/chat", { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// }, +// body: JSON.stringify({ +// userMessage: message, +// history: historyRef.current, // Use the ref for history +// settings: settings, +// }), +// }); - const data = await response.json(); +// const data = await response.json(); - if (data.error) { - console.error("AI Error:", data.error); - return; - } +// if (data.error) { +// console.error("AI Error:", data.error); +// return; +// } - const aiMessage: Message = { - role: "model" as MessageRole, - parts: [{ text: data.response }], - }; +// const aiMessage: Message = { +// role: "model" as MessageRole, +// parts: [{ text: data.response }], +// }; - setHistory(prevHistory => [...prevHistory, aiMessage]); +// setHistory(prevHistory => [...prevHistory, aiMessage]); - } - catch (error) { - console.error("Request Failed:", error); - } - }; - sendApiRequest(); +// } +// catch (error) { +// console.error("Request Failed:", error); +// } +// }; +// sendApiRequest(); - return currentHistory; - }); - }, [settings]); // Now handleSend only depends on settings +// return currentHistory; +// }); +// }, [settings]); // Now handleSend only depends on settings - useEffect(() => { - if (!initialMessageSent.current) { - const title = searchParams.get('title'); - const summary = searchParams.get('summary'); +// useEffect(() => { +// if (!initialMessageSent.current) { +// const title = searchParams.get('title'); +// const summary = searchParams.get('summary'); - if (title && summary) { - const message = `Explain the project titled '${title}' with the summary '${summary}' in detail, and suggest suitable roles for a team working on it.`; +// if (title && summary) { +// const message = `Explain the project titled '${title}' with the summary '${summary}' in detail, and suggest suitable roles for a team working on it.`; - const newUserMessage: Message = { - role: "user", - parts: [{ text: message }], - }; +// const newUserMessage: Message = { +// role: "user", +// parts: [{ text: message }], +// }; - setTimeout(() => { - setHistory((prevHistory) => [...prevHistory, newUserMessage]); // Add user message to history - }, 0); +// setTimeout(() => { +// setHistory((prevHistory) => [...prevHistory, newUserMessage]); // Add user message to history +// }, 0); - const sendInitialApiRequest = async () => { - try { - const response = await fetch("/api/chat", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - userMessage: message, - history: [...historyRef.current, newUserMessage], // Use ref for history - settings: settings, - }), - }); +// const sendInitialApiRequest = async () => { +// try { +// const response = await fetch("/api/chat", { +// method: "POST", +// headers: { +// "Content-Type": "application/json", +// }, +// body: JSON.stringify({ +// userMessage: message, +// history: [...historyRef.current, newUserMessage], // Use ref for history +// settings: settings, +// }), +// }); - const data = await response.json(); +// const data = await response.json(); - if (data.error) { - console.error("AI Error:", data.error); - return; - } +// if (data.error) { +// console.error("AI Error:", data.error); +// return; +// } - const aiMessage: Message = { - role: "model" as MessageRole, - parts: [{ text: data.response }], - }; +// const aiMessage: Message = { +// role: "model" as MessageRole, +// parts: [{ text: data.response }], +// }; - setHistory((prevHistory) => [...prevHistory, aiMessage]); - } catch (error) { - console.error("Request Failed:", error); - } - }; +// setHistory((prevHistory) => [...prevHistory, aiMessage]); +// } catch (error) { +// console.error("Request Failed:", error); +// } +// }; - sendInitialApiRequest(); - initialMessageSent.current = true; - } - } - }, [searchParams, settings]); // Dependencies for this useEffect +// sendInitialApiRequest(); +// initialMessageSent.current = true; +// } +// } +// }, [searchParams, settings]); // Dependencies for this useEffect - return ( -
- - {}} /> -
- ); -} \ No newline at end of file +// return ( +//
+// +// {}} /> +//
+// ); +// } \ No newline at end of file diff --git a/components/ProtectedNavButton.tsx b/app/components/ProtectedNavButton.tsx similarity index 84% rename from components/ProtectedNavButton.tsx rename to app/components/ProtectedNavButton.tsx index 34fa0e7..eedd6a6 100644 --- a/components/ProtectedNavButton.tsx +++ b/app/components/ProtectedNavButton.tsx @@ -19,7 +19,9 @@ export default function ProtectedNavButton({ const token = typeof window !== "undefined" ? localStorage.getItem("token") : null; if (token) { - router.push("/dashboard"); + // 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"); } diff --git a/app/exportType/types.ts b/app/exportType/types.ts index eca26ad..3c9a4c0 100644 --- a/app/exportType/types.ts +++ b/app/exportType/types.ts @@ -1,30 +1,30 @@ -export type MessageRole = "user" | "model"; +// export type MessageRole = "user" | "model"; -export type MessagePart = { - text: string; -} +// export type MessagePart = { +// text: string; +// } -export interface Message{ - role: MessageRole; - parts:MessagePart[]; -} -export type ChatHistory = Message[]; +// export interface Message{ +// role: MessageRole; +// parts:MessagePart[]; +// } +// export type ChatHistory = Message[]; -export interface GenerateConfig{ - temperature : number; - topP : number; - responseMimeType : string; -} +// export interface GenerateConfig{ +// temperature : number; +// topP : number; +// responseMimeType : string; +// } -export interface ChatSetting{ - temperature :number; - model: string; - sysTemInstructions: string; -} +// export interface ChatSetting{ +// temperature :number; +// model: string; +// sysTemInstructions: string; +// } -export interface CardData { - id: number; - title: string; - tracks: string[]; - summary: string; -} \ No newline at end of file +// export interface CardData { +// id: number; +// title: string; +// tracks: string[]; +// summary: string; +// } \ No newline at end of file diff --git a/app/formfile/FormPage.tsx b/app/formfile/FormPage.tsx index 8059518..acdfc85 100644 --- a/app/formfile/FormPage.tsx +++ b/app/formfile/FormPage.tsx @@ -1,294 +1,294 @@ -"use client"; +// "use client"; -import React, { useState } from "react"; +// import React, { useState } from "react"; -import { - FormData, - PROFICIENCY_LEVELS -} from './formTypes'; // Ensure path is correct +// import { +// FormData, +// PROFICIENCY_LEVELS +// } from './formTypes'; // Ensure path is correct -interface FormPageProps { - onFormSubmit: (data: FormData) => void; -} +// interface FormPageProps { +// onFormSubmit: (data: FormData) => void; +// } -const FormPage: React.FC = ({ onFormSubmit }) => { - const [formData, setFormData] = useState({ - Hackathon: '', - mainTheme: '', - tracksStack: [''], - students: [{ - studentName: '', - skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] - }], - }); +// const FormPage: React.FC = ({ onFormSubmit }) => { +// const [formData, setFormData] = useState({ +// Hackathon: '', +// mainTheme: '', +// tracksStack: [''], +// students: [{ +// studentName: '', +// skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] +// }], +// }); - const handleChange = (event: React.ChangeEvent) => { - setFormData({ - ...formData, - [event.target.name]: event.target.value, - }); - }; +// const handleChange = (event: React.ChangeEvent) => { +// setFormData({ +// ...formData, +// [event.target.name]: event.target.value, +// }); +// }; - const handleTracksChange = (event: React.ChangeEvent, index: number) => { - const newTracksStack = [...formData.tracksStack]; - newTracksStack[index] = event.target.value; +// const handleTracksChange = (event: React.ChangeEvent, index: number) => { +// const newTracksStack = [...formData.tracksStack]; +// newTracksStack[index] = event.target.value; - setFormData({ - ...formData, - tracksStack: newTracksStack, - }); - }; +// setFormData({ +// ...formData, +// tracksStack: newTracksStack, +// }); +// }; - const handleAddTracks = () => { - setFormData({ - ...formData, - tracksStack: [...formData.tracksStack, ''], - }); - }; +// const handleAddTracks = () => { +// setFormData({ +// ...formData, +// tracksStack: [...formData.tracksStack, ''], +// }); +// }; - const handleRemoveTracks = (index: number) => { - const newTracksStack = formData.tracksStack.filter((_, i) => i !== index); - setFormData({ - ...formData, - tracksStack: newTracksStack, - }); - }; +// const handleRemoveTracks = (index: number) => { +// const newTracksStack = formData.tracksStack.filter((_, i) => i !== index); +// setFormData({ +// ...formData, +// tracksStack: newTracksStack, +// }); +// }; - const handleStudentNameChange = (e: React.ChangeEvent, studentIndex: number) => { - const newStudents = [...formData.students]; - newStudents[studentIndex].studentName = e.target.value; - setFormData({ ...formData, students: newStudents }); - }; +// const handleStudentNameChange = (e: React.ChangeEvent, studentIndex: number) => { +// const newStudents = [...formData.students]; +// newStudents[studentIndex].studentName = e.target.value; +// setFormData({ ...formData, students: newStudents }); +// }; - const handleAddStudent = () => { - setFormData({ - ...formData, - students: [...formData.students, { studentName: '', skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] }] - }); - }; +// const handleAddStudent = () => { +// setFormData({ +// ...formData, +// students: [...formData.students, { studentName: '', skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] }] +// }); +// }; - const handleRemoveStudent = (studentIndex: number) => { - const newStudents = formData.students.filter((_, i) => i !== studentIndex); - setFormData({ ...formData, students: newStudents }); - }; +// const handleRemoveStudent = (studentIndex: number) => { +// const newStudents = formData.students.filter((_, i) => i !== studentIndex); +// setFormData({ ...formData, students: newStudents }); +// }; - const handleSkillChange = ( - e: React.ChangeEvent, - studentIndex: number, - skillIndex: number - ) => { - const newStudents = [...formData.students]; - const targetName = e.target.name; - const targetValue = e.target.value; +// const handleSkillChange = ( +// e: React.ChangeEvent, +// studentIndex: number, +// skillIndex: number +// ) => { +// const newStudents = [...formData.students]; +// const targetName = e.target.name; +// const targetValue = e.target.value; - if (targetName === 'skillName') { - newStudents[studentIndex].skills[skillIndex].skillName = targetValue; - } else if (targetName === 'proficiency') { - newStudents[studentIndex].skills[skillIndex].proficiency = targetValue; - } +// if (targetName === 'skillName') { +// newStudents[studentIndex].skills[skillIndex].skillName = targetValue; +// } else if (targetName === 'proficiency') { +// newStudents[studentIndex].skills[skillIndex].proficiency = targetValue; +// } - setFormData({ ...formData, students: newStudents }); - }; +// setFormData({ ...formData, students: newStudents }); +// }; - const handleAddSkill = (studentIndex: number) => { - const newStudents = [...formData.students]; - newStudents[studentIndex].skills.push({ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }); - setFormData({ ...formData, students: newStudents }); - }; +// const handleAddSkill = (studentIndex: number) => { +// const newStudents = [...formData.students]; +// newStudents[studentIndex].skills.push({ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }); +// setFormData({ ...formData, students: newStudents }); +// }; - const handleRemoveSkill = (studentIndex: number, skillIndex: number) => { - const newStudents = [...formData.students]; - newStudents[studentIndex].skills = newStudents[studentIndex].skills.filter((_, i) => i !== skillIndex); - setFormData({ ...formData, students: newStudents }); - }; +// const handleRemoveSkill = (studentIndex: number, skillIndex: number) => { +// const newStudents = [...formData.students]; +// newStudents[studentIndex].skills = newStudents[studentIndex].skills.filter((_, i) => i !== skillIndex); +// setFormData({ ...formData, students: newStudents }); +// }; - const handleSubmit = (event: React.FormEvent) => { - event.preventDefault(); - onFormSubmit(formData); // Call the prop function with formData - }; +// const handleSubmit = (event: React.FormEvent) => { +// event.preventDefault(); +// onFormSubmit(formData); // Call the prop function with formData +// }; - return ( -
-
-

- Generate Project Idea -

+// return ( +//
+//
+//

+// Generate Project Idea +//

-
-
-

Project Context

-
- - -
+// +//
+//

Project Context

+//
+// +// +//
-
- - -
-
+//
+// +// +//
+//
-
- -
- {formData.tracksStack.map((tracks, index) => ( -
- handleTracksChange(e, index)} - className="flex-grow px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-green-500 focus:border-green-500 transition duration-150" - /> - {formData.tracksStack.length > 1 && ( - - )} -
- ))} -
+//
+// +//
+// {formData.tracksStack.map((tracks, index) => ( +//
+// handleTracksChange(e, index)} +// className="flex-grow px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-green-500 focus:border-green-500 transition duration-150" +// /> +// {formData.tracksStack.length > 1 && ( +// +// )} +//
+// ))} +//
- -
+// +//
-
-

Team Members and Skills

+//
+//

Team Members and Skills

-
- {formData.students.map((student, studentIndex) => ( -
+//
+// {formData.students.map((student, studentIndex) => ( +//
-
-

Student #{studentIndex + 1}

- {formData.students.length > 1 && ( - - )} -
+//
+//

Student #{studentIndex + 1}

+// {formData.students.length > 1 && ( +// +// )} +//
-
- - handleStudentNameChange(e, studentIndex)} - className="w-full px-4 py-2 border border-indigo-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500" - /> -
+//
+// +// handleStudentNameChange(e, studentIndex)} +// className="w-full px-4 py-2 border border-indigo-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500" +// /> +//
-
-
Skills
- {student.skills.map((skill, skillIndex) => ( -
- handleSkillChange(e, studentIndex, skillIndex)} - className="flex-grow px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-purple-500 focus:border-purple-500" - /> - - {student.skills.length > 1 && ( - - )} -
- ))} - -
-
- ))} -
+//
+//
Skills
+// {student.skills.map((skill, skillIndex) => ( +//
+// handleSkillChange(e, studentIndex, skillIndex)} +// className="flex-grow px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-purple-500 focus:border-purple-500" +// /> +// +// {student.skills.length > 1 && ( +// +// )} +//
+// ))} +// +//
+//
+// ))} +//
- -
+// +//
- -
+// +// -
-
- ); -}; +//
+//
+// ); +// }; -export default FormPage; \ No newline at end of file +// export default FormPage; \ No newline at end of file diff --git a/app/formfile/formTypes.ts b/app/formfile/formTypes.ts index e3d23c6..d2cb325 100644 --- a/app/formfile/formTypes.ts +++ b/app/formfile/formTypes.ts @@ -1,21 +1,21 @@ -// Define Skill structure -export interface Skill { - skillName: string; - proficiency: string; -} +// // Define Skill structure +// export interface Skill { +// skillName: string; +// proficiency: string; +// } -// Define Student structure -export interface Student { - studentName: string; - skills: Skill[]; -} +// // Define Student structure +// export interface Student { +// studentName: string; +// skills: Skill[]; +// } -// Updated main form interface -export interface FormData { - Hackathon: string; - mainTheme: string; - tracksStack: string[]; - students: Student[]; // Array for dynamic students -} +// // Updated main form interface +// export interface FormData { +// Hackathon: string; +// mainTheme: string; +// tracksStack: string[]; +// students: Student[]; // Array for dynamic students +// } -export const PROFICIENCY_LEVELS = ['Beginner', 'Intermediate', 'Expert', 'Master']; \ No newline at end of file +// export const PROFICIENCY_LEVELS = ['Beginner', 'Intermediate', 'Expert', 'Master']; \ No newline at end of file diff --git a/app/formfile/generate-idea.ts b/app/formfile/generate-idea.ts index c9f1f3f..be76f38 100644 --- a/app/formfile/generate-idea.ts +++ b/app/formfile/generate-idea.ts @@ -1,71 +1,71 @@ -import { GoogleGenerativeAI } from "@google/generative-ai"; -import type { NextApiRequest, NextApiResponse } from 'next'; +// import { GoogleGenerativeAI } from "@google/generative-ai"; +// import type { NextApiRequest, NextApiResponse } from 'next'; -// Initialize the Gemini Client with your API Key -// IMPORTANT: The GEMINI_API_KEY should be an environment variable. -const apiKey = process.env.GEMINI_API_KEY; +// // Initialize the Gemini Client with your API Key +// // IMPORTANT: The GEMINI_API_KEY should be an environment variable. +// const apiKey = process.env.GEMINI_API_KEY; -if(!apiKey){ - throw new Error("api key not found"); -} -const ai = new GoogleGenerativeAI(apiKey); +// if(!apiKey){ +// throw new Error("api key not found"); +// } +// const ai = new GoogleGenerativeAI(apiKey); -// Define the handler function for the API route -export default async function handler( - req: NextApiRequest, - res: NextApiResponse -) { - // Only allow POST requests - if (req.method !== 'POST') { - return res.status(405).json({ error: 'Method Not Allowed' }); - } +// // Define the handler function for the API route +// export default async function handler( +// req: NextApiRequest, +// res: NextApiResponse +// ) { +// // Only allow POST requests +// if (req.method !== 'POST') { +// return res.status(405).json({ error: 'Method Not Allowed' }); +// } - // Destructure the data sent from the frontend - let { prompt, settings } = req.body; +// // Destructure the data sent from the frontend +// let { prompt, settings } = req.body; - // Basic validation - if (!prompt || typeof prompt !== 'string') { - return res.status(400).json({ error: 'Prompt is required' }); - } +// // Basic validation +// if (!prompt || typeof prompt !== 'string') { +// return res.status(400).json({ error: 'Prompt is required' }); +// } - // Modify the prompt to instruct the AI to generate only the game, concept, and track - prompt = `You're going to fill out a card base off the document. - you will Generate the project short title. - you will list out the track you used ${prompt}`; +// // Modify the prompt to instruct the AI to generate only the game, concept, and track +// prompt = `You're going to fill out a card base off the document. +// you will Generate the project short title. +// you will list out the track you used ${prompt}`; - try { - // 1. Call the Gemini API using the correct method signature +// try { +// // 1. Call the Gemini API using the correct method signature - const model = settings?.model || 'gemini-2.5-flash-lite'; - const generativeModel = ai.getGenerativeModel({ model }); +// const model = settings?.model || 'gemini-2.5-flash-lite'; +// const generativeModel = ai.getGenerativeModel({ model }); - // 1. Define the generation configuration object - const generationConfig = { - temperature: settings?.temperature || 0.9, - // The SDK property name for system instructions is 'systemInstruction' - systemInstruction: settings?.sysTemInstructions, - }; +// // 1. Define the generation configuration object +// const generationConfig = { +// temperature: settings?.temperature || 0.9, +// // The SDK property name for system instructions is 'systemInstruction' +// systemInstruction: settings?.sysTemInstructions, +// }; - // 2. Call generateContent with the single GenerateContentRequest object. - const result = await generativeModel.generateContent({ - // contents must be an array of Content objects - contents: [{ - role: "user", - parts: [{ text: prompt }] - }], +// // 2. Call generateContent with the single GenerateContentRequest object. +// const result = await generativeModel.generateContent({ +// // contents must be an array of Content objects +// contents: [{ +// role: "user", +// parts: [{ text: prompt }] +// }], - // The fixed property name that resolves the TypeScript error - generationConfig: generationConfig, - }); +// // The fixed property name that resolves the TypeScript error +// generationConfig: generationConfig, +// }); - // 2. Extract the response text - // The result object now contains a property 'text' at the top level for simple text generation - const geminiResponseText = result.response.text(); res.status(200).json({ response: geminiResponseText }); +// // 2. Extract the response text +// // The result object now contains a property 'text' at the top level for simple text generation +// const geminiResponseText = result.response.text(); res.status(200).json({ response: geminiResponseText }); - } catch (error) { - console.error("Gemini API Error:", error); - res.status(500).json({ error: 'Failed to generate idea from AI.' }); - } -} +// } catch (error) { +// console.error("Gemini API Error:", error); +// res.status(500).json({ error: 'Failed to generate idea from AI.' }); +// } +// } diff --git a/app/formfile/page.tsx b/app/formfile/page.tsx index ccf46ef..91678b7 100644 --- a/app/formfile/page.tsx +++ b/app/formfile/page.tsx @@ -1,188 +1,172 @@ -// 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 } from "../exportType/types"; +// import { FormData, PROFICIENCY_LEVELS } from './formTypes'; -"use client"; -import React, { useState, useEffect, useCallback } from "react"; -import FormPage from './FormPage'; -import { ChatSetting, CardData } from "@/app/exportType/types"; -import { FormData, PROFICIENCY_LEVELS } from './formTypes'; -import SwipeCards from '../cards/page'; +// // --- Helper function to get default form data --- +// const getDefaultFormData = (): FormData => ({ +// Hackathon: '', +// mainTheme: '', +// tracksStack: [''], +// students: [{ +// studentName: '', +// skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] +// }], +// }); -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; - } - } - return { - Hackathon: '', - mainTheme: '', - tracksStack: [''], - students: [{ - studentName: '', - skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] - }], - }; - }); +// // --- New Initializer Function --- +// const getInitialState = () => { +// if (typeof window === 'undefined') { +// return { +// 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 +// // 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 +// **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.]`, +// }; - 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. -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 parseAiResponse = (markdownString: string): CardData[] => { - console.log("Raw AI Response:", markdownString); - const ideas: CardData[] = []; - const ideaBlocks = markdownString.split("### ").filter(block => block.trim() !== ""); +// 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. - ideaBlocks.forEach((block, index) => { - // Match title: anything from the start of the block until the first newline or the start of "**Track**" - const titleMatch = block.match(/^(.*?)(?=\n\*\*Track\*\*|$)/s); - // Match track: "**Track**" followed by optional whitespace and then capture everything until the next "**Concept**" or end of block/line - const trackMatch = block.match(/\*\*Track\*\*\s*:\s*(.*?)(?=\n\*\*Concept\*\*|$)/s); // Added ':' and made whitespace more flexible - // Match concept: "**Concept:**" followed by optional whitespace and then capture everything until the end of the block - const conceptMatch = block.match(/\*\*Concept:\*\*\s*(.*)/s); +// const handleFormSubmitFromFormPage = (submittedData: FormData) => { +// setFormData(submittedData); +// setShowForm(false); +// generateIdeas(submittedData); +// }; - const title = titleMatch ? titleMatch[1].trim() : `Idea ${index + 1}`; - const summary = conceptMatch ? conceptMatch[1].trim() : "No concept provided."; - const tracksRaw = trackMatch ? trackMatch[1].trim() : ""; - console.log("tracksRaw:", tracksRaw); // Added console.log for debugging - const tracks = tracksRaw.split(',').map(track => track.trim()).filter(track => track !== ''); +// // Wrapped generateIdeas in useCallback +// const generateIdeas = useCallback(async (dataToProcess: FormData) => { +// // 1. Data Cleaning +// const submissionData: FormData = { +// ...dataToProcess, +// tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''), +// students: dataToProcess.students +// .map(student => ({ +// ...student, +// skills: student.skills.filter(skill => skill.skillName.trim() !== ''), +// })) +// .filter(student => student.studentName.trim() !== '' || student.skills.length > 0), +// }; - ideas.push({ - id: index + 1, - title, - tracks, - summary, - }); - }); - console.log("Parsed Cards:", ideas); - return ideas; -}; +// // 2. Prompt Construction +// const prompt = ` +// Hackathon: ${submissionData.Hackathon} +// Main Theme: ${submissionData.mainTheme} +// Required Tracks Stack: ${submissionData.tracksStack.join(', ')} +// 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.`; - const handleFormSubmitFromFormPage = (submittedData: FormData) => { - setFormData(submittedData); - setShowForm(false); - generateIdeas(submittedData); - }; +// // 3. API Call +// try { +// setIdeaResponse("Generating ideas... Please wait."); + +// 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 +// }), +// }); - // eslint-disable-next-line react-hooks/preserve-manual-memoization - const generateIdeas = useCallback(async (dataToProcess: FormData) => { - const submissionData: FormData = { - ...dataToProcess, - tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''), - students: dataToProcess.students - .map(student => ({ - ...student, - skills: student.skills.filter(skill => skill.skillName.trim() !== ''), - })) - .filter(student => student.studentName.trim() !== '' || student.skills.length > 0), - }; +// const data = await response.json(); +// if (data.error || !response.ok) { +// console.error("AI Error:", data.error); +// setIdeaResponse(`Error: Failed to generate idea. ${data.error || response.statusText}`); +// return; +// } +// 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 +// }, []); - const prompt = ` - Hackathon: ${submissionData.Hackathon} - Main Theme: ${submissionData.mainTheme} - Required Tracks Stack: ${submissionData.tracksStack.join(', ')} - Team Members and Skills: ${submissionData.students.map(s => - `${s.studentName || 'Unamed Member'} (Skills: ${s.skills.map(sk => `${sk.skillName} - ${sk.proficiency}`).join(', ')})` - ).join('; ')} +// // Replaced useEffect +// useEffect(() => { +// if (initialState.runEffect) { +// generateIdeas(initialState.data); +// } +// }, [initialState, generateIdeas]); - Using the SYSTEM INSTRUCTIONS, generate 5 project ideas based on the data above.`; - - try { - setIdeaResponse("Generating ideas... Please wait."); - setGeneratedCards([]); // Clear previous cards - const response = await fetch("/api/generate-idea", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - prompt: prompt, - settings: settings, - }), - }); - - const data = await response.json(); - - if (data.error || !response.ok) { - console.error("AI Error:", data.error); - setIdeaResponse(`Error: Failed to generate idea. ${data.error || response.statusText}`); - return; - } - - setIdeaResponse(data.response); - const parsedCards = parseAiResponse(data.response); - setGeneratedCards(parsedCards); - - } catch (error) { - console.error("Request Failed:", error); - let errorMessage = "An unknown error occurred."; - if (error instanceof Error) { - errorMessage = error.message; - } else if (typeof error === 'string') { - errorMessage = error; - } - setIdeaResponse(`A network error occurred. Please try again. Details: ${errorMessage}`); - } - }, [setIdeaResponse, setGeneratedCards, settings, parseAiResponse]); - - useEffect(() => { - if (typeof window !== 'undefined') { - const storedFormData = localStorage.getItem('formData'); - if (storedFormData) { - const parsedData: FormData = JSON.parse(storedFormData); - setTimeout(() => setShowForm(false), 0); - generateIdeas(parsedData); - localStorage.removeItem('formData'); - } - } - }, [generateIdeas]); - - return ( -
-
- {showForm ? ( - - ) : ( - <> - {generatedCards.length > 0 ? ( - - ) : ( - <> -

- Generated Project Idea 💡 -

-
-

Generated Ideas:

-
') }} - /> - {ideaResponse === "" &&

Submit the form to generate project ideas.

} -
- - )} - - - )} -
-
- ); -} \ No newline at end of file +// // --- JSX Rendering --- +// return ( +//
+//
+// {showForm ? ( +// +// ) : ( +// <> +//

+// Generated Project Idea 💡 +//

+//
+//

Generated Ideas:

+//
') }} +// /> +// {ideaResponse === "" &&

Submit the form to generate project ideas.

} +//
+// +// +// )} +//
+//
+// ); +// } \ No newline at end of file diff --git a/app/globals.css b/app/globals.css index 89e0fba..28e3220 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,3 +1,29 @@ +/* @import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +:root { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} */ /* 1. Import BOTH fonts in one go */ @import url('https://fonts.googleapis.com/css2?family=Concert+One&family=Pixelify+Sans:wght@400;700&display=swap'); diff --git a/app/layout.tsx b/app/layout.tsx index a396698..6c86ea1 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -4,6 +4,7 @@ import type { Metadata } from "next"; // 1. Import your two new fonts import { Concert_One, Pixelify_Sans } from "next/font/google"; import "./globals.css"; +// import { Auth0Provider } from "@auth0/nextjs-auth0"; // 2. Set up Concert One as the body/sans font const concertOne = Concert_One({ diff --git a/app/page.tsx b/app/page.tsx index f85cd0b..5bcb886 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,127 +1,290 @@ -"use client"; +import Image from "next/image"; +import ProtectedNavButton from "./components/ProtectedNavButton"; -import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; -import Image from 'next/image'; -import ProtectedNavButton from "../components/ProtectedNavButton"; -import Link from 'next/link'; - -export default function Page() { +export default function Home() {   return ( -    
+    
      
         -         -           +               
-      
-        
-           -          
-            

-              (project name) +      
+        
+          
+            

+              Welcome! This is HackSpark             

-            

-              Looking for a starting point or more instructions? Head over to{" "} -               +              Got a hackathon coming up? Tell us your track, your team’s skills, what you’re passionate about, and more — and we’ll provide you with the perfect project idea!{" "} +              {/*                 Templates -              {" "} +              {" "}               or the{" "} -                               Learning -              {" "} -              center. +              {" "} */} +              {/* center. */}             

-            Get Started +            {/* Get Started */} +                       
          
-            
+            
              Image Placeholder             
          
-        
+          
   -        
-          
-            

-              Guide: -            

-          
- -          
-            
-              

-                First Text Block +        
+          {/*
*/} +          
+            {/*
*/} +              

+                Guide:               

-              

-                This is the content for the first text block. You can write anything here. -              

-            
-            
-              
-                Image Placeholder -              
-            
-          
-           -          
-            
-              
-                Image Placeholder -              
-            
+            {/*
*/} -            
-              
+            
+              
                

-                  Second Text Block +                  First Text Block                 

                

-                  This is the content for the second text block. You can write anything here. +                  This is the content for the first text block. You can write anything here.                 

              
-            
-          
- -          
-            
-              

-                Third Text Block -              

-              

-                This is the content for the third text block. You can write anything here. -              

-            
-            
-              
+              
+                
                  Image Placeholder +                
              
            
-          
-        

+             +            
+              
+                
+                  Image Placeholder +                
+              
+              
+                
+                  

+                    Second Text Block +                  

+                  

+                    This is the content for the second text block. You can write anything here. +                  

+                
+              
+            
+ +            
+              
+                

+                  Third Text Block +                

+                

+                  This is the content for the third text block. You can write anything here. +                

+              
+              
+                
+                    Image Placeholder +                
+              
+            
+           +        

      
    
  ); } + + +// {/* */} + + +// "use client"; + +// import React, { use, useState } from "react"; +// import { useRouter } from "next/navigation"; + +// export default function Dashboard() { +//   const router = useRouter();   +//   const[query, setQuery] = useState(""); +//   // const [projects, setProjects] = useState( [ +//   //     { id: 1, name: "Alpha Project", createdAt: new Date("2025-01-01")}, +//   //     { id: 2, name: "Beta Board", createdAt: new Date("2025-02-15")}, +//   //     { id: 3, name: "Gamma Task", createdAt: new Date("2025-03-10")} +//   // ]); +//   // const [newProjectName, setNewProjectName] = useState(""); +//   // const filtered = projects.filter( (p) => p.name.toLowerCase().includes(query.toLowerCase()) ); +//   // const handleCreate = () => { +//   //   if(!newProjectName.trim()) return; +//   //   const newProject = { +//   //     id: projects.length+1, name: newProjectName, createdAt: new Date(), +//   //   }; +//   // }; +//   const projects = [ +//     {name: "Alpha Project", createdAt: "2025-01-01"}, +//     {name: "Beta Board", createdAt: "2025-02-15"}, +//     {name: "Gamma Tasl", createdAt: "2025-03-10"}, +//   ] +//   const filtered = projects.filter( +//     (p) => p.name.toLowerCase().includes(query.toLowerCase()) +//   ); + +//  return ( +//    
+//      
+//        
+//          
+//            {/* */} +//             setQuery(e.target.value)} +//              placeholder="Search projects, boards or tasks..." +//              className="w-full max-w-md px-4 py-2 rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-blue-500" +//            /> +//          
+ +//          
+//            {/* setNewProjectName(e.target.value)} +//               placeholder="New Project Name" +//               className="px-3 py-2 rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900  text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-blue-500" +//             /> */} +//              +//          
+//        
+//      
+ +//      
+//        

+//          Project Names +//        

+ +//        
+//          
    +//            {filtered.map((project, index) => ( +//              
  • +//                {project.name} +//                  +//                   {/* {project.createdAt.toLocaleDateString()} */} +//                   Created: {project.createdAt} +//                  +//              
  • +//            ))} + +//            {filtered.length === 0 && ( +//              
  • No results found
  • +//            )} +//          
+//        
+//      
+//    
+//  ); +// } fix the formatting of this page, I want the divs to be more centered and the divs below the button to be equal size \ No newline at end of file diff --git a/app/utils/geminiHelper.ts b/app/utils/geminiHelper.ts index 4fa619c..6615637 100644 --- a/app/utils/geminiHelper.ts +++ b/app/utils/geminiHelper.ts @@ -1,42 +1,42 @@ -import { GoogleGenerativeAI } from "@google/generative-ai"; -import { ChatHistory, GenerateConfig,ChatSetting } from "../exportType/types"; +// import { GoogleGenerativeAI } from "@google/generative-ai"; +// import { ChatHistory, GenerateConfig,ChatSetting } from "../exportType/types"; -const apiKey = process.env.GEMINI_API_KEY; +// const apiKey = process.env.GEMINI_API_KEY; -if(!apiKey){ - throw new Error("api key not found"); -} +// if(!apiKey){ +// throw new Error("api key not found"); +// } -const genAI = new GoogleGenerativeAI(apiKey); +// const genAI = new GoogleGenerativeAI(apiKey); -export async function chatToGemini( - userMessage:string , - history:ChatHistory, - settings:ChatSetting -):Promise{ - const model = genAI.getGenerativeModel({ - model:settings.model || "gemini-2.5-flash", - systemInstruction: settings.sysTemInstructions || "you are going to create a project idea, explain it in summery first before going to detail", - }); +// export async function chatToGemini( +// userMessage:string , +// history:ChatHistory, +// settings:ChatSetting +// ):Promise{ +// const model = genAI.getGenerativeModel({ +// model:settings.model || "gemini-2.5-flash", +// systemInstruction: settings.sysTemInstructions || "you are going to create a project idea, explain it in summery first before going to detail", +// }); - const generationConfig:GenerateConfig = { - temperature : settings.temperature || 1, - topP : 0.9, - responseMimeType: "text/plain", - maxOutputTokens: 1900, // Increased to allow for longer responses - } +// const generationConfig:GenerateConfig = { +// temperature : settings.temperature || 1, +// topP : 0.9, +// responseMimeType: "text/plain", +// maxOutputTokens: 1900, // Increased to allow for longer responses +// } - const chatSession = model.startChat({ - generationConfig, - history - }) +// const chatSession = model.startChat({ +// generationConfig, +// history +// }) - try { - const result = await chatSession.sendMessage(userMessage); - return result.response.text(); - } - catch(error){ - console.error(error) - throw error - } - } \ No newline at end of file +// try { +// const result = await chatSession.sendMessage(userMessage); +// return result.response.text(); +// } +// catch(error){ +// console.error(error) +// throw error +// } +// } \ No newline at end of file From 44b5a4dc49ea757e9790ba8309edc6b37d764105 Mon Sep 17 00:00:00 2001 From: PawelC4 Date: Sun, 9 Nov 2025 00:37:24 -0500 Subject: [PATCH 2/4] Fixed commented out programs --- app/Dashboard/page.tsx | 222 +++++----- app/api/chat/route.ts | 42 +- app/api/generate-idea/route.ts | 40 +- app/cards/page.tsx | 378 ++++++++-------- app/chatbot/page.tsx | 228 +++++----- app/components/Cards.tsx | 300 +++++++++++++ app/components/ProtectedNavButton.tsx | 46 +- app/exportType/types.ts | 50 +-- app/formfile/FormPage.tsx | 524 +++++++++++------------ app/formfile/formTypes.ts | 36 +- app/formfile/generate-idea.ts | 118 ++--- app/formfile/page.tsx | 318 +++++++------- app/globals.css | 13 +- app/page.tsx | 283 ++++++------ app/utils/component/ui/ChatInput.tsx | 97 +++-- app/utils/component/ui/MessageWindow.tsx | 48 +-- app/utils/geminiHelper.ts | 72 ++-- 17 files changed, 1558 insertions(+), 1257 deletions(-) create mode 100644 app/components/Cards.tsx diff --git a/app/Dashboard/page.tsx b/app/Dashboard/page.tsx index dfe6113..86da3e8 100644 --- a/app/Dashboard/page.tsx +++ b/app/Dashboard/page.tsx @@ -1,121 +1,119 @@ -// "use client"; +"use client"; -// import React, { useState } from "react"; -// import { useRouter } from "next/navigation"; -// import Link from 'next/link'; +import React, { useState } from "react"; +import { useRouter } from "next/navigation"; +import Link from 'next/link'; -// function Dashboard() { // 2. Changed from 'export default function' -// const router = useRouter(); -// const [query, setQuery] = useState(""); -// const [sideBarOpen, setSidebarOpen] = useState(true); +function Dashboard() { // 2. Changed from 'export default function' + const router = useRouter(); + const [query, setQuery] = useState(""); + const [sideBarOpen, setSidebarOpen] = useState(true); -// const projects = [ -// { name: "Alpha Project", createdAt: "2025-01-01" }, -// { name: "Beta Board", createdAt: "2025-02-15" }, -// { name: "Gamma Tasl", createdAt: "2025-03-10" }, -// ]; -// const filtered = projects.filter((p) => -// p.name.toLowerCase().includes(query.toLowerCase()) -// ); + const projects = [ + { name: "Alpha Project", createdAt: "2025-01-01" }, + { name: "Beta Board", createdAt: "2025-02-15" }, + { name: "Gamma Tasl", createdAt: "2025-03-10" }, + ]; + const filtered = projects.filter((p) => + p.name.toLowerCase().includes(query.toLowerCase()) + ); -// return ( -//
-// -//
-//
-//
-//
-// setQuery(e.target.value)} -// placeholder="Search projects, boards or tasks..." -// className="w-full max-w-md px-4 py-2 rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-blue-500" -// /> -//
+
+
+
+
+ setQuery(e.target.value)} + placeholder="Search projects, boards or tasks..." + className="w-full max-w-md px-4 py-2 rounded-md border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
-//
-// -//
-//
-//
+
+ +
+
+
-//
-//

-// Project Names -//

+
+

+ Project Names +

-//
-//
    -// {filtered.map((project, index) => ( -//
  • -// {project.name} -// -// Created: {project.createdAt} -// -//
  • -// ))} -// {filtered.length === 0 && ( -//
  • No results found
  • -// )} -//
-//
-//
-//
-//
-// ); -// } \ No newline at end of file +
+
    + {filtered.map((project, index) => ( +
  • + {project.name} + + Created: {project.createdAt} + +
  • + ))} + {filtered.length === 0 && ( +
  • No results found
  • + )} +
+
+ +
+ + ); +} \ No newline at end of file diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 3c980c0..6c3e35a 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,24 +1,24 @@ -// import { NextResponse } from "next/server"; -// import { chatToGemini } from "@/app/utils/geminiHelper"; -// import { ChatHistory, ChatSetting } from "@/app/exportType/types"; +import { NextResponse } from "next/server"; +import { chatToGemini } from "@/app/utils/geminiHelper"; +import { ChatHistory, ChatSetting } from "@/app/exportType/types"; -// export async function POST(request: Request) { -// try { -// const { userMessage, history , settings } = await request.json() as { -// userMessage :string; -// history : ChatHistory; -// settings : ChatSetting; -// }; +export async function POST(request: Request) { + try { + const { userMessage, history, settings } = await request.json() as { + userMessage: string; + history: ChatHistory; + settings: ChatSetting; + }; -// const aiResponse = await chatToGemini(userMessage , history, settings); -// return NextResponse.json({response : aiResponse}); -// } -// catch(error){ -// console.error(error); -// return NextResponse.json( -// {error: "Error with the model response "}, -// {status : 500} -// ); -// } -// } + const aiResponse = await chatToGemini(userMessage, history, settings); + return NextResponse.json({ response: aiResponse }); + } + catch (error) { + console.error(error); + return NextResponse.json( + { error: "Error with the model response " }, + { status: 500 } + ); + } +} diff --git a/app/api/generate-idea/route.ts b/app/api/generate-idea/route.ts index 517ec6c..9a2a9f4 100644 --- a/app/api/generate-idea/route.ts +++ b/app/api/generate-idea/route.ts @@ -1,23 +1,23 @@ -// import { NextResponse } from "next/server"; -// import { chatToGemini } from "@/app/utils/geminiHelper"; -// import { ChatSetting } from "@/app/exportType/types"; +import { NextResponse } from "next/server"; +import { chatToGemini } from "@/app/utils/geminiHelper"; +import { ChatSetting } from "@/app/exportType/types"; -// export async function POST(request: Request) { -// try { -// const { prompt, settings } = await request.json() as { -// prompt :string; -// settings : ChatSetting; -// }; +export async function POST(request: Request) { + try { + const { prompt, settings } = await request.json() as { + prompt: string; + settings: ChatSetting; + }; -// const aiResponse = await chatToGemini(prompt , [], settings); -// return NextResponse.json({response : aiResponse}); -// } -// catch(error){ -// console.error(error); -// return NextResponse.json( -// {error: "Error with the model response "}, -// {status : 500} -// ); -// } -// } + const aiResponse = await chatToGemini(prompt, [], settings); + return NextResponse.json({ response: aiResponse }); + } + catch (error) { + console.error(error); + return NextResponse.json( + { error: "Error with the model response " }, + { status: 500 } + ); + } +} diff --git a/app/cards/page.tsx b/app/cards/page.tsx index 5c4858a..37faf57 100644 --- a/app/cards/page.tsx +++ b/app/cards/page.tsx @@ -1,210 +1,210 @@ -// "use client"; +"use client"; -// import React, { useState, useEffect } from "react"; -// import { motion, useMotionValue, useTransform, useAnimation } from "framer-motion"; -// import { useRouter } from "next/navigation"; +import React, { useState, useEffect } from "react"; +import { motion, useMotionValue, useTransform, useAnimation } from "framer-motion"; +import { useRouter } from "next/navigation"; -// // 1. Updated ColorWay interface -// interface ColorWay { -// card: string; -// text: string; -// titleColor: string; // Added title color -// } +// 1. Updated ColorWay interface +interface ColorWay { + card: string; + text: string; + titleColor: string; // Added title color +} -// // 2. Updated COLOR_WAYS array -// const COLOR_WAYS: ColorWay[] = [ -// { card: "#FEEEDF", text: "#173C46", titleColor: "#173C46" }, -// { card: "#FEEEDF", text: "#EA627F", titleColor: "#173C46" }, // Example: Title is dark, text is pink -// { card: "#DEE5D4", text: "#173C46", titleColor: "#EA627F" }, -// { card: "#DEE5D4", text: "#EA627F", titleColor: "#173C46" }, -// { card: "#B8C0AD", text: "#173C46", titleColor: "#173C46" }, -// { card: "#B8C0AD", text: "#173C46", titleColor: "#EA627F" }, -// ]; +// 2. Updated COLOR_WAYS array +const COLOR_WAYS: ColorWay[] = [ + { card: "#FEEEDF", text: "#173C46", titleColor: "#173C46" }, + { card: "#FEEEDF", text: "#EA627F", titleColor: "#173C46" }, // Example: Title is dark, text is pink + { card: "#DEE5D4", text: "#173C46", titleColor: "#EA627F" }, + { card: "#DEE5D4", text: "#EA627F", titleColor: "#173C46" }, + { card: "#B8C0AD", text: "#173C46", titleColor: "#173C46" }, + { card: "#B8C0AD", text: "#173C46", titleColor: "#EA627F" }, +]; -// interface CardData { -// id: number; -// title: string; -// summary: string; -// tracks: string[]; -// } +interface CardData { + id: number; + title: string; + summary: string; + tracks: string[]; +} -// const SwipeCards: React.FC<{ initialCards: CardData[] }> = ({ initialCards }) => { -// const [cards, setCards] = useState(initialCards); -// const router = useRouter(); +const SwipeCards: React.FC<{ initialCards: CardData[] }> = ({ initialCards }) => { + const [cards, setCards] = useState(initialCards); + const router = useRouter(); -// // Update cards state when initialCards prop changes -// useEffect(() => { -// setCards(initialCards); -// }, [initialCards]); + // Update cards state when initialCards prop changes + useEffect(() => { + setCards(initialCards); + }, [initialCards]); -// const removeCard = () => { -// setCards((prev) => prev.slice(0, prev.length - 1)); -// }; + const removeCard = () => { + setCards((prev) => prev.slice(0, prev.length - 1)); + }; -// const handleAccept = (cardData: CardData) => { -// removeCard(); -// // Redirect to chatbot with card data -// router.push(`/chatbot?title=${encodeURIComponent(cardData.title)}&summary=${encodeURIComponent(cardData.summary)}`); -// }; + const handleAccept = (cardData: CardData) => { + removeCard(); + // Redirect to chatbot with card data + router.push(`/chatbot?title=${encodeURIComponent(cardData.title)}&summary=${encodeURIComponent(cardData.summary)}`); + }; -// const handleReject = () => { -// removeCard(); -// }; + const handleReject = () => { + removeCard(); + }; -// const handleReset = () => { -// setCards([]); // Reset to initial cards -// }; + const handleReset = () => { + setCards([]); // Reset to initial cards + }; -// return ( -//
-// {cards.length > 0 ? ( -// cards.map((card, index) => { -// const colorWay = COLOR_WAYS[card.id % COLOR_WAYS.length]; -// return ( -// -// ); -// }) -// ) : ( -// // ... (empty state) -//
-//

-// No more cards! -//

-//

-// You've swiped through them all. -//

-// -//
-// )} -//
-// ); -// }; + return ( +
+ {cards.length > 0 ? ( + cards.map((card, index) => { + const colorWay = COLOR_WAYS[card.id % COLOR_WAYS.length]; + return ( + + ); + }) + ) : ( + // ... (empty state) +
+

+ No more cards! +

+

+ You've swiped through them all. +

+ +
+ )} +
+ ); +}; -// interface CardProps { -// cardData: CardData; -// colorWay: ColorWay; -// isFront: boolean; -// onAccept: (cardData: CardData) => void; -// onReject: () => void; -// } +interface CardProps { + cardData: CardData; + colorWay: ColorWay; + isFront: boolean; + onAccept: (cardData: CardData) => void; + onReject: () => void; +} -// const Card: React.FC = ({ cardData, colorWay, isFront, onAccept, onReject }) => { -// const { title, summary, tracks } = cardData; +const Card: React.FC = ({ cardData, colorWay, isFront, onAccept, onReject }) => { + const { title, summary, tracks } = cardData; -// const x = useMotionValue(0); -// const rotate = useTransform(x, [-250, 250], [-25, 25]); -// const opacity = useTransform( -// x, -// [-250, -100, 0, 100, 250], -// [0, 1, 1, 1, 0], -// ); -// const controls = useAnimation(); + const x = useMotionValue(0); + const rotate = useTransform(x, [-250, 250], [-25, 25]); + const opacity = useTransform( + x, + [-250, -100, 0, 100, 250], + [0, 1, 1, 1, 0], + ); + const controls = useAnimation(); -// const acceptOpacity = useTransform(x, [50, 150], [0, 1]); -// const rejectOpacity = useTransform(x, [-150, -50], [1, 0]); -// const badgeRotate = useTransform(x, [-150, 150], [-15, 15]); + const acceptOpacity = useTransform(x, [50, 150], [0, 1]); + const rejectOpacity = useTransform(x, [-150, -50], [1, 0]); + const badgeRotate = useTransform(x, [-150, 150], [-15, 15]); -// const handleDragEnd = async (event: MouseEvent | TouchEvent | PointerEvent, info: { offset: { x: number } }) => { -// if (info.offset.x > 100) { -// // Card accepted -// await controls.start({ x: 1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly -// onAccept(cardData); // Then call onAccept which removes the card and redirects -// } else if (info.offset.x < -100) { -// // Card rejected -// await controls.start({ x: -1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly -// onReject(); // Then call onReject which removes the card -// } else { -// // Card not swiped far enough, snap back to center -// controls.start({ x: 0, rotate: 0, opacity: 1, transition: { type: "spring", stiffness: 300, damping: 30 } }); -// } -// }; + const handleDragEnd = async (event: MouseEvent | TouchEvent | PointerEvent, info: { offset: { x: number } }) => { + if (info.offset.x > 100) { + // Card accepted + await controls.start({ x: 1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly + onAccept(cardData); // Then call onAccept which removes the card and redirects + } else if (info.offset.x < -100) { + // Card rejected + await controls.start({ x: -1000, opacity: 0, transition: { duration: 0.1 } }); // Animate off-screen quickly + onReject(); // Then call onReject which removes the card + } else { + // Card not swiped far enough, snap back to center + controls.start({ x: 0, rotate: 0, opacity: 1, transition: { type: "spring", stiffness: 300, damping: 30 } }); + } + }; -// return ( -// -// {/* Accept/Reject Badges */} -// -//

Accept

-//
-// -//

Reject

-//
+ return ( + + {/* Accept/Reject Badges */} + +

Accept

+
+ +

Reject

+
-// {/* Card Content */} -//
-// {/* 3. Applied the specific titleColor here */} -//

-// {title} -//

-// {/* This summary

will inherit colorWay.text from the parent */} -//

{summary}

-//
+ {/* Card Content */} +
+ {/* 3. Applied the specific titleColor here */} +

+ {title} +

+ {/* This summary

will inherit colorWay.text from the parent */} +

{summary}

+
-//
-// {tracks.slice(0, 2).map((track, index) => ( -// -// {track} -// {index === 0 && tracks.length > 1 && ", "} -// -// ))} -//
-//
-// ); +
+ {tracks.slice(0, 2).map((track, index) => ( + + {track} + {index === 0 && tracks.length > 1 && ", "} + + ))} +
+
+ ); -// }; +}; -// export default SwipeCards; +export default SwipeCards; diff --git a/app/chatbot/page.tsx b/app/chatbot/page.tsx index 37e8143..80f21ae 100644 --- a/app/chatbot/page.tsx +++ b/app/chatbot/page.tsx @@ -1,135 +1,135 @@ -// "use client"; +"use client"; -// import { useState, useEffect, useRef, useCallback } from "react"; -// import { useSearchParams } from "next/navigation"; -// import ChatInput from "../utils/component/ui/ChatInput"; -// import MessageWindow from "../utils/component/ui/MessageWindow"; -// import { ChatHistory, ChatSetting, Message , MessageRole } from "@/app/exportType/types"; +import { useState, useEffect, useRef, useCallback } from "react"; +import { useSearchParams } from "next/navigation"; +import ChatInput from "../utils/component/ui/ChatInput"; +import MessageWindow from "../utils/component/ui/MessageWindow"; +import { ChatHistory, ChatSetting, Message, MessageRole } from "@/app/exportType/types"; -// export default function Home(){ -// const [history, setHistory] = useState([]) -// const historyRef = useRef([]); // Create a ref for history -// const [settings] = useState({ -// temperature:1, -// model:"gemini-2.5-pro", -// sysTemInstructions:"you are a ai helper. Your goal is to expand the project idea and interact with the user on any problem or question they have with the project. You are not allow to code the project for them and stray away from your job" - -// }); -// const searchParams = useSearchParams(); -// const initialMessageSent = useRef(false); +export default function Home() { + const [history, setHistory] = useState([]) + const historyRef = useRef([]); // Create a ref for history + const [settings] = useState({ + temperature: 1, + model: "gemini-2.5-pro", + sysTemInstructions: "you are a ai helper. Your goal is to expand the project idea and interact with the user on any problem or question they have with the project. You are not allow to code the project for them and stray away from your job" -// useEffect(() => { -// historyRef.current = history; // Keep the ref updated with the latest history -// }, [history]); + }); + const searchParams = useSearchParams(); + const initialMessageSent = useRef(false); -// const handleSend = useCallback(async(message:string)=>{ -// const newUserMessage:Message = { -// role:"user", -// parts:[{text:message}], -// }; + useEffect(() => { + historyRef.current = history; // Keep the ref updated with the latest history + }, [history]); -// setHistory(prevHistory => { -// const currentHistory = [...prevHistory, newUserMessage]; - -// const sendApiRequest = async () => { -// try{ -// const response = await fetch("/api/chat", { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// }, -// body: JSON.stringify({ -// userMessage: message, -// history: historyRef.current, // Use the ref for history -// settings: settings, -// }), -// }); + const handleSend = useCallback(async (message: string) => { + const newUserMessage: Message = { + role: "user", + parts: [{ text: message }], + }; -// const data = await response.json(); + setHistory(prevHistory => { + const currentHistory = [...prevHistory, newUserMessage]; -// if (data.error) { -// console.error("AI Error:", data.error); -// return; -// } + const sendApiRequest = async () => { + try { + const response = await fetch("/api/chat", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userMessage: message, + history: historyRef.current, // Use the ref for history + settings: settings, + }), + }); -// const aiMessage: Message = { -// role: "model" as MessageRole, -// parts: [{ text: data.response }], -// }; + const data = await response.json(); -// setHistory(prevHistory => [...prevHistory, aiMessage]); - -// } -// catch (error) { -// console.error("Request Failed:", error); -// } -// }; -// sendApiRequest(); + if (data.error) { + console.error("AI Error:", data.error); + return; + } -// return currentHistory; -// }); -// }, [settings]); // Now handleSend only depends on settings + const aiMessage: Message = { + role: "model" as MessageRole, + parts: [{ text: data.response }], + }; -// useEffect(() => { -// if (!initialMessageSent.current) { -// const title = searchParams.get('title'); -// const summary = searchParams.get('summary'); + setHistory(prevHistory => [...prevHistory, aiMessage]); -// if (title && summary) { -// const message = `Explain the project titled '${title}' with the summary '${summary}' in detail, and suggest suitable roles for a team working on it.`; - -// const newUserMessage: Message = { -// role: "user", -// parts: [{ text: message }], -// }; + } + catch (error) { + console.error("Request Failed:", error); + } + }; + sendApiRequest(); -// setTimeout(() => { -// setHistory((prevHistory) => [...prevHistory, newUserMessage]); // Add user message to history -// }, 0); + return currentHistory; + }); + }, [settings]); // Now handleSend only depends on settings -// const sendInitialApiRequest = async () => { -// try { -// const response = await fetch("/api/chat", { -// method: "POST", -// headers: { -// "Content-Type": "application/json", -// }, -// body: JSON.stringify({ -// userMessage: message, -// history: [...historyRef.current, newUserMessage], // Use ref for history -// settings: settings, -// }), -// }); + useEffect(() => { + if (!initialMessageSent.current) { + const title = searchParams.get('title'); + const summary = searchParams.get('summary'); -// const data = await response.json(); + if (title && summary) { + const message = `Explain the project titled '${title}' with the summary '${summary}' in detail, and suggest suitable roles for a team working on it.`; -// if (data.error) { -// console.error("AI Error:", data.error); -// return; -// } + const newUserMessage: Message = { + role: "user", + parts: [{ text: message }], + }; -// const aiMessage: Message = { -// role: "model" as MessageRole, -// parts: [{ text: data.response }], -// }; + setTimeout(() => { + setHistory((prevHistory) => [...prevHistory, newUserMessage]); // Add user message to history + }, 0); -// setHistory((prevHistory) => [...prevHistory, aiMessage]); -// } catch (error) { -// console.error("Request Failed:", error); -// } -// }; + const sendInitialApiRequest = async () => { + try { + const response = await fetch("/api/chat", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + userMessage: message, + history: [...historyRef.current, newUserMessage], // Use ref for history + settings: settings, + }), + }); -// sendInitialApiRequest(); -// initialMessageSent.current = true; -// } -// } -// }, [searchParams, settings]); // Dependencies for this useEffect + const data = await response.json(); + + if (data.error) { + console.error("AI Error:", data.error); + return; + } + + const aiMessage: Message = { + role: "model" as MessageRole, + parts: [{ text: data.response }], + }; + + setHistory((prevHistory) => [...prevHistory, aiMessage]); + } catch (error) { + console.error("Request Failed:", error); + } + }; + + sendInitialApiRequest(); + initialMessageSent.current = true; + } + } + }, [searchParams, settings]); // Dependencies for this useEffect -// return ( -//
-// -// {}} /> -//
-// ); -// } \ No newline at end of file + return ( +
+ + { }} /> +
+ ); +} \ No newline at end of file diff --git a/app/components/Cards.tsx b/app/components/Cards.tsx new file mode 100644 index 0000000..322b377 --- /dev/null +++ b/app/components/Cards.tsx @@ -0,0 +1,300 @@ +"use client"; + +import React, { useState } from "react"; +import { motion, useMotionValue, useTransform } from "framer-motion"; + +// Removed local fallback JSX declaration — use the official React type definitions instead: +// install @types/react and @types/react-dom so JSX.IntrinsicElements is provided by those packages. +// 1. Updated ColorWay interface +interface ColorWay { + card: string; + text: string; + titleColor: string; // Added title color +} + +// 2. Updated COLOR_WAYS array +const COLOR_WAYS: ColorWay[] = [ + { card: "#FEEEDF", text: "#173C46", titleColor: "#173C46" }, + { card: "#FEEEDF", text: "#EA627F", titleColor: "#173C46" }, // Example: Title is dark, text is pink + { card: "#DEE5D4", text: "#173C46", titleColor: "#EA627F" }, + { card: "#DEE5D4", text: "#EA627F", titleColor: "#173C46" }, + { card: "#B8C0AD", text: "#173C46", titleColor: "#173C46" }, + { card: "#B8C0AD", text: "#173C46", titleColor: "#EA627F" }, +]; + +interface CardData { + id: number; + title: string; + summary: string; + tracks: string[]; +} + +const cardData: CardData[] = [ + { + + id: 1, + + title: " WEBSITE", + + summary: + + "FFind out what makes GoonMAXXER unique.With this innovative website you will be able to explore various features and functionalities that set GoonMAXXER apart from the rest.", + + tracks: ["Gemini", "Auth0", "VibeCODING", "SmellyMaxxing", "shitposting"], + + }, + + { + + id: 2, + + title: "Intro to React", + + summary: + + "Learn the fundamentals of React, including components, state, and props.", + + tracks: ["React", "JS", "Frontend"], + + }, + + { + + id: 3, + + title: "State Management", + + summary: + + "Explore complex state solutions with Zustand, Redux, and Context API.", + + tracks: ["React", "Zustand", "State"], + + }, + + { + + id: 4, + + title: "Next.js 14", + + summary: "Master the app router, server actions, and data fetching.", + + tracks: ["Next.js", "React", "Fullstack"], + + }, + + { + + id: 5, + + title: "UI/UX Principles", + + summary: + + "A complete guide to user-centric design, prototyping, and testing.", + + tracks: ["Design", "UI", "UX"], + + }, + + { + + id: 6, + + title: "Node.js Essentials", + + summary: + + "Build scalable, high-performance backend applications with Node.js.", + + tracks: ["Node", "Backend", "JS"], + + }, + + { + + id: 7, + + title: "TypeScript", + + summary: + + "Add static typing to your JavaScript projects for robust, large-scale apps.", + + tracks: ["TypeScript", "JS", "DevOps"], + + }, + + { + + id: 8, + + title: "Framer Motion", + + summary: "Create production-ready animations for your React applications.", + + tracks: ["React", "Animation", "Framer"], + + }, + +].reverse(); + +const SwipeCards: React.FC = () => { + const [cards, setCards] = useState(cardData); + + const onSwipe = () => { + setCards((prev) => prev.slice(0, prev.length - 1)); + }; + + const handleReset = () => { + setCards(cardData); + }; + + return ( +
+ {cards.length > 0 ? ( + cards.map((card, index) => { + const colorWay = COLOR_WAYS[card.id % COLOR_WAYS.length]; + return ( + + ); + }) + ) : ( + // ... (empty state) +
+

+ No more cards! +

+

+ You've swiped through them all. +

+ +
+ )} +
+ ); +}; + +interface CardProps { + cardData: CardData; + colorWay: ColorWay; + isFront: boolean; + onSwipe: () => void; +} + +const Card: React.FC = ({ cardData, colorWay, isFront, onSwipe }) => { + const { title, summary, tracks } = cardData; + + const x = useMotionValue(0); + const rotate = useTransform(x, [-250, 250], [-25, 25]); + const opacity = useTransform( + x, + [-250, -100, 0, 100, 250], + [0, 1, 1, 1, 0], + ); + + const acceptOpacity = useTransform(x, [50, 150], [0, 1]); + const rejectOpacity = useTransform(x, [-150, -50], [1, 0]); + const badgeRotate = useTransform(x, [-150, 150], [-15, 15]); + + const handleDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: { offset: { x: number } }) => { + if (Math.abs(info.offset.x) > 100) { + onSwipe(); + } + }; + + return ( + + {/* Accept/Reject Badges */} + +

Accept

+
+ +

Reject

+
+ + {/* Card Content */} +
+ {/* 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 index eedd6a6..5a5c48b 100644 --- a/app/components/ProtectedNavButton.tsx +++ b/app/components/ProtectedNavButton.tsx @@ -4,32 +4,32 @@ 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 = "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; + children?: React.ReactNode; + className?: string; }) { - const router = useRouter(); + 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; + 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"); - } - }; + 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 ( - - ); + return ( + + ); } diff --git a/app/exportType/types.ts b/app/exportType/types.ts index 3c9a4c0..9b2afbb 100644 --- a/app/exportType/types.ts +++ b/app/exportType/types.ts @@ -1,30 +1,30 @@ -// export type MessageRole = "user" | "model"; +export type MessageRole = "user" | "model"; -// export type MessagePart = { -// text: string; -// } +export type MessagePart = { + text: string; +} -// export interface Message{ -// role: MessageRole; -// parts:MessagePart[]; -// } -// export type ChatHistory = Message[]; +export interface Message { + role: MessageRole; + parts: MessagePart[]; +} +export type ChatHistory = Message[]; -// export interface GenerateConfig{ -// temperature : number; -// topP : number; -// responseMimeType : string; -// } +export interface GenerateConfig { + temperature: number; + topP: number; + responseMimeType: string; +} -// export interface ChatSetting{ -// temperature :number; -// model: string; -// sysTemInstructions: string; -// } +export interface ChatSetting { + temperature: number; + model: string; + sysTemInstructions: string; +} -// export interface CardData { -// id: number; -// title: string; -// tracks: string[]; -// summary: string; -// } \ No newline at end of file +export interface CardData { + id: number; + title: string; + tracks: string[]; + summary: string; +} \ No newline at end of file diff --git a/app/formfile/FormPage.tsx b/app/formfile/FormPage.tsx index acdfc85..d9b8960 100644 --- a/app/formfile/FormPage.tsx +++ b/app/formfile/FormPage.tsx @@ -1,294 +1,294 @@ -// "use client"; +"use client"; -// import React, { useState } from "react"; +import React, { useState } from "react"; -// import { -// FormData, -// PROFICIENCY_LEVELS -// } from './formTypes'; // Ensure path is correct +import { + FormData, + PROFICIENCY_LEVELS +} from './formTypes'; // Ensure path is correct -// interface FormPageProps { -// onFormSubmit: (data: FormData) => void; -// } +interface FormPageProps { + onFormSubmit: (data: FormData) => void; +} -// const FormPage: React.FC = ({ onFormSubmit }) => { -// const [formData, setFormData] = useState({ -// Hackathon: '', -// mainTheme: '', -// tracksStack: [''], -// students: [{ -// studentName: '', -// skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] -// }], -// }); +const FormPage: React.FC = ({ onFormSubmit }) => { + const [formData, setFormData] = useState({ + Hackathon: '', + mainTheme: '', + tracksStack: [''], + students: [{ + studentName: '', + skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] + }], + }); -// const handleChange = (event: React.ChangeEvent) => { -// setFormData({ -// ...formData, -// [event.target.name]: event.target.value, -// }); -// }; + const handleChange = (event: React.ChangeEvent) => { + setFormData({ + ...formData, + [event.target.name]: event.target.value, + }); + }; -// const handleTracksChange = (event: React.ChangeEvent, index: number) => { -// const newTracksStack = [...formData.tracksStack]; -// newTracksStack[index] = event.target.value; + const handleTracksChange = (event: React.ChangeEvent, index: number) => { + const newTracksStack = [...formData.tracksStack]; + newTracksStack[index] = event.target.value; -// setFormData({ -// ...formData, -// tracksStack: newTracksStack, -// }); -// }; + setFormData({ + ...formData, + tracksStack: newTracksStack, + }); + }; -// const handleAddTracks = () => { -// setFormData({ -// ...formData, -// tracksStack: [...formData.tracksStack, ''], -// }); -// }; + const handleAddTracks = () => { + setFormData({ + ...formData, + tracksStack: [...formData.tracksStack, ''], + }); + }; -// const handleRemoveTracks = (index: number) => { -// const newTracksStack = formData.tracksStack.filter((_, i) => i !== index); -// setFormData({ -// ...formData, -// tracksStack: newTracksStack, -// }); -// }; + const handleRemoveTracks = (index: number) => { + const newTracksStack = formData.tracksStack.filter((_, i) => i !== index); + setFormData({ + ...formData, + tracksStack: newTracksStack, + }); + }; -// const handleStudentNameChange = (e: React.ChangeEvent, studentIndex: number) => { -// const newStudents = [...formData.students]; -// newStudents[studentIndex].studentName = e.target.value; -// setFormData({ ...formData, students: newStudents }); -// }; + const handleStudentNameChange = (e: React.ChangeEvent, studentIndex: number) => { + const newStudents = [...formData.students]; + newStudents[studentIndex].studentName = e.target.value; + setFormData({ ...formData, students: newStudents }); + }; -// const handleAddStudent = () => { -// setFormData({ -// ...formData, -// students: [...formData.students, { studentName: '', skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] }] -// }); -// }; + const handleAddStudent = () => { + setFormData({ + ...formData, + students: [...formData.students, { studentName: '', skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] }] + }); + }; -// const handleRemoveStudent = (studentIndex: number) => { -// const newStudents = formData.students.filter((_, i) => i !== studentIndex); -// setFormData({ ...formData, students: newStudents }); -// }; + const handleRemoveStudent = (studentIndex: number) => { + const newStudents = formData.students.filter((_, i) => i !== studentIndex); + setFormData({ ...formData, students: newStudents }); + }; -// const handleSkillChange = ( -// e: React.ChangeEvent, -// studentIndex: number, -// skillIndex: number -// ) => { -// const newStudents = [...formData.students]; -// const targetName = e.target.name; -// const targetValue = e.target.value; + const handleSkillChange = ( + e: React.ChangeEvent, + studentIndex: number, + skillIndex: number + ) => { + const newStudents = [...formData.students]; + const targetName = e.target.name; + const targetValue = e.target.value; -// if (targetName === 'skillName') { -// newStudents[studentIndex].skills[skillIndex].skillName = targetValue; -// } else if (targetName === 'proficiency') { -// newStudents[studentIndex].skills[skillIndex].proficiency = targetValue; -// } + if (targetName === 'skillName') { + newStudents[studentIndex].skills[skillIndex].skillName = targetValue; + } else if (targetName === 'proficiency') { + newStudents[studentIndex].skills[skillIndex].proficiency = targetValue; + } -// setFormData({ ...formData, students: newStudents }); -// }; + setFormData({ ...formData, students: newStudents }); + }; -// const handleAddSkill = (studentIndex: number) => { -// const newStudents = [...formData.students]; -// newStudents[studentIndex].skills.push({ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }); -// setFormData({ ...formData, students: newStudents }); -// }; + const handleAddSkill = (studentIndex: number) => { + const newStudents = [...formData.students]; + newStudents[studentIndex].skills.push({ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }); + setFormData({ ...formData, students: newStudents }); + }; -// const handleRemoveSkill = (studentIndex: number, skillIndex: number) => { -// const newStudents = [...formData.students]; -// newStudents[studentIndex].skills = newStudents[studentIndex].skills.filter((_, i) => i !== skillIndex); -// setFormData({ ...formData, students: newStudents }); -// }; + const handleRemoveSkill = (studentIndex: number, skillIndex: number) => { + const newStudents = [...formData.students]; + newStudents[studentIndex].skills = newStudents[studentIndex].skills.filter((_, i) => i !== skillIndex); + setFormData({ ...formData, students: newStudents }); + }; -// const handleSubmit = (event: React.FormEvent) => { -// event.preventDefault(); -// onFormSubmit(formData); // Call the prop function with formData -// }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + onFormSubmit(formData); // Call the prop function with formData + }; -// return ( -//
-//
-//

-// Generate Project Idea -//

+ return ( +
+
+

+ Generate Project Idea +

-//
-//
-//

Project Context

-//
-// -// -//
+ +
+

Project Context

+
+ + +
-//
-// -// -//
-//
+
+ + +
+
-//
-// -//
-// {formData.tracksStack.map((tracks, index) => ( -//
-// handleTracksChange(e, index)} -// className="flex-grow px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-green-500 focus:border-green-500 transition duration-150" -// /> -// {formData.tracksStack.length > 1 && ( -// -// )} -//
-// ))} -//
+
+ +
+ {formData.tracksStack.map((tracks, index) => ( +
+ handleTracksChange(e, index)} + className="flex-grow px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:ring-green-500 focus:border-green-500 transition duration-150" + /> + {formData.tracksStack.length > 1 && ( + + )} +
+ ))} +
-// -//
+ +
-//
-//

Team Members and Skills

+
+

Team Members and Skills

-//
-// {formData.students.map((student, studentIndex) => ( -//
+
+ {formData.students.map((student, studentIndex) => ( +
-//
-//

Student #{studentIndex + 1}

-// {formData.students.length > 1 && ( -// -// )} -//
+
+

Student #{studentIndex + 1}

+ {formData.students.length > 1 && ( + + )} +
-//
-// -// handleStudentNameChange(e, studentIndex)} -// className="w-full px-4 py-2 border border-indigo-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500" -// /> -//
+
+ + handleStudentNameChange(e, studentIndex)} + className="w-full px-4 py-2 border border-indigo-300 rounded-lg shadow-sm focus:ring-indigo-500 focus:border-indigo-500" + /> +
-//
-//
Skills
-// {student.skills.map((skill, skillIndex) => ( -//
-// handleSkillChange(e, studentIndex, skillIndex)} -// className="flex-grow px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-purple-500 focus:border-purple-500" -// /> -// -// {student.skills.length > 1 && ( -// -// )} -//
-// ))} -// -//
-//
-// ))} -//
+
+
Skills
+ {student.skills.map((skill, skillIndex) => ( +
+ handleSkillChange(e, studentIndex, skillIndex)} + className="flex-grow px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-purple-500 focus:border-purple-500" + /> + + {student.skills.length > 1 && ( + + )} +
+ ))} + +
+
+ ))} +
-// -//
+ +
-// -//
+ + -//
-//
-// ); -// }; +
+
+ ); +}; -// export default FormPage; \ No newline at end of file +export default FormPage; \ No newline at end of file diff --git a/app/formfile/formTypes.ts b/app/formfile/formTypes.ts index d2cb325..a4267eb 100644 --- a/app/formfile/formTypes.ts +++ b/app/formfile/formTypes.ts @@ -1,21 +1,21 @@ -// // Define Skill structure -// export interface Skill { -// skillName: string; -// proficiency: string; -// } +// Define Skill structure +export interface Skill { + skillName: string; + proficiency: string; +} -// // Define Student structure -// export interface Student { -// studentName: string; -// skills: Skill[]; -// } +// Define Student structure +export interface Student { + studentName: string; + skills: Skill[]; +} -// // Updated main form interface -// export interface FormData { -// Hackathon: string; -// mainTheme: string; -// tracksStack: string[]; -// students: Student[]; // Array for dynamic students -// } +// Updated main form interface +export interface FormData { + Hackathon: string; + mainTheme: string; + tracksStack: string[]; + students: Student[]; // Array for dynamic students +} -// export const PROFICIENCY_LEVELS = ['Beginner', 'Intermediate', 'Expert', 'Master']; \ No newline at end of file +export const PROFICIENCY_LEVELS = ['Beginner', 'Intermediate', 'Expert', 'Master']; \ No newline at end of file diff --git a/app/formfile/generate-idea.ts b/app/formfile/generate-idea.ts index be76f38..791b19f 100644 --- a/app/formfile/generate-idea.ts +++ b/app/formfile/generate-idea.ts @@ -1,71 +1,71 @@ -// import { GoogleGenerativeAI } from "@google/generative-ai"; -// import type { NextApiRequest, NextApiResponse } from 'next'; +import { GoogleGenerativeAI } from "@google/generative-ai"; +import type { NextApiRequest, NextApiResponse } from 'next'; -// // Initialize the Gemini Client with your API Key -// // IMPORTANT: The GEMINI_API_KEY should be an environment variable. -// const apiKey = process.env.GEMINI_API_KEY; +// Initialize the Gemini Client with your API Key +// IMPORTANT: The GEMINI_API_KEY should be an environment variable. +const apiKey = process.env.GEMINI_API_KEY; -// if(!apiKey){ -// throw new Error("api key not found"); -// } -// const ai = new GoogleGenerativeAI(apiKey); +if (!apiKey) { + throw new Error("api key not found"); +} +const ai = new GoogleGenerativeAI(apiKey); -// // Define the handler function for the API route -// export default async function handler( -// req: NextApiRequest, -// res: NextApiResponse -// ) { -// // Only allow POST requests -// if (req.method !== 'POST') { -// return res.status(405).json({ error: 'Method Not Allowed' }); -// } +// Define the handler function for the API route +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + // Only allow POST requests + if (req.method !== 'POST') { + return res.status(405).json({ error: 'Method Not Allowed' }); + } -// // Destructure the data sent from the frontend -// let { prompt, settings } = req.body; - -// // Basic validation -// if (!prompt || typeof prompt !== 'string') { -// return res.status(400).json({ error: 'Prompt is required' }); -// } + // Destructure the data sent from the frontend + let { prompt, settings } = req.body; -// // Modify the prompt to instruct the AI to generate only the game, concept, and track -// prompt = `You're going to fill out a card base off the document. -// you will Generate the project short title. -// you will list out the track you used ${prompt}`; + // Basic validation + if (!prompt || typeof prompt !== 'string') { + return res.status(400).json({ error: 'Prompt is required' }); + } -// try { -// // 1. Call the Gemini API using the correct method signature - -// const model = settings?.model || 'gemini-2.5-flash-lite'; -// const generativeModel = ai.getGenerativeModel({ model }); + // Modify the prompt to instruct the AI to generate only the game, concept, and track + prompt = `You're going to fill out a card base off the document. + you will Generate the project short title. + you will list out the track you used ${prompt}`; -// // 1. Define the generation configuration object -// const generationConfig = { -// temperature: settings?.temperature || 0.9, -// // The SDK property name for system instructions is 'systemInstruction' -// systemInstruction: settings?.sysTemInstructions, -// }; + try { + // 1. Call the Gemini API using the correct method signature -// // 2. Call generateContent with the single GenerateContentRequest object. -// const result = await generativeModel.generateContent({ -// // contents must be an array of Content objects -// contents: [{ -// role: "user", -// parts: [{ text: prompt }] -// }], - -// // The fixed property name that resolves the TypeScript error -// generationConfig: generationConfig, -// }); + const model = settings?.model || 'gemini-2.5-flash-lite'; + const generativeModel = ai.getGenerativeModel({ model }); -// // 2. Extract the response text -// // The result object now contains a property 'text' at the top level for simple text generation -// const geminiResponseText = result.response.text(); res.status(200).json({ response: geminiResponseText }); + // 1. Define the generation configuration object + const generationConfig = { + temperature: settings?.temperature || 0.9, + // The SDK property name for system instructions is 'systemInstruction' + systemInstruction: settings?.sysTemInstructions, + }; -// } catch (error) { -// console.error("Gemini API Error:", error); -// res.status(500).json({ error: 'Failed to generate idea from AI.' }); -// } -// } + // 2. Call generateContent with the single GenerateContentRequest object. + const result = await generativeModel.generateContent({ + // contents must be an array of Content objects + contents: [{ + role: "user", + parts: [{ text: prompt }] + }], + + // The fixed property name that resolves the TypeScript error + generationConfig: generationConfig, + }); + + // 2. Extract the response text + // The result object now contains a property 'text' at the top level for simple text generation + const geminiResponseText = result.response.text(); res.status(200).json({ response: geminiResponseText }); + + } catch (error) { + console.error("Gemini API Error:", error); + res.status(500).json({ error: 'Failed to generate idea from AI.' }); + } +} diff --git a/app/formfile/page.tsx b/app/formfile/page.tsx index 91678b7..3f92abe 100644 --- a/app/formfile/page.tsx +++ b/app/formfile/page.tsx @@ -1,172 +1,172 @@ -// "use client"; -// import React, { useState, useEffect, useCallback } from "react"; -// import FormPage from './FormPage'; -// import { ChatSetting } from "../exportType/types"; -// import { FormData, PROFICIENCY_LEVELS } from './formTypes'; +"use client"; +import React, { useState, useEffect, useCallback } from "react"; +import FormPage from './FormPage'; +import { ChatSetting } from "../exportType/types"; +import { FormData, PROFICIENCY_LEVELS } from './formTypes'; -// // --- Helper function to get default form data --- -// const getDefaultFormData = (): FormData => ({ -// Hackathon: '', -// mainTheme: '', -// tracksStack: [''], -// students: [{ -// studentName: '', -// skills: [{ skillName: '', proficiency: PROFICIENCY_LEVELS[1] }] -// }], -// }); +// --- 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 { -// 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 -// }; -// }; +// --- New Initializer Function --- +const getInitialState = () => { + if (typeof window === 'undefined') { + return { + 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 + }; +}; -// // 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 -// **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.]`, -// }; +// 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 +**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() { - -// 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. +export default function Home() { -// const handleFormSubmitFromFormPage = (submittedData: FormData) => { -// setFormData(submittedData); -// setShowForm(false); -// generateIdeas(submittedData); -// }; + const [initialState] = useState(getInitialState); + const [showForm, setShowForm] = useState(initialState.showForm); + const [formData, setFormData] = useState(initialState.data); + const [ideaResponse, setIdeaResponse] = useState(""); -// // Wrapped generateIdeas in useCallback -// const generateIdeas = useCallback(async (dataToProcess: FormData) => { -// // 1. Data Cleaning -// const submissionData: FormData = { -// ...dataToProcess, -// tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''), -// students: dataToProcess.students -// .map(student => ({ -// ...student, -// skills: student.skills.filter(skill => skill.skillName.trim() !== ''), -// })) -// .filter(student => student.studentName.trim() !== '' || student.skills.length > 0), -// }; + // The 'settings' state [useState] is now removed from here. -// // 2. Prompt Construction -// const prompt = ` -// Hackathon: ${submissionData.Hackathon} -// Main Theme: ${submissionData.mainTheme} -// Required Tracks Stack: ${submissionData.tracksStack.join(', ')} -// Team Members and Skills: ${submissionData.students.map(s => -// `${s.studentName || 'Unamed Member'} (Skills: ${s.skills.map(sk => `${sk.skillName} - ${sk.proficiency}`).join(', ')})` -// ).join('; ')} + const handleFormSubmitFromFormPage = (submittedData: FormData) => { + setFormData(submittedData); + setShowForm(false); + generateIdeas(submittedData); + }; + + // Wrapped generateIdeas in useCallback + const generateIdeas = useCallback(async (dataToProcess: FormData) => { + // 1. Data Cleaning + const submissionData: FormData = { + ...dataToProcess, + tracksStack: dataToProcess.tracksStack.filter(tracks => tracks.trim() !== ''), + students: dataToProcess.students + .map(student => ({ + ...student, + skills: student.skills.filter(skill => skill.skillName.trim() !== ''), + })) + .filter(student => student.studentName.trim() !== '' || student.skills.length > 0), + }; + + // 2. Prompt Construction + const prompt = ` + Hackathon: ${submissionData.Hackathon} + Main Theme: ${submissionData.mainTheme} + Required Tracks Stack: ${submissionData.tracksStack.join(', ')} + 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.`; + Using the SYSTEM INSTRUCTIONS, generate 5 project ideas based on the data above.`; -// // 3. API Call -// try { -// setIdeaResponse("Generating ideas... Please wait."); - -// 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 -// }), -// }); + // 3. API Call + try { + setIdeaResponse("Generating ideas... Please wait."); -// const data = await response.json(); -// if (data.error || !response.ok) { -// console.error("AI Error:", data.error); -// setIdeaResponse(`Error: Failed to generate idea. ${data.error || response.statusText}`); -// return; -// } -// 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 -// }, []); + 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 + }), + }); -// // Replaced useEffect -// useEffect(() => { -// if (initialState.runEffect) { -// generateIdeas(initialState.data); -// } -// }, [initialState, generateIdeas]); + const data = await response.json(); + if (data.error || !response.ok) { + console.error("AI Error:", data.error); + setIdeaResponse(`Error: Failed to generate idea. ${data.error || response.statusText}`); + return; + } + setIdeaResponse(data.response); -// // --- JSX Rendering --- -// return ( -//
-//
-// {showForm ? ( -// -// ) : ( -// <> -//

-// Generated Project Idea 💡 -//

-//
-//

Generated Ideas:

-//
') }} -// /> -// {ideaResponse === "" &&

Submit the form to generate project ideas.

} -//
-// -// -// )} -//
-//
-// ); -// } \ No newline at end of file + // 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 ( +
+
+ {showForm ? ( + + ) : ( + <> +

+ Generated Project Idea 💡 +

+
+

Generated Ideas:

+
') }} + /> + {ideaResponse === "" &&

Submit the form to generate project ideas.

} +
+ + + )} +
+
+ ); +} \ No newline at end of file diff --git a/app/globals.css b/app/globals.css index 28e3220..0091de0 100644 --- a/app/globals.css +++ b/app/globals.css @@ -39,10 +39,10 @@ body { --color-foreground: var(--foreground); /* 3. Assign fonts to Tailwind's theme */ - + /* --font-sans is for regular text (Concert One) */ --font-sans: var(--font-concert-one); - + /* We add a new font family for headers (Pixelify Sans) */ /* This also creates a 'font-header' utility class */ --font-header: var(--font-pixelify); @@ -60,12 +60,17 @@ body { body { background: var(--background); color: var(--foreground); - + /* 4. Body uses --font-sans (Concert One) by default */ font-family: var(--font-sans); } /* 5. (Optional but helpful) Apply header font to h-tags by default */ -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { font-family: var(--font-header); } \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 5bcb886..c297bb6 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,46 +1,45 @@ import Image from "next/image"; -import ProtectedNavButton from "./components/ProtectedNavButton"; export default function Home() { -  return ( -    
-      
-         -         -      
+ return ( +
+
+ Next.js logo + +
-      
-        
-          
-            

-              Welcome! This is HackSpark -            

-            

-              Got a hackathon coming up? Tell us your track, your team’s skills, what you’re passionate about, and more — and we’ll provide you with the perfect project idea!{" "} -              {/* +

+
+

+ Welcome! This is HackSpark +

+

+ Got a hackathon coming up? Tell us your track, your team’s skills, what you’re passionate about, and more — and we’ll provide you with the perfect project idea!{" "} + {/* @@ -53,113 +52,113 @@ export default function Home() {               >                 Learning               {" "} */} -              {/* center. */} -            

+ {/* center. */} +

-            {/* Get Started */} -             -          
+ {/* Get Started */} + +
-          
-            
-              Image Placeholder -            
-          
-          
   +
+
+ Image Placeholder +
+
+
-        
-          {/*
*/} -          
-            {/*
*/} -              

-                Guide: -              

-            {/*
*/} +
+ {/*
*/} +
+ {/*
*/} +

+ Guide: +

+ {/*
*/} -            
-              
-                

-                  First Text Block -                

-                

-                  This is the content for the first text block. You can write anything here. -                

-              
-              
-                
-                  Image Placeholder -                
-              
-            
-             -            
-              
-                
-                  Image Placeholder -                
-              
-              
-                
-                  

-                    Second Text Block -                  

-                  

-                    This is the content for the second text block. You can write anything here. -                  

-                
-              
-            
+
+
+

+ First Text Block +

+

+ This is the content for the first text block. You can write anything here. +

+
+
+
+ Image Placeholder +
+
+
-            
-              
-                

-                  Third Text Block -                

-                

-                  This is the content for the third text block. You can write anything here. -                

-              
-              
-                
-                    Image Placeholder -                
-              
-            
-          
-        
-      
-    
-  ); +
+
+
+ Image Placeholder +
+
+
+
+

+ Second Text Block +

+

+ This is the content for the second text block. You can write anything here. +

+
+
+
+ +
+
+

+ Third Text Block +

+

+ This is the content for the third text block. You can write anything here. +

+
+
+
+ Image Placeholder +
+
+
+ +
+ + + ); } @@ -287,4 +286,4 @@ export default function Home() { //       //     //  ); -// } fix the formatting of this page, I want the divs to be more centered and the divs below the button to be equal size \ No newline at end of file +// } \ No newline at end of file diff --git a/app/utils/component/ui/ChatInput.tsx b/app/utils/component/ui/ChatInput.tsx index 53c5bf8..e7d5cb2 100644 --- a/app/utils/component/ui/ChatInput.tsx +++ b/app/utils/component/ui/ChatInput.tsx @@ -17,8 +17,8 @@ export default function ChatInput({ onSend, onOpenSettings }: ChatInputProps) { const handleSend = () => { if (message.trim()) { - onSend(message.trim()); - setMessage(""); + onSend(message.trim()); + setMessage(""); } }; @@ -34,62 +34,61 @@ export default function ChatInput({ onSend, onOpenSettings }: ChatInputProps) { return (
-
- -
-