import type { OfferTemplate } from '~/composables/useOfferSuggestor'; export const offerTemplates: OfferTemplate[] = [ { id: 'pitch-polish', name: 'Pitch Polish', type: 'clinic', skillRequirements: ['writing', 'design'], problemTargets: ['unclear-pitch', 'grant-budget-help'], scope: [ 'Comprehensive deck review and analysis', 'Rewrite key sections for clarity and impact', '90-minute live presentation coaching session', 'Final edit pass with visual polish' ], defaultDays: 2, defaultHours: { writing: 6, design: 6, pm: 2 }, whyThisTemplate: [ 'Combines writing expertise with design polish', 'Time-boxed format keeps scope manageable', 'Live coaching session builds confidence', 'Immediate impact on funding success' ], riskTemplate: 'Client may resist feedback on core concept or messaging' }, { id: 'brand-store-page-sprint', name: 'Brand/Store Page Sprint', type: 'sprint', skillRequirements: ['design', 'dev'], problemTargets: ['need-landing-store-page', 'marketing-assets'], scope: [ 'Develop clear messaging and brand voice', 'Design and build one-page marketing site', 'Create store page assets and layout', 'Implement responsive design and basic SEO' ], defaultDays: 7, defaultHours: { design: 12, writing: 6, dev: 10, pm: 4 }, whyThisTemplate: [ 'Full-stack approach from concept to deployment', 'Combines brand strategy with technical execution', 'Creates immediate market presence', 'Scalable foundation for future marketing' ], riskTemplate: 'Scope creep around additional pages or complex integrations' }, { id: 'dev-sprint', name: 'Dev Sprint', type: 'sprint', skillRequirements: ['dev'], problemTargets: ['vertical-slice', 'tech-debt'], scope: [ 'Backlog triage and feature prioritization', 'Implement 1-2 focused features or fixes', 'Create demo build for stakeholder review', 'Document changes and deployment process' ], defaultDays: 7, defaultHours: { dev: 24, qa: 4, pm: 4 }, whyThisTemplate: [ 'Focused development with clear deliverables', 'Includes quality assurance and project management', 'Demo build provides immediate feedback opportunity', 'Manageable scope reduces technical risk' ], riskTemplate: 'Technical complexity may exceed initial estimates' }, { id: 'maintenance-retainer', name: 'Maintenance Retainer', type: 'retainer', skillRequirements: ['dev', 'pm'], problemTargets: ['launch-checklist'], scope: [ 'Handle small fixes and bug reports', 'Apply security and dependency updates', 'Provide technical support and guidance', 'Monthly progress reports and recommendations' ], defaultDays: 30, // Monthly defaultHours: { dev: 6, pm: 2 }, whyThisTemplate: [ 'Predictable monthly income stream', 'Builds long-term client relationships', 'Low-risk work with defined boundaries', 'Efficient use of development skills' ], riskTemplate: 'Client expectations may exceed allocated hours' } ]; /** * Lightweight matching rules for offer templates */ export function matchTemplateToInput( selectedSkills: string[], selectedProblems: string[] ): OfferTemplate[] { const matches: OfferTemplate[] = []; // Pitch Polish: Writing + Design + pitch/funding problems if (selectedSkills.includes('writing') && selectedSkills.includes('design')) { if (selectedProblems.includes('unclear-pitch') || selectedProblems.includes('grant-budget-help')) { matches.push(offerTemplates[0]); // Pitch Polish } } // Brand/Store Page: Design + Dev + website/marketing problems if (selectedSkills.includes('design') && selectedSkills.includes('dev')) { if (selectedProblems.includes('need-landing-store-page') || selectedProblems.includes('marketing-assets')) { matches.push(offerTemplates[1]); // Brand/Store Page Sprint } } // Dev Sprint: Dev + development-related problems if (selectedSkills.includes('dev')) { if (selectedProblems.includes('vertical-slice') || selectedProblems.includes('tech-debt')) { matches.push(offerTemplates[2]); // Dev Sprint } } // Maintenance Retainer: Dev + PM + launch/maintenance problems if (selectedSkills.includes('dev') && selectedSkills.includes('pm')) { if (selectedProblems.includes('launch-checklist') || matches.length === 0) { // Also use as fallback matches.push(offerTemplates[3]); // Maintenance Retainer } } return matches; } /** * Get default hour allocation for a template based on available members */ export function getTemplateHours( template: OfferTemplate, availableSkills: string[] ): Array<{ skill: string; hours: number }> { const allocations: Array<{ skill: string; hours: number }> = []; // Convert template hours to skill-based allocations if (template.defaultHours) { Object.entries(template.defaultHours).forEach(([skill, hours]) => { if (availableSkills.includes(skill)) { allocations.push({ skill, hours }); } }); } return allocations; } /** * Calculate total hours for a template */ export function getTemplateTotalHours(template: OfferTemplate): number { if (!template.defaultHours) return template.defaultDays * 8; // Fallback: 8 hours per day return Object.values(template.defaultHours).reduce((sum, hours) => sum + hours, 0); }