118 lines
5.3 KiB
TypeScript
118 lines
5.3 KiB
TypeScript
import { PlusIcon } from '@heroicons/react/24/outline'
|
|
import type { PoolUser } from '../hooks/usePoolManageState'
|
|
|
|
type Translator = (key: string, params?: Record<string, string | number>) => string
|
|
|
|
type Props = {
|
|
t: Translator
|
|
users: PoolUser[]
|
|
membersLoading: boolean
|
|
membersError: string
|
|
removeError: string
|
|
removingMemberId: string | null
|
|
isCore: boolean
|
|
onOpenSearch: () => void
|
|
onRemove: (userId: string) => void
|
|
}
|
|
|
|
export default function PoolMembersSection({
|
|
t,
|
|
users,
|
|
membersLoading,
|
|
membersError,
|
|
removeError,
|
|
removingMemberId,
|
|
isCore,
|
|
onOpenSearch,
|
|
onRemove,
|
|
}: Props) {
|
|
return (
|
|
<section className="rounded-[28px] border border-white/80 bg-white/85 shadow-[0_24px_70px_-40px_rgba(15,23,42,0.32)] p-6 sm:p-7 backdrop-blur-md">
|
|
<div className="flex flex-wrap items-center justify-between gap-3 mb-4">
|
|
<div className="flex items-center gap-3 min-w-0">
|
|
<h2 className="text-lg font-semibold text-slate-900 break-words">{t('autofix.kfd227aa9')}</h2>
|
|
<span className="inline-flex items-center rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-medium text-slate-700">
|
|
{users.length}
|
|
</span>
|
|
</div>
|
|
|
|
<button
|
|
onClick={onOpenSearch}
|
|
className="inline-flex items-center gap-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-50 px-5 py-3 text-sm font-semibold shadow transition"
|
|
>
|
|
<PlusIcon className="h-5 w-5" />
|
|
{t('autofix.k750c1eb5')}
|
|
</button>
|
|
</div>
|
|
|
|
{removeError && (
|
|
<div className="mb-4 rounded-xl border border-red-200 bg-red-50/90 px-4 py-3 text-sm text-red-700">
|
|
{removeError}
|
|
</div>
|
|
)}
|
|
|
|
{membersLoading && <div className="text-center text-slate-500 italic py-8">{t('autofix.k5d4d494e')}</div>}
|
|
|
|
{membersError && !membersLoading && <div className="text-center text-red-600 py-8 break-words">{membersError}</div>}
|
|
|
|
{users.length === 0 && !membersLoading && !membersError && (
|
|
<div className="text-center text-slate-500 italic py-8">{t('autofix.kcbc17bbd')}</div>
|
|
)}
|
|
|
|
{users.length > 0 && !membersLoading && (
|
|
<div className="overflow-x-auto rounded-xl border border-slate-200">
|
|
<table className="min-w-[760px] w-full divide-y divide-slate-200 text-sm">
|
|
<thead className="bg-slate-50">
|
|
<tr>
|
|
<th className="px-4 py-3 text-left font-semibold text-slate-700">{t('autofix.k5b2c4431')}</th>
|
|
<th className="px-4 py-3 text-left font-semibold text-slate-700">{t('autofix.kb1438ed0')}</th>
|
|
<th className="px-4 py-3 text-left font-semibold text-slate-700">{t('autofix.k7bed84a7')}</th>
|
|
<th className="px-4 py-3 text-right font-semibold text-slate-700">{isCore ? t('autofix.k22a3f7c1') : t('autofix.k69adf332')}</th>
|
|
<th className="px-4 py-3 text-right font-semibold text-slate-700" />
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-slate-100 bg-white">
|
|
{users.map((poolUser) => (
|
|
<tr key={poolUser.id} className="hover:bg-slate-50 transition">
|
|
<td className="px-4 py-3">
|
|
<div className="flex items-center gap-2 min-w-0">
|
|
<div className="h-7 w-7 rounded-full bg-slate-100 border border-slate-200 flex items-center justify-center text-xs font-bold text-slate-800 shrink-0">
|
|
{(poolUser.name?.[0] || '?').toUpperCase()}
|
|
</div>
|
|
<span className="font-medium text-slate-900 break-words">{poolUser.name}</span>
|
|
</div>
|
|
</td>
|
|
<td className="px-4 py-3 text-slate-600 break-all">{poolUser.email}</td>
|
|
<td className="px-4 py-3 text-slate-600 whitespace-nowrap">
|
|
{new Date(poolUser.joinedAt).toLocaleDateString('de-DE', { year: 'numeric', month: 'short', day: '2-digit' })}
|
|
</td>
|
|
<td className="px-4 py-3 text-right whitespace-nowrap">
|
|
<span
|
|
className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold ${
|
|
poolUser.share > 0
|
|
? 'bg-green-50 text-green-700 border border-green-200'
|
|
: 'bg-slate-50 text-slate-500 border border-slate-200'
|
|
}`}
|
|
>
|
|
EUR {poolUser.share.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
|
|
</span>
|
|
</td>
|
|
<td className="px-4 py-3 text-right whitespace-nowrap">
|
|
<button
|
|
onClick={() => onRemove(poolUser.id)}
|
|
disabled={removingMemberId === poolUser.id}
|
|
className="px-3 py-1.5 text-xs font-medium rounded-md border border-red-200 bg-red-50 text-red-700 hover:bg-red-100 transition disabled:opacity-60 disabled:cursor-not-allowed"
|
|
>
|
|
{removingMemberId === poolUser.id ? t('autofix.k18fd92a1') : t('autofix.k2ee90f41')}
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
)}
|
|
</section>
|
|
)
|
|
}
|