Skip to content

Commit

Permalink
Merge pull request #25 from L-Steinmacher/app-router
Browse files Browse the repository at this point in the history
Migrate comments to app router
  • Loading branch information
L-Steinmacher authored Oct 23, 2023
2 parents cde0113 + 002820c commit de2a22e
Show file tree
Hide file tree
Showing 21 changed files with 364 additions and 791 deletions.
28 changes: 13 additions & 15 deletions src/app/blog/[slug]/commentCard.tsx
Original file line number Diff line number Diff line change
@@ -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<CommentCardProps> = ({ 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 (
<div
Expand All @@ -38,14 +36,14 @@ const CommentCard: React.FC<CommentCardProps> = ({ comment }) => {
<p className="font-bold">{comment.commenter?.name}</p>
</div>
{isOwner ? (
<CommentEditModal comment={comment} />

<CommentEditModal comment={comment} user={user} />
): isAdmin ? (
<CommentDeleteButton commentId={comment.id} />) : null }
<CommentDeleteButton commentId={comment.id} />
) : null }
</div>
<p className="text-gray-700">{comment.content}</p>
<p className="mt-2 text-sm text-gray-500">Created: {displayTime}</p>
</div>
);
};

export default CommentCard;
19 changes: 5 additions & 14 deletions src/app/blog/[slug]/commentDeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@
'use client';
import { useRouter } from 'next/navigation';
import { api } from '~/utils/api';

export default function CommentDeleteButton({
commentId,
}: {
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 (
<>
<button
className="items-center rounded-md border border-transparent bg-none px-4 py-2 text-base font-medium text-white shadow-sm shadow-slate-400 hover:bg-red-200 focus:outline-none"
onClick={e => {
e.preventDefault();
handleDeleteComment(commentId);
deleteComment.mutate({ commentId });
}}
>
Expand Down
35 changes: 23 additions & 12 deletions src/app/blog/[slug]/commentEditModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
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';
import { type Session } from 'next-auth';
import { useRouter } from 'next/navigation';
import useController from '~/hooks/useController';

export default function CommentEditModal({ comment }: { comment: Comment }) {
export default function CommentEditModal({ comment, user }: { comment: Comment, user: Session["user"] }) {
const commentId = comment?.id;
const initialContent = comment?.content;

const { data: sessionData } = useSession();
const user = sessionData?.user;
const router = useRouter();

const [isModalOpen, setIsModalOpen] = useState(false);
const [commentContent, setCommentContent] = useState<string>(
Expand All @@ -28,11 +29,11 @@ export default function CommentEditModal({ comment }: { comment: Comment }) {
const closeModal = () => {
setIsModalOpen(false);
};
const {
postComments,
} = useController({ slug: comment.postSlug })

useEffect(() => {
// if (!commentContent) {
// setCommentContent(comment?.content);
// }
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
closeModal();
Expand Down Expand Up @@ -62,16 +63,16 @@ export default function CommentEditModal({ comment }: { comment: Comment }) {
// 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));
}
router.refresh();
await close();
const { comment } = res;
setCommentContent(comment.content);
await utils.comments.invalidate();
closeModal();
},
onError(error) {
Expand All @@ -82,13 +83,23 @@ export default function CommentEditModal({ comment }: { comment: Comment }) {
setIsTranslating(false);
},
});
const commentToUpdate = postComments?.find(c => c.id === commentId);

const updateMutation = api.comments.updateComment.useMutation({
async onSuccess() {
await utils.comments.invalidate();
onMutate() {
if (commentToUpdate) {
commentToUpdate.content = commentContent;
}

},
onSuccess() {
router.refresh();
closeModal();
},
onError(error) {
if (commentToUpdate) {
commentToUpdate.content = initialContent;
}
console.log('error updating comment', error);
},
onSettled() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
'use client';
import { signIn } from 'next-auth/react';
import ReCAPTCHA from 'react-google-recaptcha';

import { typedBoolean } from '~/utils/miscUtils';
import ReCAPTCHA from 'react-google-recaptcha';
import { type Comment } from '~/interfaces/comments';
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 }) {

export default function CommentForm({
slug,
allComments,
}: {
slug: string;
allComments: Comment[];
}) {
const {
submitting,
setSubmitting,
setToken,
comment,
setComment,
allComments,
errors,
setGotime,
commentContainerRef,
userIsLoggedIn,
} = useController({ slug })
} = useController({
slug,
});

return (
<div>
<>
<section aria-labelledby="comments-heading" className="pt-16">
<div className="w-full">
<form
Expand Down Expand Up @@ -99,7 +104,7 @@ export function CommentLayout({ slug }: { slug: string }) {
{errors.length
? errors.map((error, i) => (
<p key={i} className="text-red-500">
{errors}
{error}
</p>
))
: null}
Expand Down Expand Up @@ -138,31 +143,21 @@ export function CommentLayout({ slug }: { slug: string }) {
</div>
</form>
</div>
<div className="mt-16 " ref={commentContainerRef}>
<div className="mt-16">
<h2 id="comments-heading" className="sr-only">
Comments
</h2>
{allComments?.length ? (
allComments
.filter(comment => typedBoolean(comment))
.map(comment => (
<div
className="relative flex flex-row items-center"
key={comment.id}
>
<CommentCard
key={comment.id}
comment={comment}
/>
</div>
))
{allComments ? (
allComments.map(comment => (
<CommentCard key={comment?.id} comment={comment} />
))
) : (
<p className="text-center text-xl text-gray-500">
Be the first to leave your thoughts!
</p>
)}
</div>
</section>
</div>
</>
);
}
28 changes: 28 additions & 0 deletions src/app/blog/[slug]/commentList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type CommentSelect } from '~/interfaces/comments';
import CommentCard from './commentCard';

export default function CommentList({
allComments,
}: {
allComments: CommentSelect[] | undefined;
}) {

return (
<div className="mt-16">
<h2 id="comments-heading" className="sr-only">
Comments
</h2>
{allComments ? (
allComments.map(comment => (
comment ? (
<CommentCard key={comment?.id} comment={comment} />
) : null
)
)) : (
<p className="text-center text-xl text-gray-500">
Be the first to leave your thoughts!
</p>
)}
</div>
);
}
Loading

0 comments on commit de2a22e

Please sign in to comment.