export function contentWritingCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Content Writing Quote Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Content Type Section
const contentSection = form.addSubform('content', { title: '📝 Content Details' });
contentSection.addRow(row => {
row.addDropdown('contentType', {
label: 'Content Type',
options: [
{ id: 'blog-post', name: 'Blog Post' },
{ id: 'article', name: 'Article / Feature' },
{ id: 'web-copy', name: 'Website Copy' },
{ id: 'landing-page', name: 'Landing Page' },
{ id: 'product-description', name: 'Product Descriptions' },
{ id: 'email-copy', name: 'Email Copy / Newsletter' },
{ id: 'social-media', name: 'Social Media Content' },
{ id: 'whitepaper', name: 'Whitepaper / eBook' },
{ id: 'case-study', name: 'Case Study' },
{ id: 'press-release', name: 'Press Release' },
{ id: 'technical', name: 'Technical Documentation' }
],
defaultValue: 'blog-post',
isRequired: true
}, '1fr');
row.addInteger('wordCount', {
label: 'Word Count',
min: 100,
max: 50000,
defaultValue: 1500,
isRequired: true,
tooltip: 'Estimated total word count'
}, '1fr');
});
contentSection.addRow(row => {
row.addDropdown('industry', {
label: 'Industry/Niche',
options: [
{ id: 'general', name: 'General / Lifestyle' },
{ id: 'business', name: 'Business / Marketing' },
{ id: 'technology', name: 'Technology / SaaS' },
{ id: 'finance', name: 'Finance / Fintech' },
{ id: 'healthcare', name: 'Healthcare / Medical' },
{ id: 'legal', name: 'Legal' },
{ id: 'real-estate', name: 'Real Estate' },
{ id: 'education', name: 'Education' },
{ id: 'ecommerce', name: 'E-commerce / Retail' },
{ id: 'travel', name: 'Travel / Hospitality' }
],
defaultValue: 'general',
tooltip: 'Specialized niches may have higher rates'
}, '1fr');
row.addInteger('numberOfPieces', {
label: 'Number of Pieces',
min: 1,
max: 100,
defaultValue: 1,
tooltip: 'Bulk orders may qualify for discounts'
}, '1fr');
});
// Research & Complexity Section
const researchSection = form.addSubform('research', { title: '🔬 Research & Complexity' });
researchSection.addRow(row => {
row.addRadioButton('researchLevel', {
label: 'Research Required',
options: [
{ id: 'minimal', name: 'Minimal - General knowledge topic' },
{ id: 'moderate', name: 'Moderate - Some research needed' },
{ id: 'extensive', name: 'Extensive - Deep research required' },
{ id: 'expert', name: 'Expert - Interviews/primary research' }
],
defaultValue: 'moderate',
isRequired: true
});
});
researchSection.addRow(row => {
row.addRadioButton('complexity', {
label: 'Content Complexity',
options: [
{ id: 'simple', name: 'Simple - Straightforward topic' },
{ id: 'moderate', name: 'Moderate - Some technical elements' },
{ id: 'complex', name: 'Complex - Technical/specialized' },
{ id: 'expert', name: 'Expert - Highly technical/regulated' }
],
defaultValue: 'moderate',
isRequired: true
});
});
// Services Section
const servicesSection = form.addSubform('services', { title: '✨ Additional Services' });
servicesSection.addRow(row => {
row.addCheckbox('seoOptimization', {
label: 'SEO Optimization',
defaultValue: true,
tooltip: 'Keyword research and on-page SEO'
}, '1fr');
row.addCheckbox('metaDescriptions', {
label: 'Meta Titles & Descriptions',
defaultValue: false,
tooltip: 'SEO meta tags for each piece'
}, '1fr');
});
servicesSection.addRow(row => {
row.addCheckbox('imageSelection', {
label: 'Image Selection',
defaultValue: false,
tooltip: 'Sourcing relevant stock images'
}, '1fr');
row.addCheckbox('cmsUpload', {
label: 'CMS Upload & Formatting',
defaultValue: false,
tooltip: 'Upload to WordPress, etc.'
}, '1fr');
});
servicesSection.addRow(row => {
row.addCheckbox('socialSnippets', {
label: 'Social Media Snippets',
defaultValue: false,
tooltip: 'Promotional posts for sharing'
}, '1fr');
row.addCheckbox('contentBrief', {
label: 'Content Brief Creation',
defaultValue: false,
tooltip: 'Detailed outline and strategy'
}, '1fr');
});
// Timeline Section
const timelineSection = form.addSubform('timeline', { title: '⏰ Timeline & Revisions' });
timelineSection.addRow(row => {
row.addDropdown('turnaround', {
label: 'Turnaround Time',
options: [
{ id: 'flexible', name: 'Flexible (7+ days)' },
{ id: 'standard', name: 'Standard (5-7 days)' },
{ id: 'rush', name: 'Rush (3-4 days)' },
{ id: 'urgent', name: 'Urgent (1-2 days)' },
{ id: 'same-day', name: 'Same Day' }
],
defaultValue: 'standard',
tooltip: 'Rush orders incur additional fees'
}, '1fr');
row.addDropdown('revisions', {
label: 'Revision Rounds',
options: [
{ id: '1', name: '1 Round Included' },
{ id: '2', name: '2 Rounds Included' },
{ id: '3', name: '3 Rounds Included' },
{ id: 'unlimited', name: 'Unlimited Revisions' }
],
defaultValue: '2',
tooltip: 'Number of revision rounds included'
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Pricing Breakdown
const breakdownSection = form.addSubform('breakdown', { title: '📊 Quote Breakdown', isCollapsible: true });
breakdownSection.addRow(row => {
row.addPriceDisplay('baseRate', {
label: 'Base Rate',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
// Base per-word rates by content type
const rates: Record<string, number> = {
'blog-post': 0.15,
'article': 0.18,
'web-copy': 0.20,
'landing-page': 0.25,
'product-description': 0.12,
'email-copy': 0.20,
'social-media': 0.15,
'whitepaper': 0.30,
'case-study': 0.25,
'press-release': 0.22,
'technical': 0.35
};
const rate = rates[contentType] || 0.15;
return Math.round(wordCount * rate * 100) / 100;
},
variant: 'default'
}, '1fr');
row.addTextPanel('perWordRate', {
label: 'Per Word Rate',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const rates: Record<string, number> = {
'blog-post': 0.15,
'article': 0.18,
'web-copy': 0.20,
'landing-page': 0.25,
'product-description': 0.12,
'email-copy': 0.20,
'social-media': 0.15,
'whitepaper': 0.30,
'case-study': 0.25,
'press-release': 0.22,
'technical': 0.35
};
return `$${(Number(rates[contentType] || 0.15) || 0).toFixed(2)}/word`;
},
customStyles: { 'font-size': '1rem', 'text-align': 'center', 'color': '#475569' }
}, '1fr');
});
breakdownSection.addRow(row => {
row.addPriceDisplay('industryAdjustment', {
label: 'Industry Adjustment',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
const industry = contentSection.dropdown('industry')?.value() || 'general';
const rates: Record<string, number> = {
'blog-post': 0.15, 'article': 0.18, 'web-copy': 0.20, 'landing-page': 0.25,
'product-description': 0.12, 'email-copy': 0.20, 'social-media': 0.15,
'whitepaper': 0.30, 'case-study': 0.25, 'press-release': 0.22, 'technical': 0.35
};
const baseRate = (rates[contentType] || 0.15) * wordCount;
const industryMultipliers: Record<string, number> = {
'general': 0, 'business': 0.1, 'technology': 0.15, 'finance': 0.25,
'healthcare': 0.3, 'legal': 0.35, 'real-estate': 0.1, 'education': 0.05,
'ecommerce': 0.1, 'travel': 0.05
};
return Math.round(baseRate * (industryMultipliers[industry] || 0) * 100) / 100;
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('complexityAdjustment', {
label: 'Research & Complexity',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
const researchLevel = researchSection.radioButton('researchLevel')?.value() || 'moderate';
const complexity = researchSection.radioButton('complexity')?.value() || 'moderate';
const rates: Record<string, number> = {
'blog-post': 0.15, 'article': 0.18, 'web-copy': 0.20, 'landing-page': 0.25,
'product-description': 0.12, 'email-copy': 0.20, 'social-media': 0.15,
'whitepaper': 0.30, 'case-study': 0.25, 'press-release': 0.22, 'technical': 0.35
};
const baseRate = (rates[contentType] || 0.15) * wordCount;
const researchMultipliers: Record<string, number> = {
'minimal': 0, 'moderate': 0.1, 'extensive': 0.25, 'expert': 0.5
};
const complexityMultipliers: Record<string, number> = {
'simple': 0, 'moderate': 0.1, 'complex': 0.25, 'expert': 0.5
};
const adjustment = (researchMultipliers[researchLevel] || 0) + (complexityMultipliers[complexity] || 0);
return Math.round(baseRate * adjustment * 100) / 100;
},
variant: 'default'
}, '1fr');
});
breakdownSection.addRow(row => {
row.addPriceDisplay('addOns', {
label: 'Additional Services',
computedValue: () => {
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
let addOns = 0;
if (servicesSection.checkbox('seoOptimization')?.value()) addOns += 50;
if (servicesSection.checkbox('metaDescriptions')?.value()) addOns += 25;
if (servicesSection.checkbox('imageSelection')?.value()) addOns += 30;
if (servicesSection.checkbox('cmsUpload')?.value()) addOns += 35;
if (servicesSection.checkbox('socialSnippets')?.value()) addOns += 40;
if (servicesSection.checkbox('contentBrief')?.value()) addOns += 75;
return addOns;
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('rushFee', {
label: 'Rush Fee',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
const turnaround = timelineSection.dropdown('turnaround')?.value() || 'standard';
const rates: Record<string, number> = {
'blog-post': 0.15, 'article': 0.18, 'web-copy': 0.20, 'landing-page': 0.25,
'product-description': 0.12, 'email-copy': 0.20, 'social-media': 0.15,
'whitepaper': 0.30, 'case-study': 0.25, 'press-release': 0.22, 'technical': 0.35
};
const baseRate = (rates[contentType] || 0.15) * wordCount;
const rushMultipliers: Record<string, number> = {
'flexible': 0, 'standard': 0, 'rush': 0.25, 'urgent': 0.5, 'same-day': 1.0
};
return Math.round(baseRate * (rushMultipliers[turnaround] || 0) * 100) / 100;
},
variant: 'default'
}, '1fr');
});
// Quote Total
const quoteSection = form.addSubform('quote', { title: '💰 Your Quote', isCollapsible: false });
quoteSection.addRow(row => {
row.addPriceDisplay('pricePerPiece', {
label: 'Price per Piece',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
const industry = contentSection.dropdown('industry')?.value() || 'general';
const researchLevel = researchSection.radioButton('researchLevel')?.value() || 'moderate';
const complexity = researchSection.radioButton('complexity')?.value() || 'moderate';
const turnaround = timelineSection.dropdown('turnaround')?.value() || 'standard';
const revisions = timelineSection.dropdown('revisions')?.value() || '2';
// Base rate
const rates: Record<string, number> = {
'blog-post': 0.15, 'article': 0.18, 'web-copy': 0.20, 'landing-page': 0.25,
'product-description': 0.12, 'email-copy': 0.20, 'social-media': 0.15,
'whitepaper': 0.30, 'case-study': 0.25, 'press-release': 0.22, 'technical': 0.35
};
let baseRate = (rates[contentType] || 0.15) * wordCount;
// Industry multiplier
const industryMultipliers: Record<string, number> = {
'general': 1, 'business': 1.1, 'technology': 1.15, 'finance': 1.25,
'healthcare': 1.3, 'legal': 1.35, 'real-estate': 1.1, 'education': 1.05,
'ecommerce': 1.1, 'travel': 1.05
};
baseRate *= industryMultipliers[industry] || 1;
// Research & complexity
const researchMultipliers: Record<string, number> = { 'minimal': 1, 'moderate': 1.1, 'extensive': 1.25, 'expert': 1.5 };
const complexityMultipliers: Record<string, number> = { 'simple': 1, 'moderate': 1.1, 'complex': 1.25, 'expert': 1.5 };
baseRate *= researchMultipliers[researchLevel] || 1;
baseRate *= complexityMultipliers[complexity] || 1;
// Rush fees
const rushMultipliers: Record<string, number> = { 'flexible': 0.95, 'standard': 1, 'rush': 1.25, 'urgent': 1.5, 'same-day': 2 };
baseRate *= rushMultipliers[turnaround] || 1;
// Revisions
const revisionMultipliers: Record<string, number> = { '1': 1, '2': 1.1, '3': 1.2, 'unlimited': 1.35 };
baseRate *= revisionMultipliers[revisions] || 1;
// Add-ons
if (servicesSection.checkbox('seoOptimization')?.value()) baseRate += 50;
if (servicesSection.checkbox('metaDescriptions')?.value()) baseRate += 25;
if (servicesSection.checkbox('imageSelection')?.value()) baseRate += 30;
if (servicesSection.checkbox('cmsUpload')?.value()) baseRate += 35;
if (servicesSection.checkbox('socialSnippets')?.value()) baseRate += 40;
if (servicesSection.checkbox('contentBrief')?.value()) baseRate += 75;
return Math.round(baseRate * 100) / 100;
},
variant: 'success'
}, '1fr');
row.addPriceDisplay('totalQuote', {
label: 'Total Quote',
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
const numberOfPieces = contentSection.integer('numberOfPieces')?.value() || 1;
const industry = contentSection.dropdown('industry')?.value() || 'general';
const researchLevel = researchSection.radioButton('researchLevel')?.value() || 'moderate';
const complexity = researchSection.radioButton('complexity')?.value() || 'moderate';
const turnaround = timelineSection.dropdown('turnaround')?.value() || 'standard';
const revisions = timelineSection.dropdown('revisions')?.value() || '2';
const rates: Record<string, number> = {
'blog-post': 0.15, 'article': 0.18, 'web-copy': 0.20, 'landing-page': 0.25,
'product-description': 0.12, 'email-copy': 0.20, 'social-media': 0.15,
'whitepaper': 0.30, 'case-study': 0.25, 'press-release': 0.22, 'technical': 0.35
};
let baseRate = (rates[contentType] || 0.15) * wordCount;
const industryMultipliers: Record<string, number> = {
'general': 1, 'business': 1.1, 'technology': 1.15, 'finance': 1.25,
'healthcare': 1.3, 'legal': 1.35, 'real-estate': 1.1, 'education': 1.05,
'ecommerce': 1.1, 'travel': 1.05
};
baseRate *= industryMultipliers[industry] || 1;
const researchMultipliers: Record<string, number> = { 'minimal': 1, 'moderate': 1.1, 'extensive': 1.25, 'expert': 1.5 };
const complexityMultipliers: Record<string, number> = { 'simple': 1, 'moderate': 1.1, 'complex': 1.25, 'expert': 1.5 };
baseRate *= researchMultipliers[researchLevel] || 1;
baseRate *= complexityMultipliers[complexity] || 1;
const rushMultipliers: Record<string, number> = { 'flexible': 0.95, 'standard': 1, 'rush': 1.25, 'urgent': 1.5, 'same-day': 2 };
baseRate *= rushMultipliers[turnaround] || 1;
const revisionMultipliers: Record<string, number> = { '1': 1, '2': 1.1, '3': 1.2, 'unlimited': 1.35 };
baseRate *= revisionMultipliers[revisions] || 1;
if (servicesSection.checkbox('seoOptimization')?.value()) baseRate += 50;
if (servicesSection.checkbox('metaDescriptions')?.value()) baseRate += 25;
if (servicesSection.checkbox('imageSelection')?.value()) baseRate += 30;
if (servicesSection.checkbox('cmsUpload')?.value()) baseRate += 35;
if (servicesSection.checkbox('socialSnippets')?.value()) baseRate += 40;
if (servicesSection.checkbox('contentBrief')?.value()) baseRate += 75;
// Bulk discount
let total = baseRate * numberOfPieces;
if (numberOfPieces >= 10) total *= 0.85;
else if (numberOfPieces >= 5) total *= 0.9;
else if (numberOfPieces >= 3) total *= 0.95;
return Math.round(total * 100) / 100;
},
variant: 'large'
}, '1fr');
});
quoteSection.addRow(row => {
row.addTextPanel('bulkDiscount', {
computedValue: () => {
const numberOfPieces = contentSection.integer('numberOfPieces')?.value() || 1;
if (numberOfPieces >= 10) return '15% bulk discount applied!';
if (numberOfPieces >= 5) return '10% bulk discount applied!';
if (numberOfPieces >= 3) return '5% bulk discount applied!';
return 'Order 3+ pieces for bulk discounts';
},
customStyles: { 'font-size': '0.9rem', 'color': '#059669', 'text-align': 'center' }
});
});
// Summary Section
const summarySection = form.addSubform('summary', {
title: '📋 Summary',
isCollapsible: false,
sticky: 'bottom'
});
summarySection.addRow(row => {
row.addTextPanel('summaryText', {
computedValue: () => {
const contentType = contentSection.dropdown('contentType')?.value() || 'blog-post';
const wordCount = contentSection.integer('wordCount')?.value() || 1500;
const numberOfPieces = contentSection.integer('numberOfPieces')?.value() || 1;
const typeLabels: Record<string, string> = {
'blog-post': 'blog post', 'article': 'article', 'web-copy': 'web copy page',
'landing-page': 'landing page', 'product-description': 'product description',
'email-copy': 'email', 'social-media': 'social media pack', 'whitepaper': 'whitepaper',
'case-study': 'case study', 'press-release': 'press release', 'technical': 'technical document'
};
const pieceText = numberOfPieces === 1 ? typeLabels[contentType] || 'piece' : `${typeLabels[contentType] || 'piece'}s`;
return `${numberOfPieces} ${pieceText} × ${wordCount.toLocaleString()} words each`;
},
customStyles: { 'font-size': '0.95rem', 'font-weight': '500', 'text-align': 'center', 'color': '#1e293b' }
});
});
summarySection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'Final pricing may vary based on specific requirements. Quote is valid for 30 days.',
customStyles: { 'font-size': '0.8rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Request Content'
});
}