Files
nextjs-boilerplate/app/[locale]/admin/users/page.tsx
T

105 lines
4.8 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.
import Link from 'next/link'
import { supabaseAdmin, listAuthUsers } from '@/lib/supabaseAdmin'
interface ProfileRow {
id: string
full_name: string | null
bar_association_no: string | null
bar_name: string | null
license_status: string | null
license_expires_at: string | null
trial_end_date: string | null
org_id: string | null
created_at: string
}
function statusBadge(status: string | null) {
const map: Record<string, string> = {
active: 'bg-green-50 text-green-700 border-green-200 dark:bg-green-950/40 dark:text-green-400 dark:border-green-900',
trial: 'bg-amber-50 text-amber-700 border-amber-200 dark:bg-amber-950/40 dark:text-amber-400 dark:border-amber-900',
expired: 'bg-red-50 text-red-700 border-red-200 dark:bg-red-950/40 dark:text-red-400 dark:border-red-900',
}
const cls = map[status || ''] || 'bg-gray-50 text-gray-600 border-gray-200 dark:bg-gray-900 dark:text-gray-400 dark:border-gray-800'
return (
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium border ${cls}`}>
{status || 'bilinmiyor'}
</span>
)
}
function formatDate(iso: string | null) {
if (!iso) return '—'
return new Date(iso).toLocaleDateString('tr-TR', { day: 'numeric', month: 'short', year: 'numeric' })
}
export default async function UsersPage({ searchParams }: { searchParams: Promise<{ deleted?: string }> }) {
const { deleted } = await searchParams
const [{ data: profiles }, authUsers] = await Promise.all([
supabaseAdmin
.from('profiles')
.select('id, full_name, bar_association_no, bar_name, license_status, license_expires_at, trial_end_date, org_id, created_at')
.order('created_at', { ascending: false }),
listAuthUsers(),
])
const rows = (profiles as ProfileRow[] | null) || []
return (
<div className="space-y-6">
{deleted && (
<div className="rounded-md bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-900 px-4 py-3 text-sm text-green-700 dark:text-green-400">
Kullanıcı silindi.
</div>
)}
<div>
<h2 className="text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Kullanıcılar</h2>
<p className="text-gray-500 dark:text-gray-400 mt-2">Toplam {rows.length} kullanıcı.</p>
</div>
<div className="rounded-lg bg-white dark:bg-gray-950 border border-gray-200 dark:border-gray-800 shadow-sm overflow-hidden">
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-800">
<thead className="bg-gray-50 dark:bg-gray-900">
<tr>
{['Kullanıcı', 'Baro', 'Durum', 'Bitiş Tarihi', 'Kayıt', ''].map((h) => (
<th key={h} className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">{h}</th>
))}
</tr>
</thead>
<tbody className="divide-y divide-gray-100 dark:divide-gray-800">
{rows.map((p) => {
const authUser = authUsers.get(p.id)
const expiryDate = p.license_status === 'trial' ? p.trial_end_date : p.license_expires_at
return (
<tr key={p.id} className="hover:bg-gray-50 dark:hover:bg-gray-900/50">
<td className="px-4 py-3 whitespace-nowrap">
<div className="text-sm font-medium text-gray-900 dark:text-white">{p.full_name || '(isimsiz)'}</div>
<div className="text-xs text-gray-500">{authUser?.email || p.id}</div>
</td>
<td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600 dark:text-gray-400">
{p.bar_name || '—'}{p.bar_association_no ? ` · ${p.bar_association_no}` : ''}
</td>
<td className="px-4 py-3 whitespace-nowrap">{statusBadge(p.license_status)}</td>
<td className="px-4 py-3 whitespace-nowrap text-sm text-gray-600 dark:text-gray-400">{formatDate(expiryDate)}</td>
<td className="px-4 py-3 whitespace-nowrap text-sm text-gray-500">{formatDate(p.created_at)}</td>
<td className="px-4 py-3 whitespace-nowrap text-right text-sm">
<Link href={`/admin/users/${p.id}`} className="text-indigo-600 dark:text-indigo-400 hover:underline">
Düzenle
</Link>
</td>
</tr>
)
})}
{rows.length === 0 && (
<tr>
<td colSpan={6} className="px-4 py-8 text-center text-sm text-gray-500">Henüz kullanıcı yok.</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</div>
)
}