diff --git a/The-Preppal b/The-Preppal new file mode 160000 index 000000000..1c5344fb0 --- /dev/null +++ b/The-Preppal @@ -0,0 +1 @@ +Subproject commit 1c5344fb06a944da6019ffd7c3b4cb4748021397 diff --git a/preppal/.gitignore b/preppal/.gitignore new file mode 100644 index 000000000..26b002aac --- /dev/null +++ b/preppal/.gitignore @@ -0,0 +1,40 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# env files (can opt-in for commiting if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/preppal/README.md b/preppal/README.md new file mode 100644 index 000000000..4744c63c6 --- /dev/null +++ b/preppal/README.md @@ -0,0 +1,57 @@ +# PrepPal + +**PrepPal** is an AI-driven web application designed to help users prepare for interviews effectively by providing feedback on their responses. It features question prompts, feedback on answers, and suggestions for improvement, making it a comprehensive tool for interview preparation. + +## Table of Contents + +- [Features](#features) +- [Technologies Used](#technologies-used) +- [Getting Started](#getting-started) +- [Usage](#usage) +- [Project Structure](#project-structure) +--- + +### Features + +- **Question Prompts:** Generate interview questions based on topics or difficulty level. +- **Real-time Feedback:** Get instant feedback on your responses, including suggestions for improvement. +- **Collapsible Feedback View:** User-friendly interface with collapsible sections for feedback per question. +- **Session Storage:** Each interview session is stored, allowing users to review past feedback and track improvement. + +### Technologies Used + +- **Frontend:** React, Next.js, Tailwind CSS +- **Backend:** Node.js, Drizzle ORM, PostgreSql +- **Other:** Lucide React Icons for UI icons, Expo for mobile compatibility (if applicable) + +--- + +### Getting Started + +#### Prerequisites + +- Node.js (version 16 or 18 is recommended) +- npm or yarn (package manager) + + +### Usage + +1. *Create an Interview Session:** Start a new interview by selecting a topic or difficulty. +2. **Answer Questions:** Respond to questions, and receive real-time feedback. +3. **Review Feedback:** Access detailed feedback on each answer, including suggestions for improvement. +4. **Start a New Session:** Return to the dashboard and start another session. + +--- + +### Project Structure + +```bash +. +├── components # Reusable UI components (buttons, collapsibles) +├── pages # Next.js pages (dashboard, feedback, etc.) +├── utils # Utility functions (db connection, schema, etc.) +├── public # Static assets +├── styles # Global styles, Tailwind CSS configuration +├── .env.local # Environment variables +└── README.md # Project documentation +``` diff --git a/preppal/app/(auth)/sign-in/[[...sign-in]]/page.jsx b/preppal/app/(auth)/sign-in/[[...sign-in]]/page.jsx new file mode 100644 index 000000000..750375ceb --- /dev/null +++ b/preppal/app/(auth)/sign-in/[[...sign-in]]/page.jsx @@ -0,0 +1,17 @@ +import { SignIn } from '@clerk/nextjs'; + +export default function Page() { + return ( +
+ {/* Background for Light Mode and Dark Mode */} +
+ + {/* SignIn Component */} + +
+ ); +} diff --git a/preppal/app/(auth)/sign-up/[[...sign-up]]/page.jsx b/preppal/app/(auth)/sign-up/[[...sign-up]]/page.jsx new file mode 100644 index 000000000..5672c1b08 --- /dev/null +++ b/preppal/app/(auth)/sign-up/[[...sign-up]]/page.jsx @@ -0,0 +1,9 @@ +import { SignUp } from '@clerk/nextjs'; + +export default function Page() { + return ( +
+ +
+ ); +} diff --git a/preppal/app/aboutme/page.jsx b/preppal/app/aboutme/page.jsx new file mode 100644 index 000000000..7098e5fc8 --- /dev/null +++ b/preppal/app/aboutme/page.jsx @@ -0,0 +1,88 @@ +"use client"; +import React, { useState, useEffect } from "react"; +import { FaGithub, FaInstagram, FaLinkedin } from "react-icons/fa"; +import Spline from "@splinetool/react-spline"; + +function AboutMe() { + const [isLoading, setIsLoading] = useState(true); + const [progress, setProgress] = useState(0); + + useEffect(() => { + let interval; + if (isLoading) { + interval = setInterval(() => { + setProgress((prev) => (prev < 99 ? prev + 1 : prev)); + }, 50); + } + return () => clearInterval(interval); + }, [isLoading]); + + const handleLoad = () => { + setIsLoading(false); + setProgress(100); + }; + + return ( + <> +
+ {/* Message and Name */} +
+

+ "All I can say is, best of luck with your placements, and have an amazing day ahead! +

+ + ~Y.M.M.R~ + + + {/* Icons just below the name */} +
+ + + + + + + + + +
+
+ + {/* Loading Spinner */} + {isLoading && ( +
+
+

+ Loading {progress}% +

+
+ )} + + {/* Spline Component */} + +
+ + ); +} + +export default AboutMe; + diff --git a/preppal/app/dashboard/_components/AddNewInterview.jsx b/preppal/app/dashboard/_components/AddNewInterview.jsx new file mode 100644 index 000000000..342523813 --- /dev/null +++ b/preppal/app/dashboard/_components/AddNewInterview.jsx @@ -0,0 +1,152 @@ +"use client"; +import React, { useState } from 'react'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "../../../components/ui/dialog"; +import { Button } from '../../../components/ui/button'; +import { Input } from '../../../components/ui/input'; +import { Textarea } from '../../../components/ui/textarea'; +import { chatSession } from '../../../utils/GeminiAIModal'; +import { db } from '../../../utils/db'; +import { MockInterview } from '../../../utils/schema'; +import { LoaderCircle } from 'lucide-react'; +import { v4 as uuidv4 } from 'uuid'; +import { useUser } from '@clerk/nextjs'; +import moment from 'moment'; +import { useRouter } from 'next/navigation'; + +function AddNewInterview() { + const [openDialog, setOpenDialog] = useState(false); + const [jobPosition, setJobPosition] = useState(''); + const [jobDesc, setJobDesc] = useState(''); + const [jobExperience, setJobExperience] = useState(''); + const [loading, setLoading] = useState(false); + const [jsonResponse, setJsonResponse] = useState([]); + const router = useRouter(); + const { user } = useUser(); + + const onSubmit = async (e) => { + setLoading(true); + e.preventDefault(); + console.log(jobPosition, jobDesc, jobExperience); + + const InputPrompt = `Job position:${jobPosition},Job Description:${jobDesc},Years of Experience:${jobExperience},Depends on Job Position,Job Description & Years of Experience give me ${process.env.NEXT_PUBLIC_INTERVIEW_QUESTION_COUNT} interview questions along with Answer in json format,give us question and answer field in json`; + + try { + const result = await chatSession.sendMessage(InputPrompt); + let MockJsonResp = result.response.text(); + + // Log the raw response to check its content + console.log("Raw Response:", MockJsonResp); + + // Clean up response to ensure it's JSON + MockJsonResp = MockJsonResp.replace(/```json/g, "") + .replace(/```/g, "") + .replace(/\n/g, "") + .trim(); + + // Attempt to parse JSON response + const parsedResponse = JSON.parse(MockJsonResp); + setJsonResponse(parsedResponse); + + if (parsedResponse) { + const resp = await db.insert(MockInterview).values({ + mockId: uuidv4(), + jsonMockResp: MockJsonResp, + jobPosition: jobPosition, + jobDesc: jobDesc, + jobExperience: jobExperience, + createdBy: user?.primaryEmailAddress?.emailAddress, + createdAt: moment().format('DD-MM-yyyy'), + }).returning({ mockId: MockInterview.mockId }); + + console.log("Inserted ID:", resp); + if (resp) { + setOpenDialog(false); + router.push('/dashboard/interview/' + resp[0]?.mockId); + } + } else { + console.log("Error: No valid JSON response received."); + } + } catch (error) { + console.error("Error occurred while processing:", error); + } finally { + setLoading(false); + } + }; + + return ( +
+
setOpenDialog(true)} + > +

+ Add New

+
+ + + + + Please share your interview details +
+
+ Please add details about the job position/role, job description, and years of experience. +
+
+
+ + setJobPosition(e.target.value)} + /> +
+
+ +