Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Q/A Session Interface #25

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f66b8e9
feat: created qna session page with temperory id
shristigupta12 Oct 17, 2023
82dccfb
feat: created question interface and mock questions data
shristigupta12 Oct 17, 2023
e41cc88
feat: created qna-question-card
shristigupta12 Oct 17, 2023
61a84d1
feat: rendered question-list
shristigupta12 Oct 17, 2023
ec2bfb5
fix: Link tab removed
shristigupta12 Oct 17, 2023
738ef59
styles: qna-question-sections
shristigupta12 Oct 22, 2023
8a90d09
feat: included text-area
shristigupta12 Oct 22, 2023
39a2067
styles: text-area fixes
shristigupta12 Oct 22, 2023
8d14fe5
feat: UI completed
shristigupta12 Oct 22, 2023
c3696c2
feat: remaining-time functionality added
shristigupta12 Oct 22, 2023
6e7ab87
feat: added functionality in questions
shristigupta12 Oct 23, 2023
c101f6a
fix: vercel deployment issue fixed
shristigupta12 Oct 23, 2023
02d99be
fix: question prerender fix
yashsehgal Oct 23, 2023
156b216
fix: minor style improvements & folder structure
yashsehgal Oct 23, 2023
76afcd6
fix: added random mock questions for better UI clarity
shristigupta12 Oct 23, 2023
f9149a1
fix: abstracted the code into components
shristigupta12 Oct 23, 2023
9dd0f58
fix: mock data fix
shristigupta12 Oct 23, 2023
c20bf71
feat: added TipTap instead of Text area
shristigupta12 Oct 23, 2023
289f70d
feat: dialog created with prevailing errros in the rendered ui
shristigupta12 Oct 23, 2023
84601a4
feat: dialog box ui completed
shristigupta12 Oct 24, 2023
982d362
add: answer updation feature
shristigupta12 Nov 25, 2023
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
2 changes: 2 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ h4 {
.form-input-wrapper {
@apply grid grid-cols-1 gap-2 my-6;
}


1 change: 1 addition & 0 deletions app/qna/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { fetchTopics } from '@/middleware/qna/sessions';
import { getTopicDepthLevels } from '@/common';

const TopicBasedQNA: React.FunctionComponent = () => {

const [recentQNASessions, setRecentQNASessions] = useState<
Array<QNASessionCardInterface>
>(fetchRecentQNASessions());
Expand Down
79 changes: 79 additions & 0 deletions app/qna/session/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use client'
import PageContent from "@/components/layouts/page-content"
import ViewContainer from "@/components/layouts/view-container"
import { Button } from "@/components/ui/button"
import { QnaQuestionsList } from "@/components/sections/qna-questions-list"
import { fetchQnaQuestions } from "@/middleware/qna/qna-questions"
import { useEffect, useState } from "react"
import { Textarea } from "@/components/ui/textarea"
import { Check } from 'lucide-react';
import { Timer } from "@/components/ui/qna-timer"
import { QnaQuesCard } from "@/components/ui/qna-ques-card";
import { BoxCard } from "@/components/layouts/box-card"
import { cn } from "@/lib/utils";


const QNASession: React.FunctionComponent = () => {

const [time, setTime] = useState("12:34")
const [progressVal, setProgressVal] = useState(0);
const qData = fetchQnaQuestions();
const [qNum, setQNum] = useState(0);
const [storeAns, setStoreAns] = useState(["", "", "", "", "", "", "", "", "", "",])
const handleAnsChange = (e: any) => {
setStoreAns([
storeAns[qNum] = e.target.value as string
])
}

return (
<PageContent>
<ViewContainer className="flex justify-between gap-[120px]">
{/* <QnaQuestionsList data={fetchQnaQuestions()}/> */}
{/**/}
<section className="qna-question-list flex flex-col items-center">
<div className="qna-topic mb-7 text-xl font-bold">Frontend Engineering</div>
<div className="qna-questions flex flex-col gap-4 overflow-y-scroll max-h-[575px] hide-scrollbar h-[90svh]">
{qData?.map((q, index) => {
return (
// <QnaQuesCard
// key={index}
// question={q.question}
// score = {q.score}
// questionId={q.questionId}
// />
<BoxCard className={cn('bg-neutral-200 hover:brightness-90 flex flex-col justify-between p-4 min-h-[140px] cursor-pointer')} onClick={() => setQNum(q?.questionId)} key={index}>
<div className="flex gap-1 align-items-center font-semibold text-lg truncate " >
<span>{q?.questionId}.</span>
<p>{q?.question}</p>
</div>
<span className="
text-neutral-400">+{q?.score} score</span>
</BoxCard>
);
})}
</div>
</section>
{/**/}
<div className="w-full flex flex-col gap-16 ">
<div className="remainingTime-endSessionAction-wrapper flex justify-between">
<Timer seconds={3600} />
<Button variant="destructive" className="end-session-btn">End Session</Button>
</div>
<div>
<div className="flex flex-col gap-11">
<h2 className="question text-3xl font-semibold">{qData[qNum].question}</h2>
<div className="answer-wrapper ">
<p className="font-medium mb-1 text-sm" >Write your answer here</p>
<Textarea className="answer-box min-h-[300px] w-full px-4 py-2 placeholder:text-base text-base" placeholder="Good luck! You will do well" onChange={handleAnsChange} value={storeAns[qNum]} />
</div>
</div>
<Button className="mark-complete-btn mt-3 flex gap-1"><Check /><span>Mark as completed</span></Button>
</div>
<Button className="submit-btn w-fit ml-auto mt-[-25px]">Submit and End Session</Button>
</div>
</ViewContainer>
</PageContent>
)
}
export default QNASession
2 changes: 1 addition & 1 deletion components/layouts/box-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const BoxCard: React.FunctionComponent<
> = ({ className, children, ...props }) => (
<div
className={cn(
'relative w-[240px] h-[140px] rounded-2xl border-transparent shadow transition-all hover:shadow-md',
'relative w-[240px] h-[140px] rounded-2xl border-transparent shadow transition-all hover:shadow-md cursor:pointer',
'max-xl:w-[220px] max-xl:h-[120px]',
'max-lg:w-[200px] max-lg:h-[100px]',
'max-sm:rounded-xl',
Expand Down
24 changes: 24 additions & 0 deletions components/sections/qna-questions-list/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { QnaQuesCard } from "@/components/ui/qna-ques-card";

const QnaQuestionsList: React.FunctionComponent<{ data: Array<QnaQueCardInterface> }> = ({ data }) => {

return(
<section className="qna-question-list flex flex-col items-center">
<div className="qna-topic mb-7 text-xl font-bold">Frontend Engineering</div>
<div className="qna-questions flex flex-col gap-4 overflow-y-scroll max-h-[575px] hide-scrollbar h-[90svh]">
{data.map((q, index) => {
return (
<QnaQuesCard
key={index}
question={q.question}
score = {q.score}
questionId={q.questionId}
/>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to use better naming conventions. Instead of q use question

);
})}
</div>
</section>
)
}

export {QnaQuestionsList};
18 changes: 18 additions & 0 deletions components/ui/qna-ques-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Link from "next/link";
import { BoxCard } from "../layouts/box-card";
import { cn } from "@/lib/utils";

const QnaQuesCard: React.FunctionComponent<QnaQueCardInterface> = ({question, questionId, score})=>{
return(
<BoxCard className={cn('bg-neutral-200 hover:brightness-90 flex flex-col justify-between p-4 min-h-[140px]')}>
<div className="flex gap-1 align-items-center font-semibold text-lg truncate " >
<span>{questionId}.</span>
<p>{question}</p>
</div>
<span className="
text-neutral-400">+{score} score</span>
</BoxCard>
)
}

export {QnaQuesCard};
51 changes: 51 additions & 0 deletions components/ui/qna-timer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

import { useEffect, useRef, useState } from "react";
import { Progress } from "@/components/ui/progress";

const formatTime = (time: number) => {
let minutes = Math.floor(time / 60);
let seconds = time % 60;

const formattedMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`;
const formattedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;

return `${formattedMinutes}:${formattedSeconds}`;
}

function Timer({ seconds }: any) {
const totalTime = seconds;
const [progressVal, setProgressVal] = useState(0);
const [timer, setTimer] = useState(seconds);
const timerId: any = useRef();

useEffect(() => {
timerId.current = setInterval(() => {
setTimer((prev: number) => prev - 1);
}, 1000);
return () => clearInterval(timerId.current);
}, []);

useEffect(() => {
const percent = ((totalTime - timer) / seconds) * 100; // Calculate progress relative to 'seconds'
setProgressVal(percent);
if (timer <= 0) {
clearInterval(timerId.current);
alert("Time up!");
}
}, [timer, seconds]);

return (
<div className="remainingTime-progress-wrapper w-3/4 flex flex-col gap-4">
<div className="remaining-time-wrapper">
<div className="remaining-time flex justify-between">
<h3 className="font-semibold text-lg">Remaining Time</h3>
<div className="text-neutral-400 font-medium">{formatTime(timer)}</div>
</div>
</div>
<Progress value={progressVal} />
</div>
);
}

export { Timer };

2 changes: 1 addition & 1 deletion components/ui/recent-session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const RecentSession: React.FunctionComponent<QNASessionCardInterface> = ({
<Link
href="#"
className="w-fit active:outline-none active:transition-none focus:outline-none h-fit rounded-2xl max-sm:rounded-xl hover:scale-95 active:scale-90 transition-all">
<BoxCard className={cn('bg-neutral-100 hover:brightness-90')}>
<BoxCard className={cn('bg-neutral-700 hover:brightness-90')}>
<MessageSquare
className={cn('absolute icon-wrapper top-4 right-4 text-black')}
/>
Expand Down
24 changes: 24 additions & 0 deletions components/ui/textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from "react"

import { cn } from "@/lib/utils"

export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}

const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={cn(
"flex min-h-[300px] w-full rounded-md border border-neutral-200 hover:border-neutral-400 bg-white px-3 py-2 text-sm ring-offset-white placeholder:text-neutral-400 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-300 disabled:cursor-not-allowed disabled:opacity-50 dark:border-neutral-800 dark:bg-neutral-950 dark:ring-offset-neutral-950 dark:placeholder:text-neutral-400 dark:focus-visible:ring-neutral-300 text-neutral-700",
className
)}
ref={ref}
{...props}
/>
)
}
)
Textarea.displayName = "Textarea"

export { Textarea }
16 changes: 16 additions & 0 deletions middleware/qna/qna-questions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Environment } from '@/common/environment-variables';
import { QnaMockQuestions } from '@/mocks/qna-questions-mock';

function fetchQnaQuestions(){
switch (Environment.ENVIRONMENT_TYPE){
case "development":
return QnaMockQuestions;
case "production":
//TODO Send topic-name and fetch questions-list with marks for each question via openAI
return [];
default:
return [];
}
}

export {fetchQnaQuestions};
57 changes: 57 additions & 0 deletions mocks/qna-questions-mock.ts
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do add random questions of different word lengths for better UI clarity. You can use ChatGPT to generate questions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@


const QnaMockQuestions: Array<QnaQueCardInterface> = [
{
question: "Define Diffing Algorithm 1",
score: 10,
questionId: 0
},
{
question: "Define Diffing Algorithm 2",
score: 10,
questionId: 1
},
{
question: "Define Diffing Algorithm 3",
score: 10,
questionId: 2
},
{
question: "Define Diffing Algorithm 4",
score: 10,
questionId: 3
},
{
question: "Define Diffing Algorithm 5",
score: 10,
questionId: 4
},
{
question: "Define Diffing Algorithm 6",
score: 10,
questionId: 5
},
{
question: "Define Diffing Algorithm 7",
score: 10,
questionId: 6
},
{
question: "Define Diffing Algorithm 8",
score: 10,
questionId: 7
},
{
question: "Define Diffing Algorithm 9",
score: 10,
questionId: 8
},
{
question: "Define Diffing Algorithm 10",
score: 10,
questionId: 9
}
]


export {QnaMockQuestions};
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "components/sections/qna-ques-list", "components/ui/qna-timer.tsx"],
"exclude": ["node_modules"]
}
5 changes: 5 additions & 0 deletions types/qna-que-card.d.ts
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is related to Q/A session, thus this type doesn't need a new file,
instead add this type to the qna-session.d.ts file

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare interface QnaQueCardInterface {
question: string;
score: number;
questionId: number;
}