diff --git a/src/app/blog/[slug]/commentCard.tsx b/src/app/blog/[slug]/commentCard.tsx index 99c0f6c..47c24e9 100644 --- a/src/app/blog/[slug]/commentCard.tsx +++ b/src/app/blog/[slug]/commentCard.tsx @@ -1,24 +1,22 @@ -'use client'; + import Image from 'next/image'; -import { type Comment } from '../../../interfaces/comments'; -import { formatRelativeTime } from '~/utils/miscUtils'; + import CommentEditModal from './commentEditModal'; -import { useSession } from 'next-auth/react'; import CommentDeleteButton from './commentDeleteButton'; +import { type Comment } from '~/interfaces/comments'; +import { api } from '~/utils/api' +import { formatRelativeTime } from '~/utils/miscUtils'; -interface CommentCardProps { - comment: Comment; -} // Create the CommentCard component -const CommentCard: React.FC = ({ comment }) => { +export default function CommentCard({ comment }: { comment: Comment }) { const commenterImage = comment.commenter?.image ?? '/images/user.png'; const createdAt = comment.createdAt.toISOString(); const displayTime = formatRelativeTime(createdAt); - const { data: sessionData } = useSession(); - const isOwner = sessionData?.user?.id === comment.commenter?.id; - const isAdmin = sessionData?.user?.isAdmin; + const user = api.user.getUserSession.useQuery().data; + const isOwner = user?.id === comment.commenter?.id; + const isAdmin = user?.isAdmin; return (
= ({ comment }) => {

{comment.commenter?.name}

{isOwner ? ( - + + ): isAdmin ? ( - ) : null } + + ) : null }

{comment.content}

