export function ndaAgreementCalculator(form: FormTs) {
// NDA types and base fees
const ndaTypes: Record<string, { baseFee: number, hours: number }> = {
'standard-unilateral': { baseFee: 350, hours: 2 },
'standard-mutual': { baseFee: 450, hours: 2.5 },
'employee': { baseFee: 300, hours: 1.5 },
'contractor': { baseFee: 350, hours: 2 },
'investor': { baseFee: 550, hours: 3 },
'merger-acquisition': { baseFee: 1200, hours: 6 },
'technology': { baseFee: 650, hours: 4 },
'healthcare': { baseFee: 750, hours: 4 },
'financial': { baseFee: 700, hours: 4 },
'custom': { baseFee: 600, hours: 3.5 }
};
// Attorney levels
const attorneyRates: Record<string, number> = {
'paralegal': 95,
'associate': 275,
'senior-associate': 375,
'partner': 500
};
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'NDA / Confidentiality Agreement Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// NDA Type Section
const typeSection = form.addSubform('ndaType', { title: '๐ Agreement Type' });
typeSection.addRow(row => {
row.addDropdown('type', {
label: 'NDA Type',
options: [
{ id: 'standard-unilateral', name: 'Standard Unilateral NDA' },
{ id: 'standard-mutual', name: 'Standard Mutual NDA' },
{ id: 'employee', name: 'Employee Confidentiality Agreement' },
{ id: 'contractor', name: 'Contractor / Vendor NDA' },
{ id: 'investor', name: 'Investor / Due Diligence NDA' },
{ id: 'merger-acquisition', name: 'M&A / Transaction NDA' },
{ id: 'technology', name: 'Technology / IP NDA' },
{ id: 'healthcare', name: 'Healthcare / HIPAA NDA' },
{ id: 'financial', name: 'Financial Services NDA' },
{ id: 'custom', name: 'Custom NDA' }
],
defaultValue: 'standard-mutual',
isRequired: true
}, '1fr');
row.addDropdown('direction', {
label: 'Information Flow',
options: [
{ id: 'unilateral', name: 'One-way (Discloser โ Recipient)' },
{ id: 'mutual', name: 'Two-way (Mutual Exchange)' }
],
defaultValue: 'mutual',
isRequired: true
}, '1fr');
});
typeSection.addRow(row => {
row.addDropdown('purpose', {
label: 'Purpose of NDA',
options: [
{ id: 'business-discussion', name: 'Business Discussions' },
{ id: 'employment', name: 'Employment / HR' },
{ id: 'partnership', name: 'Partnership Evaluation' },
{ id: 'investment', name: 'Investment / Funding' },
{ id: 'vendor', name: 'Vendor / Supplier Relationship' },
{ id: 'technology', name: 'Technology Licensing' },
{ id: 'merger', name: 'Merger / Acquisition' },
{ id: 'other', name: 'Other' }
],
defaultValue: 'business-discussion',
isRequired: true
}, '1fr');
row.addInteger('partyCount', {
label: 'Number of Parties',
min: 2,
max: 10,
defaultValue: 2
}, '1fr');
});
// Scope Section
const scopeSection = form.addSubform('scope', { title: '๐ Scope & Provisions' });
scopeSection.addRow(row => {
row.addDropdown('duration', {
label: 'Confidentiality Period',
options: [
{ id: '1-year', name: '1 Year' },
{ id: '2-years', name: '2 Years' },
{ id: '3-years', name: '3 Years' },
{ id: '5-years', name: '5 Years' },
{ id: 'indefinite', name: 'Indefinite / Perpetual' }
],
defaultValue: '2-years',
isRequired: true
}, '1fr');
row.addDropdown('jurisdictions', {
label: 'Governing Jurisdiction',
options: [
{ id: 'single-state', name: 'Single State' },
{ id: 'multi-state', name: 'Multi-State (+$150)' },
{ id: 'international', name: 'International (+$350)' }
],
defaultValue: 'single-state',
isRequired: true
}, '1fr');
});
scopeSection.addRow(row => {
row.addCheckbox('nonCompete', {
label: 'Include Non-Compete Clause (+$200)',
defaultValue: false
}, '1fr');
row.addCheckbox('nonSolicitation', {
label: 'Include Non-Solicitation (+$150)',
defaultValue: false
}, '1fr');
});
scopeSection.addRow(row => {
row.addCheckbox('ipAssignment', {
label: 'IP Assignment Provisions (+$250)',
defaultValue: false
}, '1fr');
row.addCheckbox('dataProtection', {
label: 'Data Protection / GDPR Clauses (+$200)',
defaultValue: false
}, '1fr');
});
scopeSection.addRow(row => {
row.addCheckbox('injunctiveRelief', {
label: 'Injunctive Relief Provisions (+$100)',
defaultValue: true
}, '1fr');
row.addCheckbox('returnOfMaterials', {
label: 'Return of Materials Clause',
defaultValue: true
}, '1fr');
});
// Service Options Section
const serviceSection = form.addSubform('service', { title: '๐ Service Options' });
serviceSection.addRow(row => {
row.addDropdown('level', {
label: 'Attorney Level',
options: [
{ id: 'paralegal', name: 'Paralegal Review ($95/hr)' },
{ id: 'associate', name: 'Associate Attorney ($275/hr)' },
{ id: 'senior-associate', name: 'Senior Associate ($375/hr)' },
{ id: 'partner', name: 'Partner ($500/hr)' }
],
defaultValue: 'associate',
isRequired: true
}, '1fr');
row.addDropdown('urgency', {
label: 'Turnaround Time',
options: [
{ id: 'standard', name: 'Standard (5-7 days)' },
{ id: 'expedited', name: 'Expedited (2-3 days) (+30%)' },
{ id: 'rush', name: 'Rush (24-48 hrs) (+60%)' },
{ id: 'same-day', name: 'Same Day (+100%)' }
],
defaultValue: 'standard',
isRequired: true
}, '1fr');
});
serviceSection.addRow(row => {
row.addDropdown('serviceType', {
label: 'Service Type',
options: [
{ id: 'template', name: 'Use Standard Template' },
{ id: 'custom', name: 'Custom Drafting (+50%)' },
{ id: 'review-only', name: 'Review Existing NDA (-25%)' }
],
defaultValue: 'template',
isRequired: true
}, '1fr');
row.addInteger('quantity', {
label: 'Number of NDAs Needed',
min: 1,
max: 50,
defaultValue: 1
}, '1fr');
});
// Additional Services
const addonsSection = form.addSubform('addons', { title: 'โจ Additional Services' });
addonsSection.addRow(row => {
row.addCheckbox('negotiationSupport', {
label: 'Negotiation Support (+$350)',
defaultValue: false
}, '1fr');
row.addCheckbox('executionSupport', {
label: 'Execution Coordination (+$150)',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('templatePackage', {
label: 'Template Package (3 variants) (+$500)',
defaultValue: false
}, '1fr');
row.addCheckbox('trainingSession', {
label: 'Training Session (30 min) (+$200)',
defaultValue: false
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Summary Section
const summarySection = form.addSubform('summary', { title: '๐ฐ Cost Estimate', isCollapsible: false });
summarySection.addRow(row => {
row.addPriceDisplay('baseFee', {
label: 'Base NDA Fee',
computedValue: () => {
const type = typeSection.dropdown('type')?.value() || 'standard-mutual';
const serviceType = serviceSection.dropdown('serviceType')?.value() || 'template';
const direction = typeSection.dropdown('direction')?.value() || 'mutual';
let fee = ndaTypes[type]?.baseFee ?? 0;
// Mutual vs unilateral adjustment
if (direction === 'mutual' && !type.includes('mutual')) {
fee *= 1.2;
}
// Service type adjustment
if (serviceType === 'custom') fee *= 1.5;
if (serviceType === 'review-only') fee *= 0.75;
return Math.round(fee);
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('provisionsFee', {
label: 'Additional Provisions',
computedValue: () => {
let total = 0;
if (scopeSection.checkbox('nonCompete')?.value()) total += 200;
if (scopeSection.checkbox('nonSolicitation')?.value()) total += 150;
if (scopeSection.checkbox('ipAssignment')?.value()) total += 250;
if (scopeSection.checkbox('dataProtection')?.value()) total += 200;
if (scopeSection.checkbox('injunctiveRelief')?.value()) total += 100;
const jurisdictions = scopeSection.dropdown('jurisdictions')?.value() || 'single-state';
if (jurisdictions === 'multi-state') total += 150;
if (jurisdictions === 'international') total += 350;
return total;
},
variant: 'default',
prefix: '+'
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('urgencyFee', {
label: 'Urgency Premium',
computedValue: () => {
const type = typeSection.dropdown('type')?.value() || 'standard-mutual';
const urgency = serviceSection.dropdown('urgency')?.value() || 'standard';
const serviceType = serviceSection.dropdown('serviceType')?.value() || 'template';
let baseFee = ndaTypes[type]?.baseFee ?? 0;
if (serviceType === 'custom') baseFee *= 1.5;
if (serviceType === 'review-only') baseFee *= 0.75;
const urgencyMultipliers: Record<string, number> = {
'standard': 0, 'expedited': 0.3, 'rush': 0.6, 'same-day': 1.0
};
return Math.round(baseFee * (urgencyMultipliers[urgency] || 0));
},
variant: 'default',
prefix: '+'
}, '1fr');
row.addPriceDisplay('addonsFee', {
label: 'Additional Services',
computedValue: () => {
let total = 0;
if (addonsSection.checkbox('negotiationSupport')?.value()) total += 350;
if (addonsSection.checkbox('executionSupport')?.value()) total += 150;
if (addonsSection.checkbox('templatePackage')?.value()) total += 500;
if (addonsSection.checkbox('trainingSession')?.value()) total += 200;
return total;
},
variant: 'default',
prefix: '+'
}, '1fr');
});
const finalSection = form.addSubform('final', {
title: '๐งพ Total Estimate',
isCollapsible: false,
sticky: 'bottom'
});
finalSection.addRow(row => {
row.addPriceDisplay('perNdaCost', {
label: 'Cost Per NDA',
computedValue: () => {
const type = typeSection.dropdown('type')?.value() || 'standard-mutual';
const serviceType = serviceSection.dropdown('serviceType')?.value() || 'template';
const direction = typeSection.dropdown('direction')?.value() || 'mutual';
const urgency = serviceSection.dropdown('urgency')?.value() || 'standard';
const partyCount = typeSection.integer('partyCount')?.value() || 2;
let fee = ndaTypes[type]?.baseFee ?? 0;
if (direction === 'mutual' && !type.includes('mutual')) fee *= 1.2;
if (serviceType === 'custom') fee *= 1.5;
if (serviceType === 'review-only') fee *= 0.75;
// Additional parties
if (partyCount > 2) fee += (partyCount - 2) * 100;
// Provisions
if (scopeSection.checkbox('nonCompete')?.value()) fee += 200;
if (scopeSection.checkbox('nonSolicitation')?.value()) fee += 150;
if (scopeSection.checkbox('ipAssignment')?.value()) fee += 250;
if (scopeSection.checkbox('dataProtection')?.value()) fee += 200;
if (scopeSection.checkbox('injunctiveRelief')?.value()) fee += 100;
const jurisdictions = scopeSection.dropdown('jurisdictions')?.value() || 'single-state';
if (jurisdictions === 'multi-state') fee += 150;
if (jurisdictions === 'international') fee += 350;
// Urgency
const urgencyMultipliers: Record<string, number> = {
'standard': 1.0, 'expedited': 1.3, 'rush': 1.6, 'same-day': 2.0
};
fee *= urgencyMultipliers[urgency] || 1.0;
return Math.round(fee);
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('totalFee', {
label: 'Total Estimate',
computedValue: () => {
const type = typeSection.dropdown('type')?.value() || 'standard-mutual';
const serviceType = serviceSection.dropdown('serviceType')?.value() || 'template';
const direction = typeSection.dropdown('direction')?.value() || 'mutual';
const urgency = serviceSection.dropdown('urgency')?.value() || 'standard';
const quantity = serviceSection.integer('quantity')?.value() || 1;
const partyCount = typeSection.integer('partyCount')?.value() || 2;
let fee = ndaTypes[type]?.baseFee ?? 0;
if (direction === 'mutual' && !type.includes('mutual')) fee *= 1.2;
if (serviceType === 'custom') fee *= 1.5;
if (serviceType === 'review-only') fee *= 0.75;
if (partyCount > 2) fee += (partyCount - 2) * 100;
if (scopeSection.checkbox('nonCompete')?.value()) fee += 200;
if (scopeSection.checkbox('nonSolicitation')?.value()) fee += 150;
if (scopeSection.checkbox('ipAssignment')?.value()) fee += 250;
if (scopeSection.checkbox('dataProtection')?.value()) fee += 200;
if (scopeSection.checkbox('injunctiveRelief')?.value()) fee += 100;
const jurisdictions = scopeSection.dropdown('jurisdictions')?.value() || 'single-state';
if (jurisdictions === 'multi-state') fee += 150;
if (jurisdictions === 'international') fee += 350;
const urgencyMultipliers: Record<string, number> = {
'standard': 1.0, 'expedited': 1.3, 'rush': 1.6, 'same-day': 2.0
};
fee *= urgencyMultipliers[urgency] || 1.0;
// Quantity discount
let totalFee = fee * quantity;
if (quantity >= 5) totalFee *= 0.9;
if (quantity >= 10) totalFee *= 0.85;
// Add-ons (one-time)
if (addonsSection.checkbox('negotiationSupport')?.value()) totalFee += 350;
if (addonsSection.checkbox('executionSupport')?.value()) totalFee += 150;
if (addonsSection.checkbox('templatePackage')?.value()) totalFee += 500;
if (addonsSection.checkbox('trainingSession')?.value()) totalFee += 200;
return Math.round(totalFee);
},
variant: 'large'
}, '1fr');
});
finalSection.addRow(row => {
row.addTextPanel('volumeDiscount', {
computedValue: () => {
const quantity = serviceSection.integer('quantity')?.value() || 1;
if (quantity >= 10) return '15% volume discount applied';
if (quantity >= 5) return '10% volume discount applied';
return 'Order 5+ for 10% discount, 10+ for 15% discount';
},
customStyles: { 'font-size': '0.9rem', 'color': '#059669', 'text-align': 'center' }
});
});
finalSection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'This is an estimate only. Final fees confirmed after reviewing your specific requirements. NDA complexity may affect final pricing.',
customStyles: { 'font-size': '0.8rem', 'color': '#64748b', 'font-style': 'italic' }
});
});
form.configureSubmitButton({
label: 'Get NDA Quote'
});
}