added extra options

This commit is contained in:
Todd
2026-05-26 16:31:53 -04:00
parent f65d1555d2
commit f96e23a790
5 changed files with 24 additions and 14 deletions

View File

@ -64,7 +64,7 @@ export default function StepAccessControl({
{isRemote ? ( {isRemote ? (
'Varies by buttons' 'Varies by buttons'
) : ( ) : (
'C$' + ac.price.toLocaleString('en-CA') 'C$' + ac.price.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
)} )}
</div> </div>
</div> </div>
@ -110,7 +110,7 @@ export default function StepAccessControl({
{opt.id}-Button {opt.id}-Button
</div> </div>
<div className={`text-xs mt-0.5 ${isBtnSelected ? 'text-blue-500' : 'text-gray-400'}`}> <div className={`text-xs mt-0.5 ${isBtnSelected ? 'text-blue-500' : 'text-gray-400'}`}>
C${opt.price.toLocaleString('en-CA')} C${opt.price.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
</button> </button>
); );
@ -171,7 +171,7 @@ export default function StepAccessControl({
onClick={onNext} onClick={onNext}
className="px-6 py-2.5 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 transition-colors" className="px-6 py-2.5 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 transition-colors"
> >
Generate Quote Continue
</button> </button>
</div> </div>
</div> </div>

View File

@ -97,7 +97,7 @@ export default function StepGroundLoops({
</div> </div>
{s.additionalCost > 0 && ( {s.additionalCost > 0 && (
<div className="mt-1 text-sm font-medium text-blue-600"> <div className="mt-1 text-sm font-medium text-blue-600">
+C${s.additionalCost.toLocaleString('en-CA')} +C${s.additionalCost.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
)} )}
</div> </div>
@ -144,7 +144,7 @@ export default function StepGroundLoops({
{t.description} {t.description}
</div> </div>
<div className="mt-2 text-lg font-bold text-blue-600"> <div className="mt-2 text-lg font-bold text-blue-600">
C${t.price.toLocaleString('en-CA')} C${t.price.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
</div> </div>
<div <div
@ -169,7 +169,7 @@ export default function StepGroundLoops({
<svg className="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg className="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" /> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg> </svg>
<span>Includes 1 Loop Detector (+C${(detectors?.[0]?.price ?? 250).toLocaleString('en-CA')})</span> <span>Includes 1 Loop Detector (+C${(detectors?.[0]?.price ?? 250).toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })})</span>
</div> </div>
<div> <div>
<label className="block text-xs font-medium text-gray-500 mb-2"> <label className="block text-xs font-medium text-gray-500 mb-2">
@ -196,7 +196,7 @@ export default function StepGroundLoops({
</div> </div>
{s.additionalCost > 0 && ( {s.additionalCost > 0 && (
<div className={`text-xs mt-0.5 ${isSizeSelected ? 'text-blue-500' : 'text-gray-400'}`}> <div className={`text-xs mt-0.5 ${isSizeSelected ? 'text-blue-500' : 'text-gray-400'}`}>
+C${s.additionalCost.toLocaleString('en-CA')} +C${s.additionalCost.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
)} )}
{s.additionalCost === 0 && ( {s.additionalCost === 0 && (

View File

@ -74,7 +74,7 @@ export default function StepOperator({
</div> </div>
<div className="mt-2 flex items-center gap-2"> <div className="mt-2 flex items-center gap-2">
<span className="text-lg font-bold text-blue-600"> <span className="text-lg font-bold text-blue-600">
C{op.basePrice.toLocaleString('en-CA')} C${op.basePrice.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</span> </span>
<span className="text-xs text-gray-400">base</span> <span className="text-xs text-gray-400">base</span>
</div> </div>
@ -121,7 +121,7 @@ export default function StepOperator({
<div> <div>
<div className="font-semibold text-gray-900">{opt.name}</div> <div className="font-semibold text-gray-900">{opt.name}</div>
<div className="mt-1 text-lg font-bold text-blue-600"> <div className="mt-1 text-lg font-bold text-blue-600">
C${opt.price.toLocaleString('en-CA')} C${opt.price.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
</div> </div>
</div> </div>
@ -157,7 +157,7 @@ export default function StepOperator({
</div> </div>
<div className="text-right shrink-0 ml-4"> <div className="text-right shrink-0 ml-4">
<div className="text-lg font-bold text-blue-600"> <div className="text-lg font-bold text-blue-600">
C${part.unitPrice.toLocaleString('en-CA')} C${part.unitPrice.toLocaleString('en-CA', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div> </div>
<div <div
className={`shrink-0 w-5 h-5 rounded border-2 flex items-center justify-center ml-auto mt-1 transition-colors ${ className={`shrink-0 w-5 h-5 rounded border-2 flex items-center justify-center ml-auto mt-1 transition-colors ${
@ -184,13 +184,20 @@ export default function StepOperator({
{selected && ( {selected && (
<div className="flex items-center justify-between pt-6 border-t border-gray-200 mt-8"> <div className="flex items-center justify-between pt-6 border-t border-gray-200 mt-8">
<div className="text-sm text-gray-500"> <div className="text-sm text-gray-500">
{selectedOp?.optionalParts?.length > 0 {selectedOp?.armOptions?.length > 0 && !armChoice
? 'Please select an arm length'
: selectedOp?.optionalParts?.length > 0
? `${optionalParts.length} optional add-on${optionalParts.length !== 1 ? 's' : ''} selected` ? `${optionalParts.length} optional add-on${optionalParts.length !== 1 ? 's' : ''} selected`
: 'Operator selected'} : 'Operator selected'}
</div> </div>
<button <button
onClick={onNext} onClick={onNext}
className="px-6 py-2.5 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 transition-colors" disabled={selectedOp?.armOptions?.length > 0 && !armChoice}
className={`px-6 py-2.5 rounded-lg font-medium transition-colors ${
selectedOp?.armOptions?.length > 0 && !armChoice
? 'bg-gray-300 text-gray-500 cursor-not-allowed'
: 'bg-blue-600 text-white hover:bg-blue-700'
}`}
> >
Continue Continue
</button> </button>

View File

@ -25,7 +25,7 @@ const initialState = {
function reducer(state, action) { function reducer(state, action) {
switch (action.type) { switch (action.type) {
case 'SELECT_OPERATOR': case 'SELECT_OPERATOR':
return { ...state, operator: action.payload, armChoice: null, optionalParts: [], step: 2 }; return { ...state, operator: action.payload, armChoice: null, optionalParts: [] };
case 'SET_ARM_CHOICE': case 'SET_ARM_CHOICE':
return { ...state, armChoice: action.payload }; return { ...state, armChoice: action.payload };
case 'TOGGLE_OPTIONAL_PART': { case 'TOGGLE_OPTIONAL_PART': {
@ -102,7 +102,7 @@ function reducer(state, action) {
}, },
}; };
case 'GO_TO_STEP': case 'GO_TO_STEP':
return { ...state, step: Math.min(action.payload, 5) }; return { ...state, step: Math.max(1, Math.min(action.payload, 5)) };
case 'RESET': case 'RESET':
return { ...initialState }; return { ...initialState };
default: default:

View File

@ -20,6 +20,9 @@
{ "id": "mounting-post", "name": "Mounting Post", "qty": 1, "unitPrice": 85 }, { "id": "mounting-post", "name": "Mounting Post", "qty": 1, "unitPrice": 85 },
{ "id": "prep-cost", "name": "In House Prep Cost", "qty": 1, "unitPrice": 150 }, { "id": "prep-cost", "name": "In House Prep Cost", "qty": 1, "unitPrice": 150 },
{ "id": "shipping", "name": "Shipping Cost", "qty": 1, "unitPrice": 200 } { "id": "shipping", "name": "Shipping Cost", "qty": 1, "unitPrice": 200 }
],
"optionalParts": [
{ "id": "add-secondary-arm", "name": "Additional Secondary Arm Kit (LA500)", "qty": 1, "unitPrice": 485 }
] ]
}, },
{ {