feat: Client Portal redesign to Quiet Luxury + milestone stepper
- New MilestoneStepper primitive (horizontal per-phase progress) - Token-migrate portal shell, phase cards, sidebar cards, kanban to dual-theme - Soft-tint status pills (emerald/amber/muted) replacing solid badges - embedded prop on ClientDashboard fixes double-header in multi-project tabs Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,42 +8,15 @@ interface PhaseTimelineProps {
|
||||
|
||||
export function PhaseTimeline({ phases, token }: PhaseTimelineProps) {
|
||||
if (phases.length === 0) {
|
||||
return <p className="text-sm text-[#999999] italic">Nessuna fase ancora configurata.</p>;
|
||||
return <p className="text-sm text-muted-foreground italic">Nessuna fase ancora configurata.</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-0">
|
||||
{phases.map((phase, index) => {
|
||||
const isLast = index === phases.length - 1;
|
||||
<div className="space-y-6">
|
||||
{phases.map((phase) => {
|
||||
// done phases start collapsed; active and upcoming start expanded
|
||||
const defaultOpen = phase.status !== 'done';
|
||||
|
||||
return (
|
||||
<div key={phase.id} className="flex gap-5">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="w-10 h-10 rounded-full bg-white border-2 border-[#e5e5e5] flex items-center justify-center shrink-0 z-10">
|
||||
{phase.status === 'done' ? (
|
||||
<svg className="w-5 h-5 text-[#1A463C]" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clipRule="evenodd" />
|
||||
</svg>
|
||||
) : phase.status === 'active' ? (
|
||||
<svg className="w-5 h-5 text-[#3b82f6]" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16z" clipRule="evenodd" />
|
||||
</svg>
|
||||
) : (
|
||||
<svg className="w-5 h-5 text-[#999999]" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24" aria-hidden="true">
|
||||
<circle cx={12} cy={12} r={9} />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
{!isLast && <div className="flex-1 w-px bg-[#e5e5e5] my-2" style={{ minHeight: '2rem' }} />}
|
||||
</div>
|
||||
|
||||
<div className={`flex-1 ${isLast ? 'pb-0' : 'pb-6'}`}>
|
||||
<PhaseCard phase={phase} token={token} defaultOpen={defaultOpen} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return <PhaseCard key={phase.id} phase={phase} token={token} defaultOpen={defaultOpen} />;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user