lms-frontend/src/features/Lessons/Questions/index.tsx

343 lines
8.9 KiB
TypeScript

import { HeartFilled, HeartOutlined } from "@ant-design/icons";
import { Avatar, Button, Flex, Form, Input, InputRef, Typography } from "antd";
import { LessonQuestion, LessonQuestionReply } from "core/types/lesson";
import { Constants } from "core/utils/utils";
import React, { useRef } from "react";
export default function Questions({ lessionID }: { lessionID: string }) {
let questions: LessonQuestion[] = [
{
Id: "1",
LessionId: "1",
Question: "What is the capital of Germany?",
Likes: 5,
CreatorUserId: "1",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "2",
LessionId: "1",
Question: "What is the capital of France?",
Likes: 3,
CreatorUserId: "2",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "3",
LessionId: "1",
Question: "What is the capital of Italy?",
Likes: 2,
CreatorUserId: "3",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
];
return (
<Flex justify="center">
<Flex style={{ width: 800, maxWidth: 800 * 0.9 }} vertical>
<Typography.Title level={3}>Questions</Typography.Title>
<Form layout="vertical">
<Form.Item label="Ask a question">
<Input.TextArea placeholder={"Type something"} />
</Form.Item>
<Form.Item>
<Button type="primary">Submit</Button>
</Form.Item>
</Form>
<Flex vertical style={{}}>
{questions.map((question) => (
<QuestionItem key={question.Id} question={question} />
))}
</Flex>
</Flex>
</Flex>
);
}
type HandleReplyFunction = (text: string, replyID?: string) => Promise<void>;
export function QuestionItem({ question }: { question: LessonQuestion }) {
const [showReplies, setShowReplies] = React.useState(1);
let user = {
Id: "132154153613",
FirstName: "Anja",
LastName: "Blasinstroment",
};
let questionsReplys: LessonQuestionReply[] = [
{
Id: "1",
QuestionId: "1",
Reply: "Berlin",
Likes: 5,
CreatorUserId: "1",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "2",
QuestionId: "1",
Reply: "Munich",
Likes: 3,
CreatorUserId: "2",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "3",
QuestionId: "1",
Reply: "Hamburg",
Likes: 2,
CreatorUserId: "3",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "4",
QuestionId: "1",
Reply: "Cologne",
Likes: 0,
CreatorUserId: "3",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "5",
QuestionId: "1",
Reply: "Frankfurt",
Likes: 0,
CreatorUserId: "3",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "6",
QuestionId: "1",
Reply: "Stuttgart",
Likes: 2,
CreatorUserId: "3",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
{
Id: "7",
QuestionId: "1",
Reply: "Düsseldorf",
Likes: 10,
CreatorUserId: "3",
CreatedAt: "2021-09-01T12:00:00Z",
UpdatedAt: "2021-09-01T12:00:00Z",
},
];
async function handleReply(text: string, replyID?: string) {
console.log("reply", text);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
return (
<QuestionUIRaw
userID={user.Id}
text={question.Question}
childContent={
<div>
{(() => {
let nodes = [];
for (let i = 0; i < questionsReplys.length; i++) {
if (i > showReplies - 1) {
nodes.push(
<Button
key="showMore"
type="link"
color="primary"
onClick={() => setShowReplies(showReplies + 3)}
style={{ marginLeft: 64 }}
>
Show more
</Button>
);
break;
}
nodes.push(
<QuestionReplyItem
key={"reply_" + questionsReplys[i].Id}
question={questionsReplys[i]}
handleReply={handleReply}
/>
);
}
return nodes;
})()}
</div>
}
likes={question.Likes}
onReply={handleReply}
onLike={() => {}}
replyID={undefined}
/>
);
}
export function QuestionReplyItem({
question,
handleReply,
}: {
question: LessonQuestionReply;
handleReply: HandleReplyFunction;
}) {
let user = {
Id: "132154153613",
FirstName: "Anja",
LastName: "Blasinstroment",
};
return (
<QuestionUIRaw
userID={user.Id}
text={question.Reply}
childContent={<></>}
likes={question.Likes}
onReply={handleReply}
onLike={() => {}}
replyID={question.Id}
/>
);
}
export function QuestionUIRaw({
userID,
text,
childContent,
likes,
replyID,
onReply,
onLike,
}: {
userID: string;
text: string;
childContent: React.ReactNode;
likes: number;
replyID?: string;
onReply: HandleReplyFunction;
onLike: () => void;
}) {
const [hasLiked, setHasLiked] = React.useState(false);
const [replyFormVisible, setReplyFormVisible] = React.useState(false);
const [replyText, setReplyText] = React.useState<null | string>(null);
const [isSendingReply, setIsSendingReply] = React.useState(false);
let user = {
Id: "132154153613",
FirstName: "Anja",
LastName: "Blasinstroment",
};
const userAt = `@${user.FirstName} ${user.LastName} `;
async function toggleLike() {
setHasLiked(!hasLiked);
}
// useref to focus on the input field
const inputRef = useRef<InputRef>(null);
return (
<>
<Flex gap={16}>
<Avatar
src={`${Constants.STATIC_CONTENT_ADDRESS}/demo/lesson_thumbnail.webp`}
size={56}
/>
<Flex vertical style={{ width: "100%" }}>
<Typography style={{ fontSize: 24, fontWeight: 800 }}>
{user.FirstName} {user.LastName}
</Typography>
<Typography style={{ fontSize: 18, fontWeight: 500 }}>
{text}
</Typography>
<Flex gap={0} align="center">
<Button
type="text"
icon={hasLiked ? <HeartFilled /> : <HeartOutlined />}
shape="circle"
size="large"
style={{
color: hasLiked ? "red" : undefined,
transform: hasLiked ? "scale(1.2)" : "scale(1)",
transition: "all 0.3s ease-in-out",
}}
onClick={toggleLike}
></Button>
<Typography
style={{ fontSize: 16, fontWeight: 400, pointerEvents: "none" }}
>
{likes >= 1 ? likes : " "}
</Typography>
<Button
type={replyFormVisible ? "link" : "text"}
onClick={() => {
if (replyText === null) setReplyText(userAt);
setReplyFormVisible(!replyFormVisible);
setTimeout(() => {
if (inputRef.current) {
const input = inputRef.current;
input.focus({ cursor: "end" });
}
}, 100);
}}
>
{replyFormVisible ? "Hide" : "Reply"}
</Button>
</Flex>
{replyFormVisible ? (
<Form
disabled={isSendingReply}
onFinish={async () => {
setIsSendingReply(true);
await onReply(replyText ? replyText : "", replyID);
setIsSendingReply(false);
setReplyFormVisible(false);
setReplyText(null);
}}
>
<Form.Item
name="reply"
rules={[{ required: true, message: "Please write a reply" }]}
>
<Input.TextArea
ref={inputRef}
defaultValue={replyText ? replyText : userAt}
value={replyText ? replyText : userAt}
placeholder="Write a reply"
onChange={(e) => setReplyText(e.target.value)}
/>
</Form.Item>
<Form.Item>
<Button
type="primary"
loading={isSendingReply}
htmlType="submit"
>
Reply
</Button>
</Form.Item>
</Form>
) : null}
{childContent}
</Flex>
</Flex>
</>
);
}