From d98bd9fd7a175e0ea0f73c74eeaa7fc423a10c3d Mon Sep 17 00:00:00 2001 From: Shaurya Jha Date: Sat, 28 Sep 2024 05:44:33 +0530 Subject: [PATCH] Connect Questions to Video --- src/actions/question/index.ts | 4 +- src/app/(main)/(pages)/question/page.tsx | 1 + src/components/CourseView.tsx | 4 +- src/components/NewPostDialog.tsx | 152 ++++++++++++++++-- .../admin/ContentRendererClient.tsx | 15 +- src/components/posts/PostCard.tsx | 29 +++- src/components/posts/form/form-input.tsx | 11 +- 7 files changed, 191 insertions(+), 25 deletions(-) diff --git a/src/actions/question/index.ts b/src/actions/question/index.ts index c2cb7ee7b..dbf5226f2 100644 --- a/src/actions/question/index.ts +++ b/src/actions/question/index.ts @@ -32,7 +32,7 @@ const createQuestionHandler = async ( }; } - const { title, content, tags } = data; + const { title, content, tags, videoId = 0 } = data; // Create initial slug let slug = generateHandle(title); @@ -89,7 +89,7 @@ const updateQuestionHandler = async ( }; } - const { title, content, tags, questionId } = data; + const { title, content, tags, questionId, videoId = 0 } = data; const userExists = await db.user.findUnique({ where: { id: session.user.id }, }); diff --git a/src/app/(main)/(pages)/question/page.tsx b/src/app/(main)/(pages)/question/page.tsx index e050f3a00..bf75acd9d 100644 --- a/src/app/(main)/(pages)/question/page.tsx +++ b/src/app/(main)/(pages)/question/page.tsx @@ -52,6 +52,7 @@ const getQuestionsWithQuery = async ( slug: true, createdAt: true, updatedAt: true, + videoId: true, votes: { where: { userId: sessionId }, select: { userId: true, voteType: true }, diff --git a/src/components/CourseView.tsx b/src/components/CourseView.tsx index 124a48f32..064bd217e 100644 --- a/src/components/CourseView.tsx +++ b/src/components/CourseView.tsx @@ -38,8 +38,8 @@ export const CourseView = ({ ? 'folder' : courseContent?.value.type; return ( -
-
+
+
{ const { theme } = useTheme(); const formRef = useRef>(null); @@ -29,8 +34,73 @@ export const NewPostDialog = () => { const tagInputRef = useRef(null); const [value, setValue] = useState('**Hello world!!!**'); const [tags, setTags] = useState([]); + const [videos, setVideos] = useState([]); + const [videoTitleValue, setVideoTitleValue] = useState(''); + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [search, setSearch] = useState(''); + const [selectedVideo, setSelectedVideo] = useState
-

Link Video

{ + setVideoTitleValue(e.target.value); + if (e.target.value === '') { + setSelectedVideo(null); + } + }} + disabled={selectedVideo !== null} + ref={videoTitleInputRef} /> + + {selectedVideo && ( + + )} + {isDropdownOpen && ( +
+ setSearch(e.target.value)} + placeholder="Search videos" + className="w-full px-4 py-2" + /> + {videos + .filter((video) => + video.title + .toLowerCase() + .includes(search.toLowerCase()), + ) + .map((video) => ( + + ))} +
+ )}
{ ); -}; \ No newline at end of file +}; diff --git a/src/components/admin/ContentRendererClient.tsx b/src/components/admin/ContentRendererClient.tsx index 018aecc71..ab807a4f6 100644 --- a/src/components/admin/ContentRendererClient.tsx +++ b/src/components/admin/ContentRendererClient.tsx @@ -105,11 +105,16 @@ export const ContentRendererClient = ({

{content.title}

- {metadata.slides ? ( - - +
+ + - ) : null} + {metadata.slides ? ( + + + + ) : null} +
{!showChapters && metadata.segments?.length > 0 && ( @@ -157,4 +162,4 @@ export const ContentRendererClient = ({
); -}; +}; \ No newline at end of file diff --git a/src/components/posts/PostCard.tsx b/src/components/posts/PostCard.tsx index 3b35f0ec0..c7c6323c1 100644 --- a/src/components/posts/PostCard.tsx +++ b/src/components/posts/PostCard.tsx @@ -1,7 +1,7 @@ 'use client'; import '@uiw/react-md-editor/markdown-editor.css'; import '@uiw/react-markdown-preview/markdown.css'; -import React, { useState, useTransition } from 'react'; +import React, { useState, useTransition, useEffect } from 'react'; import VoteForm from './form/form-vote'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; @@ -54,6 +54,7 @@ const PostCard: React.FC = ({ const { theme } = useTheme(); const [markDownValue, setMarkDownValue] = useState(''); const [enableReply, setEnableReply] = useState(false); + const handleMarkdownChange = (newValue?: string) => { if (typeof newValue === 'string') { setMarkDownValue(newValue); @@ -62,7 +63,7 @@ const PostCard: React.FC = ({ const router = useRouter(); - const [isPending, startTransition] = useTransition(); + const [isPending, startTransition] = useTransition(); const { execute, fieldErrors } = useAction(createAnswer, { onSuccess: () => { @@ -93,6 +94,24 @@ const PostCard: React.FC = ({ return num.toString(); }; + const [videoTitles, setVideoTitles] = useState({}); + + useEffect(() => { + const fetchVideoTitles = async () => { + const response = await fetch('/api/search?q=videos'); + const data = await response.json(); + const videoTitlesMap = data.reduce( + (acc: { [x: string]: any }, video: { id: number; title: string }) => { + acc[video.id] = video.title; + return acc; + }, + {}, + ); + setVideoTitles(videoTitlesMap); + }; + fetchVideoTitles(); + }, []); + return (
= ({
)} + {isExtendedQuestion(post) && post.videoId && ( +

+ Video: {videoTitles[post.videoId] || post.videoId} +

+ )} +
; className?: string; defaultValue?: string; + value?: string; + onChange?: (e: React.ChangeEvent) => void; + onClick?:() => void; onBlur?: () => void; onKeyUp?: (event: React.KeyboardEvent) => void; } @@ -35,6 +38,9 @@ export const FormPostInput = forwardRef( errors, className, defaultValue = '', + onClick, + value, + onChange, onKeyUp, onBlur, }, @@ -55,11 +61,13 @@ export const FormPostInput = forwardRef( ) : null} ( className, )} aria-describedby={`${id}-error`} + defaultValue={value === undefined ? defaultValue : undefined} />