CoolFace
Apppublic

kunjasd/anycoder-36bad3f9

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
PostCard.jsx182 linesDownload Raw Back to components
1import { useState } from 'react';2import { useSession } from 'next-auth/react';3import { FaHeart, FaRegHeart, FaComment, FaTrash } from 'react-icons/fa';4import useSWR, { mutate } from 'swr';5import Link from 'next/link';6 7const fetcher = (url) => fetch(url).then((res) => res.json());8 9export default function PostCard({ post, onDelete }) {10  const { data: session } = useSession();11  const [commentContent, setCommentContent] = useState('');12  const [showComments, setShowComments] = useState(false);13 14  const { data: likes } = useSWR(15    post ? `/api/posts/${post.id}/likes` : null,16    fetcher17  );18 19  const { data: comments } = useSWR(20    showComments && post ? `/api/posts/${post.id}/comments` : null,21    fetcher22  );23 24  const isLiked = likes?.some((like) => like.userId === session?.user.id);25 26  const handleLike = async () => {27    if (!session) return;28 29    try {30      await fetch(`/api/posts/${post.id}/like`, {31        method: isLiked ? 'DELETE' : 'POST',32      });33      mutate(`/api/posts/${post.id}/likes`);34    } catch (error) {35      console.error('Error liking post:', error);36    }37  };38 39  const handleComment = async (e) => {40    e.preventDefault();41    if (!commentContent.trim() || !session) return;42 43    try {44      await fetch(`/api/posts/${post.id}/comments`, {45        method: 'POST',46        headers: {47          'Content-Type': 'application/json',48        },49        body: JSON.stringify({ content: commentContent }),50      });51      setCommentContent('');52      mutate(`/api/posts/${post.id}/comments`);53    } catch (error) {54      console.error('Error adding comment:', error);55    }56  };57 58  const handleDelete = async () => {59    if (window.confirm('Are you sure you want to delete this post?')) {60      try {61        await fetch(`/api/posts/${post.id}`, {62          method: 'DELETE',63        });64        onDelete(post.id);65      } catch (error) {66        console.error('Error deleting post:', error);67      }68    }69  };70 71  return (72    <div className="bg-white rounded-lg shadow-md p-4 mb-4">73      <div className="flex justify-between items-start mb-2">74        <div className="flex items-center space-x-2">75          <Link href={`/profile/${post.authorId}`}>76            <img77              src={post.author.image || '/default-avatar.png'}78              alt={post.author.name}79              className="w-10 h-10 rounded-full"80            />81          </Link>82          <div>83            <Link href={`/profile/${post.authorId}`}>84              <h3 className="font-semibold text-primary hover:underline">85                {post.author.name}86              </h3>87            </Link>88            <p className="text-sm text-gray-500">89              {new Date(post.createdAt).toLocaleString()}90            </p>91          </div>92        </div>93 94        {session?.user.id === post.authorId && (95          <button96            onClick={handleDelete}97            className="text-red-500 hover:text-red-700"98          >99            <FaTrash />100          </button>101        )}102      </div>103 104      <p className="mb-4">{post.content}</p>105 106      {post.image && (107        <img108          src={post.image}109          alt="Post content"110          className="w-full rounded-md mb-4"111        />112      )}113 114      <div className="flex items-center space-x-4 text-sm text-gray-500">115        <button116          onClick={handleLike}117          className="flex items-center space-x-1 hover:text-red-500"118          disabled={!session}119        >120          {isLiked ? <FaHeart className="text-red-500" /> : <FaRegHeart />}121          <span>{likes?.length || 0}</span>122        </button>123 124        <button125          onClick={() => setShowComments(!showComments)}126          className="flex items-center space-x-1 hover:text-primary"127        >128          <FaComment />129          <span>{comments?.length || 0}</span>130        </button>131      </div>132 133      {showComments && (134        <div className="mt-4">135          {session && (136            <form onSubmit={handleComment} className="mb-4">137              <input138                type="text"139                value={commentContent}140                onChange={(e) => setCommentContent(e.target.value)}141                placeholder="Add a comment..."142                className="w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-primary"143                required144              />145              <button146                type="submit"147                className="mt-2 bg-primary text-white px-4 py-2 rounded-md hover:bg-secondary transition-colors"148              >149                Comment150              </button>151            </form>152          )}153 154          <div className="space-y-3">155            {comments?.map((comment) => (156              <div key={comment.id} className="flex space-x-2">157                <Link href={`/profile/${comment.authorId}`}>158                  <img159                    src={comment.author.image || '/default-avatar.png'}160                    alt={comment.author.name}161                    className="w-8 h-8 rounded-full"162                  />163                </Link>164                <div className="flex-1">165                  <Link href={`/profile/${comment.authorId}`}>166                    <h4 className="font-semibold text-primary hover:underline">167                      {comment.author.name}168                    </h4>169                  </Link>170                  <p className="text-sm">{comment.content}</p>171                  <p className="text-xs text-gray-500">172                    {new Date(comment.createdAt).toLocaleString()}173                  </p>174                </div>175              </div>176            ))}177          </div>178        </div>179      )}180    </div>181  );182}