Seth
Claude Sonnet 5
Add dashboard activity/lead/deal stat boxes and backfill Contacts/Companies ownership scoping
de29580
Raw History Blame Contribute Delete
3.22 kB
import React from 'react';
import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
import { cn } from '@/lib/utils';
import { OwnerAvatarCircle, ownerDisplayLabel } from '@/lib/ownerAvatar';
const EMPTY_OWNER_KEY = '__owner_none__';
const MEMBER_TAKE_OWNERSHIP_VALUE = '__member_take_ownership__';
/**
* Owner avatar + reassignment dropdown, shared across Leads/Contacts/Companies. Admins can
* assign to anyone or unassign; members can only self-claim an unassigned row (same rules the
* backend enforces on the owner_user_id patch).
*/
export default function OwnerCell({ row, isAdmin, tenantMembers, currentUserId, onChangeOwner }) {
const trigger = (
<SelectTrigger
className={cn(
'h-9 w-9 shrink-0 p-0 justify-center border-slate-200 shadow-none',
'[&>svg]:hidden'
)}
title={isAdmin ? 'Change owner' : ownerDisplayLabel(row)}
aria-label={`Owner: ${ownerDisplayLabel(row)}. Open menu ${isAdmin ? 'to change' : 'for details'}.`}
>
<OwnerAvatarCircle userId={row.owner_user_id} initials={row.owner_initials} />
</SelectTrigger>
);
const header = (
<div role="presentation" className="pointer-events-none border-b border-slate-100 px-2 py-2 mb-1">
<div className="flex items-center gap-2">
<OwnerAvatarCircle userId={row.owner_user_id} initials={row.owner_initials} />
<div className="min-w-0 flex-1">
<div className="truncate text-sm font-semibold text-slate-900">
{ownerDisplayLabel(row)}
</div>
</div>
</div>
</div>
);
const currentValue =
row.owner_user_id != null && row.owner_user_id !== '' ? String(row.owner_user_id) : EMPTY_OWNER_KEY;
if (isAdmin) {
return (
<Select
value={currentValue}
onValueChange={(v) => onChangeOwner(v === EMPTY_OWNER_KEY ? null : Number(v))}
>
{trigger}
<SelectContent className="min-w-[12rem]">
{header}
<SelectItem value={EMPTY_OWNER_KEY}>Unassigned</SelectItem>
{(tenantMembers || []).map((m) => (
<SelectItem key={m.user_id} value={String(m.user_id)}>
{(m.name || m.email || `User ${m.user_id}`).trim()}
</SelectItem>
))}
</SelectContent>
</Select>
);
}
return (
<Select
value={currentValue}
onValueChange={(v) => {
if (v === MEMBER_TAKE_OWNERSHIP_VALUE) onChangeOwner(currentUserId);
}}
>
{trigger}
<SelectContent className="min-w-[12rem]">
{header}
{currentUserId != null && (row.owner_user_id == null || row.owner_user_id === '') ? (
<SelectItem value={MEMBER_TAKE_OWNERSHIP_VALUE}>Take ownership</SelectItem>
) : null}
</SelectContent>
</Select>
);
}