import * as fs from 'node:fs'; import * as path from 'node:path'; import * as readline from 'node:readline/promises'; import { fileURLToPath } from 'node:url'; import { createElement } from 'react'; import { renderToFile } from '@react-pdf/renderer'; import { calculatePositions, calculateTotals } from '../src/logic/pricing/calculator.js'; import { CombinedQuotePDF } from '../src/components/CombinedQuotePDF.js'; import { initialState, PRICING } from '../src/logic/pricing/constants.js'; import { getTechDetails, getPrinciples } from '../src/logic/content-provider.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); async function main() { const args = process.argv.slice(2); const isInteractive = args.includes('--interactive') || args.includes('-I'); const isEstimationOnly = args.includes('--estimation') || args.includes('-E'); const inputPath = args.find((_, i) => args[i - 1] === '--input' || args[i - 1] === '-i'); let state = { ...initialState }; if (inputPath) { const rawData = fs.readFileSync(path.resolve(process.cwd(), inputPath), 'utf8'); const diskState = JSON.parse(rawData); state = { ...state, ...diskState }; } if (isInteractive) { state = await runWizard(state); } // Final confirmation of data needed for PDF if (!state.name || !state.email) { console.warn('⚠️ Missing recipient name or email. Document might look incomplete.'); } const totals = calculateTotals(state, PRICING); const { totalPrice, monthlyPrice, totalPagesCount } = totals; const finalOutputPath = generateDefaultPath(state); const outputDir = path.dirname(finalOutputPath); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } // Resolve assets for the PDF const assetsDir = path.resolve(process.cwd(), 'src/assets'); const headerIcon = path.join(assetsDir, 'logo/Icon White Transparent.png'); const footerLogo = path.join(assetsDir, 'logo/Logo Black Transparent.png'); console.log(`🚀 Generating PDF: ${finalOutputPath}`); const estimationProps = { state, totalPrice, monthlyPrice, totalPagesCount, pricing: PRICING, headerIcon, footerLogo }; await renderToFile( createElement(CombinedQuotePDF as any, { estimationProps, techDetails: getTechDetails(), principles: getPrinciples(), mode: isEstimationOnly ? 'estimation' : 'full', showAgbs: !isEstimationOnly // AGBS only for full quotes }) as any, finalOutputPath ); console.log('✅ Done!'); } async function runWizard(state: any) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); console.log('\n--- Mintel Quote Generator Wizard ---\n'); const ask = async (q: string, def?: string) => { const answer = await rl.question(`${q}${def ? ` [${def}]` : ''}: `); return answer || def || ''; }; const selectOne = async (q: string, options: { id: string, label: string }[]) => { console.log(`\n${q}:`); options.forEach((opt, i) => console.log(`${i + 1}) ${opt.label}`)); const answer = await rl.question('Selection (number): '); const idx = parseInt(answer) - 1; return options[idx]?.id || options[0].id; }; state.name = await ask('Recipient Name', state.name); state.email = await ask('Recipient Email', state.email); state.companyName = await ask('Company Name', state.companyName); state.projectType = await selectOne('Project Type', [ { id: 'website', label: 'Website' }, { id: 'web-app', label: 'Web App' } ]); if (state.projectType === 'website') { state.websiteTopic = await ask('Website Topic', state.websiteTopic); // Simplified for now, in a real tool we'd loop through all options } rl.close(); return state; } function generateDefaultPath(state: any) { const now = new Date(); const month = now.toISOString().slice(0, 7); const day = now.toISOString().slice(0, 10); // Add seconds and minutes for 100% unique names without collision const time = now.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' }).replace(/:/g, '-'); const company = (state.companyName || state.name || 'Unknown').replace(/[^a-z0-9]/gi, '_'); return path.join(process.cwd(), 'out', 'estimations', month, `${day}_${time}_${company}_${state.projectType}.pdf`); } main().catch(err => { console.error('❌ Error:', err); process.exit(1); });