first commit

This commit is contained in:
Dhananjaya99
2026-09-28 11:48:14 +05:30
commit a1b870fa8a
242 changed files with 39483 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
import { EyeIcon, HeartIcon, PencilIcon, Trash2Icon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { StatusBadge } from "@/components/hexa/status-badge"
interface PostCardAuthor {
name: string
role?: string
avatarUrl?: string
}
interface PostCardProps {
imageUrl?: string
title: string
description: string
tag?: string
author: PostCardAuthor
published: boolean
likes: number
createdAt: string
liked?: boolean
onToggleLike?: () => void
onView?: () => void
onEdit?: () => void
onDelete?: () => void
className?: string
}
function PostCard({
imageUrl,
title,
description,
tag,
author,
published,
likes,
createdAt,
liked,
onToggleLike,
onView,
onEdit,
onDelete,
className,
}: PostCardProps) {
return (
<Card className={cn("gap-0 overflow-hidden p-0", className)}>
{imageUrl && (
<div className="aspect-video w-full overflow-hidden bg-muted">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={imageUrl} alt="" className="size-full object-cover" />
</div>
)}
<div className="flex flex-col gap-3 p-4">
<div className="flex items-start justify-between gap-2">
<h3 className="font-semibold">{title}</h3>
<StatusBadge status={published ? "success" : "neutral"}>
{published ? "Published" : "Draft"}
</StatusBadge>
</div>
<p className="line-clamp-2 text-sm text-muted-foreground">{description}</p>
{tag && (
<Badge variant="secondary" className="w-fit">
{tag}
</Badge>
)}
<div className="flex items-center justify-between gap-2 border-t pt-3">
<div className="flex min-w-0 items-center gap-2">
<Avatar size="sm">
<AvatarImage src={author.avatarUrl} alt={author.name} />
<AvatarFallback>{author.name.slice(0, 1)}</AvatarFallback>
</Avatar>
<div className="min-w-0 leading-tight">
<p className="truncate text-sm font-medium">{author.name}</p>
{author.role && (
<p className="truncate text-xs text-muted-foreground">{author.role}</p>
)}
</div>
</div>
<div className="flex shrink-0 items-center gap-3 text-xs text-muted-foreground">
{onToggleLike ? (
<button
type="button"
aria-label={liked ? "Unlike post" : "Like post"}
className="flex items-center gap-1"
onClick={onToggleLike}
>
<HeartIcon
className={cn(
"size-3.5",
liked ? "fill-rose-500 text-rose-500" : "text-muted-foreground"
)}
/>
{likes}
</button>
) : (
<span className="flex items-center gap-1">
<HeartIcon className="size-3.5 fill-rose-500 text-rose-500" />
{likes}
</span>
)}
<span>{createdAt}</span>
</div>
</div>
{(onView || onEdit || onDelete) && (
<div className="flex items-center justify-end gap-1.5">
{onView && (
<Button variant="outline" size="icon-sm" aria-label="View" onClick={onView}>
<EyeIcon />
</Button>
)}
{onEdit && (
<Button variant="outline" size="icon-sm" aria-label="Edit" onClick={onEdit}>
<PencilIcon />
</Button>
)}
{onDelete && (
<Button variant="destructive" size="icon-sm" aria-label="Delete" onClick={onDelete}>
<Trash2Icon />
</Button>
)}
</div>
)}
</div>
</Card>
)
}
export { PostCard }
export type { PostCardAuthor }