Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { NextRequest, NextResponse } from "next/server";
import { systemPrompt } from "@/data/chatbot-data";

const GEMINI_API_URL =
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent";

export async function POST(req: NextRequest) {
try {
const { message, history } = await req.json();

if (!message || typeof message !== "string") {
return NextResponse.json(
{ error: "Message is required" },
{ status: 400 },
);
}

const apiKey = process.env.GEMINI_API_KEY;
if (!apiKey) {
return NextResponse.json(
{ error: "Gemini API key not configured" },
{ status: 500 },
);
}

// Build conversation contents for Gemini
const contents: { role: string; parts: { text: string }[] }[] = [];

// Add conversation history
if (history && Array.isArray(history)) {
for (const msg of history) {
contents.push({
role: msg.role === "user" ? "user" : "model",
parts: [{ text: msg.text }],
});
}
}

// Add the current user message
contents.push({
role: "user",
parts: [{ text: message }],
});

const response = await fetch(`${GEMINI_API_URL}?key=${apiKey}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
system_instruction: {
parts: [{ text: systemPrompt }],
},
contents,
generationConfig: {
temperature: 0.7,
topP: 0.9,
topK: 40,
maxOutputTokens: 1024,
},
}),
});

if (!response.ok) {
const errorData = await response.text();
console.error("Gemini API error:", response.status, errorData);
return NextResponse.json(
{ error: "Failed to get response from AI" },
{ status: 502 },
);
}

const data = await response.json();

const aiText =
data?.candidates?.[0]?.content?.parts?.[0]?.text ||
"I'm having trouble thinking right now. Please try again! 🤔";

return NextResponse.json({ reply: aiText });
} catch (error) {
console.error("Chat API error:", error);
return NextResponse.json(
{ error: "Something went wrong. Please try again." },
{ status: 500 },
);
}
}
99 changes: 58 additions & 41 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
"use client"
import { useState } from "react"
import { AboutSection } from "@/components/sections/about-section"
import { WhyParticipateSection } from "@/components/sections/why-participate-section"
import { WhoCanParticipateSection } from "@/components/sections/who-can-participate-section"
import { PrizesSection } from "@/components/sections/prizes-section"
import { SponsorsSection } from "@/components/sections/sponsors-section"
import { TrainingSection } from "@/components/sections/training-section"
import { MentorsSection } from "@/components/sections/mentors-section"
import { TeamSection } from "@/components/sections/team-section"
import { HeroSection } from "@/components/sections/hero-section"
import { TimelineSection } from "@/components/sections/timeline-section"
import { FAQSection } from "@/components/sections/faq-section"
import { FooterSection } from "@/components/sections/footer-section"
"use client";
import { useState } from "react";
import { AboutSection } from "@/components/sections/about-section";
import { WhyParticipateSection } from "@/components/sections/why-participate-section";
import { WhoCanParticipateSection } from "@/components/sections/who-can-participate-section";
import { PrizesSection } from "@/components/sections/prizes-section";
import { SponsorsSection } from "@/components/sections/sponsors-section";
import { TrainingSection } from "@/components/sections/training-section";
import { MentorsSection } from "@/components/sections/mentors-section";
import { TeamSection } from "@/components/sections/team-section";
import { HeroSection } from "@/components/sections/hero-section";
import { TimelineSection } from "@/components/sections/timeline-section";
import { FooterSection } from "@/components/sections/footer-section";
import { AIChatbot } from "@/components/sections/ai-chatbot";

export default function HackathonLanding() {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);

// const [isModalOpen, setIsModalOpen] = useState(false)
// const openModal = () => setIsModalOpen(true)
// const closeModal = () => setIsModalOpen(false)

const scrollToSchedule = () => {
const scheduleSection = document.getElementById("schedule")
const scheduleSection = document.getElementById("schedule");
if (scheduleSection) {
scheduleSection.scrollIntoView({ behavior: "smooth" })
scheduleSection.scrollIntoView({ behavior: "smooth" });
}
}
};

const handleMobileMenuClick = () => {
setIsMobileMenuOpen(false)
}
setIsMobileMenuOpen(false);
};

return (
<div className="min-h-screen bg-linear-to-b from-[#0a0b0f] via-[#0B0C10] to-[#0a0b0f] text-white">
Expand All @@ -40,7 +40,12 @@ export default function HackathonLanding() {
{/* Logo */}
<div className="flex items-center gap-3">
<div className="text-[#13ec80]">
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<svg
className="w-8 h-8"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
Expand All @@ -49,23 +54,31 @@ export default function HackathonLanding() {
/>
</svg>
</div>
<h2 className="text-white text-xl font-bold tracking-tight">Hack4COOU</h2>
<h2 className="text-white text-xl font-bold tracking-tight">
Hack4COOU
</h2>
</div>

{/* Desktop Menu */}
<div className="hidden md:flex items-center gap-8">
<a className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium" href="#about">
<a
className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium"
href="#about"
>
About
</a>
<a className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium" href="#training">
<a
className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium"
href="#training"
>
Training
</a>
<a className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium" href="#prizes">
<a
className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium"
href="#prizes"
>
Prizes
</a>
<a className="text-gray-300 hover:text-[#13ec80] transition-colors text-sm font-medium" href="#faq">
FAQ
</a>
</div>

{/* CTA Button */}
Expand All @@ -87,8 +100,18 @@ export default function HackathonLanding() {
className="text-white hover:text-[#13ec80] transition-colors"
aria-label="Toggle menu"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
</button>
</div>
Expand Down Expand Up @@ -117,13 +140,7 @@ export default function HackathonLanding() {
>
Prizes
</a>
<a
href="#faq"
onClick={handleMobileMenuClick}
className="block px-4 py-2 text-gray-300 hover:text-[#13ec80] hover:bg-[#283930]/30 transition-colors text-sm font-medium"
>
FAQ
</a>

<div className="px-4 py-2">
<a
href="https://gdg.community.dev/events/details/google-gdg-on-campus-chukwuemeka-odumegwu-ojukwu-university-anambra-nigeria-presents-hack4coou-innovate-amp-build/"
Expand Down Expand Up @@ -175,11 +192,11 @@ export default function HackathonLanding() {
{/* Team Section */}
<TeamSection />

{/* FAQ Section */}
<FAQSection />

{/* Footer Section */}
<FooterSection />

{/* AI Chatbot Assistant */}
<AIChatbot />
</div>
)
);
}
Loading