redesign: complete UI overhaul for 54 nodes and 26 projects
- Replace D3 force graph with categorized grid layout for topology (54 nodes organized by type: infrastructure, servers, PCs, etc.) - Replace individual task cards with project summary cards (progress bars and stage chips instead of 1700+ task cards) - Compact node cards with status-colored backgrounds - Better calendar empty state with centered icon - Refined dark theme with more color depth - Remove D3 dependency (no longer needed) - Fix text sizes for 4K TV readability at distance Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,53 +24,88 @@ export function CalendarView({ events }: CalendarViewProps) {
|
||||
});
|
||||
};
|
||||
|
||||
const hasEvents = events.length > 0;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full p-12 overflow-hidden">
|
||||
<section className="mb-10">
|
||||
<h2 className="text-3xl font-bold text-text-primary mb-6">
|
||||
Hoy — {formatDate(today)}
|
||||
</h2>
|
||||
{todayEvents.length === 0 ? (
|
||||
<p className="text-xl text-text-secondary">Sin eventos programados</p>
|
||||
<div className="flex flex-col h-full">
|
||||
{/* Summary bar */}
|
||||
<div className="flex items-center gap-8 px-16 py-4 bg-bg-secondary border-b border-border">
|
||||
<span className="text-lg text-text-secondary">
|
||||
<span className="font-bold text-text-primary">{events.length}</span> eventos esta
|
||||
semana
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 overflow-y-auto px-16 py-8">
|
||||
{!hasEvents ? (
|
||||
<div className="flex flex-col items-center justify-center h-full gap-6 -mt-16">
|
||||
<span className="text-8xl opacity-30">📅</span>
|
||||
<p className="text-3xl font-semibold text-text-secondary">
|
||||
Sin eventos programados
|
||||
</p>
|
||||
<p className="text-xl text-text-muted">
|
||||
Los próximos eventos del calendario de Odoo aparecerán aquí
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{todayEvents.map((e) => (
|
||||
<EventCard key={e.id} event={e} />
|
||||
))}
|
||||
<div className="grid grid-cols-3 gap-10 h-full">
|
||||
{/* Today */}
|
||||
<section className="flex flex-col">
|
||||
<h2 className="text-2xl font-bold text-text-primary mb-2">Hoy</h2>
|
||||
<p className="text-base text-text-muted capitalize mb-6">{formatDate(today)}</p>
|
||||
{todayEvents.length === 0 ? (
|
||||
<p className="text-lg text-text-secondary">Sin eventos</p>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{todayEvents.map((e) => (
|
||||
<EventCard key={e.id} event={e} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* Tomorrow */}
|
||||
<section className="flex flex-col">
|
||||
<h2 className="text-2xl font-bold text-text-primary mb-2">Mañana</h2>
|
||||
<p className="text-base text-text-muted capitalize mb-6">
|
||||
{formatDate(tomorrow)}
|
||||
</p>
|
||||
{tomorrowEvents.length === 0 ? (
|
||||
<p className="text-lg text-text-secondary">Sin eventos</p>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{tomorrowEvents.map((e) => (
|
||||
<EventCard key={e.id} event={e} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* This week */}
|
||||
<section className="flex flex-col">
|
||||
<h2 className="text-2xl font-bold text-text-primary mb-2">Esta semana</h2>
|
||||
<p className="text-base text-text-muted mb-6">Próximos días</p>
|
||||
{laterEvents.length === 0 ? (
|
||||
<p className="text-lg text-text-secondary">Sin eventos</p>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
{laterEvents.map((e) => (
|
||||
<div
|
||||
key={e.id}
|
||||
className="flex gap-4 text-base bg-bg-card rounded-lg px-4 py-3 border border-border"
|
||||
>
|
||||
<span className="font-mono text-text-muted min-w-[160px] capitalize">
|
||||
{formatDate(e.start)}
|
||||
</span>
|
||||
<span className="text-text-primary truncate">{e.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="mb-10">
|
||||
<h2 className="text-2xl font-bold text-text-primary mb-4">
|
||||
Mañana — {formatDate(tomorrow)}
|
||||
</h2>
|
||||
{tomorrowEvents.length === 0 ? (
|
||||
<p className="text-lg text-text-secondary">Sin eventos programados</p>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{tomorrowEvents.map((e) => (
|
||||
<EventCard key={e.id} event={e} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{laterEvents.length > 0 && (
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-text-primary mb-4">Esta semana</h2>
|
||||
<div className="space-y-3">
|
||||
{laterEvents.map((e) => (
|
||||
<div key={e.id} className="flex gap-4 text-lg text-text-secondary">
|
||||
<span className="font-mono min-w-[200px] capitalize">
|
||||
{formatDate(e.start)}
|
||||
</span>
|
||||
<span className="text-text-primary">{e.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user