first commit
This commit is contained in:
132
frontend/app/admin/posts/_components/columns.tsx
Normal file
132
frontend/app/admin/posts/_components/columns.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
"use client"
|
||||
|
||||
import { ColumnDef } from "@tanstack/react-table"
|
||||
import { Post } from "@/types/post"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Edit, Trash, RotateCcw } from "lucide-react"
|
||||
|
||||
interface PostColumnsProps {
|
||||
onEdit: (post: Post) => void
|
||||
onDelete: (id: number) => void
|
||||
onRestore: (id: number) => void
|
||||
statusFilter: string
|
||||
deletedIds: number[]
|
||||
}
|
||||
|
||||
export const getPostColumns = ({ onEdit, onDelete, onRestore, statusFilter, deletedIds }: PostColumnsProps): ColumnDef<Post>[] => [
|
||||
{
|
||||
accessorKey: "images",
|
||||
header: "Görsel",
|
||||
cell: ({ row }) => {
|
||||
const rawImages = row.original.images
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8080"
|
||||
|
||||
// Backend tarafında "images" alanı virgülle ayrılmış birden fazla path içerebilir.
|
||||
// Liste görünümünde ilk path'i küçük görsel için kullanalım.
|
||||
const firstImage = rawImages
|
||||
? rawImages
|
||||
.split(",")
|
||||
.map(p => p.trim())
|
||||
.filter(Boolean)[0]
|
||||
: null
|
||||
|
||||
const fullUrl = firstImage
|
||||
? (firstImage.startsWith("http") ? firstImage : `${apiUrl}${firstImage}`)
|
||||
: null
|
||||
|
||||
return (
|
||||
<div className="w-16 h-10 bg-gray-100 rounded overflow-hidden flex items-center justify-center">
|
||||
{fullUrl ? (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img src={fullUrl} alt={row.original.title} className="w-full h-full object-cover" />
|
||||
) : (
|
||||
<span className="text-xs text-gray-400">Yok</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Başlık",
|
||||
},
|
||||
{
|
||||
accessorKey: "categories",
|
||||
header: "Kategoriler",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{row.original.categories?.map((cat, index) => (
|
||||
<span key={cat.id || cat.title || index} className="px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full">
|
||||
{cat.title}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Etiketler",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{row.original.tags?.map((tag, index) => (
|
||||
<span key={tag.id || tag.name || index} className="px-2 py-1 bg-gray-100 text-gray-800 text-xs rounded-full">
|
||||
{tag.name}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "updated_at",
|
||||
header: "Son Güncelleme",
|
||||
cell: ({ row }) => {
|
||||
const updatedAt = row.original.updated_at || row.original.UpdatedAt
|
||||
return updatedAt ? new Date(updatedAt).toLocaleDateString("tr-TR") : "-"
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
cell: ({ row }) => {
|
||||
const id = row.original.id || row.original.ID
|
||||
const inDeletedList = typeof id === "number" && deletedIds.includes(id)
|
||||
|
||||
// "Sadece Silinenler" filtresinde hepsi silinmiş kabul edilir.
|
||||
// "Tümü (Dahil)" filtresinde ise deletedIds listesine bakılır.
|
||||
const isDeleted = statusFilter === "only" || inDeletedList
|
||||
return (
|
||||
<div className="flex gap-2 justify-end">
|
||||
{isDeleted ? (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onRestore(row.original.id || row.original.ID!)}
|
||||
className="h-8 w-8 p-0 text-green-600 hover:text-green-700 hover:bg-green-50"
|
||||
title="Geri Yükle"
|
||||
>
|
||||
<RotateCcw className="h-4 w-4" />
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onEdit(row.original)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
onClick={() => onDelete(row.original.id || row.original.ID!)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<Trash className="h-4 w-4" />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
Reference in New Issue
Block a user