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> <p className="text-xs text-zinc-400 mt-1">Add team members with commission rules to see the distribution.</p>
</div> </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]"> <table className="w-full text-left min-w-[600px]">
<thead> <thead>
<tr className="border-b border-zinc-200 dark:border-white/5 bg-zinc-50 dark:bg-white/[0.02]"> <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> </tfoot>
</table> </table>
</div> </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> </div>
); );
+64 -7
View File
@@ -393,8 +393,9 @@ const TeamManagementPanel = ({
transition={{ duration: 0.25 }} transition={{ duration: 0.25 }}
className="overflow-hidden" className="overflow-hidden"
> >
<div className="overflow-x-auto rounded-xl border border-zinc-200 dark:border-white/5"> {/* ── Desktop table (sm+) ── */}
<table className="w-full text-left"> <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> <thead>
<tr className="border-b border-zinc-200 dark:border-white/5 bg-zinc-50 dark:bg-white/[0.02]"> <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> <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> </div>
</td> </td>
<td className="px-4 py-3"> <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} {mc.jobRole}
</span> </span>
</td> </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-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"> <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' {mc.resolved.type === 'flat' || mc.resolved.type === 'custom'
? formatCurrency(mc.resolved.rate) ? formatCurrency(mc.resolved.rate)
: `${mc.resolved.rate}%`} : `${mc.resolved.rate}%`}
</td> </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)} {formatCurrency(mc.value)}
</td> </td>
<td className="px-4 py-3 text-center"> <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"> <tfoot className="border-t-2 border-zinc-300 dark:border-white/10">
<tr className="bg-zinc-50 dark:bg-white/[0.03]"> <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 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))} {formatCurrency(memberCommissions.filter(m => m.status === 'active').reduce((s, mc) => s + mc.value, 0))}
</td> </td>
<td /> <td />
@@ -453,6 +454,62 @@ const TeamManagementPanel = ({
</tfoot> </tfoot>
</table> </table>
</div> </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> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>