Capital Planning: show beyond-window projects in Future bucket, 2-col layout
Projects with target years beyond the 5-year planning window now appear in the Future column of the Kanban board (previously they were invisible). Cards for these projects show their specific target year as a badge. The Future column uses a 2-column grid layout when it has more than 3 projects to maximize screen utilization. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,9 @@ interface KanbanCardProps {
|
||||
|
||||
function KanbanCard({ project, onEdit, onDragStart }: KanbanCardProps) {
|
||||
const plannedLabel = formatPlannedDate(project.planned_date);
|
||||
// For projects in the Future bucket with a specific year, show the year
|
||||
const currentYear = new Date().getFullYear();
|
||||
const isBeyondWindow = project.target_year > currentYear + 4 && project.target_year !== FUTURE_YEAR;
|
||||
|
||||
return (
|
||||
<Card
|
||||
@@ -105,6 +108,11 @@ function KanbanCard({ project, onEdit, onDragStart }: KanbanCardProps) {
|
||||
<Badge size="xs" color={priorityColor(project.priority)} variant="outline">
|
||||
P{project.priority}
|
||||
</Badge>
|
||||
{isBeyondWindow && (
|
||||
<Badge size="xs" variant="light" color="gray">
|
||||
{project.target_year}
|
||||
</Badge>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<Text size="xs" ff="monospace" fw={500} mb={4}>
|
||||
@@ -145,14 +153,16 @@ function KanbanColumn({
|
||||
isDragOver, onDragOverHandler, onDragLeave,
|
||||
}: KanbanColumnProps) {
|
||||
const totalEst = projects.reduce((s, p) => s + parseFloat(p.estimated_cost || '0'), 0);
|
||||
const isFuture = year === FUTURE_YEAR;
|
||||
const useWideLayout = isFuture && projects.length > 3;
|
||||
|
||||
return (
|
||||
<Paper
|
||||
withBorder
|
||||
radius="md"
|
||||
p="sm"
|
||||
miw={280}
|
||||
maw={320}
|
||||
miw={useWideLayout ? 580 : 280}
|
||||
maw={useWideLayout ? 640 : 320}
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
display: 'flex',
|
||||
@@ -167,8 +177,10 @@ function KanbanColumn({
|
||||
>
|
||||
<Group justify="space-between" mb="sm">
|
||||
<Title order={5}>{yearLabel(year)}</Title>
|
||||
<Group gap={6}>
|
||||
<Badge size="sm" variant="light">{fmt(totalEst)}</Badge>
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
<Text size="xs" c="dimmed" mb="xs">
|
||||
{projects.length} project{projects.length !== 1 ? 's' : ''}
|
||||
@@ -179,6 +191,16 @@ function KanbanColumn({
|
||||
<Text size="xs" c="dimmed" ta="center" py="lg">
|
||||
Drop projects here
|
||||
</Text>
|
||||
) : useWideLayout ? (
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr 1fr',
|
||||
gap: 'var(--mantine-spacing-xs)',
|
||||
}}>
|
||||
{projects.map((p) => (
|
||||
<KanbanCard key={p.id} project={p} onEdit={onEdit} onDragStart={onDragStart} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
projects.map((p) => (
|
||||
<KanbanCard key={p.id} project={p} onEdit={onEdit} onDragStart={onDragStart} />
|
||||
@@ -530,11 +552,16 @@ export function CapitalProjectsPage() {
|
||||
|
||||
// ---- Render: Kanban view ----
|
||||
|
||||
const maxPlannedYear = currentYear + 4; // last year in the 5-year window
|
||||
|
||||
const renderKanbanView = () => (
|
||||
<ScrollArea type="auto" offsetScrollbars>
|
||||
<Group align="flex-start" wrap="nowrap" gap="md" py="sm" style={{ minWidth: kanbanYears.length * 300 }}>
|
||||
{kanbanYears.map((year) => {
|
||||
const yearProjects = projects.filter((p) => p.target_year === year);
|
||||
// Future bucket: collect projects with target_year === 9999 OR beyond the 5-year window
|
||||
const yearProjects = year === FUTURE_YEAR
|
||||
? projects.filter((p) => p.target_year === FUTURE_YEAR || p.target_year > maxPlannedYear)
|
||||
: projects.filter((p) => p.target_year === year);
|
||||
return (
|
||||
<KanbanColumn
|
||||
key={year}
|
||||
|
||||
Reference in New Issue
Block a user