@burdenoff/microfe-store 2026.819.2 → 2026.819.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"SellerSourcingOpportunityDetailPage.js","names":[],"sources":["../../src/pages/SellerSourcingOpportunityDetailPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from 'react';\nimport type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport {\n BadgeCheck,\n CalendarDays,\n Check,\n CircleDollarSign,\n Loader2,\n MapPin,\n PackageSearch,\n Save,\n TicketCheck,\n} from 'lucide-react';\nimport { EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingOfferStatus } from '../generated/global-types';\nimport type { UpsertSourcingOfferInput } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport {\n type SellerSourcingOfferDetail,\n type SellerSourcingOpportunityDetail,\n useSourcingApi,\n} from '../hooks/useSourcing';\nimport { usePublisherSourcingAccess } from '../providers/SourcingAccessProvider';\nimport {\n ContextRequiredPanel,\n formatDateTime,\n formatLocation,\n formatMoney,\n formatSourcingUnit,\n helpClassName,\n inputClassName,\n joinStorePath,\n labelClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n SourcingErrorState,\n SourcingLoadingState,\n SourcingPageHeader,\n SourcingStatusBadge,\n toDateTimeLocal,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\n\ninterface OfferFormState {\n unitPrice: string;\n deliveryDate: string;\n storeProductId: string;\n message: string;\n}\n\ntype OfferField = keyof OfferFormState;\ntype OfferErrors = Partial<Record<OfferField, string>>;\n\nconst EMPTY_FORM: OfferFormState = {\n unitPrice: '',\n deliveryDate: '',\n storeProductId: '',\n message: '',\n};\nconst MONEY_PATTERN = /^(?:0|[1-9]\\d{0,15})(?:\\.\\d{1,2})?$/;\n\nfunction validateOffer(\n form: OfferFormState,\n opportunity: SellerSourcingOpportunityDetail\n): OfferErrors {\n const errors: OfferErrors = {};\n const amount = form.unitPrice.trim();\n const delivery = new Date(form.deliveryDate);\n const start = new Date(opportunity.deliveryWindowStart);\n const end = new Date(opportunity.deliveryWindowEnd);\n\n if (!MONEY_PATTERN.test(amount) || Number(amount) <= 0) {\n errors.unitPrice = 'Enter a positive unit price with no more than two decimal places.';\n }\n if (\n !form.deliveryDate ||\n Number.isNaN(delivery.getTime()) ||\n delivery < start ||\n delivery > end\n ) {\n errors.deliveryDate = 'Choose a delivery date within the buyer’s requested window.';\n }\n if (form.message.trim().length > 1000) {\n errors.message = 'Offer message cannot exceed 1,000 characters.';\n }\n return errors;\n}\n\nexport const SellerSourcingOpportunityDetailPage: FC = () => {\n const navigate = useNavigate();\n const { requestId } = useParams<{ requestId: string }>();\n const { basePath } = useStore();\n const {\n profile,\n products,\n productsLoading,\n productsError,\n loading: accessLoading,\n error: accessError,\n isEligible,\n refresh: refreshAccess,\n refreshProducts,\n } = usePublisherSourcingAccess();\n const { getOpportunity, upsertOffer } = useSourcingApi();\n const [opportunity, setOpportunity] = useState<SellerSourcingOpportunityDetail | null>(null);\n const [offer, setOffer] = useState<SellerSourcingOfferDetail | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [form, setForm] = useState<OfferFormState>(EMPTY_FORM);\n const [errors, setErrors] = useState<OfferErrors>({});\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [success, setSuccess] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const opportunitiesPath = joinStorePath(basePath, 'publisher/sourcing/opportunities');\n\n const load = useCallback(\n async (initializeForm = false) => {\n if (!isEligible || !requestId) return;\n setLoading(true);\n setError(null);\n try {\n const result = await getOpportunity(requestId);\n setOpportunity(result.opportunity);\n setOffer(result.offer);\n setIsOpen(result.isOpen);\n if (!result.opportunity) {\n setError('This sourcing opportunity is no longer available.');\n } else if (initializeForm) {\n setForm({\n unitPrice: result.offer?.unitPrice ?? '',\n deliveryDate: result.offer\n ? toDateTimeLocal(result.offer.deliveryDate)\n : toDateTimeLocal(result.opportunity.deliveryWindowStart),\n storeProductId: result.offer?.storeProductId ?? '',\n message: result.offer?.message ?? '',\n });\n }\n } catch (loadError) {\n setError(toErrorMessage(loadError, 'The sourcing opportunity could not be loaded.'));\n } finally {\n setLoading(false);\n }\n },\n [getOpportunity, isEligible, requestId]\n );\n\n useEffect(() => {\n void load(true);\n }, [load]);\n\n const publishedProducts = useMemo(\n () =>\n [...products]\n .filter((product) => product.status === 'PUBLISHED')\n .sort((left, right) => left.name.localeCompare(right.name)),\n [products]\n );\n\n const updateField =\n (field: OfferField) =>\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {\n setForm((current) => ({ ...current, [field]: event.target.value }));\n setErrors((current) => ({ ...current, [field]: undefined }));\n setSuccess(null);\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!opportunity || !requestId || !isOpen || submitting) return;\n\n const validationErrors = validateOffer(form, opportunity);\n setErrors(validationErrors);\n setSubmitError(null);\n setSuccess(null);\n if (Object.keys(validationErrors).length > 0) return;\n\n const input: UpsertSourcingOfferInput = {\n requestId,\n quantity: opportunity.quantity,\n unit: opportunity.unit,\n unitPrice: form.unitPrice.trim(),\n currency: 'USD',\n deliveryDate: new Date(form.deliveryDate).toISOString(),\n storeProductId: form.storeProductId || undefined,\n message: form.message.trim() || undefined,\n };\n\n setSubmitting(true);\n try {\n const saved = await upsertOffer(input);\n setSuccess(offer ? 'Your offer was updated.' : 'Your offer was submitted.');\n setOffer(saved);\n await load(false);\n } catch (saveError) {\n setSubmitError(\n toErrorMessage(\n saveError,\n 'Your offer could not be saved. The request may have closed while you were editing.'\n )\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n const fieldError = (field: OfferField) => {\n const message = errors[field];\n return message ? (\n <p id={`${field}-error`} className=\"mt-1 text-xs text-text-danger\">\n {message}\n </p>\n ) : null;\n };\n\n const canEdit = isOpen && (!offer || offer.status === SourcingOfferStatus.Active);\n\n return (\n <div className=\"min-h-full bg-surface-default\">\n <SourcingPageHeader\n title={opportunity?.productName ?? 'Sourcing opportunity'}\n description=\"Review the sanitized buyer request and create or update your publisher’s offer.\"\n icon={<TicketCheck className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(opportunitiesPath)}\n actions={\n <button\n type=\"button\"\n onClick={() => navigate(joinStorePath(basePath, 'publisher/sourcing/offers'))}\n className={secondaryButtonClassName}\n >\n My offers\n </button>\n }\n />\n\n <main className=\"mx-auto max-w-6xl px-4 py-6 sm:px-6\">\n <PagePurpose className=\"mb-6\">\n Quantity and unit are fixed by the buyer request. Store validates publisher identity, USD\n settlement price, delivery window, and optional linked product on every save. You can\n update one active offer until the request closes.\n </PagePurpose>\n\n {accessLoading ? (\n <SourcingLoadingState label=\"Checking Store Publisher access…\" />\n ) : accessError ? (\n <SourcingErrorState\n title=\"Publisher access could not be checked\"\n message={accessError}\n onRetry={() => void refreshAccess()}\n />\n ) : !profile ? (\n <ContextRequiredPanel\n title=\"Store Publisher profile required\"\n description=\"Only users who own a verified Store Publisher profile can view this opportunity or submit an offer.\"\n />\n ) : !isEligible ? (\n <ContextRequiredPanel\n title=\"Verified publisher status required\"\n description={`The publisher profile “${profile.name}” is currently ${profile.verificationStatus.toLowerCase().replaceAll('_', ' ')}.`}\n />\n ) : loading && !opportunity ? (\n <SourcingLoadingState label=\"Loading opportunity and your offer…\" />\n ) : error && !opportunity ? (\n <SourcingErrorState\n title=\"Opportunity unavailable\"\n message={error}\n onRetry={requestId ? () => void load(true) : undefined}\n />\n ) : opportunity ? (\n <>\n {submitError ? (\n <div\n role=\"alert\"\n className=\"mb-5 rounded-lg border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {submitError}\n </div>\n ) : null}\n {success ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"mb-5 flex items-center gap-2 rounded-lg border border-status-success-border bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text\"\n >\n <Check className=\"size-4\" aria-hidden=\"true\" />\n {success}\n </div>\n ) : null}\n\n {offer?.order ? (\n <EmphasisPanel className=\"mb-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <p className=\"text-sm font-semibold text-status-success-text\">\n This offer was accepted\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Store order {offer.order.id} ·{' '}\n {formatMoney(offer.order.total, offer.order.currency)} · {offer.order.status}\n </p>\n </div>\n {offer.order.fulfillment ? (\n <span className=\"rounded-full border border-border-default bg-surface-muted px-3 py-1.5 text-xs font-medium text-text-secondary\">\n Fulfillment {offer.order.fulfillment.status.replaceAll('_', ' ')}\n </span>\n ) : null}\n </div>\n </EmphasisPanel>\n ) : null}\n\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1.2fr)_minmax(340px,0.8fr)]\">\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <p className=\"text-sm font-medium text-text-accent\">{opportunity.category}</p>\n <h2 className=\"mt-1 text-xl font-semibold text-text-primary\">\n {opportunity.productName}\n </h2>\n </div>\n <span\n className={`rounded-full border px-2.5 py-1 text-xs font-semibold ${\n isOpen\n ? 'border-status-success-border bg-status-success-bg-subtle text-status-success-text'\n : 'border-border-default bg-surface-muted text-text-secondary'\n }`}\n >\n {isOpen ? 'OPEN' : 'CLOSED'}\n </span>\n </div>\n\n {opportunity.summary ? (\n <p className=\"mt-4 whitespace-pre-wrap text-sm leading-6 text-text-secondary\">\n {opportunity.summary}\n </p>\n ) : null}\n\n <dl className=\"mt-6 grid gap-5 border-t border-border-seam pt-5 sm:grid-cols-2\">\n <div className=\"flex gap-3\">\n <PackageSearch\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Required quantity</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {opportunity.quantity.toLocaleString()}{' '}\n {formatSourcingUnit(opportunity.unit)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CircleDollarSign\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Buyer target</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatMoney(opportunity.targetUnitPrice, opportunity.targetCurrency)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CalendarDays\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Delivery window</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(opportunity.deliveryWindowStart)} –{' '}\n {formatDateTime(opportunity.deliveryWindowEnd)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <MapPin\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Destination</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatLocation({\n country: opportunity.deliveryCountry,\n region: opportunity.deliveryRegion,\n city: opportunity.deliveryCity,\n })}\n </dd>\n </div>\n </div>\n </dl>\n </GlassCard>\n\n {canEdit ? (\n <form onSubmit={(event) => void handleSubmit(event)} noValidate>\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {offer ? 'Update your offer' : 'Create an offer'}\n </h2>\n <p className=\"mt-1 text-xs text-text-tertiary\">\n Offering as {profile.name}\n </p>\n </div>\n <BadgeCheck\n className=\"size-5 text-text-accent\"\n aria-label=\"Verified publisher\"\n />\n </div>\n\n <div className=\"mt-5 space-y-5\">\n <label className={labelClassName}>\n Unit price\n <div className=\"mt-1.5 grid grid-cols-[1fr_96px] gap-2\">\n <input\n type=\"text\"\n value={form.unitPrice}\n onChange={updateField('unitPrice')}\n inputMode=\"decimal\"\n required\n maxLength={19}\n aria-invalid={Boolean(errors.unitPrice)}\n aria-describedby={\n errors.unitPrice ? 'unitPrice-error' : 'unitPrice-help'\n }\n placeholder=\"125.50\"\n className={`${inputClassName} mt-0`}\n />\n <span\n aria-label=\"Offer currency\"\n className=\"mt-0 flex items-center justify-center rounded-md border border-border-default bg-surface-muted px-3 text-sm font-semibold text-text-secondary\"\n >\n USD\n </span>\n </div>\n {fieldError('unitPrice')}\n {!errors.unitPrice ? (\n <p id=\"unitPrice-help\" className={helpClassName}>\n Price per {formatSourcingUnit(opportunity.unit).toLowerCase()}. Store\n sourcing currently settles in USD.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Promised delivery date\n <input\n type=\"datetime-local\"\n value={form.deliveryDate}\n onChange={updateField('deliveryDate')}\n required\n min={toDateTimeLocal(opportunity.deliveryWindowStart)}\n max={toDateTimeLocal(opportunity.deliveryWindowEnd)}\n aria-invalid={Boolean(errors.deliveryDate)}\n aria-describedby={\n errors.deliveryDate ? 'deliveryDate-error' : 'deliveryDate-help'\n }\n className={inputClassName}\n />\n {fieldError('deliveryDate')}\n {!errors.deliveryDate ? (\n <p id=\"deliveryDate-help\" className={helpClassName}>\n Must fall inside the buyer’s delivery window.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Link a published product{' '}\n <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <select\n value={form.storeProductId}\n onChange={updateField('storeProductId')}\n disabled={productsLoading}\n aria-describedby={\n productsError ? 'store-product-error' : 'store-product-help'\n }\n className={inputClassName}\n >\n <option value=\"\">\n {productsLoading\n ? 'Loading published products…'\n : 'No linked Store product'}\n </option>\n {publishedProducts.map((product) => (\n <option key={product.id} value={product.id}>\n {product.name}\n </option>\n ))}\n </select>\n {productsError ? (\n <div\n id=\"store-product-error\"\n role=\"alert\"\n className=\"mt-2 flex flex-wrap items-center gap-2 text-xs text-text-danger\"\n >\n <span>{productsError}</span>\n <button\n type=\"button\"\n onClick={() => void refreshProducts()}\n className=\"font-semibold underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg\"\n >\n Try again\n </button>\n </div>\n ) : (\n <p id=\"store-product-help\" className={helpClassName}>\n Only products owned by this publisher and currently published are\n accepted. The link is reference metadata and does not reserve catalog\n inventory or create digital entitlements.\n </p>\n )}\n </label>\n\n <label className={labelClassName}>\n Message <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <textarea\n value={form.message}\n onChange={updateField('message')}\n maxLength={1000}\n rows={4}\n aria-invalid={Boolean(errors.message)}\n aria-describedby={errors.message ? 'message-error' : 'message-help'}\n placeholder=\"Add packaging, quality, or delivery notes relevant to this offer.\"\n className={`${inputClassName} resize-y`}\n />\n {fieldError('message')}\n {!errors.message ? (\n <p id=\"message-help\" className={helpClassName}>\n {form.message.length}/1,000 characters\n </p>\n ) : null}\n </label>\n </div>\n\n <button\n type=\"submit\"\n disabled={submitting}\n className={`${primaryButtonClassName} mt-6 w-full`}\n >\n {submitting ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden=\"true\" />\n ) : offer ? (\n <Save className=\"size-4\" aria-hidden=\"true\" />\n ) : (\n <TicketCheck className=\"size-4\" aria-hidden=\"true\" />\n )}\n {submitting ? 'Saving offer…' : offer ? 'Update offer' : 'Submit offer'}\n </button>\n </GlassCard>\n </form>\n ) : offer ? (\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Your offer</h2>\n <p className=\"mt-1 text-xs text-text-tertiary\">\n Updated {formatDateTime(offer.updatedAt)}\n </p>\n </div>\n <SourcingStatusBadge status={offer.status} />\n </div>\n <dl className=\"mt-5 space-y-4 text-sm\">\n <div>\n <dt className=\"text-xs text-text-tertiary\">Unit price</dt>\n <dd className=\"mt-0.5 text-lg font-semibold text-text-primary\">\n {formatMoney(offer.unitPrice, offer.currency)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Promised delivery</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(offer.deliveryDate)}\n </dd>\n </div>\n {offer.message ? (\n <div>\n <dt className=\"text-xs text-text-tertiary\">Message</dt>\n <dd className=\"mt-1 whitespace-pre-wrap text-text-secondary\">\n {offer.message}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n ) : (\n <ContextRequiredPanel\n title=\"This request is closed\"\n description=\"The buyer matched or canceled this request before your publisher submitted an offer.\"\n />\n )}\n </div>\n </>\n ) : null}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"SellerSourcingOpportunityDetailPage.js","names":[],"sources":["../../src/pages/SellerSourcingOpportunityDetailPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from 'react';\nimport type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport {\n BadgeCheck,\n CalendarDays,\n Check,\n CircleDollarSign,\n Loader2,\n MapPin,\n PackageSearch,\n Save,\n TicketCheck,\n} from 'lucide-react';\nimport { EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingOfferStatus } from '../generated/global-types';\nimport type { UpsertSourcingOfferInput } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport {\n type SellerSourcingOfferDetail,\n type SellerSourcingOpportunityDetail,\n useSourcingApi,\n} from '../hooks/useSourcing';\nimport { usePublisherSourcingAccess } from '../providers/SourcingAccessProvider';\nimport {\n ContextRequiredPanel,\n formatDateTime,\n formatLocation,\n formatMoney,\n formatSourcingUnit,\n helpClassName,\n inputClassName,\n joinStorePath,\n labelClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n SourcingErrorState,\n SourcingLoadingState,\n SourcingPageHeader,\n SourcingStatusBadge,\n toDateTimeLocal,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\n\ninterface OfferFormState {\n unitPrice: string;\n deliveryDate: string;\n storeProductId: string;\n message: string;\n}\n\ntype OfferField = keyof OfferFormState;\ntype OfferErrors = Partial<Record<OfferField, string>>;\n\nconst EMPTY_FORM: OfferFormState = {\n unitPrice: '',\n deliveryDate: '',\n storeProductId: '',\n message: '',\n};\nconst MONEY_PATTERN = /^(?:0|[1-9]\\d{0,15})(?:\\.\\d{1,2})?$/;\n\nfunction validateOffer(\n form: OfferFormState,\n opportunity: SellerSourcingOpportunityDetail\n): OfferErrors {\n const errors: OfferErrors = {};\n const amount = form.unitPrice.trim();\n const delivery = new Date(form.deliveryDate);\n const start = new Date(opportunity.deliveryWindowStart);\n const end = new Date(opportunity.deliveryWindowEnd);\n\n if (!MONEY_PATTERN.test(amount) || Number(amount) <= 0) {\n errors.unitPrice = 'Enter a positive unit price with no more than two decimal places.';\n }\n if (\n !form.deliveryDate ||\n Number.isNaN(delivery.getTime()) ||\n delivery < start ||\n delivery > end\n ) {\n errors.deliveryDate = 'Choose a delivery date within the buyer’s requested window.';\n }\n if (form.message.trim().length > 1000) {\n errors.message = 'Offer message cannot exceed 1,000 characters.';\n }\n return errors;\n}\n\nexport const SellerSourcingOpportunityDetailPage: FC = () => {\n const navigate = useNavigate();\n const { requestId } = useParams<{ requestId: string }>();\n const { basePath } = useStore();\n const {\n profile,\n products,\n productsLoading,\n productsError,\n loading: accessLoading,\n error: accessError,\n isEligible,\n refresh: refreshAccess,\n refreshProducts,\n } = usePublisherSourcingAccess();\n const { getOpportunity, upsertOffer } = useSourcingApi();\n const [opportunity, setOpportunity] = useState<SellerSourcingOpportunityDetail | null>(null);\n const [offer, setOffer] = useState<SellerSourcingOfferDetail | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const [form, setForm] = useState<OfferFormState>(EMPTY_FORM);\n const [errors, setErrors] = useState<OfferErrors>({});\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [success, setSuccess] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const opportunitiesPath = joinStorePath(basePath, 'publisher/sourcing/opportunities');\n\n const load = useCallback(\n async (initializeForm = false) => {\n if (!isEligible || !requestId) return;\n setLoading(true);\n setError(null);\n try {\n const result = await getOpportunity(requestId);\n setOpportunity(result.opportunity);\n setOffer(result.offer);\n setIsOpen(result.isOpen);\n if (!result.opportunity) {\n setError('This sourcing opportunity is no longer available.');\n } else if (initializeForm) {\n setForm({\n unitPrice: result.offer?.unitPrice ?? '',\n deliveryDate: result.offer\n ? toDateTimeLocal(result.offer.deliveryDate)\n : toDateTimeLocal(result.opportunity.deliveryWindowStart),\n storeProductId: result.offer?.storeProductId ?? '',\n message: result.offer?.message ?? '',\n });\n }\n } catch (loadError) {\n setError(toErrorMessage(loadError, 'The sourcing opportunity could not be loaded.'));\n } finally {\n setLoading(false);\n }\n },\n [getOpportunity, isEligible, requestId]\n );\n\n useEffect(() => {\n void load(true);\n }, [load]);\n\n const publishedProducts = useMemo(\n () =>\n [...products]\n .filter((product) => product.status === 'PUBLISHED')\n .sort((left, right) => left.name.localeCompare(right.name)),\n [products]\n );\n\n const updateField =\n (field: OfferField) =>\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {\n setForm((current) => ({ ...current, [field]: event.target.value }));\n setErrors((current) => ({ ...current, [field]: undefined }));\n setSuccess(null);\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!opportunity || !requestId || !isOpen || submitting) return;\n\n const validationErrors = validateOffer(form, opportunity);\n setErrors(validationErrors);\n setSubmitError(null);\n setSuccess(null);\n if (Object.keys(validationErrors).length > 0) return;\n\n const input: UpsertSourcingOfferInput = {\n requestId,\n quantity: opportunity.quantity,\n unit: opportunity.unit,\n unitPrice: form.unitPrice.trim(),\n currency: 'USD',\n deliveryDate: new Date(form.deliveryDate).toISOString(),\n storeProductId: form.storeProductId || undefined,\n message: form.message.trim() || undefined,\n };\n\n setSubmitting(true);\n try {\n const saved = await upsertOffer(input);\n setSuccess(offer ? 'Your offer was updated.' : 'Your offer was submitted.');\n setOffer(saved);\n await load(false);\n } catch (saveError) {\n setSubmitError(\n toErrorMessage(\n saveError,\n 'Your offer could not be saved. The request may have closed while you were editing.'\n )\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n const fieldError = (field: OfferField) => {\n const message = errors[field];\n return message ? (\n <p id={`${field}-error`} className=\"mt-1 text-xs text-status-error-text\">\n {message}\n </p>\n ) : null;\n };\n\n const canEdit = isOpen && (!offer || offer.status === SourcingOfferStatus.Active);\n\n return (\n <div className=\"min-h-full bg-surface\">\n <SourcingPageHeader\n title={opportunity?.productName ?? 'Sourcing opportunity'}\n description=\"Review the sanitized buyer request and create or update your publisher’s offer.\"\n icon={<TicketCheck className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(opportunitiesPath)}\n actions={\n <button\n type=\"button\"\n onClick={() => navigate(joinStorePath(basePath, 'publisher/sourcing/offers'))}\n className={secondaryButtonClassName}\n >\n My offers\n </button>\n }\n />\n\n <main className=\"mx-auto max-w-6xl px-4 py-6 sm:px-6\">\n <PagePurpose className=\"mb-6\">\n Quantity and unit are fixed by the buyer request. Store validates publisher identity, USD\n settlement price, delivery window, and optional linked product on every save. You can\n update one active offer until the request closes.\n </PagePurpose>\n\n {accessLoading ? (\n <SourcingLoadingState label=\"Checking Store Publisher access…\" />\n ) : accessError ? (\n <SourcingErrorState\n title=\"Publisher access could not be checked\"\n message={accessError}\n onRetry={() => void refreshAccess()}\n />\n ) : !profile ? (\n <ContextRequiredPanel\n title=\"Store Publisher profile required\"\n description=\"Only users who own a verified Store Publisher profile can view this opportunity or submit an offer.\"\n />\n ) : !isEligible ? (\n <ContextRequiredPanel\n title=\"Verified publisher status required\"\n description={`The publisher profile “${profile.name}” is currently ${profile.verificationStatus.toLowerCase().replaceAll('_', ' ')}.`}\n />\n ) : loading && !opportunity ? (\n <SourcingLoadingState label=\"Loading opportunity and your offer…\" />\n ) : error && !opportunity ? (\n <SourcingErrorState\n title=\"Opportunity unavailable\"\n message={error}\n onRetry={requestId ? () => void load(true) : undefined}\n />\n ) : opportunity ? (\n <>\n {submitError ? (\n <div\n role=\"alert\"\n className=\"mb-5 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text\"\n >\n {submitError}\n </div>\n ) : null}\n {success ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"mb-5 flex items-center gap-2 rounded-lg border border-status-success-border bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text\"\n >\n <Check className=\"size-4\" aria-hidden=\"true\" />\n {success}\n </div>\n ) : null}\n\n {offer?.order ? (\n <EmphasisPanel className=\"mb-6\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <p className=\"text-sm font-semibold text-status-success-text\">\n This offer was accepted\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Store order {offer.order.id} ·{' '}\n {formatMoney(offer.order.total, offer.order.currency)} · {offer.order.status}\n </p>\n </div>\n {offer.order.fulfillment ? (\n <span className=\"rounded-full border border-border-default bg-surface-sunken px-3 py-1.5 text-xs font-medium text-text-secondary\">\n Fulfillment {offer.order.fulfillment.status.replaceAll('_', ' ')}\n </span>\n ) : null}\n </div>\n </EmphasisPanel>\n ) : null}\n\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1.2fr)_minmax(340px,0.8fr)]\">\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <p className=\"text-sm font-medium text-accent-primary\">\n {opportunity.category}\n </p>\n <h2 className=\"mt-1 text-xl font-semibold text-text-primary\">\n {opportunity.productName}\n </h2>\n </div>\n <span\n className={`rounded-full border px-2.5 py-1 text-xs font-semibold ${\n isOpen\n ? 'border-status-success-border bg-status-success-bg-subtle text-status-success-text'\n : 'border-border-default bg-surface-sunken text-text-secondary'\n }`}\n >\n {isOpen ? 'OPEN' : 'CLOSED'}\n </span>\n </div>\n\n {opportunity.summary ? (\n <p className=\"mt-4 whitespace-pre-wrap text-sm leading-6 text-text-secondary\">\n {opportunity.summary}\n </p>\n ) : null}\n\n <dl className=\"mt-6 grid gap-5 border-t border-border-subtle pt-5 sm:grid-cols-2\">\n <div className=\"flex gap-3\">\n <PackageSearch\n className=\"mt-0.5 size-5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-muted\">Required quantity</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {opportunity.quantity.toLocaleString()}{' '}\n {formatSourcingUnit(opportunity.unit)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CircleDollarSign\n className=\"mt-0.5 size-5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-muted\">Buyer target</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatMoney(opportunity.targetUnitPrice, opportunity.targetCurrency)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CalendarDays\n className=\"mt-0.5 size-5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-muted\">Delivery window</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(opportunity.deliveryWindowStart)} –{' '}\n {formatDateTime(opportunity.deliveryWindowEnd)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <MapPin className=\"mt-0.5 size-5 shrink-0 text-text-muted\" aria-hidden=\"true\" />\n <div>\n <dt className=\"text-xs text-text-muted\">Destination</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatLocation({\n country: opportunity.deliveryCountry,\n region: opportunity.deliveryRegion,\n city: opportunity.deliveryCity,\n })}\n </dd>\n </div>\n </div>\n </dl>\n </GlassCard>\n\n {canEdit ? (\n <form onSubmit={(event) => void handleSubmit(event)} noValidate>\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {offer ? 'Update your offer' : 'Create an offer'}\n </h2>\n <p className=\"mt-1 text-xs text-text-muted\">Offering as {profile.name}</p>\n </div>\n <BadgeCheck\n className=\"size-5 text-accent-primary\"\n aria-label=\"Verified publisher\"\n />\n </div>\n\n <div className=\"mt-5 space-y-5\">\n <label className={labelClassName}>\n Unit price\n <div className=\"mt-1.5 grid grid-cols-[1fr_96px] gap-2\">\n <input\n type=\"text\"\n value={form.unitPrice}\n onChange={updateField('unitPrice')}\n inputMode=\"decimal\"\n required\n maxLength={19}\n aria-invalid={Boolean(errors.unitPrice)}\n aria-describedby={\n errors.unitPrice ? 'unitPrice-error' : 'unitPrice-help'\n }\n placeholder=\"125.50\"\n className={`${inputClassName} mt-0`}\n />\n <span\n aria-label=\"Offer currency\"\n className=\"mt-0 flex items-center justify-center rounded-md border border-border-default bg-surface-sunken px-3 text-sm font-semibold text-text-secondary\"\n >\n USD\n </span>\n </div>\n {fieldError('unitPrice')}\n {!errors.unitPrice ? (\n <p id=\"unitPrice-help\" className={helpClassName}>\n Price per {formatSourcingUnit(opportunity.unit).toLowerCase()}. Store\n sourcing currently settles in USD.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Promised delivery date\n <input\n type=\"datetime-local\"\n value={form.deliveryDate}\n onChange={updateField('deliveryDate')}\n required\n min={toDateTimeLocal(opportunity.deliveryWindowStart)}\n max={toDateTimeLocal(opportunity.deliveryWindowEnd)}\n aria-invalid={Boolean(errors.deliveryDate)}\n aria-describedby={\n errors.deliveryDate ? 'deliveryDate-error' : 'deliveryDate-help'\n }\n className={inputClassName}\n />\n {fieldError('deliveryDate')}\n {!errors.deliveryDate ? (\n <p id=\"deliveryDate-help\" className={helpClassName}>\n Must fall inside the buyer’s delivery window.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Link a published product{' '}\n <span className=\"font-normal text-text-muted\">(optional)</span>\n <select\n value={form.storeProductId}\n onChange={updateField('storeProductId')}\n disabled={productsLoading}\n aria-describedby={\n productsError ? 'store-product-error' : 'store-product-help'\n }\n className={inputClassName}\n >\n <option value=\"\">\n {productsLoading\n ? 'Loading published products…'\n : 'No linked Store product'}\n </option>\n {publishedProducts.map((product) => (\n <option key={product.id} value={product.id}>\n {product.name}\n </option>\n ))}\n </select>\n {productsError ? (\n <div\n id=\"store-product-error\"\n role=\"alert\"\n className=\"mt-2 flex flex-wrap items-center gap-2 text-xs text-status-error-text\"\n >\n <span>{productsError}</span>\n <button\n type=\"button\"\n onClick={() => void refreshProducts()}\n className=\"font-semibold underline underline-offset-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg\"\n >\n Try again\n </button>\n </div>\n ) : (\n <p id=\"store-product-help\" className={helpClassName}>\n Only products owned by this publisher and currently published are\n accepted. The link is reference metadata and does not reserve catalog\n inventory or create digital entitlements.\n </p>\n )}\n </label>\n\n <label className={labelClassName}>\n Message <span className=\"font-normal text-text-muted\">(optional)</span>\n <textarea\n value={form.message}\n onChange={updateField('message')}\n maxLength={1000}\n rows={4}\n aria-invalid={Boolean(errors.message)}\n aria-describedby={errors.message ? 'message-error' : 'message-help'}\n placeholder=\"Add packaging, quality, or delivery notes relevant to this offer.\"\n className={`${inputClassName} resize-y`}\n />\n {fieldError('message')}\n {!errors.message ? (\n <p id=\"message-help\" className={helpClassName}>\n {form.message.length}/1,000 characters\n </p>\n ) : null}\n </label>\n </div>\n\n <button\n type=\"submit\"\n disabled={submitting}\n className={`${primaryButtonClassName} mt-6 w-full`}\n >\n {submitting ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden=\"true\" />\n ) : offer ? (\n <Save className=\"size-4\" aria-hidden=\"true\" />\n ) : (\n <TicketCheck className=\"size-4\" aria-hidden=\"true\" />\n )}\n {submitting ? 'Saving offer…' : offer ? 'Update offer' : 'Submit offer'}\n </button>\n </GlassCard>\n </form>\n ) : offer ? (\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Your offer</h2>\n <p className=\"mt-1 text-xs text-text-muted\">\n Updated {formatDateTime(offer.updatedAt)}\n </p>\n </div>\n <SourcingStatusBadge status={offer.status} />\n </div>\n <dl className=\"mt-5 space-y-4 text-sm\">\n <div>\n <dt className=\"text-xs text-text-muted\">Unit price</dt>\n <dd className=\"mt-0.5 text-lg font-semibold text-text-primary\">\n {formatMoney(offer.unitPrice, offer.currency)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-muted\">Promised delivery</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(offer.deliveryDate)}\n </dd>\n </div>\n {offer.message ? (\n <div>\n <dt className=\"text-xs text-text-muted\">Message</dt>\n <dd className=\"mt-1 whitespace-pre-wrap text-text-secondary\">\n {offer.message}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n ) : (\n <ContextRequiredPanel\n title=\"This request is closed\"\n description=\"The buyer matched or canceled this request before your publisher submitted an offer.\"\n />\n )}\n </div>\n </>\n ) : null}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -64,7 +64,7 @@ var O = () => {
64
64
  }
65
65
  }, $ = ve ?? F?.acceptedOrder ?? null;
66
66
  return /* @__PURE__ */ T("div", {
67
- className: "min-h-full bg-surface-default",
67
+ className: "min-h-full bg-surface",
68
68
  children: [
69
69
  /* @__PURE__ */ w(re, {
70
70
  title: F?.productName ?? "Sourcing request",
@@ -136,7 +136,7 @@ var O = () => {
136
136
  }),
137
137
  V ? /* @__PURE__ */ w("div", {
138
138
  role: "alert",
139
- className: "mb-5 rounded-lg border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
139
+ className: "mb-5 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text",
140
140
  children: V
141
141
  }) : null,
142
142
  $ ? /* @__PURE__ */ w(ge, {
@@ -197,7 +197,7 @@ var O = () => {
197
197
  /* @__PURE__ */ T("div", {
198
198
  className: "flex flex-wrap items-start justify-between gap-3",
199
199
  children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
200
- className: "text-sm font-medium text-text-accent",
200
+ className: "text-sm font-medium text-accent-primary",
201
201
  children: F.category
202
202
  }), /* @__PURE__ */ w("h2", {
203
203
  className: "mt-1 text-xl font-semibold text-text-primary",
@@ -209,15 +209,15 @@ var O = () => {
209
209
  children: F.summary
210
210
  }) : null,
211
211
  /* @__PURE__ */ T("dl", {
212
- className: "mt-6 grid gap-5 border-t border-border-seam pt-5 sm:grid-cols-2",
212
+ className: "mt-6 grid gap-5 border-t border-border-subtle pt-5 sm:grid-cols-2",
213
213
  children: [
214
214
  /* @__PURE__ */ T("div", {
215
215
  className: "flex gap-3",
216
216
  children: [/* @__PURE__ */ w(fe, {
217
- className: "mt-0.5 size-5 shrink-0 text-text-tertiary",
217
+ className: "mt-0.5 size-5 shrink-0 text-text-muted",
218
218
  "aria-hidden": "true"
219
219
  }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
220
- className: "text-xs text-text-tertiary",
220
+ className: "text-xs text-text-muted",
221
221
  children: "Quantity"
222
222
  }), /* @__PURE__ */ T("dd", {
223
223
  className: "mt-0.5 font-medium text-text-primary",
@@ -231,10 +231,10 @@ var O = () => {
231
231
  /* @__PURE__ */ T("div", {
232
232
  className: "flex gap-3",
233
233
  children: [/* @__PURE__ */ w(de, {
234
- className: "mt-0.5 size-5 shrink-0 text-text-tertiary",
234
+ className: "mt-0.5 size-5 shrink-0 text-text-muted",
235
235
  "aria-hidden": "true"
236
236
  }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
237
- className: "text-xs text-text-tertiary",
237
+ className: "text-xs text-text-muted",
238
238
  children: "Target unit price"
239
239
  }), /* @__PURE__ */ w("dd", {
240
240
  className: "mt-0.5 font-medium text-text-primary",
@@ -244,10 +244,10 @@ var O = () => {
244
244
  /* @__PURE__ */ T("div", {
245
245
  className: "flex gap-3",
246
246
  children: [/* @__PURE__ */ w(le, {
247
- className: "mt-0.5 size-5 shrink-0 text-text-tertiary",
247
+ className: "mt-0.5 size-5 shrink-0 text-text-muted",
248
248
  "aria-hidden": "true"
249
249
  }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
250
- className: "text-xs text-text-tertiary",
250
+ className: "text-xs text-text-muted",
251
251
  children: "Delivery window"
252
252
  }), /* @__PURE__ */ T("dd", {
253
253
  className: "mt-0.5 font-medium text-text-primary",
@@ -262,10 +262,10 @@ var O = () => {
262
262
  /* @__PURE__ */ T("div", {
263
263
  className: "flex gap-3",
264
264
  children: [/* @__PURE__ */ w(x, {
265
- className: "mt-0.5 size-5 shrink-0 text-text-tertiary",
265
+ className: "mt-0.5 size-5 shrink-0 text-text-muted",
266
266
  "aria-hidden": "true"
267
267
  }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
268
- className: "text-xs text-text-tertiary",
268
+ className: "text-xs text-text-muted",
269
269
  children: "Destination"
270
270
  }), /* @__PURE__ */ w("dd", {
271
271
  className: "mt-0.5 font-medium text-text-primary",
@@ -288,28 +288,28 @@ var O = () => {
288
288
  className: "mt-4 space-y-4 text-sm",
289
289
  children: [
290
290
  /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
291
- className: "text-text-tertiary",
291
+ className: "text-text-muted",
292
292
  children: "Created"
293
293
  }), /* @__PURE__ */ w("dd", {
294
294
  className: "font-medium text-text-primary",
295
295
  children: c(F.createdAt)
296
296
  })] }),
297
297
  /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
298
- className: "text-text-tertiary",
298
+ className: "text-text-muted",
299
299
  children: "Last updated"
300
300
  }), /* @__PURE__ */ w("dd", {
301
301
  className: "font-medium text-text-primary",
302
302
  children: c(F.updatedAt)
303
303
  })] }),
304
304
  F.matchedAt ? /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
305
- className: "text-text-tertiary",
305
+ className: "text-text-muted",
306
306
  children: "Matched"
307
307
  }), /* @__PURE__ */ w("dd", {
308
308
  className: "font-medium text-text-primary",
309
309
  children: c(F.matchedAt)
310
310
  })] }) : null,
311
311
  F.canceledAt ? /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
312
- className: "text-text-tertiary",
312
+ className: "text-text-muted",
313
313
  children: "Canceled"
314
314
  }), /* @__PURE__ */ w("dd", {
315
315
  className: "font-medium text-text-primary",
@@ -365,7 +365,7 @@ var O = () => {
365
365
  alt: "",
366
366
  className: "size-11 shrink-0 rounded-lg object-cover"
367
367
  }) : /* @__PURE__ */ w("span", {
368
- className: "flex size-11 shrink-0 items-center justify-center rounded-lg bg-surface-muted text-text-tertiary",
368
+ className: "flex size-11 shrink-0 items-center justify-center rounded-lg bg-surface-sunken text-text-muted",
369
369
  children: /* @__PURE__ */ w(he, {
370
370
  className: "size-5",
371
371
  "aria-hidden": "true"
@@ -378,11 +378,11 @@ var O = () => {
378
378
  className: "truncate font-semibold text-text-primary",
379
379
  children: e.publisher?.name ?? "Verified publisher"
380
380
  }), e.publisher?.isVerified ? /* @__PURE__ */ w(ce, {
381
- className: "size-4 shrink-0 text-text-accent",
381
+ className: "size-4 shrink-0 text-accent-primary",
382
382
  "aria-label": "Verified publisher"
383
383
  }) : null]
384
384
  }), /* @__PURE__ */ T("p", {
385
- className: "text-xs text-text-tertiary",
385
+ className: "text-xs text-text-muted",
386
386
  children: ["Offered ", s(e.createdAt)]
387
387
  })]
388
388
  })]
@@ -391,13 +391,13 @@ var O = () => {
391
391
  /* @__PURE__ */ T("dl", {
392
392
  className: "mt-5 grid grid-cols-2 gap-4 text-sm",
393
393
  children: [/* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
394
- className: "text-xs text-text-tertiary",
394
+ className: "text-xs text-text-muted",
395
395
  children: "Unit price"
396
396
  }), /* @__PURE__ */ w("dd", {
397
397
  className: "mt-0.5 text-lg font-semibold text-text-primary",
398
398
  children: l(e.unitPrice, e.currency)
399
399
  })] }), /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
400
- className: "text-xs text-text-tertiary",
400
+ className: "text-xs text-text-muted",
401
401
  children: "Delivery date"
402
402
  }), /* @__PURE__ */ w("dd", {
403
403
  className: "mt-0.5 font-medium text-text-primary",
@@ -405,7 +405,7 @@ var O = () => {
405
405
  })] })]
406
406
  }),
407
407
  e.message ? /* @__PURE__ */ w("p", {
408
- className: "mt-4 rounded-lg bg-surface-muted p-3 text-sm leading-6 text-text-secondary",
408
+ className: "mt-4 rounded-lg bg-surface-sunken p-3 text-sm leading-6 text-text-secondary",
409
409
  children: e.message
410
410
  }) : null,
411
411
  t ? /* @__PURE__ */ T("button", {
@@ -1 +1 @@
1
- {"version":3,"file":"SourcingRequestDetailPage.js","names":[],"sources":["../../src/pages/SourcingRequestDetailPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { FC } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport {\n BadgeCheck,\n CalendarDays,\n Check,\n CircleDollarSign,\n FileText,\n MapPin,\n PackageSearch,\n Receipt,\n ShoppingBag,\n Trash2,\n UserRound,\n} from 'lucide-react';\nimport { EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingOfferStatus, SourcingRequestStatus } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport {\n type AcceptedSourcingOrder,\n type BuyerSourcingRequestDetail,\n useSourcingApi,\n} from '../hooks/useSourcing';\nimport {\n ContextRequiredPanel,\n dangerButtonClassName,\n formatDate,\n formatDateTime,\n formatLocation,\n formatMoney,\n formatSourcingUnit,\n joinStorePath,\n primaryButtonClassName,\n secondaryButtonClassName,\n SourcingEmptyState,\n SourcingErrorState,\n SourcingLoadingState,\n SourcingPageHeader,\n SourcingStatusBadge,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\nimport { SourcingConfirmationDialog } from '../components/sourcing/SourcingConfirmationDialog';\n\nexport const SourcingRequestDetailPage: FC = () => {\n const navigate = useNavigate();\n const { requestId } = useParams<{ requestId: string }>();\n const { basePath } = useStore();\n const { hasOrganizationContext, getBuyerRequest, acceptOffer, cancelBuyerRequest } =\n useSourcingApi();\n const [request, setRequest] = useState<BuyerSourcingRequestDetail | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n const [confirmOfferId, setConfirmOfferId] = useState<string | null>(null);\n const [confirmCancel, setConfirmCancel] = useState(false);\n const [acting, setActing] = useState(false);\n const [acceptedOrder, setAcceptedOrder] = useState<AcceptedSourcingOrder | null>(null);\n const acceptTriggerRef = useRef<HTMLButtonElement | null>(null);\n\n const listPath = joinStorePath(basePath, 'sourcing/requests');\n\n const load = useCallback(async () => {\n if (!hasOrganizationContext || !requestId) return;\n setLoading(true);\n setError(null);\n try {\n const result = await getBuyerRequest(requestId);\n setRequest(result);\n if (!result) setError('This sourcing request was not found in the active organization.');\n } catch (loadError) {\n setError(toErrorMessage(loadError, 'The sourcing request could not be loaded.'));\n } finally {\n setLoading(false);\n }\n }, [getBuyerRequest, hasOrganizationContext, requestId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const closeOfferConfirmation = () => {\n setConfirmOfferId(null);\n window.requestAnimationFrame(() => acceptTriggerRef.current?.focus());\n };\n\n const offers = useMemo(() => {\n if (!request) return [];\n const rank: Record<SourcingOfferStatus, number> = {\n [SourcingOfferStatus.Accepted]: 0,\n [SourcingOfferStatus.Active]: 1,\n [SourcingOfferStatus.Rejected]: 2,\n };\n return [...request.offers].sort((left, right) => rank[left.status] - rank[right.status]);\n }, [request]);\n\n const confirmingOffer = confirmOfferId\n ? offers.find((offer) => offer.id === confirmOfferId)\n : undefined;\n\n const handleAccept = async (offerId: string) => {\n if (acting) return;\n setActing(true);\n setActionError(null);\n try {\n const order = await acceptOffer(offerId);\n setAcceptedOrder(order);\n setConfirmOfferId(null);\n await load();\n } catch (acceptError) {\n closeOfferConfirmation();\n setActionError(\n toErrorMessage(\n acceptError,\n 'This offer could not be accepted. The request may already have been matched.'\n )\n );\n } finally {\n setActing(false);\n }\n };\n\n const handleCancel = async () => {\n if (!request || acting) return;\n setActing(true);\n setActionError(null);\n try {\n await cancelBuyerRequest(request.id);\n setConfirmCancel(false);\n await load();\n } catch (cancelError) {\n setConfirmCancel(false);\n setActionError(toErrorMessage(cancelError, 'This sourcing request could not be canceled.'));\n } finally {\n setActing(false);\n }\n };\n\n const order = acceptedOrder ?? request?.acceptedOrder ?? null;\n\n return (\n <div className=\"min-h-full bg-surface-default\">\n <SourcingPageHeader\n title={request?.productName ?? 'Sourcing request'}\n description=\"Review request details and compare offers visible only to the owning buyer organization.\"\n icon={<FileText className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(listPath)}\n actions={\n request?.status === SourcingRequestStatus.Open ? (\n <button\n type=\"button\"\n onClick={() => setConfirmCancel(true)}\n disabled={acting}\n className={dangerButtonClassName}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n Cancel request\n </button>\n ) : undefined\n }\n />\n\n <SourcingConfirmationDialog\n open={confirmCancel}\n title=\"Cancel this open request?\"\n description=\"Publishers will no longer be able to discover it or submit offers. Existing active offers will be rejected. This action cannot be undone.\"\n confirmLabel=\"Confirm cancellation\"\n cancelLabel=\"Keep request open\"\n busy={acting}\n destructive\n onConfirm={() => void handleCancel()}\n onCancel={() => setConfirmCancel(false)}\n />\n\n <SourcingConfirmationDialog\n open={Boolean(confirmingOffer)}\n title=\"Accept this offer?\"\n description={\n confirmingOffer ? (\n <>\n Accept {confirmingOffer.publisher?.name ?? 'this verified publisher'}’s offer for{' '}\n {confirmingOffer.quantity.toLocaleString()} {formatSourcingUnit(confirmingOffer.unit)}{' '}\n at {formatMoney(confirmingOffer.unitPrice, confirmingOffer.currency)} per{' '}\n {formatSourcingUnit(confirmingOffer.unit)}? Store will calculate the authoritative\n total from this persisted offer, create one unpaid order, and reject all competing\n offers. You cannot choose another offer afterward.\n </>\n ) : null\n }\n confirmLabel=\"Confirm and create order\"\n cancelLabel=\"Not yet\"\n busy={acting}\n onConfirm={() => {\n if (confirmingOffer) void handleAccept(confirmingOffer.id);\n }}\n onCancel={closeOfferConfirmation}\n />\n\n <main className=\"mx-auto max-w-6xl px-4 py-6 sm:px-6\">\n {!hasOrganizationContext ? (\n <ContextRequiredPanel\n title=\"Choose the request's organization\"\n description=\"Select the global organization that owns this sourcing request. A farm workspace is not required.\"\n />\n ) : loading && !request ? (\n <SourcingLoadingState label=\"Loading request and offers…\" />\n ) : error && !request ? (\n <SourcingErrorState\n title=\"Sourcing request unavailable\"\n message={error}\n onRetry={requestId ? () => void load() : undefined}\n />\n ) : request ? (\n <>\n <PagePurpose className=\"mb-6\">\n Compare the seller's unit price, promised delivery date, and message. Acceptance is\n atomic: Store claims this open request, creates exactly one order from the persisted\n offer, accepts the winner, and rejects every sibling offer.\n </PagePurpose>\n\n {actionError ? (\n <div\n role=\"alert\"\n className=\"mb-5 rounded-lg border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {actionError}\n </div>\n ) : null}\n\n {order ? (\n <EmphasisPanel className=\"mb-6\">\n <div\n aria-live=\"polite\"\n className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex items-start gap-3\">\n <span className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-status-success-bg-subtle text-status-success-text\">\n <Check className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div>\n <h2 className=\"font-semibold text-text-primary\">\n Offer accepted and order created\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Order {order.id} · {formatMoney(order.total, order.currency)} ·{' '}\n {order.status}\n </p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n {order.status === 'PENDING' ? (\n <button\n type=\"button\"\n onClick={() => navigate(`/billing/checkout/store/${order.id}`)}\n className={primaryButtonClassName}\n >\n <ShoppingBag className=\"size-4\" aria-hidden=\"true\" />\n Continue to checkout\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={() => navigate(joinStorePath(basePath, 'orders'))}\n className={secondaryButtonClassName}\n >\n <Receipt className=\"size-4\" aria-hidden=\"true\" />\n View my orders\n </button>\n </div>\n </div>\n </EmphasisPanel>\n ) : null}\n\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,2fr)_minmax(280px,1fr)]\">\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <p className=\"text-sm font-medium text-text-accent\">{request.category}</p>\n <h2 className=\"mt-1 text-xl font-semibold text-text-primary\">\n {request.productName}\n </h2>\n </div>\n <SourcingStatusBadge status={request.status} />\n </div>\n {request.summary ? (\n <p className=\"mt-4 whitespace-pre-wrap text-sm leading-6 text-text-secondary\">\n {request.summary}\n </p>\n ) : null}\n\n <dl className=\"mt-6 grid gap-5 border-t border-border-seam pt-5 sm:grid-cols-2\">\n <div className=\"flex gap-3\">\n <PackageSearch\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Quantity</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {request.quantity.toLocaleString()} {formatSourcingUnit(request.unit)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CircleDollarSign\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Target unit price</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatMoney(request.targetUnitPrice, request.targetCurrency)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CalendarDays\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Delivery window</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(request.deliveryWindowStart)} –{' '}\n {formatDateTime(request.deliveryWindowEnd)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <MapPin\n className=\"mt-0.5 size-5 shrink-0 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-tertiary\">Destination</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatLocation({\n country: request.deliveryCountry,\n region: request.deliveryRegion,\n city: request.deliveryCity,\n })}\n </dd>\n </div>\n </div>\n </dl>\n </GlassCard>\n\n <GlassCard className=\"p-5\">\n <h2 className=\"font-semibold text-text-primary\">Request timeline</h2>\n <dl className=\"mt-4 space-y-4 text-sm\">\n <div>\n <dt className=\"text-text-tertiary\">Created</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-tertiary\">Last updated</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.updatedAt)}\n </dd>\n </div>\n {request.matchedAt ? (\n <div>\n <dt className=\"text-text-tertiary\">Matched</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.matchedAt)}\n </dd>\n </div>\n ) : null}\n {request.canceledAt ? (\n <div>\n <dt className=\"text-text-tertiary\">Canceled</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.canceledAt)}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n </div>\n\n <section aria-labelledby=\"sourcing-offers-heading\" className=\"mt-8\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div>\n <h2\n id=\"sourcing-offers-heading\"\n className=\"text-xl font-semibold text-text-primary\"\n >\n Publisher offers\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {offers.length} {offers.length === 1 ? 'offer' : 'offers'} received\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => void load()}\n disabled={loading || acting}\n className={secondaryButtonClassName}\n >\n Refresh offers\n </button>\n </div>\n\n {offers.length === 0 ? (\n <div className=\"mt-5\">\n <SourcingEmptyState\n title={\n request.status === SourcingRequestStatus.Open\n ? 'No offers yet'\n : 'No offers were received'\n }\n description={\n request.status === SourcingRequestStatus.Open\n ? 'Eligible verified publishers can discover this request while it remains open.'\n : 'This request closed without any publisher offers.'\n }\n />\n </div>\n ) : (\n <ul className=\"mt-5 grid gap-4 lg:grid-cols-2\">\n {offers.map((offer) => {\n const canAccept =\n request.status === SourcingRequestStatus.Open &&\n offer.status === SourcingOfferStatus.Active;\n return (\n <li key={offer.id}>\n <GlassCard className=\"h-full p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n {offer.publisher?.logoUrl ? (\n <img\n src={offer.publisher.logoUrl}\n alt=\"\"\n className=\"size-11 shrink-0 rounded-lg object-cover\"\n />\n ) : (\n <span className=\"flex size-11 shrink-0 items-center justify-center rounded-lg bg-surface-muted text-text-tertiary\">\n <UserRound className=\"size-5\" aria-hidden=\"true\" />\n </span>\n )}\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n <h3 className=\"truncate font-semibold text-text-primary\">\n {offer.publisher?.name ?? 'Verified publisher'}\n </h3>\n {offer.publisher?.isVerified ? (\n <BadgeCheck\n className=\"size-4 shrink-0 text-text-accent\"\n aria-label=\"Verified publisher\"\n />\n ) : null}\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Offered {formatDate(offer.createdAt)}\n </p>\n </div>\n </div>\n <SourcingStatusBadge status={offer.status} />\n </div>\n\n <dl className=\"mt-5 grid grid-cols-2 gap-4 text-sm\">\n <div>\n <dt className=\"text-xs text-text-tertiary\">Unit price</dt>\n <dd className=\"mt-0.5 text-lg font-semibold text-text-primary\">\n {formatMoney(offer.unitPrice, offer.currency)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-tertiary\">Delivery date</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(offer.deliveryDate)}\n </dd>\n </div>\n </dl>\n\n {offer.message ? (\n <p className=\"mt-4 rounded-lg bg-surface-muted p-3 text-sm leading-6 text-text-secondary\">\n {offer.message}\n </p>\n ) : null}\n\n {canAccept ? (\n <button\n type=\"button\"\n onClick={(event) => {\n acceptTriggerRef.current = event.currentTarget;\n setActionError(null);\n setConfirmOfferId(offer.id);\n }}\n className={`${primaryButtonClassName} mt-5 w-full`}\n >\n <ShoppingBag className=\"size-4\" aria-hidden=\"true\" />\n Accept offer\n </button>\n ) : offer.order ? (\n <div className=\"mt-5 rounded-lg border border-status-success-border bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text\">\n Order {offer.order.id} ·{' '}\n {formatMoney(offer.order.total, offer.order.currency)}\n </div>\n ) : null}\n </GlassCard>\n </li>\n );\n })}\n </ul>\n )}\n </section>\n </>\n ) : null}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"SourcingRequestDetailPage.js","names":[],"sources":["../../src/pages/SourcingRequestDetailPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { FC } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport {\n BadgeCheck,\n CalendarDays,\n Check,\n CircleDollarSign,\n FileText,\n MapPin,\n PackageSearch,\n Receipt,\n ShoppingBag,\n Trash2,\n UserRound,\n} from 'lucide-react';\nimport { EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingOfferStatus, SourcingRequestStatus } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport {\n type AcceptedSourcingOrder,\n type BuyerSourcingRequestDetail,\n useSourcingApi,\n} from '../hooks/useSourcing';\nimport {\n ContextRequiredPanel,\n dangerButtonClassName,\n formatDate,\n formatDateTime,\n formatLocation,\n formatMoney,\n formatSourcingUnit,\n joinStorePath,\n primaryButtonClassName,\n secondaryButtonClassName,\n SourcingEmptyState,\n SourcingErrorState,\n SourcingLoadingState,\n SourcingPageHeader,\n SourcingStatusBadge,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\nimport { SourcingConfirmationDialog } from '../components/sourcing/SourcingConfirmationDialog';\n\nexport const SourcingRequestDetailPage: FC = () => {\n const navigate = useNavigate();\n const { requestId } = useParams<{ requestId: string }>();\n const { basePath } = useStore();\n const { hasOrganizationContext, getBuyerRequest, acceptOffer, cancelBuyerRequest } =\n useSourcingApi();\n const [request, setRequest] = useState<BuyerSourcingRequestDetail | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n const [confirmOfferId, setConfirmOfferId] = useState<string | null>(null);\n const [confirmCancel, setConfirmCancel] = useState(false);\n const [acting, setActing] = useState(false);\n const [acceptedOrder, setAcceptedOrder] = useState<AcceptedSourcingOrder | null>(null);\n const acceptTriggerRef = useRef<HTMLButtonElement | null>(null);\n\n const listPath = joinStorePath(basePath, 'sourcing/requests');\n\n const load = useCallback(async () => {\n if (!hasOrganizationContext || !requestId) return;\n setLoading(true);\n setError(null);\n try {\n const result = await getBuyerRequest(requestId);\n setRequest(result);\n if (!result) setError('This sourcing request was not found in the active organization.');\n } catch (loadError) {\n setError(toErrorMessage(loadError, 'The sourcing request could not be loaded.'));\n } finally {\n setLoading(false);\n }\n }, [getBuyerRequest, hasOrganizationContext, requestId]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const closeOfferConfirmation = () => {\n setConfirmOfferId(null);\n window.requestAnimationFrame(() => acceptTriggerRef.current?.focus());\n };\n\n const offers = useMemo(() => {\n if (!request) return [];\n const rank: Record<SourcingOfferStatus, number> = {\n [SourcingOfferStatus.Accepted]: 0,\n [SourcingOfferStatus.Active]: 1,\n [SourcingOfferStatus.Rejected]: 2,\n };\n return [...request.offers].sort((left, right) => rank[left.status] - rank[right.status]);\n }, [request]);\n\n const confirmingOffer = confirmOfferId\n ? offers.find((offer) => offer.id === confirmOfferId)\n : undefined;\n\n const handleAccept = async (offerId: string) => {\n if (acting) return;\n setActing(true);\n setActionError(null);\n try {\n const order = await acceptOffer(offerId);\n setAcceptedOrder(order);\n setConfirmOfferId(null);\n await load();\n } catch (acceptError) {\n closeOfferConfirmation();\n setActionError(\n toErrorMessage(\n acceptError,\n 'This offer could not be accepted. The request may already have been matched.'\n )\n );\n } finally {\n setActing(false);\n }\n };\n\n const handleCancel = async () => {\n if (!request || acting) return;\n setActing(true);\n setActionError(null);\n try {\n await cancelBuyerRequest(request.id);\n setConfirmCancel(false);\n await load();\n } catch (cancelError) {\n setConfirmCancel(false);\n setActionError(toErrorMessage(cancelError, 'This sourcing request could not be canceled.'));\n } finally {\n setActing(false);\n }\n };\n\n const order = acceptedOrder ?? request?.acceptedOrder ?? null;\n\n return (\n <div className=\"min-h-full bg-surface\">\n <SourcingPageHeader\n title={request?.productName ?? 'Sourcing request'}\n description=\"Review request details and compare offers visible only to the owning buyer organization.\"\n icon={<FileText className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(listPath)}\n actions={\n request?.status === SourcingRequestStatus.Open ? (\n <button\n type=\"button\"\n onClick={() => setConfirmCancel(true)}\n disabled={acting}\n className={dangerButtonClassName}\n >\n <Trash2 className=\"size-4\" aria-hidden=\"true\" />\n Cancel request\n </button>\n ) : undefined\n }\n />\n\n <SourcingConfirmationDialog\n open={confirmCancel}\n title=\"Cancel this open request?\"\n description=\"Publishers will no longer be able to discover it or submit offers. Existing active offers will be rejected. This action cannot be undone.\"\n confirmLabel=\"Confirm cancellation\"\n cancelLabel=\"Keep request open\"\n busy={acting}\n destructive\n onConfirm={() => void handleCancel()}\n onCancel={() => setConfirmCancel(false)}\n />\n\n <SourcingConfirmationDialog\n open={Boolean(confirmingOffer)}\n title=\"Accept this offer?\"\n description={\n confirmingOffer ? (\n <>\n Accept {confirmingOffer.publisher?.name ?? 'this verified publisher'}’s offer for{' '}\n {confirmingOffer.quantity.toLocaleString()} {formatSourcingUnit(confirmingOffer.unit)}{' '}\n at {formatMoney(confirmingOffer.unitPrice, confirmingOffer.currency)} per{' '}\n {formatSourcingUnit(confirmingOffer.unit)}? Store will calculate the authoritative\n total from this persisted offer, create one unpaid order, and reject all competing\n offers. You cannot choose another offer afterward.\n </>\n ) : null\n }\n confirmLabel=\"Confirm and create order\"\n cancelLabel=\"Not yet\"\n busy={acting}\n onConfirm={() => {\n if (confirmingOffer) void handleAccept(confirmingOffer.id);\n }}\n onCancel={closeOfferConfirmation}\n />\n\n <main className=\"mx-auto max-w-6xl px-4 py-6 sm:px-6\">\n {!hasOrganizationContext ? (\n <ContextRequiredPanel\n title=\"Choose the request's organization\"\n description=\"Select the global organization that owns this sourcing request. A farm workspace is not required.\"\n />\n ) : loading && !request ? (\n <SourcingLoadingState label=\"Loading request and offers…\" />\n ) : error && !request ? (\n <SourcingErrorState\n title=\"Sourcing request unavailable\"\n message={error}\n onRetry={requestId ? () => void load() : undefined}\n />\n ) : request ? (\n <>\n <PagePurpose className=\"mb-6\">\n Compare the seller's unit price, promised delivery date, and message. Acceptance is\n atomic: Store claims this open request, creates exactly one order from the persisted\n offer, accepts the winner, and rejects every sibling offer.\n </PagePurpose>\n\n {actionError ? (\n <div\n role=\"alert\"\n className=\"mb-5 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text\"\n >\n {actionError}\n </div>\n ) : null}\n\n {order ? (\n <EmphasisPanel className=\"mb-6\">\n <div\n aria-live=\"polite\"\n className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\"\n >\n <div className=\"flex items-start gap-3\">\n <span className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-status-success-bg-subtle text-status-success-text\">\n <Check className=\"size-5\" aria-hidden=\"true\" />\n </span>\n <div>\n <h2 className=\"font-semibold text-text-primary\">\n Offer accepted and order created\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Order {order.id} · {formatMoney(order.total, order.currency)} ·{' '}\n {order.status}\n </p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n {order.status === 'PENDING' ? (\n <button\n type=\"button\"\n onClick={() => navigate(`/billing/checkout/store/${order.id}`)}\n className={primaryButtonClassName}\n >\n <ShoppingBag className=\"size-4\" aria-hidden=\"true\" />\n Continue to checkout\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={() => navigate(joinStorePath(basePath, 'orders'))}\n className={secondaryButtonClassName}\n >\n <Receipt className=\"size-4\" aria-hidden=\"true\" />\n View my orders\n </button>\n </div>\n </div>\n </EmphasisPanel>\n ) : null}\n\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,2fr)_minmax(280px,1fr)]\">\n <GlassCard className=\"p-5 sm:p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <p className=\"text-sm font-medium text-accent-primary\">{request.category}</p>\n <h2 className=\"mt-1 text-xl font-semibold text-text-primary\">\n {request.productName}\n </h2>\n </div>\n <SourcingStatusBadge status={request.status} />\n </div>\n {request.summary ? (\n <p className=\"mt-4 whitespace-pre-wrap text-sm leading-6 text-text-secondary\">\n {request.summary}\n </p>\n ) : null}\n\n <dl className=\"mt-6 grid gap-5 border-t border-border-subtle pt-5 sm:grid-cols-2\">\n <div className=\"flex gap-3\">\n <PackageSearch\n className=\"mt-0.5 size-5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-muted\">Quantity</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {request.quantity.toLocaleString()} {formatSourcingUnit(request.unit)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CircleDollarSign\n className=\"mt-0.5 size-5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-muted\">Target unit price</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatMoney(request.targetUnitPrice, request.targetCurrency)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <CalendarDays\n className=\"mt-0.5 size-5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <div>\n <dt className=\"text-xs text-text-muted\">Delivery window</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(request.deliveryWindowStart)} –{' '}\n {formatDateTime(request.deliveryWindowEnd)}\n </dd>\n </div>\n </div>\n <div className=\"flex gap-3\">\n <MapPin className=\"mt-0.5 size-5 shrink-0 text-text-muted\" aria-hidden=\"true\" />\n <div>\n <dt className=\"text-xs text-text-muted\">Destination</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatLocation({\n country: request.deliveryCountry,\n region: request.deliveryRegion,\n city: request.deliveryCity,\n })}\n </dd>\n </div>\n </div>\n </dl>\n </GlassCard>\n\n <GlassCard className=\"p-5\">\n <h2 className=\"font-semibold text-text-primary\">Request timeline</h2>\n <dl className=\"mt-4 space-y-4 text-sm\">\n <div>\n <dt className=\"text-text-muted\">Created</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-muted\">Last updated</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.updatedAt)}\n </dd>\n </div>\n {request.matchedAt ? (\n <div>\n <dt className=\"text-text-muted\">Matched</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.matchedAt)}\n </dd>\n </div>\n ) : null}\n {request.canceledAt ? (\n <div>\n <dt className=\"text-text-muted\">Canceled</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDateTime(request.canceledAt)}\n </dd>\n </div>\n ) : null}\n </dl>\n </GlassCard>\n </div>\n\n <section aria-labelledby=\"sourcing-offers-heading\" className=\"mt-8\">\n <div className=\"flex flex-wrap items-end justify-between gap-3\">\n <div>\n <h2\n id=\"sourcing-offers-heading\"\n className=\"text-xl font-semibold text-text-primary\"\n >\n Publisher offers\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {offers.length} {offers.length === 1 ? 'offer' : 'offers'} received\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => void load()}\n disabled={loading || acting}\n className={secondaryButtonClassName}\n >\n Refresh offers\n </button>\n </div>\n\n {offers.length === 0 ? (\n <div className=\"mt-5\">\n <SourcingEmptyState\n title={\n request.status === SourcingRequestStatus.Open\n ? 'No offers yet'\n : 'No offers were received'\n }\n description={\n request.status === SourcingRequestStatus.Open\n ? 'Eligible verified publishers can discover this request while it remains open.'\n : 'This request closed without any publisher offers.'\n }\n />\n </div>\n ) : (\n <ul className=\"mt-5 grid gap-4 lg:grid-cols-2\">\n {offers.map((offer) => {\n const canAccept =\n request.status === SourcingRequestStatus.Open &&\n offer.status === SourcingOfferStatus.Active;\n return (\n <li key={offer.id}>\n <GlassCard className=\"h-full p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n {offer.publisher?.logoUrl ? (\n <img\n src={offer.publisher.logoUrl}\n alt=\"\"\n className=\"size-11 shrink-0 rounded-lg object-cover\"\n />\n ) : (\n <span className=\"flex size-11 shrink-0 items-center justify-center rounded-lg bg-surface-sunken text-text-muted\">\n <UserRound className=\"size-5\" aria-hidden=\"true\" />\n </span>\n )}\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5\">\n <h3 className=\"truncate font-semibold text-text-primary\">\n {offer.publisher?.name ?? 'Verified publisher'}\n </h3>\n {offer.publisher?.isVerified ? (\n <BadgeCheck\n className=\"size-4 shrink-0 text-accent-primary\"\n aria-label=\"Verified publisher\"\n />\n ) : null}\n </div>\n <p className=\"text-xs text-text-muted\">\n Offered {formatDate(offer.createdAt)}\n </p>\n </div>\n </div>\n <SourcingStatusBadge status={offer.status} />\n </div>\n\n <dl className=\"mt-5 grid grid-cols-2 gap-4 text-sm\">\n <div>\n <dt className=\"text-xs text-text-muted\">Unit price</dt>\n <dd className=\"mt-0.5 text-lg font-semibold text-text-primary\">\n {formatMoney(offer.unitPrice, offer.currency)}\n </dd>\n </div>\n <div>\n <dt className=\"text-xs text-text-muted\">Delivery date</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDateTime(offer.deliveryDate)}\n </dd>\n </div>\n </dl>\n\n {offer.message ? (\n <p className=\"mt-4 rounded-lg bg-surface-sunken p-3 text-sm leading-6 text-text-secondary\">\n {offer.message}\n </p>\n ) : null}\n\n {canAccept ? (\n <button\n type=\"button\"\n onClick={(event) => {\n acceptTriggerRef.current = event.currentTarget;\n setActionError(null);\n setConfirmOfferId(offer.id);\n }}\n className={`${primaryButtonClassName} mt-5 w-full`}\n >\n <ShoppingBag className=\"size-4\" aria-hidden=\"true\" />\n Accept offer\n </button>\n ) : offer.order ? (\n <div className=\"mt-5 rounded-lg border border-status-success-border bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text\">\n Order {offer.order.id} ·{' '}\n {formatMoney(offer.order.total, offer.order.currency)}\n </div>\n ) : null}\n </GlassCard>\n </li>\n );\n })}\n </ul>\n )}\n </section>\n </>\n ) : null}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -40,7 +40,7 @@ var P = 30, F = () => {
40
40
  offers: 0
41
41
  }), [z]), $ = p(I, "sourcing/requests/new");
42
42
  return /* @__PURE__ */ j("div", {
43
- className: "min-h-full bg-surface-default",
43
+ className: "min-h-full bg-surface",
44
44
  children: [/* @__PURE__ */ A(s, {
45
45
  title: "Sourcing requests",
46
46
  description: "Request products from verified Store publishers and compare private offers for your organization.",
@@ -64,7 +64,7 @@ var P = 30, F = () => {
64
64
  className: "mb-6",
65
65
  children: "Create one request for the exact quantity, delivery window, and destination you need. Offers remain private to your organization. Accepting one offer creates a Store order and closes the request; all other offers are rejected automatically."
66
66
  }), L ? /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ j("div", {
67
- className: "mb-5 flex flex-col gap-3 rounded-xl border border-border-seam bg-surface-raised p-4 sm:flex-row sm:items-end sm:justify-between",
67
+ className: "mb-5 flex flex-col gap-3 rounded-xl border border-border-subtle bg-surface-elevated p-4 sm:flex-row sm:items-end sm:justify-between",
68
68
  children: [/* @__PURE__ */ j("label", {
69
69
  className: "block sm:max-w-xs sm:flex-1",
70
70
  children: [/* @__PURE__ */ A("span", {
@@ -73,7 +73,7 @@ var P = 30, F = () => {
73
73
  }), /* @__PURE__ */ j("select", {
74
74
  value: V,
75
75
  onChange: (e) => H(e.target.value),
76
- className: "mt-1.5 w-full rounded-lg border border-border-default bg-surface-default px-3 py-2 text-sm text-text-primary outline-none focus:border-action-primary-bg focus:ring-2 focus:ring-action-primary-bg/20",
76
+ className: "mt-1.5 w-full rounded-lg border border-border-default bg-surface px-3 py-2 text-sm text-text-primary outline-none focus:border-action-primary-bg focus:ring-2 focus:ring-action-primary-bg/20",
77
77
  children: [
78
78
  /* @__PURE__ */ A("option", {
79
79
  value: "",
@@ -133,7 +133,7 @@ var P = 30, F = () => {
133
133
  }) : /* @__PURE__ */ j(k, { children: [
134
134
  Y ? /* @__PURE__ */ A("div", {
135
135
  role: "alert",
136
- className: "mb-4 rounded-lg border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
136
+ className: "mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text",
137
137
  children: Y
138
138
  }) : null,
139
139
  /* @__PURE__ */ A("ul", {
@@ -148,7 +148,7 @@ var P = 30, F = () => {
148
148
  children: [/* @__PURE__ */ j("div", {
149
149
  className: "min-w-0",
150
150
  children: [/* @__PURE__ */ j("div", {
151
- className: "flex items-center gap-2 text-xs font-medium text-text-accent",
151
+ className: "flex items-center gap-2 text-xs font-medium text-accent-primary",
152
152
  children: [/* @__PURE__ */ A(T, {
153
153
  className: "size-4",
154
154
  "aria-hidden": "true"
@@ -168,10 +168,10 @@ var P = 30, F = () => {
168
168
  /* @__PURE__ */ j("div", {
169
169
  className: "flex items-start gap-2",
170
170
  children: [/* @__PURE__ */ A(D, {
171
- className: "mt-0.5 size-4 shrink-0 text-text-tertiary",
171
+ className: "mt-0.5 size-4 shrink-0 text-text-muted",
172
172
  "aria-hidden": "true"
173
173
  }), /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ A("dt", {
174
- className: "text-xs text-text-tertiary",
174
+ className: "text-xs text-text-muted",
175
175
  children: "Quantity"
176
176
  }), /* @__PURE__ */ j("dd", {
177
177
  className: "font-medium text-text-primary",
@@ -185,10 +185,10 @@ var P = 30, F = () => {
185
185
  /* @__PURE__ */ j("div", {
186
186
  className: "flex items-start gap-2",
187
187
  children: [/* @__PURE__ */ A(E, {
188
- className: "mt-0.5 size-4 shrink-0 text-text-tertiary",
188
+ className: "mt-0.5 size-4 shrink-0 text-text-muted",
189
189
  "aria-hidden": "true"
190
190
  }), /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ A("dt", {
191
- className: "text-xs text-text-tertiary",
191
+ className: "text-xs text-text-muted",
192
192
  children: "Deliver to"
193
193
  }), /* @__PURE__ */ A("dd", {
194
194
  className: "font-medium text-text-primary",
@@ -202,10 +202,10 @@ var P = 30, F = () => {
202
202
  /* @__PURE__ */ j("div", {
203
203
  className: "flex items-start gap-2 sm:col-span-2",
204
204
  children: [/* @__PURE__ */ A(C, {
205
- className: "mt-0.5 size-4 shrink-0 text-text-tertiary",
205
+ className: "mt-0.5 size-4 shrink-0 text-text-muted",
206
206
  "aria-hidden": "true"
207
207
  }), /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ A("dt", {
208
- className: "text-xs text-text-tertiary",
208
+ className: "text-xs text-text-muted",
209
209
  children: "Delivery window"
210
210
  }), /* @__PURE__ */ j("dd", {
211
211
  className: "font-medium text-text-primary",
@@ -220,7 +220,7 @@ var P = 30, F = () => {
220
220
  ]
221
221
  }),
222
222
  /* @__PURE__ */ j("div", {
223
- className: "mt-5 flex flex-wrap items-center justify-between gap-3 border-t border-border-seam pt-4",
223
+ className: "mt-5 flex flex-wrap items-center justify-between gap-3 border-t border-border-subtle pt-4",
224
224
  children: [/* @__PURE__ */ j("div", { children: [/* @__PURE__ */ j("p", {
225
225
  className: "text-sm font-medium text-text-primary",
226
226
  children: [
@@ -229,7 +229,7 @@ var P = 30, F = () => {
229
229
  t === 1 ? "offer" : "offers"
230
230
  ]
231
231
  }), /* @__PURE__ */ j("p", {
232
- className: "text-xs text-text-tertiary",
232
+ className: "text-xs text-text-muted",
233
233
  children: [
234
234
  "Target",
235
235
  " ",