Clean up and optimize frontend code - Remove temporary files: verify-auth.js, frontend_test_results.txt, test-output.css - Remove empty directories: src/pages, src/hooks - Remove unused dependencies: @tanstack/react-query, react-hook-form - Remove unused utility file: parseCIMData.ts - Clean up commented mock data and unused imports in App.tsx - Maintain all working functionality while reducing bundle size
This commit is contained in:
@@ -12,14 +12,12 @@
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.8.4",
|
||||
"axios": "^1.6.2",
|
||||
"clsx": "^2.0.0",
|
||||
"lucide-react": "^0.294.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-hook-form": "^7.48.2",
|
||||
"react-router-dom": "^6.20.1",
|
||||
"tailwind-merge": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -19,64 +19,6 @@ import {
|
||||
TrendingUp
|
||||
} from 'lucide-react';
|
||||
import { cn } from './utils/cn';
|
||||
// import { parseCIMReviewData } from './utils/parseCIMData';
|
||||
|
||||
// Mock data for demonstration
|
||||
// const mockDocuments = [
|
||||
// {
|
||||
// id: '1',
|
||||
// name: 'Sample CIM Document 1',
|
||||
// originalName: 'sample_cim_1.pdf',
|
||||
// status: 'completed' as const,
|
||||
// uploadedAt: '2024-01-15T10:30:00Z',
|
||||
// processedAt: '2024-01-15T10:35:00Z',
|
||||
// uploadedBy: 'John Doe',
|
||||
// fileSize: 2048576,
|
||||
// pageCount: 25,
|
||||
// summary: 'This is a sample CIM document for demonstration purposes.',
|
||||
// },
|
||||
// {
|
||||
// id: '2',
|
||||
// name: 'Sample CIM Document 2',
|
||||
// originalName: 'sample_cim_2.pdf',
|
||||
// status: 'processing' as const,
|
||||
// uploadedAt: '2024-01-15T11:00:00Z',
|
||||
// uploadedBy: 'Jane Smith',
|
||||
// fileSize: 1536000,
|
||||
// pageCount: 18,
|
||||
// },
|
||||
// ];
|
||||
|
||||
// const mockExtractedData = {
|
||||
// companyName: 'Sample Company Inc.',
|
||||
// industry: 'Technology',
|
||||
// revenue: '$50M',
|
||||
// ebitda: '$8M',
|
||||
// employees: '150',
|
||||
// founded: '2010',
|
||||
// location: 'San Francisco, CA',
|
||||
// summary: 'A technology company focused on innovative solutions.',
|
||||
// keyMetrics: {
|
||||
// 'Revenue Growth': '25%',
|
||||
// 'EBITDA Margin': '16%',
|
||||
// 'Employee Count': '150',
|
||||
// },
|
||||
// financials: {
|
||||
// revenue: ['$40M', '$45M', '$50M'],
|
||||
// ebitda: ['$6M', '$7M', '$8M'],
|
||||
// margins: ['15%', '15.6%', '16%'],
|
||||
// },
|
||||
// risks: [
|
||||
// 'Market competition',
|
||||
// 'Technology disruption',
|
||||
// 'Talent retention',
|
||||
// ],
|
||||
// opportunities: [
|
||||
// 'Market expansion',
|
||||
// 'Product diversification',
|
||||
// 'Strategic partnerships',
|
||||
// ],
|
||||
// };
|
||||
|
||||
// Dashboard component
|
||||
const Dashboard: React.FC = () => {
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
/**
|
||||
* Parse BPCP CIM Review Template data from generated summary
|
||||
* Converts the markdown-like format into structured data
|
||||
*/
|
||||
export function parseCIMReviewData(generatedSummary: string): any {
|
||||
if (!generatedSummary) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const data: any = {};
|
||||
|
||||
// Parse each section
|
||||
const sections = generatedSummary.split(/\*\*\([A-Z]\)\s+/);
|
||||
|
||||
sections.forEach(section => {
|
||||
if (!section.trim()) return;
|
||||
|
||||
const lines = section.split('\n').filter(line => line.trim());
|
||||
if (lines.length === 0) return;
|
||||
|
||||
const sectionTitle = lines[0].replace(/\*\*/, '').trim();
|
||||
const sectionKey = getSectionKey(sectionTitle);
|
||||
|
||||
if (sectionKey) {
|
||||
data[sectionKey] = parseSection(sectionTitle, lines.slice(1));
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function getSectionKey(sectionTitle: string): string | null {
|
||||
const sectionMap: Record<string, string> = {
|
||||
'Deal Overview': 'dealOverview',
|
||||
'Business Description': 'businessDescription',
|
||||
'Market & Industry Analysis': 'marketIndustryAnalysis',
|
||||
'Financial Summary': 'financialSummary',
|
||||
'Management Team Overview': 'managementTeamOverview',
|
||||
'Preliminary Investment Thesis': 'preliminaryInvestmentThesis',
|
||||
'Key Questions & Next Steps': 'keyQuestionsNextSteps'
|
||||
};
|
||||
|
||||
return sectionMap[sectionTitle] || null;
|
||||
}
|
||||
|
||||
function parseSection(sectionTitle: string, lines: string[]): any {
|
||||
const section: any = {};
|
||||
|
||||
switch (sectionTitle) {
|
||||
case 'Deal Overview':
|
||||
return parseDealOverview(lines);
|
||||
case 'Business Description':
|
||||
return parseBusinessDescription(lines);
|
||||
case 'Market & Industry Analysis':
|
||||
return parseMarketIndustryAnalysis(lines);
|
||||
case 'Financial Summary':
|
||||
return parseFinancialSummary(lines);
|
||||
case 'Management Team Overview':
|
||||
return parseManagementTeamOverview(lines);
|
||||
case 'Preliminary Investment Thesis':
|
||||
return parsePreliminaryInvestmentThesis(lines);
|
||||
case 'Key Questions & Next Steps':
|
||||
return parseKeyQuestionsNextSteps(lines);
|
||||
default:
|
||||
return section;
|
||||
}
|
||||
}
|
||||
|
||||
function parseDealOverview(lines: string[]): any {
|
||||
const overview: any = {};
|
||||
|
||||
lines.forEach(line => {
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'TargetCompanyName':
|
||||
overview.targetCompanyName = cleanValue;
|
||||
break;
|
||||
case 'Industry/Sector':
|
||||
overview.industrySector = cleanValue;
|
||||
break;
|
||||
case 'Geography(HQ&KeyOperations)':
|
||||
overview.geography = cleanValue;
|
||||
break;
|
||||
case 'DealSource':
|
||||
overview.dealSource = cleanValue;
|
||||
break;
|
||||
case 'TransactionType':
|
||||
overview.transactionType = cleanValue;
|
||||
break;
|
||||
case 'DateCIMReceived':
|
||||
overview.dateCIMReceived = cleanValue;
|
||||
break;
|
||||
case 'DateReviewed':
|
||||
overview.dateReviewed = cleanValue;
|
||||
break;
|
||||
case 'Reviewer(s)':
|
||||
overview.reviewers = cleanValue;
|
||||
break;
|
||||
case 'CIMPageCount':
|
||||
overview.cimPageCount = cleanValue;
|
||||
break;
|
||||
case 'StatedReasonforSale':
|
||||
overview.statedReasonForSale = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return overview;
|
||||
}
|
||||
|
||||
function parseBusinessDescription(lines: string[]): any {
|
||||
const description: any = {
|
||||
customerBaseOverview: {},
|
||||
keySupplierOverview: {}
|
||||
};
|
||||
|
||||
|
||||
lines.forEach(line => {
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'CoreOperationsSummary':
|
||||
description.coreOperationsSummary = cleanValue;
|
||||
break;
|
||||
case 'KeyProducts/Services&RevenueMix':
|
||||
description.keyProductsServices = cleanValue;
|
||||
break;
|
||||
case 'UniqueValueProposition':
|
||||
description.uniqueValueProposition = cleanValue;
|
||||
break;
|
||||
case 'KeyCustomerSegments':
|
||||
description.customerBaseOverview.keyCustomerSegments = cleanValue;
|
||||
break;
|
||||
case 'CustomerConcentration':
|
||||
description.customerBaseOverview.customerConcentrationRisk = cleanValue;
|
||||
break;
|
||||
case 'TypicalContractLength':
|
||||
description.customerBaseOverview.typicalContractLength = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
function parseMarketIndustryAnalysis(lines: string[]): any {
|
||||
const analysis: any = {
|
||||
competitiveLandscape: {}
|
||||
};
|
||||
|
||||
lines.forEach(line => {
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'EstimatedMarketSize':
|
||||
analysis.estimatedMarketSize = cleanValue;
|
||||
break;
|
||||
case 'EstimatedMarketGrowthRate':
|
||||
analysis.estimatedMarketGrowthRate = cleanValue;
|
||||
break;
|
||||
case 'KeyIndustryTrends&Drivers':
|
||||
analysis.keyIndustryTrends = cleanValue;
|
||||
break;
|
||||
case 'KeyCompetitors':
|
||||
analysis.competitiveLandscape.keyCompetitors = cleanValue;
|
||||
break;
|
||||
case 'Target\'sMarketPosition':
|
||||
analysis.competitiveLandscape.targetMarketPosition = cleanValue;
|
||||
break;
|
||||
case 'BasisofCompetition':
|
||||
analysis.competitiveLandscape.basisOfCompetition = cleanValue;
|
||||
break;
|
||||
case 'BarrierstoEntry':
|
||||
analysis.barriersToEntry = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return analysis;
|
||||
}
|
||||
|
||||
function parseFinancialSummary(lines: string[]): any {
|
||||
const summary: any = {
|
||||
financials: {
|
||||
fy3: {}, fy2: {}, fy1: {}, ltm: {}
|
||||
}
|
||||
};
|
||||
|
||||
let currentTable = false;
|
||||
let tableData: string[] = [];
|
||||
|
||||
lines.forEach(line => {
|
||||
if (line.includes('|Metric|')) {
|
||||
currentTable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTable && line.includes('|')) {
|
||||
tableData.push(line);
|
||||
} else if (currentTable) {
|
||||
currentTable = false;
|
||||
// Parse table data
|
||||
const parsedTable = parseFinancialTable(tableData);
|
||||
if (parsedTable) {
|
||||
summary.financials = parsedTable;
|
||||
}
|
||||
}
|
||||
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'KeyFinancialNotes':
|
||||
summary.keyFinancialNotes = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
function parseFinancialTable(tableData: string[]): any {
|
||||
if (tableData.length < 2) return null;
|
||||
|
||||
const periods = ['fy3', 'fy2', 'fy1', 'ltm'];
|
||||
const financials: any = {};
|
||||
|
||||
periods.forEach(period => {
|
||||
financials[period] = {
|
||||
revenue: '',
|
||||
revenueGrowth: '',
|
||||
grossProfit: '',
|
||||
grossMargin: '',
|
||||
ebitda: '',
|
||||
ebitdaMargin: ''
|
||||
};
|
||||
});
|
||||
|
||||
// Simple parsing - in a real implementation, you'd want more robust table parsing
|
||||
return financials;
|
||||
}
|
||||
|
||||
function parseManagementTeamOverview(lines: string[]): any {
|
||||
const overview: any = {};
|
||||
|
||||
lines.forEach(line => {
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'KeyLeadersIdentified':
|
||||
overview.keyLeaders = cleanValue;
|
||||
break;
|
||||
case 'InitialAssessment':
|
||||
overview.managementQualityAssessment = cleanValue;
|
||||
break;
|
||||
case 'Management\'sPost-TransactionRole':
|
||||
overview.postTransactionIntentions = cleanValue;
|
||||
break;
|
||||
case 'OrganizationalStructure':
|
||||
overview.organizationalStructure = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return overview;
|
||||
}
|
||||
|
||||
function parsePreliminaryInvestmentThesis(lines: string[]): any {
|
||||
const thesis: any = {};
|
||||
|
||||
lines.forEach(line => {
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'KeyAttractions':
|
||||
thesis.keyAttractions = cleanValue;
|
||||
break;
|
||||
case 'PotentialRisks':
|
||||
thesis.potentialRisks = cleanValue;
|
||||
break;
|
||||
case 'ValueCreationLevers':
|
||||
thesis.valueCreationLevers = cleanValue;
|
||||
break;
|
||||
case 'AlignmentwithFundStrategy':
|
||||
thesis.alignmentWithFundStrategy = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return thesis;
|
||||
}
|
||||
|
||||
function parseKeyQuestionsNextSteps(lines: string[]): any {
|
||||
const questions: any = {};
|
||||
|
||||
lines.forEach(line => {
|
||||
const match = line.match(/-\s*`([^:]+):`\s*(.+)/);
|
||||
if (match) {
|
||||
const [, key, value] = match;
|
||||
const cleanKey = key.trim().replace(/\s+/g, '');
|
||||
const cleanValue = value.trim();
|
||||
|
||||
switch (cleanKey) {
|
||||
case 'CriticalQuestions':
|
||||
questions.criticalQuestions = cleanValue;
|
||||
break;
|
||||
case 'KeyMissingInformation':
|
||||
questions.missingInformation = cleanValue;
|
||||
break;
|
||||
case 'PreliminaryRecommendation':
|
||||
questions.preliminaryRecommendation = cleanValue;
|
||||
break;
|
||||
case 'Rationale':
|
||||
questions.rationaleForRecommendation = cleanValue;
|
||||
break;
|
||||
case 'ProposedNextSteps':
|
||||
questions.proposedNextSteps = cleanValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return questions;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user