I see this error with the app, reported by NextJS, please fix it. The er

This commit is contained in:
Leon Serfaty G
2025-07-17 10:51:28 +00:00
parent 2ff1f5da7a
commit 5f1c344406
5 changed files with 148 additions and 7 deletions
@@ -1,3 +1,4 @@
"use client"; "use client";
import React, { useState, useTransition, useMemo } from 'react'; import React, { useState, useTransition, useMemo } from 'react';
@@ -10,7 +11,8 @@ import { Step6Animations } from './step-6-animations';
import { Step7Illustrations } from './step-7-illustrations'; import { Step7Illustrations } from './step-7-illustrations';
import { Step8Branding } from './step-8-branding'; import { Step8Branding } from './step-8-branding';
import { Step9AdditionalFeatures } from './step-9-additional-features'; import { Step9AdditionalFeatures } from './step-9-additional-features';
import { Step10Results, calculateTotalHours } from './step-10-results'; import { Step10ShoppingCart } from './step-10-shopping-cart';
import { Step11Results, calculateTotalHours } from './step-11-results';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
@@ -33,6 +35,7 @@ export type FormData = {
illustrations: IllustrationSelection; illustrations: IllustrationSelection;
branding: BrandingSelection; branding: BrandingSelection;
additionalFeatures: string[]; additionalFeatures: string[];
shoppingCart: boolean | null;
}; };
export function CostEstimatorForm() { export function CostEstimatorForm() {
@@ -52,6 +55,7 @@ export function CostEstimatorForm() {
}, },
branding: null, branding: null,
additionalFeatures: [], additionalFeatures: [],
shoppingCart: null,
}); });
const [isPending, startTransition] = useTransition(); const [isPending, startTransition] = useTransition();
@@ -87,6 +91,7 @@ export function CostEstimatorForm() {
}, },
branding: null, branding: null,
additionalFeatures: [], additionalFeatures: [],
shoppingCart: null,
}); });
setCurrentStep(1); setCurrentStep(1);
} }
@@ -177,7 +182,16 @@ export function CostEstimatorForm() {
); );
case 10: case 10:
return ( return (
<Step10Results <Step10ShoppingCart
onNext={handleNextStep}
onBack={handlePrevStep}
onUpdateData={handleUpdateFormData}
formData={formData}
/>
);
case 11:
return (
<Step11Results
formData={formData} formData={formData}
onReset={handleReset} onReset={handleReset}
estimatedHours={estimatedHours} estimatedHours={estimatedHours}
@@ -0,0 +1,123 @@
"use client";
import type { FormData } from './cost-estimator-form';
import { Button } from '@/components/ui/button';
import { Gauge } from 'lucide-react';
import React, { useState, useMemo } from 'react';
type Step10Props = {
onNext: () => void;
onBack: () => void;
onUpdateData: (data: Partial<FormData>) => void;
formData: FormData;
};
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': 70, 'brush-up': 30, 'logo-only': 20, 'none': 0 };
const featuresHoursMap: Record<string, number> = {
'registration': 10,
'member-profiles': 20,
'admin-panel': 28,
'crm-integration': 31,
'dashboard': 40,
'blog': 35,
'event-scheduling': 35,
'reservations': 35,
'chat-live-chat': 50,
'image-video-galleries': 5,
'location-based': 40,
'live-streaming': 55,
};
const shoppingCartHours = 45;
const calculateHours = (
formData: FormData,
shoppingCart: boolean | null
): 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;
const additionalFeaturesHours = formData.additionalFeatures.reduce((total, feature) => {
return total + (featuresHoursMap[feature] || 0);
}, 0);
const cartHours = shoppingCart ? shoppingCartHours : 0;
return pageHours + stageHours + designHours + animationHours + illustrationTotalHours + brandingH + additionalFeaturesHours + cartHours;
};
export function Step10ShoppingCart({ onNext, onBack, onUpdateData, formData }: Step10Props) {
const [selectedOption, setSelectedOption] = useState<boolean | null>(formData.shoppingCart);
const handleSelect = (option: boolean) => {
setSelectedOption(option);
onUpdateData({ shoppingCart: option });
};
const estimatedHours = useMemo(() => {
return calculateHours(formData, selectedOption);
}, [selectedOption, formData]);
return (
<div className="flex flex-col items-start">
<h2 className="font-headline text-3xl font-bold tracking-tight text-center w-full">Do you need a shopping cart for buying multiple products with one check-out?</h2>
<div className="mt-8 grid w-full grid-cols-1 gap-4 md:grid-cols-2">
<Button
variant={selectedOption === true ? 'default' : 'outline'}
className="w-full justify-start p-6 text-lg"
onClick={() => handleSelect(true)}
>
Yes
</Button>
<Button
variant={selectedOption === false ? 'default' : 'outline'}
className="w-full justify-start p-6 text-lg"
onClick={() => handleSelect(false)}
>
No
</Button>
</div>
<div className="mt-16 flex w-full items-center justify-between">
<div className="flex items-center gap-2">
<Gauge className="h-6 w-6 text-primary" />
<span className="font-headline text-lg font-bold">{estimatedHours}+ hours</span>
</div>
<div className="flex items-center gap-4">
<Button variant="ghost" onClick={onBack}>Back</Button>
<div className="flex items-center gap-2">
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" />
</div>
<Button onClick={onNext} disabled={selectedOption === null}>
Submit
</Button>
</div>
</div>
</div>
);
}
@@ -1,4 +1,3 @@
"use client"; "use client";
import type { FormData } from './cost-estimator-form'; import type { FormData } from './cost-estimator-form';
@@ -7,7 +6,7 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/com
import { PartyPopper, RefreshCw } from 'lucide-react'; import { PartyPopper, RefreshCw } from 'lucide-react';
import React from 'react'; import React from 'react';
type Step10Props = { type Step11Props = {
formData: FormData; formData: FormData;
onReset: () => void; onReset: () => void;
estimatedHours: number; estimatedHours: number;
@@ -30,6 +29,7 @@ const featuresHoursMap: Record<string, number> = {
'location-based': 40, 'location-based': 40,
'live-streaming': 55, 'live-streaming': 55,
}; };
const shoppingCartHours = 45;
export const calculateTotalHours = (formData: FormData): number => { export const calculateTotalHours = (formData: FormData): number => {
@@ -55,12 +55,14 @@ export const calculateTotalHours = (formData: FormData): number => {
return total + (featuresHoursMap[feature] || 0); return total + (featuresHoursMap[feature] || 0);
}, 0); }, 0);
return pageHours + stageHours + designHours + animationHours + illustrationTotalHours + brandingH + additionalFeaturesHours; const cartHours = formData.shoppingCart ? shoppingCartHours : 0;
return pageHours + stageHours + designHours + animationHours + illustrationTotalHours + brandingH + additionalFeaturesHours + cartHours;
}; };
const HOURLY_RATE = 75; // Example hourly rate in USD const HOURLY_RATE = 75; // Example hourly rate in USD
export function Step10Results({ formData, onReset, estimatedHours }: Step10Props) { export function Step11Results({ formData, onReset, estimatedHours }: Step11Props) {
const estimatedCost = estimatedHours * HOURLY_RATE; const estimatedCost = estimatedHours * HOURLY_RATE;
@@ -102,6 +102,7 @@ export function Step8Branding({ onNext, onBack, onUpdateData, formData }: Step8P
<div className="w-10 h-2 bg-primary rounded-full" /> <div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" /> <div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-muted rounded-full" /> <div className="w-10 h-2 bg-muted rounded-full" />
<div className="w-10 h-2 bg-muted rounded-full" />
</div> </div>
<Button onClick={onNext} disabled={selected === null}> <Button onClick={onNext} disabled={selected === null}>
Next Next
@@ -126,9 +126,10 @@ export function Step9AdditionalFeatures({ onNext, onBack, onUpdateData, formData
<div className="w-10 h-2 bg-primary rounded-full" /> <div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" /> <div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-primary rounded-full" /> <div className="w-10 h-2 bg-primary rounded-full" />
<div className="w-10 h-2 bg-muted rounded-full" />
</div> </div>
<Button onClick={onNext}> <Button onClick={onNext}>
See Results Next
</Button> </Button>
</div> </div>
</div> </div>