Created: {displayTime}

); }; - -export default CommentCard; diff --git a/src/app/blog/[slug]/commentDeleteButton.tsx b/src/app/blog/[slug]/commentDeleteButton.tsx index 8730aec..26c7377 100644 --- a/src/app/blog/[slug]/commentDeleteButton.tsx +++ b/src/app/blog/[slug]/commentDeleteButton.tsx @@ -1,4 +1,5 @@ 'use client'; +import { useRouter } from 'next/navigation'; import { api } from '~/utils/api'; export default function CommentDeleteButton({ @@ -6,33 +7,23 @@ export default function CommentDeleteButton({ }: { commentId: string; }) { - const utils = api.useContext(); + const router = useRouter(); const deleteComment = api.comments.deleteComment.useMutation({ - onSuccess: async () => { - await utils.comments.invalidate(); + onSuccess: () => { + router.refresh(); }, onError: error => { console.log('error deleting comment', error); } }); - function handleDeleteComment(commentId: string) { - return deleteComment.mutate( - { commentId }, - { - onSettled: () => { - console.log('Comment deleted'); - }, - }, - ); - } return ( <> + + + ) +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ada45ee..3279ad7 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -5,6 +5,7 @@ import Layout from '~/app/pageLayout'; import { TRPCReactProvider } from '~/trpc/react'; import { headers } from 'next/headers'; + export const metadata: Metadata = { title: 'Lucas Steinmacher - Software Engineering Blog', description: @@ -16,10 +17,11 @@ export default function RootLayout({ }: { children: React.ReactNode; }) { + return ( - + {children} diff --git a/src/components/commentCard.tsx b/src/components/commentCard.tsx deleted file mode 100644 index 2b458cc..0000000 --- a/src/components/commentCard.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import Image from 'next/image'; -import { type Comment } from '../interfaces/comments'; -import { formatRelativeTime } from '~/utils/miscUtils'; -import CommentEditModal from './commentEditModal'; -import { useSession } from 'next-auth/react'; -import CommentDeleteButton from './commentDeleteButton'; - -interface CommentCardProps { - comment: Comment; -} - -// Create the CommentCard component -const CommentCard: React.FC = ({ comment }) => { - const commenterImage = comment.commenter?.image ?? '/images/user.png'; - const createdAt = comment.createdAt.toISOString(); - const displayTime = formatRelativeTime(createdAt); - - const { data: sessionData } = useSession(); - const isOwner = sessionData?.user?.id === comment.commenter?.id; - const isAdmin = sessionData?.user?.isAdmin; - - return ( -
-
-
- {comment.commenter?.name -

{comment.commenter?.name}

-
- {isOwner ? ( - - ): isAdmin ? ( - ) : null } -
-

{comment.content}

-

Created: {displayTime}

-
- ); -}; - -export default CommentCard; diff --git a/src/components/commentDeleteButton.tsx b/src/components/commentDeleteButton.tsx deleted file mode 100644 index 592390b..0000000 --- a/src/components/commentDeleteButton.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { api } from '~/utils/api'; - -export default function CommentDeleteButton({ - commentId, -}: { - commentId: string; -}) { - const utils = api.useContext(); - const deleteComment = api.comments.deleteComment.useMutation({ - onSuccess: async () => { - await utils.comments.invalidate(); - }, - onError: error => { - console.log('error deleting comment', error); - } - }); - - function handleDeleteComment(commentId: string) { - return deleteComment.mutate( - { commentId }, - { - onSettled: () => { - console.log('Comment deleted'); - }, - }, - ); - } - return ( - <> - - - ); -} diff --git a/src/components/commentEditModal.tsx b/src/components/commentEditModal.tsx deleted file mode 100644 index a9c118e..0000000 --- a/src/components/commentEditModal.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import { api } from '~/utils/api'; -import CommentDeleteButton from './commentDeleteButton'; -import { useSession } from 'next-auth/react'; -import { type Comment } from '~/interfaces/comments'; -import { translateCases, type TranslateCase } from '~/interfaces/translate'; - -export default function CommentEditModal({ comment }: { comment: Comment }) { - const commentId = comment?.id; - const initialContent = comment?.content; - - const { data: sessionData } = useSession(); - const user = sessionData?.user; - - const [isModalOpen, setIsModalOpen] = useState(false); - const [commentContent, setCommentContent] = useState( - comment.content, - ); - const [caseType, setCaseType] = useState('none'); - const [isTranslating, setIsTranslating] = useState(false); - - const modalRef = useRef(null); - const openModal = () => { - setIsModalOpen(true); - }; - - const closeModal = () => { - setIsModalOpen(false); - }; - - useEffect(() => { - // if (!commentContent) { - // setCommentContent(comment?.content); - // } - const handleKeyDown = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - closeModal(); - } - }; - - // TODO this is not working yet - const handleOutsideClick = (e: MouseEvent) => { - if ( - isModalOpen && - modalRef.current && - !modalRef.current.contains(e.target as Node) - ) { - closeModal(); - } - }; - - window.addEventListener('keydown', handleKeyDown); - if (isModalOpen) { - document.addEventListener('click', handleOutsideClick); - } - - return () => { - window.removeEventListener('keydown', handleKeyDown); - document.removeEventListener('click', handleOutsideClick); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const utils = api.useContext(); - const translateMutation = api.translations.translateComment.useMutation({ - async onSuccess(res) { - async function close() { - await new Promise(resolve => setTimeout(resolve, 2000)); - } - await close(); - const { comment } = res; - setCommentContent(comment.content); - await utils.comments.invalidate(); - closeModal(); - }, - onError(error) { - console.log('error translating comment', error); - }, - onSettled() { - console.log('settled'); - setIsTranslating(false); - }, - }); - - const updateMutation = api.comments.updateComment.useMutation({ - async onSuccess() { - await utils.comments.invalidate(); - closeModal(); - }, - onError(error) { - console.log('error updating comment', error); - }, - onSettled() { - console.log('settled'); - setIsTranslating(false); - }, - }); - - function handleUpdate() { - setIsTranslating(true); - if (caseType === 'none') { - updateMutation.mutate({ commentId, content: commentContent }); - } else { - translateMutation.mutate({ - commentId, - caseType: caseType as TranslateCase, - }); - } - } - - return ( - <> - {isModalOpen && ( -
- - {isTranslating && ( -
-

- One moment while we translate... -

-
- )} -
-
-
-
- - -
- - -
-
-
-
-
- - What is this? - -

- Each user gets 5 free translation - tokens to transform your text using - OpenAI ChatGPT. You have{' '} - {user?.langToken} tokens left. -

-
- -
-
- - - - -
-
-
-
-
- )} -

- -

- - ); -} diff --git a/src/components/commentLayout.tsx b/src/components/commentLayout.tsx deleted file mode 100644 index 65c43ae..0000000 --- a/src/components/commentLayout.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { signIn } from 'next-auth/react'; -import ReCAPTCHA from 'react-google-recaptcha'; - -import { typedBoolean } from '~/utils/miscUtils'; -import CommentCard from './commentCard'; -import useController from '~/hooks/useController'; - -const RECAPTCHA_SITE_KEY = process.env.GOOGLE_PUBLIC_RECAPTCHA_KEY; - -export function CommentLayout({ slug }: { slug: string }) { - - const { - submitting, - setSubmitting, - setToken, - comment, - setComment, - allComments, - errors, - setGotime, - commentContainerRef, - userIsLoggedIn, - } = useController({ slug }) - - return ( -
-
-
-
{ - e.preventDefault(); - setSubmitting(true); - }} - > -

- Have an opinion of what I said? Find a typo? Just - want to be nice? -
Feel free to leave a comment! -

- -
-