|
|
"use client";
|
|
|
|
|
|
import { useState } from "react";
|
|
|
import { FLOCK_UI } from "@/lib/flock/ui-labels";
|
|
|
import type { FlockDisplayLine } from "@/modules/flock/quote-storage";
|
|
|
import type {
|
|
|
FlockCarrierOption,
|
|
|
FlockCheckoutTier,
|
|
|
FlockFlexibilityKey,
|
|
|
FlockFlexibilityOption,
|
|
|
FlockPricingOptionsType,
|
|
|
} from "@/lib/flock/flock-checkout-selection";
|
|
|
import { flockFlexibilityKeyLabel } from "@/lib/flock/flock-checkout-selection";
|
|
|
import { ErrorBanner } from "@/components/ui/error-banner";
|
|
|
import { LoadingSpinner } from "@/components/ui/loading-spinner";
|
|
|
|
|
|
export type FlockLoggedInQuoteSidebarStep = "select" | "details";
|
|
|
|
|
|
export type FlockFlexibilityByTier = Partial<
|
|
|
Record<FlockCheckoutTier, FlockFlexibilityOption[]>
|
|
|
>;
|
|
|
|
|
|
export type FlockCarriersByTier = Partial<
|
|
|
Record<FlockCheckoutTier, FlockCarrierOption[]>
|
|
|
>;
|
|
|
|
|
|
export interface FlockLoggedInQuoteSidebarProps {
|
|
|
lines: FlockDisplayLine[];
|
|
|
reference?: string | null;
|
|
|
/** 首价同步的两侧灵活性价 */
|
|
|
flexibilityByTier?: FlockFlexibilityByTier;
|
|
|
/** 首价同步的承运商列表(Standard LTL) */
|
|
|
carriersByTier?: FlockCarriersByTier;
|
|
|
selectedTier: FlockCheckoutTier | null;
|
|
|
selectedFlexibility?: FlockFlexibilityKey | null;
|
|
|
selectedCarrier?: string | null;
|
|
|
flexBusy?: boolean;
|
|
|
flexMessage?: string | null;
|
|
|
checkoutBusy?: boolean;
|
|
|
checkoutMessage?: string | null;
|
|
|
/** 已确认继续填写二级(或无 hold)后可结账 */
|
|
|
detailsUnlocked?: boolean;
|
|
|
onSelectTier: (tier: FlockCheckoutTier) => void;
|
|
|
onSelectFlexibility: (key: FlockFlexibilityKey) => void;
|
|
|
onSelectCarrier: (carrierName: string) => void;
|
|
|
onCheckout: () => void;
|
|
|
onReset?: () => void;
|
|
|
}
|
|
|
|
|
|
function formatUsd(n: number): string {
|
|
|
return n.toLocaleString("en-US", {
|
|
|
style: "currency",
|
|
|
currency: "USD",
|
|
|
maximumFractionDigits: 0,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function formatUsdExact(n: number): string {
|
|
|
return n.toLocaleString("en-US", {
|
|
|
style: "currency",
|
|
|
currency: "USD",
|
|
|
minimumFractionDigits: 2,
|
|
|
maximumFractionDigits: 2,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
function FeatureRow({
|
|
|
ok,
|
|
|
text,
|
|
|
}: {
|
|
|
ok: boolean;
|
|
|
text: string;
|
|
|
}) {
|
|
|
return (
|
|
|
<li className="flex gap-2 text-sm leading-snug text-text-primary">
|
|
|
<span
|
|
|
className={
|
|
|
"mt-0.5 shrink-0 text-base font-bold " +
|
|
|
(ok ? "text-emerald-600" : "text-text-disabled")
|
|
|
}
|
|
|
aria-hidden
|
|
|
>
|
|
|
{ok ? "✓" : "×"}
|
|
|
</span>
|
|
|
<span className={ok ? "" : "text-text-secondary"}>{text}</span>
|
|
|
</li>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
function PricingOptionsModal({
|
|
|
tier,
|
|
|
reference,
|
|
|
optionsType,
|
|
|
options,
|
|
|
carrierOptions,
|
|
|
selectedFlexibility,
|
|
|
selectedCarrier,
|
|
|
busy,
|
|
|
message,
|
|
|
onClose,
|
|
|
onSelectFlexibility,
|
|
|
onSelectCarrier,
|
|
|
}: {
|
|
|
tier: FlockCheckoutTier;
|
|
|
reference?: string | null;
|
|
|
optionsType: FlockPricingOptionsType;
|
|
|
options: FlockFlexibilityOption[];
|
|
|
carrierOptions: FlockCarrierOption[];
|
|
|
selectedFlexibility?: FlockFlexibilityKey | null;
|
|
|
selectedCarrier?: string | null;
|
|
|
busy?: boolean;
|
|
|
message?: string | null;
|
|
|
onClose: () => void;
|
|
|
onSelectFlexibility: (key: FlockFlexibilityKey) => void;
|
|
|
onSelectCarrier: (carrierName: string) => void;
|
|
|
}) {
|
|
|
const tierName =
|
|
|
tier === "flock_direct" ? FLOCK_UI.directName : FLOCK_UI.standardName;
|
|
|
const isCarriers = optionsType === "carriers";
|
|
|
const empty =
|
|
|
!busy &&
|
|
|
(isCarriers ? carrierOptions.length === 0 : options.length === 0);
|
|
|
|
|
|
return (
|
|
|
<div
|
|
|
className="fixed inset-0 z-[60] flex items-center justify-center bg-black/45 p-4"
|
|
|
role="dialog"
|
|
|
aria-modal="true"
|
|
|
aria-labelledby="flock-pricing-options-title"
|
|
|
data-testid="flock-pricing-options-modal"
|
|
|
>
|
|
|
<div className="max-h-[90vh] w-full max-w-3xl overflow-y-auto rounded-xl border border-border bg-white shadow-xl">
|
|
|
<div className="border-b border-border px-5 py-4">
|
|
|
<h2
|
|
|
id="flock-pricing-options-title"
|
|
|
className="text-base font-semibold text-text-primary"
|
|
|
>
|
|
|
{reference
|
|
|
? `#${reference} ${FLOCK_UI.pricingOptionsHeading}`
|
|
|
: FLOCK_UI.pricingOptionsHeading}
|
|
|
</h2>
|
|
|
<button
|
|
|
type="button"
|
|
|
onClick={onClose}
|
|
|
className="mt-3 text-sm font-medium text-text-primary underline-offset-2 hover:underline"
|
|
|
data-testid="flock-pricing-go-back"
|
|
|
>
|
|
|
← {FLOCK_UI.goBackToShipping}
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
<div className="space-y-4 px-5 py-5">
|
|
|
<h3 className="text-lg font-semibold text-text-primary">
|
|
|
{isCarriers
|
|
|
? FLOCK_UI.selectPreferredCarrier
|
|
|
: FLOCK_UI.isPickupFlexible}
|
|
|
</h3>
|
|
|
{!isCarriers ? (
|
|
|
<div className="rounded-md bg-[#1a1a1a] px-4 py-2.5 text-sm font-semibold text-white">
|
|
|
{tierName}
|
|
|
</div>
|
|
|
) : null}
|
|
|
|
|
|
{busy ? (
|
|
|
<div className="flex items-center gap-2 rounded-md border border-border bg-surface px-3 py-4 text-sm text-text-secondary">
|
|
|
<LoadingSpinner />
|
|
|
{message ||
|
|
|
(isCarriers
|
|
|
? "正在加载承运商报价…"
|
|
|
: "正在加载灵活性报价…")}
|
|
|
</div>
|
|
|
) : null}
|
|
|
|
|
|
{empty ? (
|
|
|
<p className="text-sm text-error">
|
|
|
{message ||
|
|
|
(isCarriers
|
|
|
? "暂无承运商报价,请稍后重试"
|
|
|
: "暂无该档灵活性报价,请稍后重试")}
|
|
|
</p>
|
|
|
) : null}
|
|
|
|
|
|
{!busy && !isCarriers && options.length > 0 ? (
|
|
|
<div className="overflow-hidden rounded-lg border border-border">
|
|
|
<div className="grid grid-cols-[1.3fr_1.2fr_1fr_auto] gap-2 border-b border-border bg-surface px-3 py-2 text-[11px] font-medium uppercase tracking-wide text-text-secondary">
|
|
|
<span>{FLOCK_UI.flexColFlexibility}</span>
|
|
|
<span>{FLOCK_UI.flexColPickup}</span>
|
|
|
<span>{FLOCK_UI.flexColDeliver}</span>
|
|
|
<span className="text-right">{FLOCK_UI.flexColRate}</span>
|
|
|
</div>
|
|
|
<ul className="divide-y divide-border">
|
|
|
{options.map((opt) => {
|
|
|
const active = selectedFlexibility === opt.key;
|
|
|
return (
|
|
|
<li key={opt.key}>
|
|
|
<button
|
|
|
type="button"
|
|
|
data-testid={`flock-flex-option-${opt.key}`}
|
|
|
onClick={() => onSelectFlexibility(opt.key)}
|
|
|
className={
|
|
|
"grid w-full grid-cols-[1.3fr_1.2fr_1fr_auto] items-center gap-2 px-3 py-3.5 text-left text-sm transition " +
|
|
|
(active
|
|
|
? "bg-emerald-50 ring-1 ring-inset ring-emerald-400"
|
|
|
: "hover:bg-surface")
|
|
|
}
|
|
|
>
|
|
|
<span className="flex items-center gap-2 font-medium text-text-primary">
|
|
|
<span
|
|
|
className={
|
|
|
"inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full border " +
|
|
|
(active
|
|
|
? "border-emerald-600 bg-emerald-600"
|
|
|
: "border-border bg-white")
|
|
|
}
|
|
|
aria-hidden
|
|
|
>
|
|
|
{active ? (
|
|
|
<span className="h-1.5 w-1.5 rounded-full bg-white" />
|
|
|
) : null}
|
|
|
</span>
|
|
|
{flockFlexibilityKeyLabel(opt.key)}
|
|
|
</span>
|
|
|
<span className="text-text-secondary">
|
|
|
{opt.pickupWindow || "—"}
|
|
|
</span>
|
|
|
<span className="text-text-secondary">
|
|
|
{opt.deliverBy || "—"}
|
|
|
</span>
|
|
|
<span className="justify-self-end font-bold tabular-nums text-text-primary">
|
|
|
{formatUsdExact(opt.rateUsd)}
|
|
|
</span>
|
|
|
</button>
|
|
|
</li>
|
|
|
);
|
|
|
})}
|
|
|
</ul>
|
|
|
</div>
|
|
|
) : null}
|
|
|
|
|
|
{!busy && isCarriers && carrierOptions.length > 0 ? (
|
|
|
<div className="overflow-hidden rounded-lg border border-border">
|
|
|
<div className="grid grid-cols-[1.6fr_1fr_1fr_1fr_auto_auto] gap-2 border-b border-border bg-surface px-3 py-2 text-[11px] font-medium uppercase tracking-wide text-text-secondary">
|
|
|
<span>{FLOCK_UI.carrierColName}</span>
|
|
|
<span>{FLOCK_UI.carrierColTransit}</span>
|
|
|
<span>{FLOCK_UI.carrierColPickup}</span>
|
|
|
<span>{FLOCK_UI.carrierColDeliver}</span>
|
|
|
<span className="text-right">{FLOCK_UI.carrierColRate}</span>
|
|
|
<span className="sr-only">{FLOCK_UI.carrierSelect}</span>
|
|
|
</div>
|
|
|
<ul className="divide-y divide-border" data-testid="flock-carrier-list">
|
|
|
{carrierOptions.map((opt) => {
|
|
|
const active = selectedCarrier === opt.carrierName;
|
|
|
return (
|
|
|
<li key={`${opt.carrierName}-${opt.rateUsd}`}>
|
|
|
<button
|
|
|
type="button"
|
|
|
data-testid={`flock-carrier-option-${opt.carrierName}`}
|
|
|
onClick={() => onSelectCarrier(opt.carrierName)}
|
|
|
className={
|
|
|
"grid w-full grid-cols-[1.6fr_1fr_1fr_1fr_auto_auto] items-center gap-2 px-3 py-3.5 text-left text-sm transition " +
|
|
|
(active
|
|
|
? "bg-emerald-50 ring-1 ring-inset ring-emerald-400"
|
|
|
: "hover:bg-surface")
|
|
|
}
|
|
|
>
|
|
|
<span className="font-medium text-text-primary">
|
|
|
{opt.carrierName}
|
|
|
</span>
|
|
|
<span className="text-text-secondary">
|
|
|
{opt.transitDays || "—"}
|
|
|
</span>
|
|
|
<span className="text-text-secondary">
|
|
|
{opt.pickupDate || "—"}
|
|
|
</span>
|
|
|
<span className="text-text-secondary">
|
|
|
{opt.deliveryEstimate || "—"}
|
|
|
</span>
|
|
|
<span className="justify-self-end font-bold tabular-nums text-text-primary">
|
|
|
{formatUsdExact(opt.rateUsd)}
|
|
|
</span>
|
|
|
<span className="justify-self-end text-xs font-semibold text-text-primary">
|
|
|
{FLOCK_UI.carrierSelect} →
|
|
|
</span>
|
|
|
</button>
|
|
|
</li>
|
|
|
);
|
|
|
})}
|
|
|
</ul>
|
|
|
</div>
|
|
|
) : null}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
/** 右栏:对齐官网 — 双卡「查看报价选项」→ 弹窗选灵活价或承运商 */
|
|
|
export function FlockLoggedInQuoteSidebar({
|
|
|
lines,
|
|
|
reference,
|
|
|
flexibilityByTier = {},
|
|
|
carriersByTier = {},
|
|
|
selectedTier,
|
|
|
selectedFlexibility = null,
|
|
|
selectedCarrier = null,
|
|
|
flexBusy = false,
|
|
|
flexMessage = null,
|
|
|
checkoutBusy = false,
|
|
|
checkoutMessage = null,
|
|
|
detailsUnlocked = false,
|
|
|
onSelectTier,
|
|
|
onSelectFlexibility,
|
|
|
onSelectCarrier,
|
|
|
onCheckout,
|
|
|
onReset,
|
|
|
}: FlockLoggedInQuoteSidebarProps) {
|
|
|
const [pricingModalTier, setPricingModalTier] =
|
|
|
useState<FlockCheckoutTier | null>(null);
|
|
|
|
|
|
const direct = lines.find((l) => l.tier === "flock_direct");
|
|
|
const standard = lines.find((l) => l.tier === "standard");
|
|
|
const selectedFlexOptions =
|
|
|
(selectedTier && flexibilityByTier[selectedTier]) || [];
|
|
|
const selectedCarrierOptions =
|
|
|
(selectedTier && carriersByTier[selectedTier]) || [];
|
|
|
const selectedFlex = selectedFlexOptions.find(
|
|
|
(o) => o.key === selectedFlexibility,
|
|
|
);
|
|
|
const selectedCarrierOpt = selectedCarrierOptions.find(
|
|
|
(o) => o.carrierName === selectedCarrier,
|
|
|
);
|
|
|
const checkoutAmount =
|
|
|
selectedFlex?.rateUsd ??
|
|
|
selectedCarrierOpt?.rateUsd ??
|
|
|
(selectedTier === "flock_direct"
|
|
|
? direct?.final_total_usd
|
|
|
: selectedTier === "standard"
|
|
|
? standard?.final_total_usd
|
|
|
: undefined);
|
|
|
|
|
|
const hasSelection = Boolean(selectedFlexibility || selectedCarrier);
|
|
|
const canCheckout =
|
|
|
detailsUnlocked && !!selectedTier && hasSelection && !checkoutBusy;
|
|
|
|
|
|
const openPricing = (tier: FlockCheckoutTier) => {
|
|
|
onSelectTier(tier);
|
|
|
setPricingModalTier(tier);
|
|
|
};
|
|
|
|
|
|
const modalFlexOptions =
|
|
|
pricingModalTier != null
|
|
|
? (flexibilityByTier[pricingModalTier] ?? [])
|
|
|
: [];
|
|
|
const modalCarrierOptions =
|
|
|
pricingModalTier != null
|
|
|
? (carriersByTier[pricingModalTier] ?? [])
|
|
|
: [];
|
|
|
const modalOptionsType: FlockPricingOptionsType =
|
|
|
modalCarrierOptions.length > 0 && modalFlexOptions.length === 0
|
|
|
? "carriers"
|
|
|
: "flexibility";
|
|
|
|
|
|
return (
|
|
|
<aside className="space-y-4">
|
|
|
<div className="flex flex-wrap items-end justify-between gap-2">
|
|
|
<div>
|
|
|
<h2 className="text-lg font-semibold text-text-primary">
|
|
|
{reference
|
|
|
? `#${reference} ${FLOCK_UI.pricingOptionsHeading}`
|
|
|
: FLOCK_UI.resultTitle}
|
|
|
</h2>
|
|
|
<p className="mt-1 text-xs text-text-secondary">
|
|
|
{FLOCK_UI.selectShippingBelow}
|
|
|
</p>
|
|
|
</div>
|
|
|
{onReset ? (
|
|
|
<button
|
|
|
type="button"
|
|
|
onClick={onReset}
|
|
|
className="rounded-md border border-border bg-surface px-3 py-1.5 text-sm text-text-primary"
|
|
|
>
|
|
|
{FLOCK_UI.buildAnother}
|
|
|
</button>
|
|
|
) : null}
|
|
|
</div>
|
|
|
|
|
|
<div className="grid gap-3 sm:grid-cols-2">
|
|
|
{direct ? (
|
|
|
<article
|
|
|
className="flex flex-col overflow-hidden rounded-xl border border-border bg-white shadow-card"
|
|
|
data-testid="flock-tier-card-flock_direct"
|
|
|
>
|
|
|
<div className="bg-[#1a1a1a] px-4 py-3">
|
|
|
<h3 className="text-base font-semibold text-white">
|
|
|
{FLOCK_UI.directName}
|
|
|
</h3>
|
|
|
</div>
|
|
|
<div className="flex flex-1 flex-col gap-3 p-4">
|
|
|
<p className="text-sm text-text-secondary">
|
|
|
{FLOCK_UI.pricesFrom}{" "}
|
|
|
<span className="text-xl font-bold text-text-primary">
|
|
|
{formatUsd(direct.final_total_usd)}
|
|
|
</span>
|
|
|
</p>
|
|
|
<p className="text-sm text-text-secondary">
|
|
|
{FLOCK_UI.transit}
|
|
|
<span className="ml-1 font-semibold text-text-primary">
|
|
|
{direct.transitDescription || direct.transitDays}
|
|
|
</span>
|
|
|
</p>
|
|
|
<ul className="space-y-2">
|
|
|
{FLOCK_UI.directFeatures.map((t) => (
|
|
|
<FeatureRow key={t} ok text={t} />
|
|
|
))}
|
|
|
</ul>
|
|
|
<div className="rounded-md border border-sky-200 bg-sky-50 px-3 py-2 text-xs leading-relaxed text-sky-950">
|
|
|
{FLOCK_UI.directCallout}
|
|
|
</div>
|
|
|
<button
|
|
|
type="button"
|
|
|
data-testid="flock-see-pricing-flock_direct"
|
|
|
onClick={() => openPricing("flock_direct")}
|
|
|
className="mt-auto w-full rounded-full bg-[#1a1a1a] px-4 py-2.5 text-sm font-semibold text-white hover:bg-black"
|
|
|
>
|
|
|
{FLOCK_UI.seePricingOptions}
|
|
|
</button>
|
|
|
</div>
|
|
|
</article>
|
|
|
) : null}
|
|
|
|
|
|
{standard ? (
|
|
|
<article
|
|
|
className="flex flex-col overflow-hidden rounded-xl border border-border bg-white shadow-card"
|
|
|
data-testid="flock-tier-card-standard"
|
|
|
>
|
|
|
<div className="bg-[#e8e8e8] px-4 py-3">
|
|
|
<h3 className="text-base font-semibold text-text-primary">
|
|
|
{FLOCK_UI.standardName}
|
|
|
</h3>
|
|
|
</div>
|
|
|
<div className="flex flex-1 flex-col gap-3 p-4">
|
|
|
<p className="text-sm text-text-secondary">
|
|
|
{FLOCK_UI.pricesFrom}{" "}
|
|
|
<span className="text-xl font-bold text-text-primary">
|
|
|
{formatUsd(standard.final_total_usd)}
|
|
|
</span>
|
|
|
</p>
|
|
|
<p className="text-sm text-text-secondary">
|
|
|
{FLOCK_UI.transit}
|
|
|
<span className="ml-1 font-semibold text-text-primary">
|
|
|
{standard.transitDescription || standard.transitDays}
|
|
|
</span>
|
|
|
</p>
|
|
|
<ul className="space-y-2">
|
|
|
{FLOCK_UI.standardFeatures.map((t) => (
|
|
|
<FeatureRow key={t} ok={false} text={t} />
|
|
|
))}
|
|
|
</ul>
|
|
|
<p className="text-xs text-text-secondary">{FLOCK_UI.standardNote}</p>
|
|
|
<button
|
|
|
type="button"
|
|
|
data-testid="flock-see-pricing-standard"
|
|
|
onClick={() => openPricing("standard")}
|
|
|
className="mt-auto w-full rounded-full border-2 border-[#1a1a1a] bg-white px-4 py-2.5 text-sm font-semibold text-text-primary hover:bg-surface"
|
|
|
>
|
|
|
{FLOCK_UI.seePricingOptions}
|
|
|
</button>
|
|
|
</div>
|
|
|
</article>
|
|
|
) : null}
|
|
|
</div>
|
|
|
|
|
|
<div className="space-y-3 border-t border-border pt-4">
|
|
|
{selectedFlex ? (
|
|
|
<p className="text-center text-xs text-success">
|
|
|
{FLOCK_UI.checkoutSelected}:
|
|
|
{selectedTier === "flock_direct"
|
|
|
? FLOCK_UI.directName
|
|
|
: FLOCK_UI.standardName}{" "}
|
|
|
· {flockFlexibilityKeyLabel(selectedFlex.key)} ·{" "}
|
|
|
{formatUsdExact(selectedFlex.rateUsd)}
|
|
|
</p>
|
|
|
) : null}
|
|
|
{selectedCarrierOpt ? (
|
|
|
<p className="text-center text-xs text-success">
|
|
|
{FLOCK_UI.checkoutSelected}:
|
|
|
{selectedTier === "flock_direct"
|
|
|
? FLOCK_UI.directName
|
|
|
: FLOCK_UI.standardName}{" "}
|
|
|
· {selectedCarrierOpt.carrierName} ·{" "}
|
|
|
{formatUsdExact(selectedCarrierOpt.rateUsd)}
|
|
|
</p>
|
|
|
) : null}
|
|
|
{!detailsUnlocked ? (
|
|
|
<p className="text-center text-xs text-text-secondary">
|
|
|
{FLOCK_UI.holdThenPickFlex}
|
|
|
</p>
|
|
|
) : !hasSelection ? (
|
|
|
<p className="text-center text-xs text-text-secondary">
|
|
|
{FLOCK_UI.pickFlexThenDetails}
|
|
|
</p>
|
|
|
) : null}
|
|
|
{checkoutMessage ? <ErrorBanner>{checkoutMessage}</ErrorBanner> : null}
|
|
|
<button
|
|
|
type="button"
|
|
|
disabled={!canCheckout}
|
|
|
onClick={onCheckout}
|
|
|
className="flex h-12 w-full items-center justify-center rounded-md bg-success px-4 text-sm font-semibold text-white disabled:cursor-not-allowed disabled:opacity-50"
|
|
|
>
|
|
|
{checkoutBusy
|
|
|
? FLOCK_UI.checkoutSyncing
|
|
|
: checkoutAmount != null
|
|
|
? `${FLOCK_UI.checkoutCta} — ${formatUsd(checkoutAmount)}`
|
|
|
: FLOCK_UI.checkoutCta}
|
|
|
</button>
|
|
|
<p className="text-center text-[11px] text-text-disabled">
|
|
|
{FLOCK_UI.checkoutFootnote}
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
{pricingModalTier ? (
|
|
|
<PricingOptionsModal
|
|
|
tier={pricingModalTier}
|
|
|
reference={reference}
|
|
|
optionsType={modalOptionsType}
|
|
|
options={modalFlexOptions}
|
|
|
carrierOptions={modalCarrierOptions}
|
|
|
selectedFlexibility={
|
|
|
selectedTier === pricingModalTier ? selectedFlexibility : null
|
|
|
}
|
|
|
selectedCarrier={
|
|
|
selectedTier === pricingModalTier ? selectedCarrier : null
|
|
|
}
|
|
|
busy={flexBusy && selectedTier === pricingModalTier}
|
|
|
message={flexMessage}
|
|
|
onClose={() => setPricingModalTier(null)}
|
|
|
onSelectFlexibility={(key) => {
|
|
|
onSelectFlexibility(key);
|
|
|
setPricingModalTier(null);
|
|
|
}}
|
|
|
onSelectCarrier={(name) => {
|
|
|
onSelectCarrier(name);
|
|
|
setPricingModalTier(null);
|
|
|
}}
|
|
|
/>
|
|
|
) : null}
|
|
|
</aside>
|
|
|
);
|
|
|
}
|