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:
barsa 2025-10-22 14:58:54 +09:00
parent da91a51323
commit 67bad7819a

View File

@ -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>