feat(uat-batch-5): UI polish — dialog width, chart centering, recommender pill, audit link, inbox reorder
Six surgical Wave-2-3 wins:
- UploadForSigningDialog: dialog widened to max-w-[1400px] w-[95vw] so
the place-fields step actually has room; recipient row converts from
fixed grid to flex (name flex-1, email flex-[2] for the longer
string, role w-40, delete shrink-0); invitation-message textarea
rows 3 → 6.
- ChartCard becomes flex-col with flex-1 + items-center on CardContent
so charts vertically center when neighbouring cards make the row
taller (e.g. Pipeline Value's full breakdown).
- Berth recommender pill: drops the "Tier {letter} · " prefix; shows
just the plain-English label ("Open" / "Fall-through" / "Active
interest" / "Late stage") as a Popover trigger that explains the
4-state ladder. HelpCircle icon makes the tooltip discoverable.
- Activity feed gains a "See all" link in the header pointing at
/<port>/admin/audit, permission-gated by `admin.view_audit_log`.
- Inbox section order swaps to Reminders above Alerts (rep-noted
priority); PageHeader title flips to "Reminders & Alerts". Section
ids, deep-link hashes, and localStorage open-state keys untouched.
- Inbox ReminderList (embedded mode only): "New Reminder" button now
shares the filter row (right-aligned via ml-auto) instead of
occupying its own dedicated row above the filters.
tsc clean. 1419/1419 vitest pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,12 +4,22 @@ import { useState, useMemo } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { ChevronDown, ChevronUp, Filter, Flame, Plus, RefreshCw, Sparkles } from 'lucide-react';
|
||||
import {
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
Filter,
|
||||
Flame,
|
||||
HelpCircle,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
Sparkles,
|
||||
} from 'lucide-react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -172,14 +182,42 @@ function RecommendationCard({ rec, portSlug, onAdd }: RecommendationCardProps) {
|
||||
<span className="font-semibold">{rec.mooringNumber}</span>
|
||||
{rec.area ? <span className="text-xs text-muted-foreground">{rec.area}</span> : null}
|
||||
<StatusPill status={statusToPill(rec.status)}>{formatStatus(rec.status)}</StatusPill>
|
||||
<span
|
||||
className={cn(
|
||||
'inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-medium',
|
||||
tier.tone,
|
||||
)}
|
||||
>
|
||||
Tier {rec.tier} · {tier.label}
|
||||
</span>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1 rounded-md border px-2 py-0.5 text-xs font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
||||
tier.tone,
|
||||
)}
|
||||
aria-label={`Recommender state: ${tier.label}`}
|
||||
>
|
||||
{tier.label}
|
||||
<HelpCircle className="size-3 opacity-60" aria-hidden />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="w-80 text-xs leading-relaxed">
|
||||
<p className="font-medium text-foreground">Recommender state</p>
|
||||
<ul className="mt-2 space-y-1.5 text-muted-foreground">
|
||||
<li>
|
||||
<span className="font-medium text-emerald-700">Open</span>: never had an
|
||||
interest, ready for new prospects.
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-medium text-amber-700">Fall-through</span>: a prior
|
||||
interest didn't close; warm and worth pitching again.
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-medium text-sky-700">Active interest</span>: another deal
|
||||
is in play. Coordinate before pitching.
|
||||
</li>
|
||||
<li>
|
||||
<span className="font-medium text-slate-700">Late stage</span>: another deal is
|
||||
near-sold; treat as backup only.
|
||||
</li>
|
||||
</ul>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
{showHeat ? (
|
||||
<span className="inline-flex items-center gap-1 rounded-md border border-rose-200 bg-rose-50 px-2 py-0.5 text-xs font-medium text-rose-800">
|
||||
<Flame className="size-3" aria-hidden />
|
||||
|
||||
Reference in New Issue
Block a user