343 lines
8.9 KiB
TypeScript
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>
|
|
</>
|
|
);
|
|
}
|