From 6571b580dcee55521d5c930d7dc849a0175707a0 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Tue, 14 Apr 2026 22:52:20 +0200 Subject: [PATCH] refactor(admin): split roadmap page.tsx into colocated components Split 876-LOC page.tsx into 146 LOC with 7 colocated components (RoadmapCard, CreateRoadmapModal, CreateItemModal, ImportWizard, RoadmapDetailView split into header + items table), plus _types.ts, _constants.ts, and _api.ts. Behavior preserved. Co-Authored-By: Claude Opus 4.6 (1M context) --- admin-compliance/app/sdk/roadmap/_api.ts | 13 + .../roadmap/_components/CreateItemModal.tsx | 105 +++ .../_components/CreateRoadmapModal.tsx | 75 ++ .../sdk/roadmap/_components/ImportWizard.tsx | 154 ++++ .../sdk/roadmap/_components/RoadmapCard.tsx | 48 ++ .../_components/RoadmapDetailHeader.tsx | 62 ++ .../roadmap/_components/RoadmapDetailView.tsx | 124 +++ .../roadmap/_components/RoadmapItemsTable.tsx | 69 ++ .../app/sdk/roadmap/_constants.ts | 44 ++ admin-compliance/app/sdk/roadmap/_types.ts | 76 ++ admin-compliance/app/sdk/roadmap/page.tsx | 746 +----------------- 11 files changed, 778 insertions(+), 738 deletions(-) create mode 100644 admin-compliance/app/sdk/roadmap/_api.ts create mode 100644 admin-compliance/app/sdk/roadmap/_components/CreateItemModal.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_components/CreateRoadmapModal.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_components/ImportWizard.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_components/RoadmapCard.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_components/RoadmapDetailHeader.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_components/RoadmapDetailView.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_components/RoadmapItemsTable.tsx create mode 100644 admin-compliance/app/sdk/roadmap/_constants.ts create mode 100644 admin-compliance/app/sdk/roadmap/_types.ts diff --git a/admin-compliance/app/sdk/roadmap/_api.ts b/admin-compliance/app/sdk/roadmap/_api.ts new file mode 100644 index 0000000..9e0656e --- /dev/null +++ b/admin-compliance/app/sdk/roadmap/_api.ts @@ -0,0 +1,13 @@ +export const API_BASE = '/api/sdk/v1/roadmap' + +export async function api(path: string, options?: RequestInit): Promise { + const res = await fetch(`${API_BASE}${path}`, { + headers: { 'Content-Type': 'application/json' }, + ...options, + }) + if (!res.ok) { + const err = await res.json().catch(() => ({ error: res.statusText })) + throw new Error(err.error || err.message || `HTTP ${res.status}`) + } + return res.json() +} diff --git a/admin-compliance/app/sdk/roadmap/_components/CreateItemModal.tsx b/admin-compliance/app/sdk/roadmap/_components/CreateItemModal.tsx new file mode 100644 index 0000000..6e9551a --- /dev/null +++ b/admin-compliance/app/sdk/roadmap/_components/CreateItemModal.tsx @@ -0,0 +1,105 @@ +import { useState } from 'react' +import { api } from '../_api' +import { categoryLabels } from '../_constants' + +export function CreateItemModal({ roadmapId, onClose, onCreated }: { + roadmapId: string + onClose: () => void + onCreated: () => void +}) { + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [category, setCategory] = useState('TECHNICAL') + const [priority, setPriority] = useState('MEDIUM') + const [assigneeName, setAssigneeName] = useState('') + const [department, setDepartment] = useState('') + const [effortDays, setEffortDays] = useState(1) + const [saving, setSaving] = useState(false) + + const handleCreate = async () => { + if (!title.trim()) return + setSaving(true) + try { + await api(`/${roadmapId}/items`, { + method: 'POST', + body: JSON.stringify({ + title: title.trim(), + description: description.trim(), + category, + priority, + assignee_name: assigneeName.trim(), + department: department.trim(), + effort_days: effortDays, + }), + }) + onCreated() + } catch (err) { + console.error('Create item error:', err) + } finally { + setSaving(false) + } + } + + return ( +
+
e.stopPropagation()}> +

Neues Item

+
+
+ + setTitle(e.target.value)} + className="w-full px-3 py-2 border rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" /> +
+
+ +