mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-07 23:17:37 +00:00
Break the legacy PRDEditor.jsx monolith into a feature-based TypeScript architecture under src/components/prd-editor while keeping behavior parity and readability. Key changes: - Replace PRDEditor.jsx with a typed orchestrator component and a compatibility export bridge at src/components/PRDEditor.tsx. - Split responsibilities into dedicated hooks: document loading/init, existing PRD registry fetching, save workflow with overwrite detection, and keyboard shortcuts. - Split UI into focused view components: header, editor/preview body, footer stats, loading state, generate-tasks modal, and overwrite-confirm modal. - Move filename concerns into utility helpers (sanitize, extension handling, default naming) and centralize template/constants. - Keep component-local state close to the UI that owns it (workspace controls/modal toggles), while shared workflow state remains in the feature container. - Reuse the existing MarkdownPreview component for safer markdown rendering instead of ad-hoc HTML conversion. - Update TaskMasterPanel integration to consume typed PRDEditor directly (remove any-cast) and pass isExisting metadata for correct overwrite behavior. - Keep all new/changed files below 300 lines and add targeted comments where behavior needs clarification. Validation: - npm run typecheck - npm run build
51 lines
1.3 KiB
TypeScript
51 lines
1.3 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react';
|
|
import { api } from '../../../utils/api';
|
|
import type { ExistingPrdFile, PrdListResponse } from '../types';
|
|
|
|
type UsePrdRegistryArgs = {
|
|
projectName?: string;
|
|
};
|
|
|
|
type UsePrdRegistryResult = {
|
|
existingPrds: ExistingPrdFile[];
|
|
refreshExistingPrds: () => Promise<void>;
|
|
};
|
|
|
|
function getPrdFiles(data: PrdListResponse): ExistingPrdFile[] {
|
|
return data.prdFiles || data.prds || [];
|
|
}
|
|
|
|
export function usePrdRegistry({ projectName }: UsePrdRegistryArgs): UsePrdRegistryResult {
|
|
const [existingPrds, setExistingPrds] = useState<ExistingPrdFile[]>([]);
|
|
|
|
const refreshExistingPrds = useCallback(async () => {
|
|
if (!projectName) {
|
|
setExistingPrds([]);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await api.get(`/taskmaster/prd/${encodeURIComponent(projectName)}`);
|
|
if (!response.ok) {
|
|
setExistingPrds([]);
|
|
return;
|
|
}
|
|
|
|
const data = (await response.json()) as PrdListResponse;
|
|
setExistingPrds(getPrdFiles(data));
|
|
} catch (error) {
|
|
console.error('Failed to fetch existing PRDs:', error);
|
|
setExistingPrds([]);
|
|
}
|
|
}, [projectName]);
|
|
|
|
useEffect(() => {
|
|
void refreshExistingPrds();
|
|
}, [refreshExistingPrds]);
|
|
|
|
return {
|
|
existingPrds,
|
|
refreshExistingPrds,
|
|
};
|
|
}
|