Refactor InstallationOptions component to simplify logic and improve accessibility
- Removed unused functions for cleaning up the codebase. - Updated installation description handling for better clarity and user experience. - Enhanced button accessibility with aria-pressed attribute and improved styling. - Streamlined price display logic for clearer presentation of payment options.
This commit is contained in:
parent
da91a51323
commit
67bad7819a
@ -14,40 +14,6 @@ interface InstallationOptionsProps {
|
||||
showSkus?: boolean;
|
||||
}
|
||||
|
||||
function getCleanName(
|
||||
installation: InternetInstallationCatalogItem,
|
||||
installationTerm: InstallationTerm | null
|
||||
): string {
|
||||
const baseName = installation.name.replace(/^(NTT\s*)?Installation\s*Fee\s*/i, "");
|
||||
switch (installationTerm) {
|
||||
case "One-time":
|
||||
return "Installation Fee (Single Payment)";
|
||||
case "12-Month":
|
||||
return "Installation Fee (12-Month Plan)";
|
||||
case "24-Month":
|
||||
return "Installation Fee (24-Month Plan)";
|
||||
default:
|
||||
return baseName || installation.name;
|
||||
}
|
||||
}
|
||||
|
||||
function getCleanDescription(
|
||||
installationTerm: InstallationTerm | null,
|
||||
description: string | undefined
|
||||
): string {
|
||||
const baseDescription = (description || "").replace(/^(NTT\s*)?Installation\s*Fee\s*/i, "");
|
||||
switch (installationTerm) {
|
||||
case "One-time":
|
||||
return "Pay the full installation fee upfront.";
|
||||
case "12-Month":
|
||||
return "Spread installation cost over 12 monthly payments.";
|
||||
case "24-Month":
|
||||
return "Spread installation cost over 24 monthly payments.";
|
||||
default:
|
||||
return baseDescription || "Select this installation option.";
|
||||
}
|
||||
}
|
||||
|
||||
function getPriceLabel(installation: InternetInstallationCatalogItem): string {
|
||||
const priceInfo = getDisplayPrice(installation);
|
||||
if (!priceInfo) {
|
||||
@ -87,54 +53,61 @@ export function InstallationOptions({
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{sortedInstallations.map(installation => {
|
||||
const installationTerm = installation.catalogMetadata?.installationTerm ?? null;
|
||||
const isSelected = selectedInstallationSku === installation.sku;
|
||||
const priceInfo = getDisplayPrice(installation);
|
||||
const installationTerm = installation.catalogMetadata?.installationTerm ?? null;
|
||||
const description =
|
||||
installation.description ||
|
||||
(installationTerm === "12-Month"
|
||||
? "Spread the installation fee across 12 payments."
|
||||
: installationTerm === "24-Month"
|
||||
? "Spread the installation fee across 24 payments."
|
||||
: "Pay the full installation fee once.");
|
||||
|
||||
return (
|
||||
<button
|
||||
key={installation.sku}
|
||||
type="button"
|
||||
onClick={() => onInstallationSelect(installation)}
|
||||
className={`p-6 rounded-xl border-2 text-left transition-all duration-200 ${
|
||||
aria-pressed={isSelected}
|
||||
className={`p-6 rounded-xl border-2 text-left transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 ${
|
||||
isSelected
|
||||
? "border-blue-500 bg-blue-50 shadow-lg transform scale-105"
|
||||
: "border-gray-200 hover:border-blue-300 hover:bg-blue-50 hover:shadow-md"
|
||||
? "border-blue-500 bg-blue-50"
|
||||
: "border-gray-200 hover:border-blue-400 hover:bg-blue-50"
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h4 className="font-semibold text-gray-900">
|
||||
{getCleanName(installation, installationTerm)}
|
||||
</h4>
|
||||
<h4 className="font-semibold text-gray-900">{installation.name}</h4>
|
||||
<div
|
||||
className={`w-4 h-4 rounded-full border-2 ${
|
||||
className={`w-4 h-4 aspect-square rounded-full border-2 flex items-center justify-center ${
|
||||
isSelected ? "bg-blue-500 border-blue-500" : "border-gray-300"
|
||||
}`}
|
||||
>
|
||||
{isSelected && (
|
||||
<svg className="w-2 h-2 text-white m-0.5" fill="currentColor" viewBox="0 0 8 8">
|
||||
<circle cx="4" cy="4" r="3" />
|
||||
</svg>
|
||||
<div className="w-2 h-2 bg-white rounded-full"></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mb-3">
|
||||
{getCleanDescription(installationTerm, installation.description)}
|
||||
</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs text-gray-500">
|
||||
{installation.billingCycle === "Monthly" ? "Monthly payment" : "One-time payment"}
|
||||
</span>
|
||||
{priceInfo ? (
|
||||
<span
|
||||
className={`text-lg font-bold ${
|
||||
installation.billingCycle === "Monthly" ? "text-blue-600" : "text-green-600"
|
||||
}`}
|
||||
>
|
||||
{getPriceLabel(installation)}
|
||||
<p className="text-sm text-gray-600 mb-3">{description}</p>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs text-gray-500">
|
||||
{installation.billingCycle === "Monthly" ? "Monthly payment" : "One-time payment"}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-sm text-gray-400">Price not available</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-end">
|
||||
{priceInfo ? (
|
||||
<span
|
||||
className={`text-lg font-bold ${
|
||||
installation.billingCycle === "Monthly" ? "text-blue-600" : "text-green-600"
|
||||
}`}
|
||||
>
|
||||
{getPriceLabel(installation)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-sm text-gray-400">Price not available</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{showSkus && <div className="text-xs text-gray-400 mt-2">SKU: {installation.sku}</div>}
|
||||
</button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user