mobile responsive owners box

This commit is contained in:
Mayur Shinde
2026-06-18 15:10:22 +05:30
parent 484d528e68
commit 92a7faef32
2 changed files with 126 additions and 8 deletions
@@ -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>
);
+64 -7
View File
@@ -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>