diff --git a/src/api-client/answers.ts b/src/api-client/answers.ts index 59a504d..859901c 100644 --- a/src/api-client/answers.ts +++ b/src/api-client/answers.ts @@ -41,13 +41,31 @@ export async function submitAnswers(formData: IFormDataProps[]) { // GET ANSWERS BY PERSON SLUG export async function getAnswersByPersonSlug(slug: string) { try { - const answersResponse = await fetch(`${BASE_URL}/api/answers/${slug}`); + const response = await fetch(`${BASE_URL}/api/answers/person/${slug}`); - if (!answersResponse.ok) { + if (!response.ok) { throw new Error("🔴 Data fetch failed"); } - const answers: IAnswer[] = await answersResponse.json(); + const answers: IAnswer[] = await response.json(); + + return answers; + } catch (error) { + console.error("Error fetching data:", error); + return null; + } +} + +// GET ANSWERS BY QUESTION SLUG +export async function getAnswersByQuestionSlug(slug: string) { + try { + const response = await fetch(`${BASE_URL}/api/answers/question/${slug}`); + + if (!response.ok) { + throw new Error("🔴 Data fetch failed"); + } + + const answers: IAnswer[] = await response.json(); return answers; } catch (error) { diff --git a/src/app/api/answers/[slug]/route.ts b/src/app/api/answers/person/[slug]/route.ts similarity index 100% rename from src/app/api/answers/[slug]/route.ts rename to src/app/api/answers/person/[slug]/route.ts diff --git a/src/app/api/answers/question/[slug]/route.ts b/src/app/api/answers/question/[slug]/route.ts new file mode 100644 index 0000000..9aa46c8 --- /dev/null +++ b/src/app/api/answers/question/[slug]/route.ts @@ -0,0 +1,54 @@ +import { NextResponse } from "next/server"; + +import { connectDB } from "~/app/lib/connectDB"; +import { IQuestion, Question } from "~/models/Question"; +import { IPerson, Person } from "~/models/Person"; +import { Answer, IAnswer } from "~/models/Answer"; + +interface ReqParams { + params: { slug: string }; +} + +// GET ANSWERS BY QUESTION SLUG +export async function GET(req: Request, { params }: ReqParams) { + const { slug } = params; + + try { + await connectDB(); + + const question: IQuestion | null = await Question.findOne({ + slug: slug, + }); + + if (!question) { + return NextResponse.json("🔴 Failed to fetch a question by slug.", { + status: 400, + }); + } + + // Remove later (make sure Questions are available before populate) + const people: IPerson[] = await Person.find({}).exec(); + + const answers: IAnswer[] = await Answer.find({ + questionId: question._id, + }) + .populate("personId") + .exec(); + + const activeAnswers = answers.filter((answer) => { + const person = answer.personId as IPerson; + return person.isActive === true; + }); + + return NextResponse.json(activeAnswers, { status: 200 }); + } catch (err) { + console.log(err); + + return NextResponse.json( + { message: "🔴 Error fetching answers by personId." }, + { + status: 500, + }, + ); + } +} diff --git a/src/app/questions/[slug]/loading.tsx b/src/app/questions/[slug]/loading.tsx new file mode 100644 index 0000000..2960001 --- /dev/null +++ b/src/app/questions/[slug]/loading.tsx @@ -0,0 +1,5 @@ +import { Loader } from "~/components/Loader"; + +export default function Loading() { + return ; +} diff --git a/src/app/questions/[slug]/page.tsx b/src/app/questions/[slug]/page.tsx new file mode 100644 index 0000000..3f6d6a7 --- /dev/null +++ b/src/app/questions/[slug]/page.tsx @@ -0,0 +1,23 @@ +import { QuestionPage } from "~/components/layouts/QuestionPage"; + +import { getQuestions } from "~/api-client/questions"; + +interface QuestionPageProps { + params: { + slug: string; + }; +} + +export async function generateStaticParams() { + const questions = await getQuestions(); + + return ( + questions?.map((question) => ({ + slug: question.slug, + })) || [] + ); +} + +export default async function Question({ params }: QuestionPageProps) { + return ; +} diff --git a/src/components/Content.tsx b/src/components/Content.tsx index d075033..fd25415 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -22,7 +22,7 @@ export function Content({ data }: ContentProps) { return (
{question.body} - +
); })} @@ -33,22 +33,22 @@ export function Content({ data }: ContentProps) { // Answer interface AnswersProps { - item: IAnswer; + answerData: IAnswer; view?: AnswerViewType; } -function Answer({ item, view }: AnswersProps) { +export function Answer({ answerData, view = "text" }: AnswersProps) { return ( <> {view === "text" && (
- {item.answer} + {answerData.answer}
)} {view === "links" && (
- {item.links?.map((link, index) => ( + {answerData.links?.map((link, index) => ( ))}
diff --git a/src/components/QuestionsNavigation.tsx b/src/components/QuestionsNavigation.tsx new file mode 100644 index 0000000..819bfdc --- /dev/null +++ b/src/components/QuestionsNavigation.tsx @@ -0,0 +1,117 @@ +import Link from "next/link"; +// import { useRouter } from "next/navigation"; + +import { IQuestion } from "~/models/Question"; +import { BASE_URL } from "~/utils/constants"; +import { cn } from "~/utils/handlers"; + +interface QuestionsNavProps { + currentIndex: number; + questions: IQuestion[]; +} + +export function QuestionsNavigation({ + questions, + currentIndex, +}: QuestionsNavProps) { + // const router = useRouter(); + + const lastIndex = questions.length - 1; + + const prevQuestion = + currentIndex === 0 ? questions[lastIndex] : questions[currentIndex - 1]; + const nextQuestion = + currentIndex === lastIndex ? questions[0] : questions[currentIndex + 1]; + + // function handleClick(path: string) { + // router.push(`${path}`, { scroll: false }); + // } + + return ( +
+ + + + + {/* handleClick(`/questions/${prevQuestion.slug}`)} + question={prevQuestion.body} + direction="prev" + /> + + handleClick(`/questions/${nextQuestion.slug}`)} + question={nextQuestion.body} + direction="next" + /> */} +
+ ); +} + +// Nav Link +// interface NavButtonProps { +// onClick: () => void; +// direction: "prev" | "next"; +// question: string; +// } + +// function NavButton({ onClick, direction, question }: NavButtonProps) { +// return ( +// +// ); +// } + +interface NavLinkProps { + url: string; + direction: "prev" | "next"; + question: string; +} + +function NavLink({ url, direction, question }: NavLinkProps) { + return ( + + + + {direction === "prev" ? "Prev" : "Next"} + + + {question} + + + + ); +} diff --git a/src/components/layouts/QuestionPage.tsx b/src/components/layouts/QuestionPage.tsx new file mode 100644 index 0000000..f90de3c --- /dev/null +++ b/src/components/layouts/QuestionPage.tsx @@ -0,0 +1,103 @@ +import Link from "next/link"; +import { notFound } from "next/navigation"; + +import { PageContainer } from "./PageContainer"; +import { PersonImage } from "../PersonImage"; +import { Answer } from "../Content"; +import { QuestionsNavigation } from "../QuestionsNavigation"; + +import { getAnswersByQuestionSlug } from "~/api-client/answers"; +import { getQuestions } from "~/api-client/questions"; +import { IPerson } from "~/models/Person"; + +import { BASE_URL } from "~/utils/constants"; + +interface QuestionPageProps { + slug: string; +} + +export async function QuestionPage({ slug }: QuestionPageProps) { + const questions = await getQuestions(); + const answers = await getAnswersByQuestionSlug(slug); + + if (!answers || !questions) { + notFound(); + } + + // console.log(answers); + + const currentIndex = questions?.findIndex((item) => item.slug === slug); + + const question = questions?.[currentIndex]; + + return ( + + {answers && question && ( + <> +
+ + All Questions + +
+ +
+

+ {question.body} +

+
+ +
    + {answers.map((answer, index) => { + const person = answer.personId as IPerson; + + return ( +
  • +
    + + +
    +
  • + ); + })} +
+ + + + )} +
+ ); +} + +// Person details +interface PersonDetailsProps { + person: IPerson; +} + +function PersonDetails({ person }: PersonDetailsProps) { + return ( +
+
+ +
+
+ + {person.name} + + {`${person.jobTitle} @ ${person.company.name}`} +
+
+ ); +} diff --git a/src/components/layouts/QuestionsPage.tsx b/src/components/layouts/QuestionsPage.tsx index 7560d6b..53fc0f8 100644 --- a/src/components/layouts/QuestionsPage.tsx +++ b/src/components/layouts/QuestionsPage.tsx @@ -10,8 +10,6 @@ import { BASE_URL } from "~/utils/constants"; export async function QuestionsPage() { const questions = await getQuestions(); - console.log(questions); - if (!questions) { notFound(); } diff --git a/src/models/Answer.ts b/src/models/Answer.ts index 3ae7c63..f42f5ce 100644 --- a/src/models/Answer.ts +++ b/src/models/Answer.ts @@ -1,9 +1,10 @@ import mongoose, { Schema, Document, model } from "mongoose"; import { IQuestion } from "./Question"; +import { IPerson } from "./Person"; export interface IAnswer extends Document { - personId: mongoose.Types.ObjectId; + personId: mongoose.Types.ObjectId | IPerson; questionId: mongoose.Types.ObjectId | IQuestion; name: string; question: string;