Skip to content

Commit

Permalink
feat: refresh web when a comment or answer is published
Browse files Browse the repository at this point in the history
During the fix I have also restyled a little bit the Editor interface so the title can use the placeholder instead of having placed text.
  • Loading branch information
PauMatas committed Mar 15, 2024
1 parent dd3e1b0 commit 5a7c679
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 82 deletions.
6 changes: 5 additions & 1 deletion src/app/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ const page = async ({ params }: PageProps) => {
include: {
author: true,
votes: true,
comments: true,
comments: {
include: {
_count: true,
},
},
subject: true,
},
orderBy: {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/subject/answer/create/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function POST(req: Request) {
authorId: session.user.id,
},
})
return new Response("Answer created", { status: 201 })
return new Response(JSON.stringify(questionId), { status: 201 })
} catch (error) {
if (error instanceof z.ZodError) {
return new Response(error.message, { status: 422 })
Expand Down
104 changes: 66 additions & 38 deletions src/components/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
"use client"

import { FC, useCallback, useEffect, useRef, useState } from "react"
import {
FC,
startTransition,
useCallback,
useEffect,
useRef,
useState,
} from "react"
import TextareaAutosize from "react-textarea-autosize"
import { useForm } from "react-hook-form"
import {
Expand All @@ -15,27 +22,34 @@ import { toast } from "@/hooks/use-toast"
import { useMutation } from "@tanstack/react-query"
import axios from "axios"
import { usePathname, useRouter } from "next/navigation"
import { Button } from "./ui/Button"

type FormData = QuestionCreationRequest | AnswerCreationRequest

interface EditorProps {
subjectId: string
contentType: "question" | "answer"
questionId?: string
formId: string
}

const Editor: FC<EditorProps> = ({ subjectId, contentType, questionId }) => {
const Editor: FC<EditorProps> = ({
subjectId,
contentType,
questionId,
formId,
}) => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<QuestionCreationRequest | AnswerCreationRequest>({
} = useForm<FormData>({
resolver: zodResolver(
contentType === "question" ? QuestionValidator : AnswerValidator,
),
defaultValues: {
subjectId,
title: `${
contentType === "question" ? "Pregunta" : "Resposta"
} ${new Date().toLocaleDateString()}`,
title: "",
content: null,
questionId: questionId || "", // Add questionId as a value in the form
},
Expand All @@ -61,6 +75,7 @@ const Editor: FC<EditorProps> = ({ subjectId, contentType, questionId }) => {
if (!ref.current) {
const editor = new EditorJS({
holder: "editor",
minHeight: 200,
onReady() {
ref.current = editor
},
Expand Down Expand Up @@ -124,13 +139,9 @@ const Editor: FC<EditorProps> = ({ subjectId, contentType, questionId }) => {
}
}, [isMounted, initializeEditor])

const { mutate: createContent } = useMutation({
mutationFn: async ({
title,
content,
subjectId,
}: QuestionCreationRequest | AnswerCreationRequest) => {
const payload: QuestionCreationRequest | AnswerCreationRequest = {
const { mutate: createContent, isLoading } = useMutation({
mutationFn: async ({ title, content, subjectId }: FormData) => {
const payload: FormData = {
title,
content,
subjectId,
Expand Down Expand Up @@ -158,22 +169,26 @@ const Editor: FC<EditorProps> = ({ subjectId, contentType, questionId }) => {
const questionId = data as string
const newPathname = pathname.replace("/q", `/q/${questionId}`)
router.push(newPathname)
router.refresh()
} else {
ref.current?.clear()
_titleRef.current!.value = ""
window.location.reload()
}
router.refresh()

return toast({
description: `La teva ${
contentType === "question" ? "pregunta" : "reposta"
contentType === "question" ? "pregunta" : "resposta"
} s'ha creat correctament`,
})
},
})

async function onSubmit() {
async function onSubmit(data: FormData) {
const blocks = await ref.current?.save()
const title = (await _titleRef.current?.value) as string
const payload: QuestionCreationRequest | AnswerCreationRequest = {
title: title,

const payload: FormData = {
title: data.title,
content: blocks,
subjectId: subjectId,
...(contentType === "answer" && { questionId: questionId }),
Expand All @@ -187,25 +202,38 @@ const Editor: FC<EditorProps> = ({ subjectId, contentType, questionId }) => {

const { ref: titleRef, ...rest } = register("title")
return (
<div className="w-full p-4 bg-zinc-50 rounded-lg border border-zinc-200 h-full">
<form
id="subject-question-form"
className="w-fit h-full"
onSubmit={handleSubmit(onSubmit)}
>
<div className="prose prose-stone dark:prose-invert h-full">
<TextareaAutosize
ref={(e) => {
titleRef(e)
// @ts-ignore
_titleRef.current = e
}}
placeholder="Títol"
className="w-full resize-none appearance-none overflow-hidden bg-transparent text-xl font-bold focus:outline-none h-12"
/>
<div id="editor" className="min-h-[500px] h-full"></div>
</div>
</form>
<div className="flex-grow">
<div className="w-full p-4 bg-zinc-50 rounded-lg border border-zinc-200">
<form
id={formId}
className="w-full h-full"
onSubmit={handleSubmit(onSubmit)}
>
<div className="prose prose-stone dark:prose-invert h-full">
<TextareaAutosize
ref={(e) => {
titleRef(e)
// @ts-ignore
_titleRef.current = e
}}
{...rest}
placeholder="Títol"
className="w-full resize-none appearance-none overflow-hidden bg-transparent text-xl font-bold focus:outline-none h-12"
/>
<div id="editor" className="min-h-[100px] h-full"></div>
</div>
</form>
</div>
<div className="flex justify-end">
<Button
type="submit"
className="w-full sm:w-auto mt-2"
form={formId}
isLoading={isLoading}
>
Compartir
</Button>
</div>
</div>
)
}
Expand Down
25 changes: 6 additions & 19 deletions src/components/MiniCreateAnswer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,12 @@ const MiniCreateAnswer: FC<MiniCreateAnswer> = ({
<span className="absolute bottom-1 right-1 transform translate-x-1/2 translate-y-1/2 rounded-full w-3 h-3 bg-green-500 outline outline-2 outline-white" />
</div>
{/* form */}
<div className="flex-grow">
<div className="h-full">
<Editor
subjectId={subjectId}
contentType={"answer"}
questionId={questionId}
/>
</div>
</div>
</div>

<div className="flex justify-end">
<Button
type="submit"
className="w-full sm:w-auto mt-2"
form="subject-question-form"
>
Compartir
</Button>
<Editor
subjectId={subjectId}
contentType={"answer"}
questionId={questionId}
formId="question-answer-form"
/>
</div>
</div>
</div>
Expand Down
14 changes: 9 additions & 5 deletions src/components/MiniCreateComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const MiniCreateComment: FC<MiniCreateComment> = ({ session, postId }) => {
const [content, setContent] = useState("")

// Define the mutation function using useMutation hook
const { mutate: createComment } = useMutation({
const { mutate: createComment, isLoading } = useMutation({
mutationFn: async () => {
const { data } = await axios.post("/api/subject/comment/create", {
content: content,
Expand All @@ -26,14 +26,18 @@ const MiniCreateComment: FC<MiniCreateComment> = ({ session, postId }) => {
return data
},
onSuccess: ({}) => {
// Handle success and show toast
toast({
description: `Comment created successfully`,
})
// You can add any additional handling specific to your needs here
setContent("")
window.location.reload()
},
onError: ({}) => {
// Handle error if needed
toast({
title: "Something went wrong",
description: `The comment could not be created. Please try again later.`,
variant: "destructive",
})
},
})

Expand Down Expand Up @@ -72,8 +76,8 @@ const MiniCreateComment: FC<MiniCreateComment> = ({ session, postId }) => {
<Button
type="submit"
className="w-full sm:w-auto mt-2"
form="subject-question-form"
onClick={handleSubmit}
isLoading={isLoading}
>
Compartir
</Button>
Expand Down
21 changes: 5 additions & 16 deletions src/components/MiniCreateQuestion.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client"

import { Session } from "next-auth"
import { Button } from "@/components/ui/Button"
import { FC } from "react"
import UserAvatar from "./UserAvatar"
import Editor from "@/components/Editor"
Expand All @@ -28,21 +27,11 @@ const MiniCreateQuestion: FC<MiniCreateQuestionProps> = ({
<span className="absolute bottom-1 right-1 transform translate-x-1/2 translate-y-1/2 rounded-full w-3 h-3 bg-green-500 outline outline-2 outline-white" />
</div>
{/* form */}
<div className="flex-grow">
<div className="h-full">
<Editor subjectId={subjectId} contentType={"question"} />
</div>
</div>
</div>

<div className="flex justify-end">
<Button
type="submit"
className="w-full sm:w-auto mt-2"
form="subject-question-form"
>
Compartir
</Button>
<Editor
subjectId={subjectId}
contentType={"question"}
formId="subject-question-form"
/>
</div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/lib/validators/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export const QuestionValidator = z.object({
export const AnswerValidator = z.object({
title: z
.string()
.min(3, { message: "Content must be at least 3 characters long" })
.max(128, { message: "Content must be at most 2048 characters long" }),
.min(3, { message: "Title must be at least 3 characters long" })
.max(128, { message: "Title must be at most 2048 characters long" }),
subjectId: z.string(),
content: z.any(),
questionId: z.string(),
Expand Down

0 comments on commit 5a7c679

Please sign in to comment.