-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
330 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { Loader } from "~/components/Loader"; | ||
|
||
export default function Loading() { | ||
return <Loader />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <QuestionPage slug={params.slug} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<div className="grid grid-cols-2 justify-between gap-6"> | ||
<NavLink | ||
url={`${BASE_URL}/questions/${prevQuestion.slug}`} | ||
question={prevQuestion.body} | ||
direction="prev" | ||
/> | ||
|
||
<NavLink | ||
url={`${BASE_URL}/questions/${nextQuestion.slug}`} | ||
question={nextQuestion.body} | ||
direction="next" | ||
/> | ||
|
||
{/* <NavButton | ||
onClick={() => handleClick(`/questions/${prevQuestion.slug}`)} | ||
question={prevQuestion.body} | ||
direction="prev" | ||
/> | ||
<NavButton | ||
onClick={() => handleClick(`/questions/${nextQuestion.slug}`)} | ||
question={nextQuestion.body} | ||
direction="next" | ||
/> */} | ||
</div> | ||
); | ||
} | ||
|
||
// Nav Link | ||
// interface NavButtonProps { | ||
// onClick: () => void; | ||
// direction: "prev" | "next"; | ||
// question: string; | ||
// } | ||
|
||
// function NavButton({ onClick, direction, question }: NavButtonProps) { | ||
// return ( | ||
// <button | ||
// onClick={onClick} | ||
// className="group/questions-nav rounded-xl border p-6" | ||
// > | ||
// <span | ||
// className={cn( | ||
// "flex flex-col gap-1", | ||
// direction === "prev" ? "text-left" : "text-right", | ||
// )} | ||
// > | ||
// <span className="text-xs uppercase text-stone-400"> | ||
// {direction === "prev" ? "Prev" : "Next"} | ||
// </span> | ||
// <span className="text-base leading-tight underline group-hover/questions-nav:no-underline group-hover/questions-nav:opacity-50"> | ||
// {question} | ||
// </span> | ||
// </span> | ||
// </button> | ||
// ); | ||
// } | ||
|
||
interface NavLinkProps { | ||
url: string; | ||
direction: "prev" | "next"; | ||
question: string; | ||
} | ||
|
||
function NavLink({ url, direction, question }: NavLinkProps) { | ||
return ( | ||
<Link | ||
href={url} | ||
className="group/questions-nav rounded-xl border p-6" | ||
scroll={false} | ||
> | ||
<span | ||
className={cn( | ||
"flex flex-col gap-1", | ||
direction === "next" && "text-right", | ||
)} | ||
> | ||
<span className="text-xs uppercase text-stone-400"> | ||
{direction === "prev" ? "Prev" : "Next"} | ||
</span> | ||
<span className="text-base leading-tight underline group-hover/questions-nav:no-underline group-hover/questions-nav:opacity-50"> | ||
{question} | ||
</span> | ||
</span> | ||
</Link> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ( | ||
<PageContainer className="max-w-4xl"> | ||
{answers && question && ( | ||
<> | ||
<div className="mb-4"> | ||
<Link | ||
href={`${BASE_URL}/questions`} | ||
className="underline hover:no-underline hover:opacity-50" | ||
scroll={false} | ||
> | ||
All Questions | ||
</Link> | ||
</div> | ||
|
||
<div className="mb-10"> | ||
<h2 className="text-4xl font-extrabold tracking-header"> | ||
{question.body} | ||
</h2> | ||
</div> | ||
|
||
<ul className="mb-6 space-y-2"> | ||
{answers.map((answer, index) => { | ||
const person = answer.personId as IPerson; | ||
|
||
return ( | ||
<li | ||
className="rounded-2xl bg-stone-100 p-8 text-xl" | ||
key={index} | ||
> | ||
<div className="space-y-8"> | ||
<Answer answerData={answer} view={question.answerView} /> | ||
<PersonDetails person={person} /> | ||
</div> | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
|
||
<QuestionsNavigation | ||
questions={questions} | ||
currentIndex={currentIndex} | ||
/> | ||
</> | ||
)} | ||
</PageContainer> | ||
); | ||
} | ||
|
||
// Person details | ||
interface PersonDetailsProps { | ||
person: IPerson; | ||
} | ||
|
||
function PersonDetails({ person }: PersonDetailsProps) { | ||
return ( | ||
<div className="flex items-start gap-3 text-base leading-none"> | ||
<div className="size-10 shrink-0 overflow-hidden rounded-full"> | ||
<PersonImage person={person} /> | ||
</div> | ||
<div className="flex flex-col gap-1.5"> | ||
<Link | ||
href={`${BASE_URL}/people/${person.slug}`} | ||
className="w-fit font-semibold tracking-header underline underline-offset-1 hover:no-underline hover:opacity-50" | ||
> | ||
{person.name} | ||
</Link> | ||
<span>{`${person.jobTitle} @ ${person.company.name}`}</span> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters