Files
goGin/frontend/app/admin/heroes/page.tsx
Beyhan Oğur 2a5b661443 first commit
2026-04-26 21:46:42 +03:00

123 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client"
import { useEffect, useState, useCallback } from "react"
import { DataTable } from "./_components/data-table"
import { getColumns } from "./_components/columns"
import { Hero } from "@/types/hero"
import { heroService } from "@/services/heroService"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Plus } from "lucide-react"
import { HeroDialog } from "./_components/hero-dialog"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
export default function HeroesPage() {
const [data, setData] = useState<Hero[]>([])
const [loading, setLoading] = useState(true)
const [page, setPage] = useState(1)
const [total, setTotal] = useState(0)
const [perPage] = useState(20)
const [search, setSearch] = useState("")
const [statusFilter, setStatusFilter] = useState("with") // "with" shows active + deleted
const [showCreateDialog, setShowCreateDialog] = useState(false)
const fetchData = useCallback(async () => {
setLoading(true)
try {
// API expects "active" logic differently perhaps?
// checking task.md/heroService docs:
// heroService.getHeroes(page, perPage, search, soft)
// soft: 'only' | 'with' | empty (defaults to active in some apis, but checking service impl)
// From service: soft param defaults to "with".
const apiSoftFilter = statusFilter === "active" ? "" : statusFilter
const res = await heroService.getHeroes(page, perPage, search, apiSoftFilter)
setData(res.items || [])
setTotal(res.total || 0)
} catch (error) {
console.error("Heroes fetch error:", error)
setData([])
} finally {
setLoading(false)
}
}, [page, perPage, search, statusFilter])
useEffect(() => {
fetchData()
}, [fetchData])
const totalPages = Math.ceil(total / perPage)
return (
<div className="p-8">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-3xl font-bold tracking-tight">Hero Banner Yönetimi</h1>
<p className="text-muted-foreground">
Ana sayfa banner alanlarını yönetin.
</p>
</div>
<Button onClick={() => setShowCreateDialog(true)}>
<Plus className="mr-2 h-4 w-4" /> Yeni Hero
</Button>
</div>
<div className="flex items-center py-4 gap-4">
<Input
placeholder="Başlık ara..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="max-w-sm"
/>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Durum" />
</SelectTrigger>
<SelectContent>
<SelectItem value="with">Tümü (Dahil)</SelectItem>
<SelectItem value="active">Sadece Aktif</SelectItem>
<SelectItem value="only">Sadece Silinenler</SelectItem>
</SelectContent>
</Select>
</div>
<DataTable columns={getColumns(fetchData)} data={data} />
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => setPage((old) => Math.max(old - 1, 1))}
disabled={page === 1 || loading}
>
Önceki
</Button>
<div className="text-sm text-muted-foreground">
Sayfa {page} / {totalPages || 1}
</div>
<Button
variant="outline"
size="sm"
onClick={() => setPage((old) => (data.length === perPage || page < totalPages ? old + 1 : old))}
disabled={page >= totalPages || loading}
>
Sonraki
</Button>
</div>
<HeroDialog
open={showCreateDialog}
onOpenChange={setShowCreateDialog}
onSuccess={fetchData}
/>
</div>
)
}