diff --git a/src/components/cost-estimator/cost-estimator-form.tsx b/src/components/cost-estimator/cost-estimator-form.tsx index 232eb7c..1287038 100644 --- a/src/components/cost-estimator/cost-estimator-form.tsx +++ b/src/components/cost-estimator/cost-estimator-form.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useState, useTransition } from 'react'; +import React, { useState, useTransition, useMemo } from 'react'; import { Step1ProjectType } from './step-1-project-type'; import { Step2ServiceType } from './step-2-service-type'; import { Step3ProjectStage } from './step-3-project-stage'; @@ -9,6 +9,7 @@ import { Step5PageCount } from './step-5-page-count'; import { Step6Animations } from './step-6-animations'; import { Step7Illustrations } from './step-7-illustrations'; import { Step8Branding } from './step-8-branding'; +import { Step9Results, calculateTotalHours } from './step-9-results'; import { Card, CardContent } from '@/components/ui/card'; import { AnimatePresence, motion } from 'framer-motion'; @@ -67,6 +68,28 @@ export function CostEstimatorForm() { setFormData((prev) => ({ ...prev, ...newData })); }; + const handleReset = () => { + setFormData({ + projectType: null, + serviceType: null, + projectStage: 0, + designProcess: null, + pageCount: 0, + animatedElements: null, + illustrations: { + has2d: false, + is2dAnimated: null, + has3d: false, + is3dAnimated: null, + }, + branding: null, + }); + setCurrentStep(1); + } + + const estimatedHours = useMemo(() => calculateTotalHours(formData), [formData]); + + const renderStep = () => { switch (currentStep) { case 1: @@ -139,6 +162,14 @@ export function CostEstimatorForm() { formData={formData} /> ); + case 9: + return ( + + ) default: return ( { setSelected(option); onUpdateData({ branding: option }); - onNext(); }; const estimatedHours = useMemo(() => { diff --git a/src/components/cost-estimator/step-9-results.tsx b/src/components/cost-estimator/step-9-results.tsx new file mode 100644 index 0000000..6cb979b --- /dev/null +++ b/src/components/cost-estimator/step-9-results.tsx @@ -0,0 +1,74 @@ +"use client"; + +import type { FormData, IllustrationSelection, BrandingSelection } from './cost-estimator-form'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +import { PartyPopper, RefreshCw } from 'lucide-react'; +import React from 'react'; + +type Step9Props = { + formData: FormData; + onReset: () => void; + estimatedHours: number; +}; + +const designHoursMap = { custom: 60, mockups: 30, existing: 0 }; +const illustrationHoursMap = { '2d_static': 10, '2d_animated': 25, '3d_static': 20, '3d_animated': 40 }; +const brandingHoursMap = { 'full-cycle': 80, 'brush-up': 40, 'logo-only': 20, 'none': 0 }; + +export const calculateTotalHours = (formData: FormData): number => { + const pageVal = formData.pageCount === 10 ? 50 : (formData.pageCount + 1) * 5 - 1; + const pageHours = pageVal * 6; + const stageHours = Math.round((formData.projectStage / 100) * 50); + const designHours = formData.designProcess ? designHoursMap[formData.designProcess] : 0; + const animationHours = formData.animatedElements ? 30 : 0; + + let illustrationTotalHours = 0; + if (formData.illustrations.has2d) { + if (formData.illustrations.is2dAnimated === 'static') illustrationTotalHours += illustrationHoursMap['2d_static']; + if (formData.illustrations.is2dAnimated === 'animated') illustrationTotalHours += illustrationHoursMap['2d_animated']; + } + if (formData.illustrations.has3d) { + if (formData.illustrations.is3dAnimated === 'static') illustrationTotalHours += illustrationHoursMap['3d_static']; + if (formData.illustrations.is3dAnimated === 'animated') illustrationTotalHours += illustrationHoursMap['3d_animated']; + } + + const brandingH = formData.branding ? (brandingHoursMap[formData.branding] ?? 0) : 0; + + return pageHours + stageHours + designHours + animationHours + illustrationTotalHours + brandingH; +}; + +const HOURLY_RATE = 75; // Example hourly rate in USD + +export function Step9Results({ formData, onReset, estimatedHours }: Step9Props) { + + const estimatedCost = estimatedHours * HOURLY_RATE; + + return ( + + + + + Your Estimate is Ready! + Based on your selections, here's our initial estimate. + + + + Estimated Cost + This is an approximation. Final cost may vary. + + + ${estimatedCost.toLocaleString()} + ({estimatedHours}+ hours) + + + + + + + Start Over + + + + ); +}
Based on your selections, here's our initial estimate.
${estimatedCost.toLocaleString()}
({estimatedHours}+ hours)