style(detail): apply gradient header strip to client/interest/yacht/company/berth/residential/invoice details
Adds shared <DetailHeaderStrip> wrapper (rounded-xl + gradient-brand-soft + shadow-xs)
and applies it to every legacy domain detail header. Residential client/interest and
invoice detail get an inline gradient strip with eyebrow ('Residential Client',
'Residential Interest', 'Invoice'). Residential bodies normalized to lg:grid-cols-[2fr_1fr]
per spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { TagBadge } from '@/components/shared/tag-badge';
|
||||
import { ArchiveConfirmDialog } from '@/components/shared/archive-confirm-dialog';
|
||||
import { DetailHeaderStrip } from '@/components/shared/detail-header-strip';
|
||||
import { PermissionGate } from '@/components/shared/permission-gate';
|
||||
import { InterestForm } from '@/components/interests/interest-form';
|
||||
import { InterestStagePicker } from '@/components/interests/interest-stage-picker';
|
||||
@@ -70,8 +71,7 @@ export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeade
|
||||
const isArchived = !!interest.archivedAt;
|
||||
|
||||
const archiveMutation = useMutation({
|
||||
mutationFn: () =>
|
||||
apiFetch(`/api/v1/interests/${interest.id}`, { method: 'DELETE' }),
|
||||
mutationFn: () => apiFetch(`/api/v1/interests/${interest.id}`, { method: 'DELETE' }),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['interests', interest.id] });
|
||||
queryClient.invalidateQueries({ queryKey: ['interests'] });
|
||||
@@ -80,8 +80,7 @@ export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeade
|
||||
});
|
||||
|
||||
const restoreMutation = useMutation({
|
||||
mutationFn: () =>
|
||||
apiFetch(`/api/v1/interests/${interest.id}/restore`, { method: 'POST' }),
|
||||
mutationFn: () => apiFetch(`/api/v1/interests/${interest.id}/restore`, { method: 'POST' }),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['interests', interest.id] });
|
||||
queryClient.invalidateQueries({ queryKey: ['interests'] });
|
||||
@@ -91,7 +90,7 @@ export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeade
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-3">
|
||||
<DetailHeaderStrip>
|
||||
<div className="flex items-start gap-3 flex-wrap">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
@@ -99,7 +98,9 @@ export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeade
|
||||
{interest.clientName ?? 'Unknown Client'}
|
||||
</h1>
|
||||
{isArchived && (
|
||||
<Badge variant="secondary" className="text-xs">Archived</Badge>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
Archived
|
||||
</Badge>
|
||||
)}
|
||||
<span
|
||||
className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-sm font-medium ${STAGE_COLORS[interest.pipelineStage] ?? 'bg-gray-100 text-gray-700'}`}
|
||||
@@ -130,8 +131,7 @@ export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeade
|
||||
)}
|
||||
{interest.source && (
|
||||
<span>
|
||||
Source:{' '}
|
||||
<span className="text-foreground capitalize">{interest.source}</span>
|
||||
Source: <span className="text-foreground capitalize">{interest.source}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -176,7 +176,7 @@ export function InterestDetailHeader({ portSlug, interest }: InterestDetailHeade
|
||||
</PermissionGate>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DetailHeaderStrip>
|
||||
|
||||
<InterestForm
|
||||
open={editOpen}
|
||||
|
||||
Reference in New Issue
Block a user