mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-12 01:17:48 +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
37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
import { useMemo } from 'react';
|
|
|
|
type PrdEditorFooterProps = {
|
|
content: string;
|
|
};
|
|
|
|
type ContentStats = {
|
|
lines: number;
|
|
characters: number;
|
|
words: number;
|
|
};
|
|
|
|
function getContentStats(content: string): ContentStats {
|
|
return {
|
|
lines: content.split('\n').length,
|
|
characters: content.length,
|
|
words: content.split(/\s+/).filter(Boolean).length,
|
|
};
|
|
}
|
|
|
|
export default function PrdEditorFooter({ content }: PrdEditorFooterProps) {
|
|
const stats = useMemo(() => getContentStats(content), [content]);
|
|
|
|
return (
|
|
<div className="flex items-center justify-between p-3 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 flex-shrink-0">
|
|
<div className="flex items-center gap-4 text-sm text-gray-600 dark:text-gray-400">
|
|
<span>Lines: {stats.lines}</span>
|
|
<span>Characters: {stats.characters}</span>
|
|
<span>Words: {stats.words}</span>
|
|
<span>Format: Markdown</span>
|
|
</div>
|
|
|
|
<div className="text-sm text-gray-500 dark:text-gray-400">Press Ctrl+S to save and Esc to close</div>
|
|
</div>
|
|
);
|
|
}
|