generated from warmachine028/github-super-starter-kit
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4dcbec0
commit d463f5b
Showing
3 changed files
with
267 additions
and
281 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { useState } from 'react' | ||
import { Button, Input, Textarea, Badge } from '@/components/ui' | ||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' | ||
import { Trash2, Edit2, Save, ThumbsUp, ThumbsDown, Eye } from 'lucide-react' | ||
import { motion } from 'framer-motion' | ||
import { | ||
Dialog, | ||
DialogClose, | ||
DialogContent, | ||
DialogDescription, | ||
DialogFooter, | ||
DialogHeader, | ||
DialogTitle, | ||
DialogTrigger | ||
} from '@/components/ui/dialog' | ||
import { useDeletePost, useUpdatePost } from '@/hooks' | ||
import { type Post as PostType } from '@/types' | ||
|
||
const tagColors = [ | ||
'bg-red-100 text-red-800', | ||
'bg-blue-100 text-blue-800', | ||
'bg-green-100 text-green-800', | ||
'bg-yellow-100 text-yellow-800', | ||
'bg-purple-100 text-purple-800', | ||
'bg-pink-100 text-pink-800', | ||
'bg-indigo-100 text-indigo-800' | ||
] | ||
|
||
const Post = ({ post }: { post: PostType }) => { | ||
const [isEditing, setIsEditing] = useState(false) | ||
const [editedPost, setEditedPost] = useState(post) | ||
|
||
const updateMutation = useUpdatePost() | ||
const deleteMutation = useDeletePost() | ||
const handleUpdatePost = (post: PostType) => updateMutation.mutate({ ...post, tags: post.tags }) | ||
|
||
const handleDeletePost = (id: number) => deleteMutation.mutate(id) | ||
|
||
const handleSave = () => { | ||
handleUpdatePost(editedPost) | ||
setIsEditing(false) | ||
} | ||
|
||
return ( | ||
<motion.div | ||
layout | ||
initial={{ opacity: 0, y: 50 }} | ||
animate={{ opacity: 1, y: 0 }} | ||
exit={{ opacity: 0, y: -50 }} | ||
transition={{ duration: 0.3 }} | ||
> | ||
<Card className="h-full flex flex-col overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300"> | ||
<CardHeader className="bg-secondary flex-shrink-0"> | ||
<div className="relative h-48 w-full mb-4"> | ||
<img | ||
src={post.imageUrl} | ||
alt={post.title} | ||
className="absolute w-full h-full object-cover rounded-lg" | ||
/> | ||
</div> | ||
<CardTitle className="text-lg font-semibold"> | ||
{isEditing ? ( | ||
<Input | ||
value={editedPost.title} | ||
onChange={(e) => setEditedPost({ ...editedPost, title: e.target.value })} | ||
className="font-semibold" | ||
/> | ||
) : ( | ||
post.title | ||
)} | ||
</CardTitle> | ||
<div className="flex flex-wrap gap-2 mt-2"> | ||
{post.tags.map((tag, index) => ( | ||
<Badge key={index} className={`text-xs ${tagColors[index % tagColors.length]}`}> | ||
{tag} | ||
</Badge> | ||
))} | ||
</div> | ||
</CardHeader> | ||
<CardContent className="p-4 flex-grow"> | ||
{isEditing ? ( | ||
<> | ||
<Textarea | ||
value={editedPost.body} | ||
onChange={(e) => setEditedPost({ ...editedPost, body: e.target.value })} | ||
className="min-h-[100px] mb-2" | ||
/> | ||
<Input | ||
value={editedPost.tags.join(', ')} | ||
onChange={(e) => | ||
setEditedPost({ | ||
...editedPost, | ||
tags: e.target.value.split(',').map((tag) => tag.trim()) | ||
}) | ||
} | ||
placeholder="Tags (comma-separated)" | ||
className="mt-2" | ||
/> | ||
</> | ||
) : ( | ||
<p className="line-clamp-3">{post.body}</p> | ||
)} | ||
</CardContent> | ||
<CardFooter className="bg-muted flex justify-between items-center p-2 flex-shrink-0"> | ||
<div className="flex items-center space-x-1"> | ||
<Badge variant="secondary" className="flex items-center gap-1"> | ||
<ThumbsUp className="h-4 w-4" /> | ||
<span className="hidden xl:block">{post.reactions.likes}</span> | ||
</Badge> | ||
<Badge variant="secondary" className="flex items-center gap-1"> | ||
<ThumbsDown className="h-4 w-4" /> | ||
<span className="hidden xl:block">{post.reactions.dislikes}</span> | ||
</Badge> | ||
<Badge variant="secondary" className="flex items-center gap-1"> | ||
<Eye className="h-4 w-4" /> | ||
<span className="hidden xl:block">{post.views}</span> | ||
</Badge> | ||
</div> | ||
<div className="flex gap-2"> | ||
{isEditing ? ( | ||
<Button onClick={handleSave} className="bg-primary text-primary-foreground"> | ||
<Save className="h-4 w-4 sm:mr-2" /> | ||
<span className="hidden sm:block">Save</span> | ||
</Button> | ||
) : ( | ||
<Button | ||
variant="ghost" | ||
onClick={() => setIsEditing(true)} | ||
className="text-primary hover:text-primary hover:bg-primary/10" | ||
> | ||
<Edit2 className="h-4 w-4 sm:mr-2" /> | ||
<span className="hidden sm:block">Edit</span> | ||
</Button> | ||
)} | ||
|
||
<Dialog> | ||
<DialogTrigger asChild> | ||
<Button | ||
variant="ghost" | ||
className="text-destructive hover:text-destructive hover:bg-destructive/10" | ||
> | ||
<Trash2 className="h-4 w-4" /> | ||
</Button> | ||
</DialogTrigger> | ||
<DialogContent> | ||
<DialogHeader> | ||
<DialogTitle>Are you sure you want to delete this post?</DialogTitle> | ||
<DialogDescription> | ||
This action cannot be undone. This will permanently delete the post. | ||
</DialogDescription> | ||
</DialogHeader> | ||
<DialogFooter> | ||
<DialogClose asChild> | ||
<Button variant="outline">Cancel</Button> | ||
</DialogClose> | ||
<Button variant="destructive" onClick={() => handleDeletePost(post.id)}> | ||
Delete | ||
</Button> | ||
</DialogFooter> | ||
</DialogContent> | ||
</Dialog> | ||
</div> | ||
</CardFooter> | ||
</Card> | ||
</motion.div> | ||
) | ||
} | ||
|
||
export default Post |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { default as AppRouter } from './AppRouter' | ||
export { default as Post } from './Post' |
Oops, something went wrong.