mobile responsive owners box
This commit is contained in:
@@ -390,7 +390,9 @@ const CommissionDistributionPanel = ({
|
||||
<p className="text-xs text-zinc-400 mt-1">Add team members with commission rules to see the distribution.</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="overflow-x-auto rounded-xl border border-zinc-200 dark:border-white/5">
|
||||
<>
|
||||
{/* ── Desktop table (sm+) ── */}
|
||||
<div className="hidden sm:block overflow-x-auto rounded-xl border border-zinc-200 dark:border-white/5">
|
||||
<table className="w-full text-left min-w-[600px]">
|
||||
<thead>
|
||||
<tr className="border-b border-zinc-200 dark:border-white/5 bg-zinc-50 dark:bg-white/[0.02]">
|
||||
@@ -465,6 +467,65 @@ const CommissionDistributionPanel = ({
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* ── Mobile cards (< sm) ── */}
|
||||
<div className="sm:hidden space-y-2.5">
|
||||
{filteredRows.length === 0 ? (
|
||||
<div className="rounded-xl border border-zinc-200 dark:border-white/5 py-10 text-center">
|
||||
<Users size={22} className="mx-auto mb-2 text-zinc-400" />
|
||||
<p className="text-sm text-zinc-500">No commission entries match the current filters.</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={clearFilters}
|
||||
className="mt-3 inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-[11px] font-bold uppercase tracking-wider text-emerald-600 dark:text-emerald-400 hover:bg-emerald-50 dark:hover:bg-emerald-500/10 border border-emerald-200 dark:border-emerald-500/20 transition-colors"
|
||||
>
|
||||
<FilterX size={12} /> Clear Filters
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{filteredRows.map((row) => (
|
||||
<div key={row.key} className="rounded-xl border border-zinc-200 dark:border-white/5 bg-white dark:bg-white/[0.02] p-3.5">
|
||||
{/* Name + Amount */}
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-2.5 min-w-0">
|
||||
<div className="w-7 h-7 rounded-full bg-emerald-500/15 flex items-center justify-center text-[10px] font-black text-emerald-600 dark:text-emerald-400 flex-shrink-0">
|
||||
{row.name?.[0] || '?'}
|
||||
</div>
|
||||
<span className="text-sm font-semibold text-zinc-900 dark:text-white truncate">{row.name}</span>
|
||||
</div>
|
||||
<span className="font-mono text-sm font-bold text-green-600 dark:text-[#39ff14] shrink-0">{fmt(row.amount)}</span>
|
||||
</div>
|
||||
{/* Role */}
|
||||
<div className="mt-2.5">
|
||||
<span className={`text-[11px] font-bold rounded-md px-1.5 py-0.5 border ${ROLE_COLORS[row.role] || 'text-zinc-400 bg-zinc-500/10 border-zinc-500/20'}`}>
|
||||
{row.role}
|
||||
</span>
|
||||
</div>
|
||||
{/* Project / Type */}
|
||||
<div className="grid grid-cols-2 gap-2 mt-3 pt-3 border-t border-zinc-100 dark:border-white/5">
|
||||
<div className="flex flex-col gap-0.5 min-w-0">
|
||||
<span className="text-[9px] font-mono font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest">Project ID</span>
|
||||
<span className="text-[11px] font-mono text-zinc-500 dark:text-zinc-400 truncate">{row.projectId}</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5 min-w-0">
|
||||
<span className="text-[9px] font-mono font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest">Commission Type</span>
|
||||
<span className="text-[11px] text-zinc-600 dark:text-zinc-400 truncate">{row.commissionType}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{/* Total */}
|
||||
<div className="rounded-xl border border-zinc-300 dark:border-white/10 bg-zinc-50 dark:bg-white/[0.03] px-3.5 py-3 flex items-center justify-between">
|
||||
<span className="text-[10px] font-mono font-bold text-zinc-500 uppercase tracking-widest">
|
||||
{hasActiveFilters ? 'Filtered Total' : 'Total'}
|
||||
</span>
|
||||
<span className="font-mono text-sm font-extrabold text-green-600 dark:text-[#39ff14]">{fmt(total)}</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -393,8 +393,9 @@ const TeamManagementPanel = ({
|
||||
transition={{ duration: 0.25 }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<div className="overflow-x-auto rounded-xl border border-zinc-200 dark:border-white/5">
|
||||
<table className="w-full text-left">
|
||||
{/* ── Desktop table (sm+) ── */}
|
||||
<div className="hidden sm:block overflow-x-auto rounded-xl border border-zinc-200 dark:border-white/5">
|
||||
<table className="w-full text-left min-w-[560px]">
|
||||
<thead>
|
||||
<tr className="border-b border-zinc-200 dark:border-white/5 bg-zinc-50 dark:bg-white/[0.02]">
|
||||
<th className="px-4 py-2.5 text-[10px] font-mono font-bold text-zinc-500 uppercase tracking-widest">Member</th>
|
||||
@@ -419,17 +420,17 @@ const TeamManagementPanel = ({
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className={`text-[11px] font-bold rounded-md px-1.5 py-0.5 border ${ROLE_COLORS[mc.jobRole] || 'text-zinc-400 bg-zinc-500/10 border-zinc-500/20'}`}>
|
||||
<span className={`text-[11px] font-bold rounded-md px-1.5 py-0.5 border whitespace-nowrap ${ROLE_COLORS[mc.jobRole] || 'text-zinc-400 bg-zinc-500/10 border-zinc-500/20'}`}>
|
||||
{mc.jobRole}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3 text-xs text-zinc-600 dark:text-zinc-400">{COMMISSION_TYPES[mc.resolved.type] || mc.resolved.type}</td>
|
||||
<td className="px-4 py-3 text-right font-mono text-xs text-zinc-900 dark:text-white">
|
||||
<td className="px-4 py-3 text-xs text-zinc-600 dark:text-zinc-400 whitespace-nowrap">{COMMISSION_TYPES[mc.resolved.type] || mc.resolved.type}</td>
|
||||
<td className="px-4 py-3 text-right font-mono text-xs text-zinc-900 dark:text-white whitespace-nowrap">
|
||||
{mc.resolved.type === 'flat' || mc.resolved.type === 'custom'
|
||||
? formatCurrency(mc.resolved.rate)
|
||||
: `${mc.resolved.rate}%`}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-right font-mono text-xs font-bold text-green-600 dark:text-[#39ff14]">
|
||||
<td className="px-4 py-3 text-right font-mono text-xs font-bold text-green-600 dark:text-[#39ff14] whitespace-nowrap">
|
||||
{formatCurrency(mc.value)}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-center">
|
||||
@@ -445,7 +446,7 @@ const TeamManagementPanel = ({
|
||||
<tfoot className="border-t-2 border-zinc-300 dark:border-white/10">
|
||||
<tr className="bg-zinc-50 dark:bg-white/[0.03]">
|
||||
<td colSpan={4} className="px-4 py-3 text-[10px] font-mono font-bold text-zinc-500 uppercase tracking-widest">Total Distribution</td>
|
||||
<td className="px-4 py-3 text-right font-mono text-xs font-bold text-green-600 dark:text-[#39ff14]">
|
||||
<td className="px-4 py-3 text-right font-mono text-xs font-bold text-green-600 dark:text-[#39ff14] whitespace-nowrap">
|
||||
{formatCurrency(memberCommissions.filter(m => m.status === 'active').reduce((s, mc) => s + mc.value, 0))}
|
||||
</td>
|
||||
<td />
|
||||
@@ -453,6 +454,62 @@ const TeamManagementPanel = ({
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* ── Mobile cards (< sm) ── */}
|
||||
<div className="sm:hidden space-y-2.5">
|
||||
{memberCommissions.filter(m => m.status === 'active').map((mc) => {
|
||||
const srcCfg = COMMISSION_SOURCE_CFG[mc.resolved.source] || COMMISSION_SOURCE_CFG.org;
|
||||
return (
|
||||
<div key={mc.id} className="rounded-xl border border-zinc-200 dark:border-white/5 bg-white dark:bg-white/[0.02] p-3.5">
|
||||
{/* Member + source */}
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<div className="w-7 h-7 rounded-full bg-violet-500/15 flex items-center justify-center text-[11px] font-black text-violet-400 flex-shrink-0">
|
||||
{mc.name?.[0]}
|
||||
</div>
|
||||
<span className="text-sm font-semibold text-zinc-900 dark:text-white truncate">{mc.name}</span>
|
||||
</div>
|
||||
<span className={`inline-flex items-center gap-1 text-[10px] font-bold rounded-full px-2 py-0.5 border shrink-0 ${srcCfg.bg}`}>
|
||||
<span className={`w-1.5 h-1.5 rounded-full ${srcCfg.dot}`} />
|
||||
<span className={srcCfg.color}>{srcCfg.label}</span>
|
||||
</span>
|
||||
</div>
|
||||
{/* Role */}
|
||||
<div className="mt-2.5">
|
||||
<span className={`text-[11px] font-bold rounded-md px-1.5 py-0.5 border ${ROLE_COLORS[mc.jobRole] || 'text-zinc-400 bg-zinc-500/10 border-zinc-500/20'}`}>
|
||||
{mc.jobRole}
|
||||
</span>
|
||||
</div>
|
||||
{/* Type / Rate / Value */}
|
||||
<div className="grid grid-cols-3 gap-2 mt-3 pt-3 border-t border-zinc-100 dark:border-white/5">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[9px] font-mono font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest">Type</span>
|
||||
<span className="text-[11px] text-zinc-700 dark:text-zinc-300">{COMMISSION_TYPES[mc.resolved.type] || mc.resolved.type}</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[9px] font-mono font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest">Rate</span>
|
||||
<span className="font-mono text-[11px] text-zinc-900 dark:text-white">
|
||||
{mc.resolved.type === 'flat' || mc.resolved.type === 'custom'
|
||||
? formatCurrency(mc.resolved.rate)
|
||||
: `${mc.resolved.rate}%`}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[9px] font-mono font-bold text-zinc-400 dark:text-zinc-500 uppercase tracking-widest">Value</span>
|
||||
<span className="font-mono text-[11px] font-bold text-green-600 dark:text-[#39ff14]">{formatCurrency(mc.value)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{/* Total */}
|
||||
<div className="rounded-xl border border-zinc-300 dark:border-white/10 bg-zinc-50 dark:bg-white/[0.03] px-3.5 py-3 flex items-center justify-between">
|
||||
<span className="text-[10px] font-mono font-bold text-zinc-500 uppercase tracking-widest">Total Distribution</span>
|
||||
<span className="font-mono text-sm font-bold text-green-600 dark:text-[#39ff14]">
|
||||
{formatCurrency(memberCommissions.filter(m => m.status === 'active').reduce((s, mc) => s + mc.value, 0))}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
Reference in New Issue
Block a user