|
|
"use client";
|
|
|
|
|
|
import { useImperativeHandle, forwardRef, useState, type ReactNode } from "react";
|
|
|
import {
|
|
|
FLOCK_CHECKOUT_FIELD_HINTS,
|
|
|
FLOCK_CHECKOUT_HOURS,
|
|
|
FLOCK_CHECKOUT_ROLE_OPTIONS,
|
|
|
emptyFlockCheckoutDetailsDraft,
|
|
|
flockDetailsHasErrors,
|
|
|
toFlockCheckoutApiDetails,
|
|
|
validateFlockCheckoutDetailsDraft,
|
|
|
type FlockCheckoutDetailsDraft,
|
|
|
type FlockCheckoutLocationDraft,
|
|
|
type FlockCheckoutRole,
|
|
|
type FlockDetailsFieldErrors,
|
|
|
} from "@/lib/flock/flock-checkout-details-rules";
|
|
|
import { ErrorBanner } from "@/components/ui/error-banner";
|
|
|
|
|
|
export type FlockLoggedInDetailsFormHandle = {
|
|
|
validateAndGetDetails: () => ReturnType<
|
|
|
typeof toFlockCheckoutApiDetails
|
|
|
> | null;
|
|
|
};
|
|
|
|
|
|
type Props = {
|
|
|
disabled?: boolean;
|
|
|
pickupZip?: string;
|
|
|
deliveryZip?: string;
|
|
|
/** 首价货件摘要(只读),对齐官网 Shipment details 货件行 */
|
|
|
shipmentSummary?: string;
|
|
|
};
|
|
|
|
|
|
const inputCls =
|
|
|
"w-full rounded-md border border-border bg-surface px-3 py-2 text-sm text-text-primary outline-none focus:border-primary disabled:opacity-60";
|
|
|
const inputErrCls =
|
|
|
"w-full rounded-md border border-error bg-surface px-3 py-2 text-sm text-text-primary outline-none focus:border-error disabled:opacity-60";
|
|
|
|
|
|
function Field({
|
|
|
label,
|
|
|
required,
|
|
|
error,
|
|
|
hint,
|
|
|
children,
|
|
|
}: {
|
|
|
label: string;
|
|
|
required?: boolean;
|
|
|
error?: string;
|
|
|
hint?: string;
|
|
|
children: ReactNode;
|
|
|
}) {
|
|
|
return (
|
|
|
<label className="block space-y-1">
|
|
|
<span className="text-xs font-medium text-text-secondary">
|
|
|
{label}
|
|
|
{required ? <span className="text-error"> *</span> : null}
|
|
|
</span>
|
|
|
{children}
|
|
|
{error ? <p className="text-[11px] text-error">{error}</p> : null}
|
|
|
{!error && hint ? (
|
|
|
<p className="text-[11px] text-text-disabled">{hint}</p>
|
|
|
) : null}
|
|
|
</label>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
function LocationAddressFields({
|
|
|
side,
|
|
|
loc,
|
|
|
errors,
|
|
|
disabled,
|
|
|
addressLocked,
|
|
|
onPatch,
|
|
|
}: {
|
|
|
side: "pickup" | "delivery";
|
|
|
loc: FlockCheckoutLocationDraft;
|
|
|
errors?: Partial<Record<keyof FlockCheckoutLocationDraft, string>>;
|
|
|
disabled?: boolean;
|
|
|
addressLocked: boolean;
|
|
|
onPatch: (patch: Partial<FlockCheckoutLocationDraft>) => void;
|
|
|
}) {
|
|
|
const locked = Boolean(disabled || addressLocked);
|
|
|
return (
|
|
|
<>
|
|
|
<Field
|
|
|
label="地址 1"
|
|
|
required={!addressLocked}
|
|
|
error={errors?.address1}
|
|
|
hint={
|
|
|
addressLocked
|
|
|
? FLOCK_CHECKOUT_FIELD_HINTS.useBilling
|
|
|
: FLOCK_CHECKOUT_FIELD_HINTS.addressMismatch
|
|
|
}
|
|
|
>
|
|
|
<input
|
|
|
disabled={locked}
|
|
|
className={errors?.address1 ? inputErrCls : inputCls}
|
|
|
value={loc.address1}
|
|
|
onChange={(e) => onPatch({ address1: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="地址 2">
|
|
|
<input
|
|
|
disabled={locked}
|
|
|
className={inputCls}
|
|
|
value={loc.address2}
|
|
|
onChange={(e) => onPatch({ address2: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="城市" required={!addressLocked} error={errors?.city}>
|
|
|
<input
|
|
|
disabled={locked}
|
|
|
className={errors?.city ? inputErrCls : inputCls}
|
|
|
value={loc.city}
|
|
|
onChange={(e) => onPatch({ city: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="州" required={!addressLocked} error={errors?.state}>
|
|
|
<input
|
|
|
disabled={locked}
|
|
|
className={errors?.state ? inputErrCls : inputCls}
|
|
|
value={loc.state}
|
|
|
onChange={(e) => onPatch({ state: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="邮编" required={!addressLocked} error={errors?.zip}>
|
|
|
<input
|
|
|
disabled={locked}
|
|
|
className={errors?.zip ? inputErrCls : inputCls}
|
|
|
value={loc.zip}
|
|
|
onChange={(e) => onPatch({ zip: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
</>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
/** 二级结账详情:对齐官网 Pickup / Delivery / Shipment details */
|
|
|
export const FlockLoggedInDetailsForm = forwardRef<
|
|
|
FlockLoggedInDetailsFormHandle,
|
|
|
Props
|
|
|
>(function FlockLoggedInDetailsForm(
|
|
|
{
|
|
|
disabled = false,
|
|
|
pickupZip = "",
|
|
|
deliveryZip = "",
|
|
|
shipmentSummary = "",
|
|
|
},
|
|
|
ref,
|
|
|
) {
|
|
|
const [draft, setDraft] = useState<FlockCheckoutDetailsDraft>(() =>
|
|
|
emptyFlockCheckoutDetailsDraft({ pickupZip, deliveryZip }),
|
|
|
);
|
|
|
const [errors, setErrors] = useState<FlockDetailsFieldErrors>({});
|
|
|
const [formError, setFormError] = useState<string | null>(null);
|
|
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
|
validateAndGetDetails: () => {
|
|
|
const next = validateFlockCheckoutDetailsDraft(draft);
|
|
|
setErrors(next);
|
|
|
if (flockDetailsHasErrors(next)) {
|
|
|
setFormError("请先修正结账详情中的必填项与格式错误");
|
|
|
return null;
|
|
|
}
|
|
|
setFormError(null);
|
|
|
return toFlockCheckoutApiDetails(draft);
|
|
|
},
|
|
|
}));
|
|
|
|
|
|
const setRole = (role: FlockCheckoutRole) => {
|
|
|
setDraft((d) => ({ ...d, role }));
|
|
|
setErrors((e) => ({ ...e, role: undefined }));
|
|
|
};
|
|
|
|
|
|
const patchPickup = (patch: Partial<FlockCheckoutLocationDraft>) => {
|
|
|
setDraft((d) => ({ ...d, pickup: { ...d.pickup, ...patch } }));
|
|
|
};
|
|
|
|
|
|
const patchDelivery = (patch: Partial<FlockCheckoutLocationDraft>) => {
|
|
|
setDraft((d) => ({ ...d, delivery: { ...d.delivery, ...patch } }));
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
<div className="space-y-5">
|
|
|
<div>
|
|
|
<h2 className="text-lg font-semibold text-text-primary">结账详情</h2>
|
|
|
<p className="mt-1 text-xs text-text-secondary">
|
|
|
{FLOCK_CHECKOUT_FIELD_HINTS.review}
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
{formError ? <ErrorBanner>{formError}</ErrorBanner> : null}
|
|
|
|
|
|
<section className="space-y-3 rounded-lg border border-border bg-surface p-4">
|
|
|
<h3 className="text-sm font-semibold text-text-primary">您的角色</h3>
|
|
|
<div className="flex flex-wrap gap-2">
|
|
|
{FLOCK_CHECKOUT_ROLE_OPTIONS.map((opt) => (
|
|
|
<button
|
|
|
key={opt.id}
|
|
|
type="button"
|
|
|
disabled={disabled}
|
|
|
onClick={() => setRole(opt.id)}
|
|
|
className={
|
|
|
"rounded-md border px-3 py-1.5 text-sm " +
|
|
|
(draft.role === opt.id
|
|
|
? "border-primary bg-primary/10 font-medium text-primary"
|
|
|
: "border-border text-text-secondary hover:border-primary/40")
|
|
|
}
|
|
|
>
|
|
|
{opt.label}
|
|
|
</button>
|
|
|
))}
|
|
|
</div>
|
|
|
{errors.role ? (
|
|
|
<p className="text-[11px] text-error">{errors.role}</p>
|
|
|
) : null}
|
|
|
</section>
|
|
|
|
|
|
<section className="space-y-3 rounded-lg border border-border bg-surface p-4">
|
|
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
|
<h3 className="text-sm font-semibold text-text-primary">提货地点</h3>
|
|
|
<label className="flex items-center gap-2 text-xs text-text-secondary">
|
|
|
<input
|
|
|
type="checkbox"
|
|
|
disabled={disabled}
|
|
|
checked={draft.use_billing_for_pickup}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({
|
|
|
...d,
|
|
|
use_billing_for_pickup: e.target.checked,
|
|
|
}))
|
|
|
}
|
|
|
/>
|
|
|
使用账单地址
|
|
|
</label>
|
|
|
</div>
|
|
|
<p className="text-[11px] text-text-disabled">
|
|
|
{FLOCK_CHECKOUT_FIELD_HINTS.useBilling}
|
|
|
</p>
|
|
|
<div className="grid gap-3 md:grid-cols-2">
|
|
|
<Field
|
|
|
label="公司名称"
|
|
|
required
|
|
|
error={errors.pickup?.company_name}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.addressSync}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.pickup?.company_name ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.pickup.company_name}
|
|
|
onChange={(e) => patchPickup({ company_name: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<LocationAddressFields
|
|
|
side="pickup"
|
|
|
loc={draft.pickup}
|
|
|
errors={errors.pickup}
|
|
|
disabled={disabled}
|
|
|
addressLocked={draft.use_billing_for_pickup}
|
|
|
onPatch={patchPickup}
|
|
|
/>
|
|
|
<Field
|
|
|
label="联系人"
|
|
|
required
|
|
|
error={errors.pickup?.contact_name}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.contactHelper}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.pickup?.contact_name ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.pickup.contact_name}
|
|
|
onChange={(e) => patchPickup({ contact_name: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field
|
|
|
label="电话"
|
|
|
required
|
|
|
error={errors.pickup?.contact_phone}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.phone}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.pickup?.contact_phone ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.pickup.contact_phone}
|
|
|
onChange={(e) => patchPickup({ contact_phone: e.target.value })}
|
|
|
placeholder="(626) 595-1180"
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field
|
|
|
label="邮箱"
|
|
|
required
|
|
|
error={errors.pickup?.contact_email}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.email}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.pickup?.contact_email ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.pickup.contact_email}
|
|
|
onChange={(e) => patchPickup({ contact_email: e.target.value })}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field
|
|
|
label="开门时间"
|
|
|
required
|
|
|
error={errors.pickup?.opens_at}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.hours}
|
|
|
>
|
|
|
<select
|
|
|
disabled={disabled}
|
|
|
className={errors.pickup?.opens_at ? inputErrCls : inputCls}
|
|
|
value={draft.pickup.opens_at}
|
|
|
onChange={(e) => patchPickup({ opens_at: e.target.value })}
|
|
|
>
|
|
|
{FLOCK_CHECKOUT_HOURS.map((h) => (
|
|
|
<option key={h} value={h}>
|
|
|
{h}
|
|
|
</option>
|
|
|
))}
|
|
|
</select>
|
|
|
</Field>
|
|
|
<Field label="关门时间" required error={errors.pickup?.closes_at}>
|
|
|
<select
|
|
|
disabled={disabled}
|
|
|
className={errors.pickup?.closes_at ? inputErrCls : inputCls}
|
|
|
value={draft.pickup.closes_at}
|
|
|
onChange={(e) => patchPickup({ closes_at: e.target.value })}
|
|
|
>
|
|
|
{FLOCK_CHECKOUT_HOURS.map((h) => (
|
|
|
<option key={h} value={h}>
|
|
|
{h}
|
|
|
</option>
|
|
|
))}
|
|
|
</select>
|
|
|
</Field>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
<section className="space-y-3 rounded-lg border border-border bg-surface p-4">
|
|
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
|
<h3 className="text-sm font-semibold text-text-primary">派送地点</h3>
|
|
|
<label className="flex items-center gap-2 text-xs text-text-secondary">
|
|
|
<input
|
|
|
type="checkbox"
|
|
|
disabled={disabled}
|
|
|
checked={draft.use_billing_for_delivery}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({
|
|
|
...d,
|
|
|
use_billing_for_delivery: e.target.checked,
|
|
|
}))
|
|
|
}
|
|
|
/>
|
|
|
使用账单地址
|
|
|
</label>
|
|
|
</div>
|
|
|
<p className="text-[11px] text-text-disabled">
|
|
|
{FLOCK_CHECKOUT_FIELD_HINTS.useBilling}
|
|
|
</p>
|
|
|
<div className="grid gap-3 md:grid-cols-2">
|
|
|
<Field
|
|
|
label="公司名称"
|
|
|
required
|
|
|
error={errors.delivery?.company_name}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.addressSync}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.delivery?.company_name ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.delivery.company_name}
|
|
|
onChange={(e) =>
|
|
|
patchDelivery({ company_name: e.target.value })
|
|
|
}
|
|
|
/>
|
|
|
</Field>
|
|
|
<LocationAddressFields
|
|
|
side="delivery"
|
|
|
loc={draft.delivery}
|
|
|
errors={errors.delivery}
|
|
|
disabled={disabled}
|
|
|
addressLocked={draft.use_billing_for_delivery}
|
|
|
onPatch={patchDelivery}
|
|
|
/>
|
|
|
<Field
|
|
|
label="联系人"
|
|
|
required
|
|
|
error={errors.delivery?.contact_name}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.delivery?.contact_name ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.delivery.contact_name}
|
|
|
onChange={(e) =>
|
|
|
patchDelivery({ contact_name: e.target.value })
|
|
|
}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field
|
|
|
label="电话"
|
|
|
required
|
|
|
error={errors.delivery?.contact_phone}
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.phone}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.delivery?.contact_phone ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.delivery.contact_phone}
|
|
|
onChange={(e) =>
|
|
|
patchDelivery({ contact_phone: e.target.value })
|
|
|
}
|
|
|
placeholder="(415) 621-8840"
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field
|
|
|
label="邮箱"
|
|
|
required
|
|
|
error={errors.delivery?.contact_email}
|
|
|
>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.delivery?.contact_email ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.delivery.contact_email}
|
|
|
onChange={(e) =>
|
|
|
patchDelivery({ contact_email: e.target.value })
|
|
|
}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="开门时间" required error={errors.delivery?.opens_at}>
|
|
|
<select
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.delivery?.opens_at ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.delivery.opens_at}
|
|
|
onChange={(e) => patchDelivery({ opens_at: e.target.value })}
|
|
|
>
|
|
|
{FLOCK_CHECKOUT_HOURS.map((h) => (
|
|
|
<option key={h} value={h}>
|
|
|
{h}
|
|
|
</option>
|
|
|
))}
|
|
|
</select>
|
|
|
</Field>
|
|
|
<Field
|
|
|
label="关门时间"
|
|
|
required
|
|
|
error={errors.delivery?.closes_at}
|
|
|
>
|
|
|
<select
|
|
|
disabled={disabled}
|
|
|
className={
|
|
|
errors.delivery?.closes_at ? inputErrCls : inputCls
|
|
|
}
|
|
|
value={draft.delivery.closes_at}
|
|
|
onChange={(e) => patchDelivery({ closes_at: e.target.value })}
|
|
|
>
|
|
|
{FLOCK_CHECKOUT_HOURS.map((h) => (
|
|
|
<option key={h} value={h}>
|
|
|
{h}
|
|
|
</option>
|
|
|
))}
|
|
|
</select>
|
|
|
</Field>
|
|
|
</div>
|
|
|
<div className="space-y-2">
|
|
|
<p className="text-xs font-medium text-text-secondary">
|
|
|
该地点是否允许周末派送?
|
|
|
</p>
|
|
|
<div className="flex gap-2">
|
|
|
{([true, false] as const).map((yes) => (
|
|
|
<button
|
|
|
key={String(yes)}
|
|
|
type="button"
|
|
|
disabled={disabled}
|
|
|
onClick={() => patchDelivery({ weekend_delivery: yes })}
|
|
|
className={
|
|
|
"rounded-md border px-3 py-1.5 text-sm " +
|
|
|
(draft.delivery.weekend_delivery === yes
|
|
|
? "border-primary bg-primary/10 font-medium text-primary"
|
|
|
: "border-border text-text-secondary")
|
|
|
}
|
|
|
>
|
|
|
{yes ? "是" : "否"}
|
|
|
</button>
|
|
|
))}
|
|
|
</div>
|
|
|
<p className="text-[11px] text-text-disabled">
|
|
|
{FLOCK_CHECKOUT_FIELD_HINTS.weekend}
|
|
|
</p>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
<section className="space-y-3 rounded-lg border border-border bg-surface p-4">
|
|
|
<h3 className="text-sm font-semibold text-text-primary">运输详情</h3>
|
|
|
{shipmentSummary ? (
|
|
|
<div className="rounded-md border border-border bg-bg px-3 py-2 text-sm text-text-primary">
|
|
|
<p className="text-xs font-medium text-text-secondary">货件摘要</p>
|
|
|
<p className="mt-1">{shipmentSummary}</p>
|
|
|
<p className="mt-1 text-[11px] text-text-disabled">
|
|
|
{FLOCK_CHECKOUT_FIELD_HINTS.shipmentItems}
|
|
|
</p>
|
|
|
</div>
|
|
|
) : null}
|
|
|
<div className="grid gap-3 md:grid-cols-2">
|
|
|
<Field label="NMFC" hint={FLOCK_CHECKOUT_FIELD_HINTS.nmfc}>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={inputCls}
|
|
|
value={draft.nmfc}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({ ...d, nmfc: e.target.value }))
|
|
|
}
|
|
|
placeholder="如 100240-01"
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="PO 单号" hint={FLOCK_CHECKOUT_FIELD_HINTS.po}>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={inputCls}
|
|
|
value={draft.po_number}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({ ...d, po_number: e.target.value }))
|
|
|
}
|
|
|
/>
|
|
|
</Field>
|
|
|
</div>
|
|
|
<Field
|
|
|
label="宣示声明"
|
|
|
hint={FLOCK_CHECKOUT_FIELD_HINTS.declaration}
|
|
|
>
|
|
|
<textarea
|
|
|
disabled={disabled}
|
|
|
rows={2}
|
|
|
className={inputCls}
|
|
|
value={draft.declaration_statement}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({
|
|
|
...d,
|
|
|
declaration_statement: e.target.value,
|
|
|
}))
|
|
|
}
|
|
|
placeholder="联系人确认、特殊要求等"
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="BOL 备注" hint={FLOCK_CHECKOUT_FIELD_HINTS.bol}>
|
|
|
<input
|
|
|
disabled={disabled}
|
|
|
className={inputCls}
|
|
|
value={draft.bol_remarks}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({ ...d, bol_remarks: e.target.value }))
|
|
|
}
|
|
|
/>
|
|
|
</Field>
|
|
|
<Field label="Flock 备注" hint={FLOCK_CHECKOUT_FIELD_HINTS.notes}>
|
|
|
<textarea
|
|
|
disabled={disabled}
|
|
|
rows={3}
|
|
|
className={inputCls}
|
|
|
value={draft.notes}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({ ...d, notes: e.target.value }))
|
|
|
}
|
|
|
/>
|
|
|
</Field>
|
|
|
<label className="flex items-start gap-2 text-sm text-text-primary">
|
|
|
<input
|
|
|
type="checkbox"
|
|
|
disabled={disabled}
|
|
|
className="mt-0.5"
|
|
|
checked={draft.documentation_required}
|
|
|
onChange={(e) =>
|
|
|
setDraft((d) => ({
|
|
|
...d,
|
|
|
documentation_required: e.target.checked,
|
|
|
}))
|
|
|
}
|
|
|
/>
|
|
|
<span>
|
|
|
提货需要单据
|
|
|
<span className="mt-0.5 block text-[11px] text-text-disabled">
|
|
|
{FLOCK_CHECKOUT_FIELD_HINTS.documentation}
|
|
|
</span>
|
|
|
</span>
|
|
|
</label>
|
|
|
</section>
|
|
|
</div>
|
|
|
);
|
|
|
});
|