| Metadata | Value |
|---|---|
| Status | Active |
| Version | 1.1.0 |
| Last Updated | 2026-09-10 |
| Author | Sangeetha Grantha Team |
| Document Type | Evidence record |
[!NOTE] Historical evidence: results, counts, commands, and observations below belong to the original work described here. The editorial update date is not a new test or corpus verification. For present behavior, use current quality checks.
Review Date: 2026-01-27
Reviewer: Claude Code Analysis
Scope: modules/frontend/sangita-admin-web/src/pages/*.tsx
| Page | Lines | Complexity | Type Safety | Issues | Priority |
|---|---|---|---|---|---|
| KrithiEditor.tsx | 1,860 | Critical | Poor | 15+ | P1 |
| ReferenceData.tsx | 966 | High | Poor | 12+ | P1 |
| BulkImport.tsx | 772 | High | Moderate | 10+ | P2 |
| ImportReview.tsx | 414 | Medium | Moderate | 6+ | P2 |
| TagsPage.tsx | 317 | Low | Good | 4+ | P3 |
| ImportsPage.tsx | 244 | Low | Good | 3+ | P3 |
| Dashboard.tsx | 225 | Low | Good | 3+ | P3 |
| AutoApproveQueue.tsx | 215 | Low | Moderate | 4+ | P3 |
| KrithiList.tsx | 135 | Low | Good | 2+ | P4 |
| RolesPage.tsx | 39 | Placeholder | N/A | 0 | N/A |
| UsersPage.tsx | 38 | Placeholder | N/A | 0 | N/A |
Total Issues Identified: 59+ Critical Files Requiring Immediate Attention: 2 (KrithiEditor, ReferenceData)
Already analyzed separately. See krithi-editor-code-review.md
Summary: Monolithic component with 25+ useState calls, pervasive any types, complex effect chains, 280-line save handler. Requires significant decomposition.
Multi-view page managing Ragas, Talas, Composers, Temples, and Deities with HOME/LIST/FORM view modes.
// These types DUPLICATE existing types from '../types'
interface Composer extends BaseEntity { type: 'Composers'; ... }
interface Raga extends BaseEntity { type: 'Ragas'; ... }
interface Tala extends BaseEntity { type: 'Talas'; ... }
Impact: Type mismatches, maintenance burden, potential runtime bugs.
any Types (Lines 142, 169, 186, 209)const FormInput = ({ label, ... }: any) => (...)
const FormTextarea = ({ ... }: any) => (...)
const FormSelect = ({ ... }: any) => (...)
const [formData, setFormData] = useState<Record<string, any>>({});
Impact: No type safety on form data.
if (entityType === 'Composers' && !formData.name) { toast.error(...); return; }
if (entityType === 'Ragas' && !formData.name) { toast.error(...); return; }
if (entityType === 'Talas' && !formData.name) { toast.error(...); return; }
// Same pattern repeated 5 times
Impact: Code duplication, maintenance burden.
Entity-specific logic spread across multiple switch statements. Should use polymorphism or strategy pattern.
Data transformation logic mixed with component code. Should be extracted to utilities.
Complex orchestration page for bulk CSV imports with real-time polling, task management, and detailed views.
const triggerAction = async (action: 'pause' | 'resume' | 'cancel' | 'retry' | 'delete' | ..., batchId: string) => {
// 50+ lines handling 9 different action types
}
Impact: High cyclomatic complexity, hard to test.
useEffect(() => {
let interval: NodeJS.Timeout;
if (isRunning && selectedBatchId) {
interval = setInterval(() => {
void loadBatchDetail(selectedBatchId); // No abort controller
}, 2000);
}
return () => clearInterval(interval);
}, [selectedBatch?.status, selectedBatchId]);
Impact: Potential memory leaks, stale closures.
console.log(`triggerAction called: ${action} for batch ${batchId}`);
Impact: Development code in production.
Queue-based import review page with bulk selection and entity resolution preview.
interface ResolutionCandidate<T> { ... }
interface ResolutionResult { ... }
Defined but ResolutionResult is parsed from JSON without validation.
let resolution: ResolutionResult;
try {
resolution = JSON.parse(selectedItem.resolutionData);
} catch (e) {
return <div className="text-xs text-rose-500">Invalid resolution data</div>;
}
Impact: Runtime errors if data structure changes.
const promises = Array.from(selectedImportIds).map(id =>
reviewImport(id, { status: 'APPROVED' })
);
await Promise.all(promises); // If one fails, all fail
Impact: One failed review blocks all reviews.
confirm()CRUD page for tag management with search and category filtering.
console.log('handleCreate called', { formData, isCreating });
console.log('Creating tag with payload:', {...});
console.log('Tag created successfully:', created);
Impact: Debug code in production.
if (!formData.slug || !formData.displayNameEn) {
toast.error('Slug and Display Name are required');
return;
}
Impact: Duplicated in create and update handlers.
Two-tab page for scraping new content and viewing import history.
const toast = { success, error }; // Helper wrapper
Unnecessary wrapper, should use destructured values directly.
useEffect(() => {
if (activeTab === 'LIST') {
loadImports();
}
}, [activeTab]);
Data not cached, reloads on every tab switch.
Landing page with stats cards and recent activity feed.
const StatCard: React.FC<{...}> = ({...}) => (...)
const RecentItem: React.FC<{...}> = ({...}) => (...)
Defined inside module but not memoized.
<div className="p-3 bg-amber-50 ...">
<h5>Missing Metadata</h5>
<p>15 records are missing 'Tala' information.</p>
</div>
Impact: Static content, not reflecting actual data.
Filtered queue for high-confidence batch auto-approval.
const params: any = {};
if (selectedBatchId) params.batchId = selectedBatchId;
Should use typed interface.
if (!confirm(`Auto-approve all ${imports.length} imports in this queue?`)) return;
Impact: Inconsistent UX, not accessible.
useEffect(() => {
loadBatches();
loadQueue(); // Called here
}, []);
useEffect(() => {
loadQueue(); // And here
}, [selectedBatchId, selectedQualityTier, confidenceMin]);
Initial load duplicated.
Simple list page with search and navigation to editor.
const STATUS_Styles: Record<string, string> = {
'PUBLISHED': '...',
// Not used anywhere in the component
};
<button className="..." disabled>Previous</button>
<button className="...">Next</button> // No onClick handler
Both are placeholder pages with “Coming Soon” messages. No issues to address until implementation.
| Pattern | Files |
|---|---|
console.error only |
Dashboard, KrithiList, ReferenceData |
toast.error |
TagsPage, ImportsPage, ImportReview |
alert() |
KrithiEditor |
Browser confirm() |
AutoApproveQueue, ImportReview, BulkImport |
No consistent pattern across pages:
| Issue | Occurrences |
|---|---|
any type props |
15+ |
as any assertions |
10+ |
| Untyped API responses | 8+ |
Record<string, any> |
5+ |
confirm() instead of accessible modalsReact.memo on any componentsuseCallback for handlersuseMemo for expensive computations (except BulkImport)any types across codebase| Metric | Current State |
|---|---|
| Total lines across pages | ~5,200 |
| Files needing refactor | 4 of 11 |
any type usages |
30+ |
| Console.log in code | 10+ |
| Missing TypeScript interfaces | 20+ |
| Components without memo | All |
| Accessible modals | 0 |
The frontend codebase is functional but exhibits inconsistent patterns, type safety gaps, and architectural issues primarily in the two largest files (KrithiEditor and ReferenceData). Addressing these would significantly improve maintainability, type safety, and developer experience. The smaller pages are reasonably well-structured and require only minor improvements.