b76a2baad2
- Split landing page into public landing page and authenticated workspace - Extract contract generation logic into use-contract-generation hook - Extract contract generation service into sub-services - Add AI quality scoring for contract generation - Expand risk rules library with employment-specific rules - Add custom exception classes (NotFoundError, ValidationError, etc.) - Add prompt asset seeding script from LexForge documentation - Add format utility library - Fix SSR hydration mismatch on Ant Design inputs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
150 lines
6.4 KiB
Python
150 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Simplify contracts page to use the useContractGeneration hook."""
|
|
import re
|
|
|
|
with open('src/app/contracts/page.tsx', 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
# 1. Replace the component function header
|
|
old_header = """export default function ContractsPage() {
|
|
const [messageApi, contextHolder] = message.useMessage();
|
|
const [form] = Form.useForm<ContractFormValues>();
|
|
const router = useRouter();
|
|
const currentUser = useAuthStore((state) => state.currentUser);
|
|
const searchParams = useSearchParams();
|
|
const restorePayload = useMemo(() => parseRestorePayload(searchParams.get("restore")), [searchParams]);
|
|
const reviewContext = useMemo(() => parseReviewContextPayload(searchParams.get("review")), [searchParams]);
|
|
const [templateLoading, setTemplateLoading] = useState(true);
|
|
const [historyLoading, setHistoryLoading] = useState(true);
|
|
const [generating, setGenerating] = useState(false);
|
|
const [previewing, setPreviewing] = useState(false);
|
|
const [downloadingCurrent, setDownloadingCurrent] = useState(false);
|
|
const [historyDownloadingId, setHistoryDownloadingId] = useState<string | null>(null);
|
|
const [currentStep, setCurrentStep] = useState(0);
|
|
const [templates, setTemplates] = useState<ContractTemplate[]>([]);
|
|
const [selectedTemplate, setSelectedTemplate] = useState<ContractTemplate | null>(null);
|
|
const [templateCategoryFilter, setTemplateCategoryFilter] = useState<string | undefined>(undefined);
|
|
const [industryCategoryFilter, setIndustryCategoryFilter] = useState<string | undefined>(undefined);
|
|
const [previewResult, setPreviewResult] = useState<ContractPreview | null>(null);
|
|
const [generatedContract, setGeneratedContract] = useState<GeneratedContract | null>(null);
|
|
const [historyContracts, setHistoryContracts] = useState<GeneratedContractListItem[]>([]);
|
|
const [historyKeyword, setHistoryKeyword] = useState("");
|
|
const [historyContractType, setHistoryContractType] = useState<string | undefined>(undefined);
|
|
const [historyLifecycleStatus, setHistoryLifecycleStatus] = useState<string | undefined>(undefined);
|
|
const [historyPage, setHistoryPage] = useState(1);
|
|
const [historyPageSize, setHistoryPageSize] = useState(10);
|
|
const [historyTotal, setHistoryTotal] = useState(0);
|
|
const [restoredOptions, setRestoredOptions] = useState<Record<string, unknown>>({});
|
|
const [appliedRestoreValue, setAppliedRestoreValue] = useState<string | null>(null);
|
|
const [lifecycleUpdating, setLifecycleUpdating] = useState(false);
|
|
const [historyCollapsed, setHistoryCollapsed] = useState(true);
|
|
const canDownloadContracts = currentUser?.role === "admin";"""
|
|
|
|
new_header = """export default function ContractsPage() {
|
|
const [form] = Form.useForm<ContractFormValues>();
|
|
const {
|
|
messageApi, contextHolder, router, currentUser, reviewContext, restorePayload,
|
|
templateLoading, historyLoading, generating, previewing, downloadingCurrent, historyDownloadingId,
|
|
currentStep, templates, selectedTemplate, templateCategoryFilter, industryCategoryFilter,
|
|
previewResult, generatedContract, historyContracts, historyKeyword, historyContractType,
|
|
historyLifecycleStatus, historyPage, historyPageSize, historyTotal, restoredOptions,
|
|
lifecycleUpdating, historyCollapsed, canDownloadContracts, contractTypeOptions,
|
|
setTemplateCategoryFilter, setIndustryCategoryFilter, setCurrentStep, setHistoryKeyword,
|
|
setHistoryContractType, setHistoryLifecycleStatus, setHistoryPage, setHistoryPageSize,
|
|
setHistoryCollapsed,
|
|
handleTemplateSelect, handlePreview, handleGenerate, handleDownload,
|
|
handleHistoryDownload, handleHistorySearch, handleHistoryFilterChange,
|
|
handleHistoryLifecycleFilterChange, handleHistoryReset, handleHistoryTableChange,
|
|
handleReset, handleLifecycleTransition, loadHistory, clearRestoreQuery,
|
|
} = useContractGeneration(form);"""
|
|
|
|
content = content.replace(old_header, new_header, 1)
|
|
|
|
# 2. Remove helper function blocks that are now in the hook
|
|
helper_funcs = [
|
|
'clearRestoreQuery',
|
|
'applyTemplateSelection',
|
|
'loadTemplates',
|
|
'loadHistory',
|
|
'contractTypeOptions',
|
|
'handleTemplateSelect',
|
|
'handlePreview',
|
|
'handleGenerate',
|
|
'handleDownload',
|
|
'handleHistoryDownload',
|
|
'handleHistorySearch',
|
|
'handleHistoryFilterChange',
|
|
'handleHistoryLifecycleFilterChange',
|
|
'handleHistoryReset',
|
|
'handleHistoryTableChange',
|
|
'handleReset',
|
|
'handleLifecycleTransition',
|
|
'handleOpenAutoReviewDetail',
|
|
'handleOpenAutoReviewChat',
|
|
'handleDownloadAutoReviewReport',
|
|
'handleOpenLifecycleModal',
|
|
'handleUpdateLifecycle',
|
|
]
|
|
|
|
# Find all lines that are function declarations and remove their bodies
|
|
lines = content.split('\n')
|
|
result = []
|
|
in_func = False
|
|
func_indent = 0
|
|
func_name = ''
|
|
|
|
for line in lines:
|
|
stripped = line.strip()
|
|
|
|
# Check if this line starts a handler function
|
|
detected_func = None
|
|
for fn in helper_funcs:
|
|
# Match patterns like: const fnName = ..., const fnName = useCallback(..., function fnName(
|
|
pattern1 = f'const {fn} = '
|
|
pattern2 = f'const {fn}:'
|
|
pattern3 = f'function {fn}('
|
|
# Also handle const { fn } = ... destructuring
|
|
if stripped.startswith(pattern1) or stripped.startswith(pattern2) or stripped.startswith(pattern3):
|
|
detected_func = fn
|
|
break
|
|
|
|
if detected_func and not in_func:
|
|
in_func = True
|
|
func_indent = len(line) - len(stripped)
|
|
func_name = detected_func
|
|
continue
|
|
|
|
if in_func:
|
|
current_indent = len(line) - len(stripped) if stripped else func_indent + 4
|
|
if stripped and current_indent <= func_indent and not stripped.startswith('//'):
|
|
in_func = False
|
|
result.append(line)
|
|
continue
|
|
continue
|
|
|
|
result.append(line)
|
|
|
|
# 3. Remove type/func definitions that moved to the hook
|
|
content = '\n'.join(result)
|
|
|
|
# Remove type definitions and helpers that migrated to the hook
|
|
removals = [
|
|
('type RefillPayload', '};'),
|
|
('type ReviewContextPayload', '};'),
|
|
('const GENERATE_RECOVERY_TIMEOUT_MS', ';'),
|
|
]
|
|
for start_pattern, end_marker in removals:
|
|
idx = content.find(start_pattern)
|
|
if idx >= 0:
|
|
end_idx = content.find(end_marker, idx) + len(end_marker)
|
|
# Find the next blank line or code
|
|
rest = content[end_idx:]
|
|
next_line = rest.find('\n')
|
|
content = content[:idx] + rest[next_line:]
|
|
|
|
with open('src/app/contracts/page.tsx', 'w', encoding='utf-8') as f:
|
|
f.write(content)
|
|
|
|
print('Done')
|
|
"
|