@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.
- package/dist/components/sourcing/SourcingConfirmationDialog.js +1 -1
- package/dist/components/sourcing/SourcingConfirmationDialog.js.map +1 -1
- package/dist/components/sourcing/SourcingUi.d.ts +2 -2
- package/dist/components/sourcing/SourcingUi.js +7 -7
- package/dist/components/sourcing/SourcingUi.js.map +1 -1
- package/dist/pages/CreateSourcingRequestPage.js +13 -14
- package/dist/pages/CreateSourcingRequestPage.js.map +1 -1
- package/dist/pages/SellerSourcingOffersPage.js +16 -16
- package/dist/pages/SellerSourcingOffersPage.js.map +1 -1
- package/dist/pages/SellerSourcingOpportunitiesPage.js +14 -14
- package/dist/pages/SellerSourcingOpportunitiesPage.js.map +1 -1
- package/dist/pages/SellerSourcingOpportunityDetailPage.js +25 -25
- package/dist/pages/SellerSourcingOpportunityDetailPage.js.map +1 -1
- package/dist/pages/SourcingRequestDetailPage.js +22 -22
- package/dist/pages/SourcingRequestDetailPage.js.map +1 -1
- package/dist/pages/SourcingRequestsPage.js +13 -13
- package/dist/pages/SourcingRequestsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ function l({ open: l, title: u, description: d, confirmLabel: f, cancelLabel: p,
|
|
|
14
14
|
ref: v,
|
|
15
15
|
"aria-labelledby": y,
|
|
16
16
|
"aria-describedby": b,
|
|
17
|
-
className: "m-auto w-[min(32rem,calc(100%-2rem))] rounded-xl border border-border-
|
|
17
|
+
className: "m-auto w-[min(32rem,calc(100%-2rem))] rounded-xl border border-border-subtle bg-surface-elevated p-0 text-text-primary shadow-elevation-4 backdrop:bg-bg-overlay backdrop:backdrop-blur-sm",
|
|
18
18
|
onCancel: (e) => {
|
|
19
19
|
e.preventDefault(), m || _();
|
|
20
20
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourcingConfirmationDialog.js","names":[],"sources":["../../../src/components/sourcing/SourcingConfirmationDialog.tsx"],"sourcesContent":["import { useEffect, useId, useRef } from 'react';\nimport type { ReactNode } from 'react';\nimport { Loader2 } from 'lucide-react';\n\nimport {\n dangerButtonClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n} from './SourcingUi';\n\ninterface SourcingConfirmationDialogProps {\n open: boolean;\n title: string;\n description: ReactNode;\n confirmLabel: string;\n cancelLabel: string;\n busy?: boolean;\n destructive?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function SourcingConfirmationDialog({\n open,\n title,\n description,\n confirmLabel,\n cancelLabel,\n busy = false,\n destructive = false,\n onConfirm,\n onCancel,\n}: SourcingConfirmationDialogProps) {\n const dialogRef = useRef<HTMLDialogElement | null>(null);\n const titleId = useId();\n const descriptionId = useId();\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open && !dialog.open) dialog.showModal();\n if (!open && dialog.open) dialog.close();\n }, [open]);\n\n useEffect(\n () => () => {\n if (dialogRef.current?.open) dialogRef.current.close();\n },\n []\n );\n\n return (\n <dialog\n ref={dialogRef}\n aria-labelledby={titleId}\n aria-describedby={descriptionId}\n className=\"m-auto w-[min(32rem,calc(100%-2rem))] rounded-xl border border-border-
|
|
1
|
+
{"version":3,"file":"SourcingConfirmationDialog.js","names":[],"sources":["../../../src/components/sourcing/SourcingConfirmationDialog.tsx"],"sourcesContent":["import { useEffect, useId, useRef } from 'react';\nimport type { ReactNode } from 'react';\nimport { Loader2 } from 'lucide-react';\n\nimport {\n dangerButtonClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n} from './SourcingUi';\n\ninterface SourcingConfirmationDialogProps {\n open: boolean;\n title: string;\n description: ReactNode;\n confirmLabel: string;\n cancelLabel: string;\n busy?: boolean;\n destructive?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function SourcingConfirmationDialog({\n open,\n title,\n description,\n confirmLabel,\n cancelLabel,\n busy = false,\n destructive = false,\n onConfirm,\n onCancel,\n}: SourcingConfirmationDialogProps) {\n const dialogRef = useRef<HTMLDialogElement | null>(null);\n const titleId = useId();\n const descriptionId = useId();\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (open && !dialog.open) dialog.showModal();\n if (!open && dialog.open) dialog.close();\n }, [open]);\n\n useEffect(\n () => () => {\n if (dialogRef.current?.open) dialogRef.current.close();\n },\n []\n );\n\n return (\n <dialog\n ref={dialogRef}\n aria-labelledby={titleId}\n aria-describedby={descriptionId}\n className=\"m-auto w-[min(32rem,calc(100%-2rem))] rounded-xl border border-border-subtle bg-surface-elevated p-0 text-text-primary shadow-elevation-4 backdrop:bg-bg-overlay backdrop:backdrop-blur-sm\"\n onCancel={(event) => {\n event.preventDefault();\n if (!busy) onCancel();\n }}\n >\n <div className=\"p-5 sm:p-6\">\n <h2 id={titleId} className=\"text-lg font-semibold text-text-primary\">\n {title}\n </h2>\n <div id={descriptionId} className=\"mt-2 text-sm leading-6 text-text-secondary\">\n {description}\n </div>\n <div className=\"mt-6 flex flex-wrap justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n disabled={busy}\n className={secondaryButtonClassName}\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n disabled={busy}\n className={destructive ? dangerButtonClassName : primaryButtonClassName}\n autoFocus\n >\n {busy ? <Loader2 className=\"size-4 animate-spin\" aria-hidden=\"true\" /> : null}\n {confirmLabel}\n </button>\n </div>\n </div>\n </dialog>\n );\n}\n"],"mappings":";;;;;AAsBA,SAAgB,EAA2B,EACzC,SACA,UACA,gBACA,iBACA,gBACA,UAAO,IACP,iBAAc,IACd,cACA,eACkC;CAClC,IAAM,IAAY,EAAiC,KAAK,EAClD,IAAU,GAAO,EACjB,IAAgB,GAAO;AAiB7B,QAfA,QAAgB;EACd,IAAM,IAAS,EAAU;AACpB,QAED,KAAQ,CAAC,EAAO,QAAM,EAAO,WAAW,EACxC,CAAC,KAAQ,EAAO,QAAM,EAAO,OAAO;IACvC,CAAC,EAAK,CAAC,EAEV,cACc;AACV,EAAI,EAAU,SAAS,QAAM,EAAU,QAAQ,OAAO;IAExD,EAAE,CACH,EAGC,kBAAC,UAAD;EACE,KAAK;EACL,mBAAiB;EACjB,oBAAkB;EAClB,WAAU;EACV,WAAW,MAAU;AAEnB,GADA,EAAM,gBAAgB,EACjB,KAAM,GAAU;;YAGvB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,MAAD;KAAI,IAAI;KAAS,WAAU;eACxB;KACE,CAAA;IACL,kBAAC,OAAD;KAAK,IAAI;KAAe,WAAU;eAC/B;KACG,CAAA;IACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,UAAU;MACV,WAAW;gBAEV;MACM,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,UAAU;MACV,WAAW,IAAc,IAAwB;MACjD,WAAA;gBALF,CAOG,IAAO,kBAAC,GAAD;OAAS,WAAU;OAAsB,eAAY;OAAS,CAAA,GAAG,MACxE,EACM;QACL;;IACF;;EACC,CAAA"}
|
|
@@ -2,9 +2,9 @@ import { ReactNode } from 'react';
|
|
|
2
2
|
import { SourcingUnit } from '../../generated/global-types';
|
|
3
3
|
|
|
4
4
|
export declare const SOURCING_UNITS: readonly [SourcingUnit.Unit, SourcingUnit.Gram, SourcingUnit.Kilogram, SourcingUnit.Milliliter, SourcingUnit.Liter, SourcingUnit.MetricTon, SourcingUnit.Box, SourcingUnit.Bag, SourcingUnit.Pallet];
|
|
5
|
-
export declare const inputClassName = "mt-1.5 w-full rounded-lg border border-border-default bg-surface
|
|
5
|
+
export declare const inputClassName = "mt-1.5 w-full rounded-lg border border-border-default bg-surface px-3 py-2.5 text-sm text-text-primary shadow-sm outline-none transition placeholder:text-text-muted focus:border-action-primary-bg focus:ring-2 focus:ring-action-primary-bg/20 disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:text-text-disabled";
|
|
6
6
|
export declare const labelClassName = "block text-sm font-medium text-text-primary";
|
|
7
|
-
export declare const helpClassName = "mt-1 text-xs text-text-
|
|
7
|
+
export declare const helpClassName = "mt-1 text-xs text-text-muted";
|
|
8
8
|
export declare const primaryButtonClassName: string;
|
|
9
9
|
export declare const secondaryButtonClassName: string;
|
|
10
10
|
export declare const dangerButtonClassName: string;
|
|
@@ -25,7 +25,7 @@ var f = [
|
|
|
25
25
|
[e.Box]: "Box",
|
|
26
26
|
[e.Bag]: "Bag",
|
|
27
27
|
[e.Pallet]: "Pallet"
|
|
28
|
-
}, m = "mt-1.5 w-full rounded-lg border border-border-default bg-surface
|
|
28
|
+
}, m = "mt-1.5 w-full rounded-lg border border-border-default bg-surface px-3 py-2.5 text-sm text-text-primary shadow-sm outline-none transition placeholder:text-text-muted focus:border-action-primary-bg focus:ring-2 focus:ring-action-primary-bg/20 disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:text-text-disabled", h = "block text-sm font-medium text-text-primary", g = "mt-1 text-xs text-text-muted", _ = u({ size: "lg" }), v = u({
|
|
29
29
|
variant: "outline",
|
|
30
30
|
size: "lg"
|
|
31
31
|
}), y = u({
|
|
@@ -65,7 +65,7 @@ function D(e, t) {
|
|
|
65
65
|
}
|
|
66
66
|
function O({ title: e, description: t, icon: r, onBack: o, actions: s }) {
|
|
67
67
|
return /* @__PURE__ */ i("div", {
|
|
68
|
-
className: "border-b border-border-
|
|
68
|
+
className: "border-b border-border-subtle bg-surface-elevated",
|
|
69
69
|
children: /* @__PURE__ */ i("div", {
|
|
70
70
|
className: "mx-auto max-w-6xl px-4 py-5 sm:px-6",
|
|
71
71
|
children: /* @__PURE__ */ i(d, {
|
|
@@ -84,11 +84,11 @@ function O({ title: e, description: t, icon: r, onBack: o, actions: s }) {
|
|
|
84
84
|
"aria-hidden": "true"
|
|
85
85
|
})
|
|
86
86
|
}), /* @__PURE__ */ i("span", {
|
|
87
|
-
className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-
|
|
87
|
+
className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-bg-accentSubtle text-accent-primary",
|
|
88
88
|
children: r
|
|
89
89
|
})]
|
|
90
90
|
}) : /* @__PURE__ */ i("span", {
|
|
91
|
-
className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-
|
|
91
|
+
className: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-bg-accentSubtle text-accent-primary",
|
|
92
92
|
children: r
|
|
93
93
|
}),
|
|
94
94
|
actions: s
|
|
@@ -102,7 +102,7 @@ function k({ label: e }) {
|
|
|
102
102
|
"aria-live": "polite",
|
|
103
103
|
className: "flex flex-col items-center py-20 text-center",
|
|
104
104
|
children: [/* @__PURE__ */ i(r, {
|
|
105
|
-
className: "mb-3 size-8 animate-spin text-
|
|
105
|
+
className: "mb-3 size-8 animate-spin text-accent-primary",
|
|
106
106
|
"aria-hidden": "true"
|
|
107
107
|
}), /* @__PURE__ */ i("p", {
|
|
108
108
|
className: "text-sm text-text-secondary",
|
|
@@ -113,10 +113,10 @@ function k({ label: e }) {
|
|
|
113
113
|
function A({ title: e, message: n, onRetry: r }) {
|
|
114
114
|
return /* @__PURE__ */ a("div", {
|
|
115
115
|
role: "alert",
|
|
116
|
-
className: "rounded-xl border border-border
|
|
116
|
+
className: "rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6 text-center",
|
|
117
117
|
children: [
|
|
118
118
|
/* @__PURE__ */ i(t, {
|
|
119
|
-
className: "mx-auto size-8 text-text
|
|
119
|
+
className: "mx-auto size-8 text-status-error-text",
|
|
120
120
|
"aria-hidden": "true"
|
|
121
121
|
}),
|
|
122
122
|
/* @__PURE__ */ i("h2", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SourcingUi.js","names":[],"sources":["../../../src/components/sourcing/SourcingUi.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { AlertCircle, ArrowLeft, Loader2 } from 'lucide-react';\nimport { PageHeader as CanonicalPageHeader } from '@burdenoff/fe-libs/chrome';\nimport {\n formatDate as formatSharedDate,\n formatDateTime as formatSharedDateTime,\n} from '@burdenoff/fe-libs/shared/utils';\nimport { Badge, IllustratedEmptyState, buttonVariants } from '@burdenoff/fe-libs/ui';\nimport { SourcingUnit } from '../../generated/global-types';\n\nexport const SOURCING_UNITS = [\n SourcingUnit.Unit,\n SourcingUnit.Gram,\n SourcingUnit.Kilogram,\n SourcingUnit.Milliliter,\n SourcingUnit.Liter,\n SourcingUnit.MetricTon,\n SourcingUnit.Box,\n SourcingUnit.Bag,\n SourcingUnit.Pallet,\n] as const;\n\nconst UNIT_LABELS: Record<SourcingUnit, string> = {\n [SourcingUnit.Unit]: 'Unit',\n [SourcingUnit.Gram]: 'Gram',\n [SourcingUnit.Kilogram]: 'Kilogram',\n [SourcingUnit.Milliliter]: 'Milliliter',\n [SourcingUnit.Liter]: 'Liter',\n [SourcingUnit.MetricTon]: 'Metric ton',\n [SourcingUnit.Box]: 'Box',\n [SourcingUnit.Bag]: 'Bag',\n [SourcingUnit.Pallet]: 'Pallet',\n};\n\nexport const inputClassName =\n 'mt-1.5 w-full rounded-lg border border-border-default bg-surface-default px-3 py-2.5 text-sm text-text-primary shadow-sm outline-none transition placeholder:text-text-tertiary focus:border-action-primary-bg focus:ring-2 focus:ring-action-primary-bg/20 disabled:cursor-not-allowed disabled:bg-surface-muted disabled:text-text-tertiary';\nexport const labelClassName = 'block text-sm font-medium text-text-primary';\nexport const helpClassName = 'mt-1 text-xs text-text-tertiary';\nexport const primaryButtonClassName = buttonVariants({ size: 'lg' });\nexport const secondaryButtonClassName = buttonVariants({ variant: 'outline', size: 'lg' });\nexport const dangerButtonClassName = buttonVariants({ variant: 'destructive', size: 'lg' });\n\nexport function joinStorePath(basePath: string, path: string): string {\n const base = basePath === '/' ? '' : basePath.replace(/\\/$/, '');\n const suffix = path.startsWith('/') ? path : `/${path}`;\n return `${base}${suffix}` || '/';\n}\n\nexport function formatSourcingUnit(unit: SourcingUnit | string): string {\n return UNIT_LABELS[unit as SourcingUnit] ?? unit.replaceAll('_', ' ').toLowerCase();\n}\n\nexport function formatDate(value: string): string {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? 'Not available' : formatSharedDate(date);\n}\n\nexport function formatDateTime(value: string): string {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? 'Not available' : formatSharedDateTime(date);\n}\n\nexport function formatMoney(value: string | null | undefined, currency: string | null | undefined) {\n if (!value || !currency) return 'Not specified';\n return `${currency.toUpperCase()} ${value}`;\n}\n\nexport function formatLocation({\n country,\n region,\n city,\n}: {\n country: string;\n region?: string | null;\n city?: string | null;\n}): string {\n return [city, region, country].filter(Boolean).join(', ');\n}\n\nexport function toDateTimeLocal(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return '';\n const local = new Date(date.getTime() - date.getTimezoneOffset() * 60_000);\n return local.toISOString().slice(0, 16);\n}\n\nexport function toErrorMessage(error: unknown, fallback: string): string {\n if (error instanceof Error && error.message.trim()) return error.message;\n return fallback;\n}\n\ninterface SourcingPageHeaderProps {\n title: string;\n description: string;\n icon: ReactNode;\n onBack?: () => void;\n actions?: ReactNode;\n}\n\nexport function SourcingPageHeader({\n title,\n description,\n icon,\n onBack,\n actions,\n}: SourcingPageHeaderProps) {\n const headerIcon = onBack ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={onBack}\n aria-label=\"Go back\"\n className=\"inline-flex size-10 shrink-0 items-center justify-center rounded-lg text-text-secondary transition hover:bg-surface-hover hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg\"\n >\n <ArrowLeft className=\"size-5\" aria-hidden=\"true\" />\n </button>\n <span className=\"flex size-10 shrink-0 items-center justify-center rounded-lg bg-surface-accent-muted text-text-accent\">\n {icon}\n </span>\n </div>\n ) : (\n <span className=\"flex size-10 shrink-0 items-center justify-center rounded-lg bg-surface-accent-muted text-text-accent\">\n {icon}\n </span>\n );\n\n return (\n <div className=\"border-b border-border-seam bg-surface-raised\">\n <div className=\"mx-auto max-w-6xl px-4 py-5 sm:px-6\">\n <CanonicalPageHeader\n className=\"mb-0\"\n title={title}\n description={description}\n icon={headerIcon}\n actions={actions}\n />\n </div>\n </div>\n );\n}\n\nexport function SourcingLoadingState({ label }: { label: string }) {\n return (\n <div role=\"status\" aria-live=\"polite\" className=\"flex flex-col items-center py-20 text-center\">\n <Loader2 className=\"mb-3 size-8 animate-spin text-text-accent\" aria-hidden=\"true\" />\n <p className=\"text-sm text-text-secondary\">{label}</p>\n </div>\n );\n}\n\nexport function SourcingErrorState({\n title,\n message,\n onRetry,\n}: {\n title: string;\n message: string;\n onRetry?: () => void;\n}) {\n return (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-border-danger bg-surface-danger-muted p-6 text-center\"\n >\n <AlertCircle className=\"mx-auto size-8 text-text-danger\" aria-hidden=\"true\" />\n <h2 className=\"mt-3 text-lg font-semibold text-text-primary\">{title}</h2>\n <p className=\"mx-auto mt-1 max-w-xl text-sm text-text-secondary\">{message}</p>\n {onRetry ? (\n <button type=\"button\" onClick={onRetry} className={`${secondaryButtonClassName} mt-4`}>\n Try again\n </button>\n ) : null}\n </div>\n );\n}\n\nexport function SourcingEmptyState({\n title,\n description,\n action,\n}: {\n title: string;\n description: string;\n action?: ReactNode;\n}) {\n return (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={title}\n description={description}\n action={action}\n />\n );\n}\n\nexport function SourcingStatusBadge({ status }: { status: string }) {\n const normalized = status.toUpperCase();\n const variant =\n normalized === 'OPEN' || normalized === 'ACTIVE'\n ? 'success'\n : normalized === 'MATCHED' || normalized === 'ACCEPTED'\n ? 'info'\n : normalized === 'CANCELED' || normalized === 'REJECTED'\n ? 'secondary'\n : 'warning';\n\n return <Badge variant={variant}>{normalized.replaceAll('_', ' ')}</Badge>;\n}\n\nexport function ContextRequiredPanel({\n title,\n description,\n}: {\n title: string;\n description: string;\n}) {\n return (\n <div\n role=\"status\"\n className=\"rounded-xl border border-status-warning-border bg-status-warning-bg-subtle p-5\"\n >\n <div className=\"flex items-start gap-3\">\n <AlertCircle\n className=\"mt-0.5 size-5 shrink-0 text-status-warning-text\"\n aria-hidden=\"true\"\n />\n <div>\n <h2 className=\"font-semibold text-text-primary\">{title}</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">{description}</p>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SourcingUi.js","names":[],"sources":["../../../src/components/sourcing/SourcingUi.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { AlertCircle, ArrowLeft, Loader2 } from 'lucide-react';\nimport { PageHeader as CanonicalPageHeader } from '@burdenoff/fe-libs/chrome';\nimport {\n formatDate as formatSharedDate,\n formatDateTime as formatSharedDateTime,\n} from '@burdenoff/fe-libs/shared/utils';\nimport { Badge, IllustratedEmptyState, buttonVariants } from '@burdenoff/fe-libs/ui';\nimport { SourcingUnit } from '../../generated/global-types';\n\nexport const SOURCING_UNITS = [\n SourcingUnit.Unit,\n SourcingUnit.Gram,\n SourcingUnit.Kilogram,\n SourcingUnit.Milliliter,\n SourcingUnit.Liter,\n SourcingUnit.MetricTon,\n SourcingUnit.Box,\n SourcingUnit.Bag,\n SourcingUnit.Pallet,\n] as const;\n\nconst UNIT_LABELS: Record<SourcingUnit, string> = {\n [SourcingUnit.Unit]: 'Unit',\n [SourcingUnit.Gram]: 'Gram',\n [SourcingUnit.Kilogram]: 'Kilogram',\n [SourcingUnit.Milliliter]: 'Milliliter',\n [SourcingUnit.Liter]: 'Liter',\n [SourcingUnit.MetricTon]: 'Metric ton',\n [SourcingUnit.Box]: 'Box',\n [SourcingUnit.Bag]: 'Bag',\n [SourcingUnit.Pallet]: 'Pallet',\n};\n\nexport const inputClassName =\n 'mt-1.5 w-full rounded-lg border border-border-default bg-surface px-3 py-2.5 text-sm text-text-primary shadow-sm outline-none transition placeholder:text-text-muted focus:border-action-primary-bg focus:ring-2 focus:ring-action-primary-bg/20 disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:text-text-disabled';\nexport const labelClassName = 'block text-sm font-medium text-text-primary';\nexport const helpClassName = 'mt-1 text-xs text-text-muted';\nexport const primaryButtonClassName = buttonVariants({ size: 'lg' });\nexport const secondaryButtonClassName = buttonVariants({ variant: 'outline', size: 'lg' });\nexport const dangerButtonClassName = buttonVariants({ variant: 'destructive', size: 'lg' });\n\nexport function joinStorePath(basePath: string, path: string): string {\n const base = basePath === '/' ? '' : basePath.replace(/\\/$/, '');\n const suffix = path.startsWith('/') ? path : `/${path}`;\n return `${base}${suffix}` || '/';\n}\n\nexport function formatSourcingUnit(unit: SourcingUnit | string): string {\n return UNIT_LABELS[unit as SourcingUnit] ?? unit.replaceAll('_', ' ').toLowerCase();\n}\n\nexport function formatDate(value: string): string {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? 'Not available' : formatSharedDate(date);\n}\n\nexport function formatDateTime(value: string): string {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? 'Not available' : formatSharedDateTime(date);\n}\n\nexport function formatMoney(value: string | null | undefined, currency: string | null | undefined) {\n if (!value || !currency) return 'Not specified';\n return `${currency.toUpperCase()} ${value}`;\n}\n\nexport function formatLocation({\n country,\n region,\n city,\n}: {\n country: string;\n region?: string | null;\n city?: string | null;\n}): string {\n return [city, region, country].filter(Boolean).join(', ');\n}\n\nexport function toDateTimeLocal(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return '';\n const local = new Date(date.getTime() - date.getTimezoneOffset() * 60_000);\n return local.toISOString().slice(0, 16);\n}\n\nexport function toErrorMessage(error: unknown, fallback: string): string {\n if (error instanceof Error && error.message.trim()) return error.message;\n return fallback;\n}\n\ninterface SourcingPageHeaderProps {\n title: string;\n description: string;\n icon: ReactNode;\n onBack?: () => void;\n actions?: ReactNode;\n}\n\nexport function SourcingPageHeader({\n title,\n description,\n icon,\n onBack,\n actions,\n}: SourcingPageHeaderProps) {\n const headerIcon = onBack ? (\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={onBack}\n aria-label=\"Go back\"\n className=\"inline-flex size-10 shrink-0 items-center justify-center rounded-lg text-text-secondary transition hover:bg-surface-hover hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg\"\n >\n <ArrowLeft className=\"size-5\" aria-hidden=\"true\" />\n </button>\n <span className=\"flex size-10 shrink-0 items-center justify-center rounded-lg bg-bg-accentSubtle text-accent-primary\">\n {icon}\n </span>\n </div>\n ) : (\n <span className=\"flex size-10 shrink-0 items-center justify-center rounded-lg bg-bg-accentSubtle text-accent-primary\">\n {icon}\n </span>\n );\n\n return (\n <div className=\"border-b border-border-subtle bg-surface-elevated\">\n <div className=\"mx-auto max-w-6xl px-4 py-5 sm:px-6\">\n <CanonicalPageHeader\n className=\"mb-0\"\n title={title}\n description={description}\n icon={headerIcon}\n actions={actions}\n />\n </div>\n </div>\n );\n}\n\nexport function SourcingLoadingState({ label }: { label: string }) {\n return (\n <div role=\"status\" aria-live=\"polite\" className=\"flex flex-col items-center py-20 text-center\">\n <Loader2 className=\"mb-3 size-8 animate-spin text-accent-primary\" aria-hidden=\"true\" />\n <p className=\"text-sm text-text-secondary\">{label}</p>\n </div>\n );\n}\n\nexport function SourcingErrorState({\n title,\n message,\n onRetry,\n}: {\n title: string;\n message: string;\n onRetry?: () => void;\n}) {\n return (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6 text-center\"\n >\n <AlertCircle className=\"mx-auto size-8 text-status-error-text\" aria-hidden=\"true\" />\n <h2 className=\"mt-3 text-lg font-semibold text-text-primary\">{title}</h2>\n <p className=\"mx-auto mt-1 max-w-xl text-sm text-text-secondary\">{message}</p>\n {onRetry ? (\n <button type=\"button\" onClick={onRetry} className={`${secondaryButtonClassName} mt-4`}>\n Try again\n </button>\n ) : null}\n </div>\n );\n}\n\nexport function SourcingEmptyState({\n title,\n description,\n action,\n}: {\n title: string;\n description: string;\n action?: ReactNode;\n}) {\n return (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={title}\n description={description}\n action={action}\n />\n );\n}\n\nexport function SourcingStatusBadge({ status }: { status: string }) {\n const normalized = status.toUpperCase();\n const variant =\n normalized === 'OPEN' || normalized === 'ACTIVE'\n ? 'success'\n : normalized === 'MATCHED' || normalized === 'ACCEPTED'\n ? 'info'\n : normalized === 'CANCELED' || normalized === 'REJECTED'\n ? 'secondary'\n : 'warning';\n\n return <Badge variant={variant}>{normalized.replaceAll('_', ' ')}</Badge>;\n}\n\nexport function ContextRequiredPanel({\n title,\n description,\n}: {\n title: string;\n description: string;\n}) {\n return (\n <div\n role=\"status\"\n className=\"rounded-xl border border-status-warning-border bg-status-warning-bg-subtle p-5\"\n >\n <div className=\"flex items-start gap-3\">\n <AlertCircle\n className=\"mt-0.5 size-5 shrink-0 text-status-warning-text\"\n aria-hidden=\"true\"\n />\n <div>\n <h2 className=\"font-semibold text-text-primary\">{title}</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">{description}</p>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -68,12 +68,12 @@ var O = () => {
|
|
|
68
68
|
let t = j[e];
|
|
69
69
|
return t ? /* @__PURE__ */ y("p", {
|
|
70
70
|
id: `${e}-error`,
|
|
71
|
-
className: "mt-1 text-xs text-text
|
|
71
|
+
className: "mt-1 text-xs text-status-error-text",
|
|
72
72
|
children: t
|
|
73
73
|
}) : null;
|
|
74
74
|
};
|
|
75
75
|
return /* @__PURE__ */ b("div", {
|
|
76
|
-
className: "min-h-full bg-surface
|
|
76
|
+
className: "min-h-full bg-surface",
|
|
77
77
|
children: [/* @__PURE__ */ y(a, {
|
|
78
78
|
title: "Create sourcing request",
|
|
79
79
|
description: "Share only the purchase details verified publishers need to prepare an offer.",
|
|
@@ -98,7 +98,7 @@ var O = () => {
|
|
|
98
98
|
children: [/* @__PURE__ */ b("div", {
|
|
99
99
|
className: "flex items-center gap-2",
|
|
100
100
|
children: [/* @__PURE__ */ y(v, {
|
|
101
|
-
className: "size-5 text-
|
|
101
|
+
className: "size-5 text-accent-primary",
|
|
102
102
|
"aria-hidden": "true"
|
|
103
103
|
}), /* @__PURE__ */ y("h2", {
|
|
104
104
|
id: "request-product-heading",
|
|
@@ -192,7 +192,7 @@ var O = () => {
|
|
|
192
192
|
children: [
|
|
193
193
|
"Summary ",
|
|
194
194
|
/* @__PURE__ */ y("span", {
|
|
195
|
-
className: "font-normal text-text-
|
|
195
|
+
className: "font-normal text-text-muted",
|
|
196
196
|
children: "(optional)"
|
|
197
197
|
}),
|
|
198
198
|
/* @__PURE__ */ y("textarea", {
|
|
@@ -229,7 +229,7 @@ var O = () => {
|
|
|
229
229
|
}),
|
|
230
230
|
/* @__PURE__ */ b("section", {
|
|
231
231
|
"aria-labelledby": "request-delivery-heading",
|
|
232
|
-
className: "mt-8 border-t border-border-
|
|
232
|
+
className: "mt-8 border-t border-border-subtle pt-6",
|
|
233
233
|
children: [/* @__PURE__ */ y("h2", {
|
|
234
234
|
id: "request-delivery-heading",
|
|
235
235
|
className: "text-lg font-semibold text-text-primary",
|
|
@@ -298,10 +298,9 @@ var O = () => {
|
|
|
298
298
|
/* @__PURE__ */ b("label", {
|
|
299
299
|
className: u,
|
|
300
300
|
children: [
|
|
301
|
-
"Region or state",
|
|
302
|
-
" ",
|
|
301
|
+
"Region or state ",
|
|
303
302
|
/* @__PURE__ */ y("span", {
|
|
304
|
-
className: "font-normal text-text-
|
|
303
|
+
className: "font-normal text-text-muted",
|
|
305
304
|
children: "(optional)"
|
|
306
305
|
}),
|
|
307
306
|
/* @__PURE__ */ y("input", {
|
|
@@ -322,7 +321,7 @@ var O = () => {
|
|
|
322
321
|
children: [
|
|
323
322
|
"City ",
|
|
324
323
|
/* @__PURE__ */ y("span", {
|
|
325
|
-
className: "font-normal text-text-
|
|
324
|
+
className: "font-normal text-text-muted",
|
|
326
325
|
children: "(optional)"
|
|
327
326
|
}),
|
|
328
327
|
/* @__PURE__ */ y("input", {
|
|
@@ -343,13 +342,13 @@ var O = () => {
|
|
|
343
342
|
}),
|
|
344
343
|
/* @__PURE__ */ b("section", {
|
|
345
344
|
"aria-labelledby": "request-budget-heading",
|
|
346
|
-
className: "mt-8 border-t border-border-
|
|
345
|
+
className: "mt-8 border-t border-border-subtle pt-6",
|
|
347
346
|
children: [
|
|
348
347
|
/* @__PURE__ */ b("h2", {
|
|
349
348
|
id: "request-budget-heading",
|
|
350
349
|
className: "text-lg font-semibold text-text-primary",
|
|
351
350
|
children: ["Target price ", /* @__PURE__ */ y("span", {
|
|
352
|
-
className: "font-normal text-text-
|
|
351
|
+
className: "font-normal text-text-muted",
|
|
353
352
|
children: "(optional)"
|
|
354
353
|
})]
|
|
355
354
|
}),
|
|
@@ -387,7 +386,7 @@ var O = () => {
|
|
|
387
386
|
children: "Settlement currency"
|
|
388
387
|
}),
|
|
389
388
|
/* @__PURE__ */ y("div", {
|
|
390
|
-
className: `${c} flex items-center bg-surface-
|
|
389
|
+
className: `${c} flex items-center bg-surface-sunken font-semibold`,
|
|
391
390
|
children: "USD"
|
|
392
391
|
}),
|
|
393
392
|
/* @__PURE__ */ y("p", {
|
|
@@ -400,11 +399,11 @@ var O = () => {
|
|
|
400
399
|
}),
|
|
401
400
|
N ? /* @__PURE__ */ y("div", {
|
|
402
401
|
role: "alert",
|
|
403
|
-
className: "mt-6 rounded-lg border border-border
|
|
402
|
+
className: "mt-6 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text",
|
|
404
403
|
children: N
|
|
405
404
|
}) : null,
|
|
406
405
|
/* @__PURE__ */ b("div", {
|
|
407
|
-
className: "mt-7 flex flex-col-reverse gap-3 border-t border-border-
|
|
406
|
+
className: "mt-7 flex flex-col-reverse gap-3 border-t border-border-subtle pt-5 sm:flex-row sm:justify-end",
|
|
408
407
|
children: [/* @__PURE__ */ y("button", {
|
|
409
408
|
type: "button",
|
|
410
409
|
onClick: () => n(L),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateSourcingRequestPage.js","names":[],"sources":["../../src/pages/CreateSourcingRequestPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useNavigate } from 'react-router';\nimport { FilePlus2, Loader2, PackageSearch } from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingUnit } from '../generated/global-types';\nimport type { CreateSourcingRequestInput } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport { useSourcingApi } from '../hooks/useSourcing';\nimport {\n ContextRequiredPanel,\n helpClassName,\n inputClassName,\n joinStorePath,\n labelClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n SOURCING_UNITS,\n SourcingPageHeader,\n formatSourcingUnit,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\n\ninterface RequestFormState {\n productName: string;\n category: string;\n summary: string;\n quantity: string;\n unit: SourcingUnit;\n deliveryWindowStart: string;\n deliveryWindowEnd: string;\n deliveryCountry: string;\n deliveryRegion: string;\n deliveryCity: string;\n targetUnitPrice: string;\n}\n\ntype FieldName = keyof RequestFormState;\ntype FieldErrors = Partial<Record<FieldName, string>>;\n\nconst INITIAL_FORM: RequestFormState = {\n productName: '',\n category: '',\n summary: '',\n quantity: '',\n unit: SourcingUnit.Unit,\n deliveryWindowStart: '',\n deliveryWindowEnd: '',\n deliveryCountry: '',\n deliveryRegion: '',\n deliveryCity: '',\n targetUnitPrice: '',\n};\n\nconst MONEY_PATTERN = /^(?:0|[1-9]\\d{0,15})(?:\\.\\d{1,2})?$/;\nconst CATEGORY_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction normalizeCategory(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replaceAll(/[_\\s]+/g, '-')\n .replaceAll(/-+/g, '-');\n}\n\nfunction validate(form: RequestFormState): FieldErrors {\n const errors: FieldErrors = {};\n const productName = form.productName.trim();\n const category = normalizeCategory(form.category);\n const quantity = Number(form.quantity);\n const start = new Date(form.deliveryWindowStart);\n const end = new Date(form.deliveryWindowEnd);\n\n if (productName.length < 2 || productName.length > 160) {\n errors.productName = 'Enter a product name between 2 and 160 characters.';\n }\n if (category.length < 2 || category.length > 64 || !CATEGORY_PATTERN.test(category)) {\n errors.category = 'Use 2–64 lowercase letters, numbers, and single hyphens.';\n }\n if (form.summary.trim().length > 1000) {\n errors.summary = 'Summary cannot exceed 1,000 characters.';\n }\n if (!Number.isSafeInteger(quantity) || quantity < 1 || quantity > 1_000_000) {\n errors.quantity = 'Quantity must be a whole number from 1 to 1,000,000.';\n }\n if (!form.deliveryWindowStart || Number.isNaN(start.getTime())) {\n errors.deliveryWindowStart = 'Choose a valid delivery window start.';\n }\n if (!form.deliveryWindowEnd || Number.isNaN(end.getTime()) || end <= start) {\n errors.deliveryWindowEnd = 'Delivery window end must be after its start.';\n }\n if (!/^[A-Za-z]{2}$/.test(form.deliveryCountry.trim())) {\n errors.deliveryCountry = 'Use a two-letter country code, such as IN or US.';\n }\n if (form.deliveryRegion.trim().length > 120) {\n errors.deliveryRegion = 'Region cannot exceed 120 characters.';\n }\n if (form.deliveryCity.trim().length > 120) {\n errors.deliveryCity = 'City cannot exceed 120 characters.';\n }\n if (\n form.targetUnitPrice &&\n (!MONEY_PATTERN.test(form.targetUnitPrice.trim()) || Number(form.targetUnitPrice) <= 0)\n ) {\n errors.targetUnitPrice = 'Enter a positive amount with no more than two decimal places.';\n }\n\n return errors;\n}\n\nexport const CreateSourcingRequestPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { createBuyerRequest, hasOrganizationContext } = useSourcingApi();\n const [form, setForm] = useState<RequestFormState>(INITIAL_FORM);\n const [errors, setErrors] = useState<FieldErrors>({});\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const listPath = joinStorePath(basePath, 'sourcing/requests');\n\n const updateField =\n <TField extends FieldName>(field: TField) =>\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {\n const value = event.target.value;\n setForm((current) => ({ ...current, [field]: value }));\n setErrors((current) => ({ ...current, [field]: undefined }));\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!hasOrganizationContext || submitting) return;\n\n const validationErrors = validate(form);\n setErrors(validationErrors);\n setSubmitError(null);\n if (Object.keys(validationErrors).length > 0) return;\n\n const optional = (value: string) => value.trim() || undefined;\n const input: CreateSourcingRequestInput = {\n productName: form.productName.trim(),\n category: normalizeCategory(form.category),\n summary: optional(form.summary),\n quantity: Number(form.quantity),\n unit: form.unit,\n deliveryWindowStart: new Date(form.deliveryWindowStart).toISOString(),\n deliveryWindowEnd: new Date(form.deliveryWindowEnd).toISOString(),\n deliveryCountry: form.deliveryCountry.trim().toUpperCase(),\n deliveryRegion: optional(form.deliveryRegion),\n deliveryCity: optional(form.deliveryCity),\n targetUnitPrice: optional(form.targetUnitPrice),\n targetCurrency: form.targetUnitPrice.trim() ? 'USD' : undefined,\n };\n\n setSubmitting(true);\n try {\n const request = await createBuyerRequest(input);\n navigate(joinStorePath(basePath, `sourcing/requests/${request.id}`), { replace: true });\n } catch (error) {\n setSubmitError(toErrorMessage(error, 'The sourcing request could not be created.'));\n } finally {\n setSubmitting(false);\n }\n };\n\n const fieldError = (field: FieldName) => {\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 return (\n <div className=\"min-h-full bg-surface-default\">\n <SourcingPageHeader\n title=\"Create sourcing request\"\n description=\"Share only the purchase details verified publishers need to prepare an offer.\"\n icon={<FilePlus2 className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(listPath)}\n />\n\n <main className=\"mx-auto max-w-4xl px-4 py-6 sm:px-6\">\n <PagePurpose className=\"mb-6\">\n Your user and active organization own this request. Billing identity is resolved securely\n by Store; it is never entered in this form. Publishers see the product, quantity,\n destination, delivery window, and optional target price only.\n </PagePurpose>\n\n {!hasOrganizationContext ? (\n <ContextRequiredPanel\n title=\"Choose an organization before creating a request\"\n description=\"Use the app context switcher to select a global organization with a billing account. You do not need to select or create a farm workspace.\"\n />\n ) : (\n <form onSubmit={(event) => void handleSubmit(event)} noValidate>\n <GlassCard className=\"p-5 sm:p-6\">\n <section aria-labelledby=\"request-product-heading\">\n <div className=\"flex items-center gap-2\">\n <PackageSearch className=\"size-5 text-text-accent\" aria-hidden=\"true\" />\n <h2\n id=\"request-product-heading\"\n className=\"text-lg font-semibold text-text-primary\"\n >\n Product needed\n </h2>\n </div>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={`${labelClassName} sm:col-span-2`}>\n Product name\n <input\n type=\"text\"\n value={form.productName}\n onChange={updateField('productName')}\n required\n maxLength={160}\n autoComplete=\"off\"\n aria-invalid={Boolean(errors.productName)}\n aria-describedby={errors.productName ? 'productName-error' : undefined}\n placeholder=\"Example: Organic basmati rice\"\n className={inputClassName}\n />\n {fieldError('productName')}\n </label>\n\n <label className={labelClassName}>\n Category\n <input\n type=\"text\"\n value={form.category}\n onChange={updateField('category')}\n onBlur={() =>\n setForm((current) => ({\n ...current,\n category: normalizeCategory(current.category),\n }))\n }\n required\n maxLength={64}\n autoComplete=\"off\"\n aria-invalid={Boolean(errors.category)}\n aria-describedby={errors.category ? 'category-error' : 'category-help'}\n placeholder=\"food-grains\"\n className={inputClassName}\n />\n {fieldError('category')}\n {!errors.category ? (\n <p id=\"category-help\" className={helpClassName}>\n A short category slug; spaces are converted to hyphens.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Quantity\n <input\n type=\"number\"\n value={form.quantity}\n onChange={updateField('quantity')}\n required\n min={1}\n max={1_000_000}\n step={1}\n inputMode=\"numeric\"\n aria-invalid={Boolean(errors.quantity)}\n aria-describedby={errors.quantity ? 'quantity-error' : undefined}\n className={inputClassName}\n />\n {fieldError('quantity')}\n </label>\n\n <label className={labelClassName}>\n Unit\n <select\n value={form.unit}\n onChange={updateField('unit')}\n className={inputClassName}\n >\n {SOURCING_UNITS.map((unit) => (\n <option key={unit} value={unit}>\n {formatSourcingUnit(unit)}\n </option>\n ))}\n </select>\n </label>\n\n <label className={`${labelClassName} sm:col-span-2`}>\n Summary <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <textarea\n value={form.summary}\n onChange={updateField('summary')}\n maxLength={1000}\n rows={4}\n aria-invalid={Boolean(errors.summary)}\n aria-describedby={errors.summary ? 'summary-error' : 'summary-help'}\n placeholder=\"Add grade, packaging, certification, or other offer requirements.\"\n className={`${inputClassName} resize-y`}\n />\n {fieldError('summary')}\n {!errors.summary ? (\n <p id=\"summary-help\" className={helpClassName}>\n {form.summary.length}/1,000 characters\n </p>\n ) : null}\n </label>\n <div\n role=\"note\"\n className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-status-warning-text sm:col-span-2\"\n >\n <p className=\"font-semibold\">This summary is visible to eligible publishers.</p>\n <p className=\"mt-1 leading-6\">\n Do not include personal or contact details, trust or compliance records,\n payment or billing information, credentials, private addresses, or other\n confidential data. Share only product and delivery requirements needed to\n prepare an offer.\n </p>\n </div>\n </div>\n </section>\n\n <section\n aria-labelledby=\"request-delivery-heading\"\n className=\"mt-8 border-t border-border-seam pt-6\"\n >\n <h2\n id=\"request-delivery-heading\"\n className=\"text-lg font-semibold text-text-primary\"\n >\n Delivery\n </h2>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={labelClassName}>\n Window starts\n <input\n type=\"datetime-local\"\n value={form.deliveryWindowStart}\n onChange={updateField('deliveryWindowStart')}\n required\n aria-invalid={Boolean(errors.deliveryWindowStart)}\n aria-describedby={\n errors.deliveryWindowStart ? 'deliveryWindowStart-error' : undefined\n }\n className={inputClassName}\n />\n {fieldError('deliveryWindowStart')}\n </label>\n <label className={labelClassName}>\n Window ends\n <input\n type=\"datetime-local\"\n value={form.deliveryWindowEnd}\n onChange={updateField('deliveryWindowEnd')}\n required\n min={form.deliveryWindowStart || undefined}\n aria-invalid={Boolean(errors.deliveryWindowEnd)}\n aria-describedby={\n errors.deliveryWindowEnd ? 'deliveryWindowEnd-error' : undefined\n }\n className={inputClassName}\n />\n {fieldError('deliveryWindowEnd')}\n </label>\n <label className={labelClassName}>\n Country code\n <input\n type=\"text\"\n value={form.deliveryCountry}\n onChange={updateField('deliveryCountry')}\n required\n minLength={2}\n maxLength={2}\n autoComplete=\"country\"\n aria-invalid={Boolean(errors.deliveryCountry)}\n aria-describedby={\n errors.deliveryCountry ? 'deliveryCountry-error' : 'deliveryCountry-help'\n }\n placeholder=\"IN\"\n className={`${inputClassName} uppercase`}\n />\n {fieldError('deliveryCountry')}\n {!errors.deliveryCountry ? (\n <p id=\"deliveryCountry-help\" className={helpClassName}>\n ISO two-letter country code.\n </p>\n ) : null}\n </label>\n <label className={labelClassName}>\n Region or state{' '}\n <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <input\n type=\"text\"\n value={form.deliveryRegion}\n onChange={updateField('deliveryRegion')}\n maxLength={120}\n autoComplete=\"address-level1\"\n aria-invalid={Boolean(errors.deliveryRegion)}\n aria-describedby={errors.deliveryRegion ? 'deliveryRegion-error' : undefined}\n className={inputClassName}\n />\n {fieldError('deliveryRegion')}\n </label>\n <label className={labelClassName}>\n City <span className=\"font-normal text-text-tertiary\">(optional)</span>\n <input\n type=\"text\"\n value={form.deliveryCity}\n onChange={updateField('deliveryCity')}\n maxLength={120}\n autoComplete=\"address-level2\"\n aria-invalid={Boolean(errors.deliveryCity)}\n aria-describedby={errors.deliveryCity ? 'deliveryCity-error' : undefined}\n className={inputClassName}\n />\n {fieldError('deliveryCity')}\n </label>\n </div>\n </section>\n\n <section\n aria-labelledby=\"request-budget-heading\"\n className=\"mt-8 border-t border-border-seam pt-6\"\n >\n <h2 id=\"request-budget-heading\" className=\"text-lg font-semibold text-text-primary\">\n Target price <span className=\"font-normal text-text-tertiary\">(optional)</span>\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n This is a target unit price, not an order total. Store calculates the accepted\n order total from the seller's persisted offer.\n </p>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={labelClassName}>\n Target unit price\n <input\n type=\"text\"\n value={form.targetUnitPrice}\n onChange={updateField('targetUnitPrice')}\n inputMode=\"decimal\"\n maxLength={19}\n aria-invalid={Boolean(errors.targetUnitPrice)}\n aria-describedby={\n errors.targetUnitPrice ? 'targetUnitPrice-error' : 'targetUnitPrice-help'\n }\n placeholder=\"125.50\"\n className={inputClassName}\n />\n {fieldError('targetUnitPrice')}\n {!errors.targetUnitPrice ? (\n <p id=\"targetUnitPrice-help\" className={helpClassName}>\n Positive amount with up to two decimal places.\n </p>\n ) : null}\n </label>\n <div>\n <span className={labelClassName}>Settlement currency</span>\n <div\n className={`${inputClassName} flex items-center bg-surface-muted font-semibold`}\n >\n USD\n </div>\n <p className={helpClassName}>\n Store sourcing offers, orders, earnings, and payouts currently settle in USD.\n </p>\n </div>\n </div>\n </section>\n\n {submitError ? (\n <div\n role=\"alert\"\n className=\"mt-6 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\n <div className=\"mt-7 flex flex-col-reverse gap-3 border-t border-border-seam pt-5 sm:flex-row sm:justify-end\">\n <button\n type=\"button\"\n onClick={() => navigate(listPath)}\n disabled={submitting}\n className={secondaryButtonClassName}\n >\n Cancel\n </button>\n <button type=\"submit\" disabled={submitting} className={primaryButtonClassName}>\n {submitting ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden=\"true\" />\n ) : (\n <FilePlus2 className=\"size-4\" aria-hidden=\"true\" />\n )}\n {submitting ? 'Creating request…' : 'Create request'}\n </button>\n </div>\n </GlassCard>\n </form>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateSourcingRequestPage.js","names":[],"sources":["../../src/pages/CreateSourcingRequestPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ChangeEvent, FC, FormEvent } from 'react';\nimport { useNavigate } from 'react-router';\nimport { FilePlus2, Loader2, PackageSearch } from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { SourcingUnit } from '../generated/global-types';\nimport type { CreateSourcingRequestInput } from '../generated/global-types';\nimport { useStore } from '../providers/StoreProvider';\nimport { useSourcingApi } from '../hooks/useSourcing';\nimport {\n ContextRequiredPanel,\n helpClassName,\n inputClassName,\n joinStorePath,\n labelClassName,\n primaryButtonClassName,\n secondaryButtonClassName,\n SOURCING_UNITS,\n SourcingPageHeader,\n formatSourcingUnit,\n toErrorMessage,\n} from '../components/sourcing/SourcingUi';\n\ninterface RequestFormState {\n productName: string;\n category: string;\n summary: string;\n quantity: string;\n unit: SourcingUnit;\n deliveryWindowStart: string;\n deliveryWindowEnd: string;\n deliveryCountry: string;\n deliveryRegion: string;\n deliveryCity: string;\n targetUnitPrice: string;\n}\n\ntype FieldName = keyof RequestFormState;\ntype FieldErrors = Partial<Record<FieldName, string>>;\n\nconst INITIAL_FORM: RequestFormState = {\n productName: '',\n category: '',\n summary: '',\n quantity: '',\n unit: SourcingUnit.Unit,\n deliveryWindowStart: '',\n deliveryWindowEnd: '',\n deliveryCountry: '',\n deliveryRegion: '',\n deliveryCity: '',\n targetUnitPrice: '',\n};\n\nconst MONEY_PATTERN = /^(?:0|[1-9]\\d{0,15})(?:\\.\\d{1,2})?$/;\nconst CATEGORY_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction normalizeCategory(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replaceAll(/[_\\s]+/g, '-')\n .replaceAll(/-+/g, '-');\n}\n\nfunction validate(form: RequestFormState): FieldErrors {\n const errors: FieldErrors = {};\n const productName = form.productName.trim();\n const category = normalizeCategory(form.category);\n const quantity = Number(form.quantity);\n const start = new Date(form.deliveryWindowStart);\n const end = new Date(form.deliveryWindowEnd);\n\n if (productName.length < 2 || productName.length > 160) {\n errors.productName = 'Enter a product name between 2 and 160 characters.';\n }\n if (category.length < 2 || category.length > 64 || !CATEGORY_PATTERN.test(category)) {\n errors.category = 'Use 2–64 lowercase letters, numbers, and single hyphens.';\n }\n if (form.summary.trim().length > 1000) {\n errors.summary = 'Summary cannot exceed 1,000 characters.';\n }\n if (!Number.isSafeInteger(quantity) || quantity < 1 || quantity > 1_000_000) {\n errors.quantity = 'Quantity must be a whole number from 1 to 1,000,000.';\n }\n if (!form.deliveryWindowStart || Number.isNaN(start.getTime())) {\n errors.deliveryWindowStart = 'Choose a valid delivery window start.';\n }\n if (!form.deliveryWindowEnd || Number.isNaN(end.getTime()) || end <= start) {\n errors.deliveryWindowEnd = 'Delivery window end must be after its start.';\n }\n if (!/^[A-Za-z]{2}$/.test(form.deliveryCountry.trim())) {\n errors.deliveryCountry = 'Use a two-letter country code, such as IN or US.';\n }\n if (form.deliveryRegion.trim().length > 120) {\n errors.deliveryRegion = 'Region cannot exceed 120 characters.';\n }\n if (form.deliveryCity.trim().length > 120) {\n errors.deliveryCity = 'City cannot exceed 120 characters.';\n }\n if (\n form.targetUnitPrice &&\n (!MONEY_PATTERN.test(form.targetUnitPrice.trim()) || Number(form.targetUnitPrice) <= 0)\n ) {\n errors.targetUnitPrice = 'Enter a positive amount with no more than two decimal places.';\n }\n\n return errors;\n}\n\nexport const CreateSourcingRequestPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { createBuyerRequest, hasOrganizationContext } = useSourcingApi();\n const [form, setForm] = useState<RequestFormState>(INITIAL_FORM);\n const [errors, setErrors] = useState<FieldErrors>({});\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n\n const listPath = joinStorePath(basePath, 'sourcing/requests');\n\n const updateField =\n <TField extends FieldName>(field: TField) =>\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {\n const value = event.target.value;\n setForm((current) => ({ ...current, [field]: value }));\n setErrors((current) => ({ ...current, [field]: undefined }));\n };\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!hasOrganizationContext || submitting) return;\n\n const validationErrors = validate(form);\n setErrors(validationErrors);\n setSubmitError(null);\n if (Object.keys(validationErrors).length > 0) return;\n\n const optional = (value: string) => value.trim() || undefined;\n const input: CreateSourcingRequestInput = {\n productName: form.productName.trim(),\n category: normalizeCategory(form.category),\n summary: optional(form.summary),\n quantity: Number(form.quantity),\n unit: form.unit,\n deliveryWindowStart: new Date(form.deliveryWindowStart).toISOString(),\n deliveryWindowEnd: new Date(form.deliveryWindowEnd).toISOString(),\n deliveryCountry: form.deliveryCountry.trim().toUpperCase(),\n deliveryRegion: optional(form.deliveryRegion),\n deliveryCity: optional(form.deliveryCity),\n targetUnitPrice: optional(form.targetUnitPrice),\n targetCurrency: form.targetUnitPrice.trim() ? 'USD' : undefined,\n };\n\n setSubmitting(true);\n try {\n const request = await createBuyerRequest(input);\n navigate(joinStorePath(basePath, `sourcing/requests/${request.id}`), { replace: true });\n } catch (error) {\n setSubmitError(toErrorMessage(error, 'The sourcing request could not be created.'));\n } finally {\n setSubmitting(false);\n }\n };\n\n const fieldError = (field: FieldName) => {\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 return (\n <div className=\"min-h-full bg-surface\">\n <SourcingPageHeader\n title=\"Create sourcing request\"\n description=\"Share only the purchase details verified publishers need to prepare an offer.\"\n icon={<FilePlus2 className=\"size-5\" aria-hidden=\"true\" />}\n onBack={() => navigate(listPath)}\n />\n\n <main className=\"mx-auto max-w-4xl px-4 py-6 sm:px-6\">\n <PagePurpose className=\"mb-6\">\n Your user and active organization own this request. Billing identity is resolved securely\n by Store; it is never entered in this form. Publishers see the product, quantity,\n destination, delivery window, and optional target price only.\n </PagePurpose>\n\n {!hasOrganizationContext ? (\n <ContextRequiredPanel\n title=\"Choose an organization before creating a request\"\n description=\"Use the app context switcher to select a global organization with a billing account. You do not need to select or create a farm workspace.\"\n />\n ) : (\n <form onSubmit={(event) => void handleSubmit(event)} noValidate>\n <GlassCard className=\"p-5 sm:p-6\">\n <section aria-labelledby=\"request-product-heading\">\n <div className=\"flex items-center gap-2\">\n <PackageSearch className=\"size-5 text-accent-primary\" aria-hidden=\"true\" />\n <h2\n id=\"request-product-heading\"\n className=\"text-lg font-semibold text-text-primary\"\n >\n Product needed\n </h2>\n </div>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={`${labelClassName} sm:col-span-2`}>\n Product name\n <input\n type=\"text\"\n value={form.productName}\n onChange={updateField('productName')}\n required\n maxLength={160}\n autoComplete=\"off\"\n aria-invalid={Boolean(errors.productName)}\n aria-describedby={errors.productName ? 'productName-error' : undefined}\n placeholder=\"Example: Organic basmati rice\"\n className={inputClassName}\n />\n {fieldError('productName')}\n </label>\n\n <label className={labelClassName}>\n Category\n <input\n type=\"text\"\n value={form.category}\n onChange={updateField('category')}\n onBlur={() =>\n setForm((current) => ({\n ...current,\n category: normalizeCategory(current.category),\n }))\n }\n required\n maxLength={64}\n autoComplete=\"off\"\n aria-invalid={Boolean(errors.category)}\n aria-describedby={errors.category ? 'category-error' : 'category-help'}\n placeholder=\"food-grains\"\n className={inputClassName}\n />\n {fieldError('category')}\n {!errors.category ? (\n <p id=\"category-help\" className={helpClassName}>\n A short category slug; spaces are converted to hyphens.\n </p>\n ) : null}\n </label>\n\n <label className={labelClassName}>\n Quantity\n <input\n type=\"number\"\n value={form.quantity}\n onChange={updateField('quantity')}\n required\n min={1}\n max={1_000_000}\n step={1}\n inputMode=\"numeric\"\n aria-invalid={Boolean(errors.quantity)}\n aria-describedby={errors.quantity ? 'quantity-error' : undefined}\n className={inputClassName}\n />\n {fieldError('quantity')}\n </label>\n\n <label className={labelClassName}>\n Unit\n <select\n value={form.unit}\n onChange={updateField('unit')}\n className={inputClassName}\n >\n {SOURCING_UNITS.map((unit) => (\n <option key={unit} value={unit}>\n {formatSourcingUnit(unit)}\n </option>\n ))}\n </select>\n </label>\n\n <label className={`${labelClassName} sm:col-span-2`}>\n Summary <span className=\"font-normal text-text-muted\">(optional)</span>\n <textarea\n value={form.summary}\n onChange={updateField('summary')}\n maxLength={1000}\n rows={4}\n aria-invalid={Boolean(errors.summary)}\n aria-describedby={errors.summary ? 'summary-error' : 'summary-help'}\n placeholder=\"Add grade, packaging, certification, or other offer requirements.\"\n className={`${inputClassName} resize-y`}\n />\n {fieldError('summary')}\n {!errors.summary ? (\n <p id=\"summary-help\" className={helpClassName}>\n {form.summary.length}/1,000 characters\n </p>\n ) : null}\n </label>\n <div\n role=\"note\"\n className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-4 text-sm text-status-warning-text sm:col-span-2\"\n >\n <p className=\"font-semibold\">This summary is visible to eligible publishers.</p>\n <p className=\"mt-1 leading-6\">\n Do not include personal or contact details, trust or compliance records,\n payment or billing information, credentials, private addresses, or other\n confidential data. Share only product and delivery requirements needed to\n prepare an offer.\n </p>\n </div>\n </div>\n </section>\n\n <section\n aria-labelledby=\"request-delivery-heading\"\n className=\"mt-8 border-t border-border-subtle pt-6\"\n >\n <h2\n id=\"request-delivery-heading\"\n className=\"text-lg font-semibold text-text-primary\"\n >\n Delivery\n </h2>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={labelClassName}>\n Window starts\n <input\n type=\"datetime-local\"\n value={form.deliveryWindowStart}\n onChange={updateField('deliveryWindowStart')}\n required\n aria-invalid={Boolean(errors.deliveryWindowStart)}\n aria-describedby={\n errors.deliveryWindowStart ? 'deliveryWindowStart-error' : undefined\n }\n className={inputClassName}\n />\n {fieldError('deliveryWindowStart')}\n </label>\n <label className={labelClassName}>\n Window ends\n <input\n type=\"datetime-local\"\n value={form.deliveryWindowEnd}\n onChange={updateField('deliveryWindowEnd')}\n required\n min={form.deliveryWindowStart || undefined}\n aria-invalid={Boolean(errors.deliveryWindowEnd)}\n aria-describedby={\n errors.deliveryWindowEnd ? 'deliveryWindowEnd-error' : undefined\n }\n className={inputClassName}\n />\n {fieldError('deliveryWindowEnd')}\n </label>\n <label className={labelClassName}>\n Country code\n <input\n type=\"text\"\n value={form.deliveryCountry}\n onChange={updateField('deliveryCountry')}\n required\n minLength={2}\n maxLength={2}\n autoComplete=\"country\"\n aria-invalid={Boolean(errors.deliveryCountry)}\n aria-describedby={\n errors.deliveryCountry ? 'deliveryCountry-error' : 'deliveryCountry-help'\n }\n placeholder=\"IN\"\n className={`${inputClassName} uppercase`}\n />\n {fieldError('deliveryCountry')}\n {!errors.deliveryCountry ? (\n <p id=\"deliveryCountry-help\" className={helpClassName}>\n ISO two-letter country code.\n </p>\n ) : null}\n </label>\n <label className={labelClassName}>\n Region or state <span className=\"font-normal text-text-muted\">(optional)</span>\n <input\n type=\"text\"\n value={form.deliveryRegion}\n onChange={updateField('deliveryRegion')}\n maxLength={120}\n autoComplete=\"address-level1\"\n aria-invalid={Boolean(errors.deliveryRegion)}\n aria-describedby={errors.deliveryRegion ? 'deliveryRegion-error' : undefined}\n className={inputClassName}\n />\n {fieldError('deliveryRegion')}\n </label>\n <label className={labelClassName}>\n City <span className=\"font-normal text-text-muted\">(optional)</span>\n <input\n type=\"text\"\n value={form.deliveryCity}\n onChange={updateField('deliveryCity')}\n maxLength={120}\n autoComplete=\"address-level2\"\n aria-invalid={Boolean(errors.deliveryCity)}\n aria-describedby={errors.deliveryCity ? 'deliveryCity-error' : undefined}\n className={inputClassName}\n />\n {fieldError('deliveryCity')}\n </label>\n </div>\n </section>\n\n <section\n aria-labelledby=\"request-budget-heading\"\n className=\"mt-8 border-t border-border-subtle pt-6\"\n >\n <h2 id=\"request-budget-heading\" className=\"text-lg font-semibold text-text-primary\">\n Target price <span className=\"font-normal text-text-muted\">(optional)</span>\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n This is a target unit price, not an order total. Store calculates the accepted\n order total from the seller's persisted offer.\n </p>\n <div className=\"mt-5 grid gap-5 sm:grid-cols-2\">\n <label className={labelClassName}>\n Target unit price\n <input\n type=\"text\"\n value={form.targetUnitPrice}\n onChange={updateField('targetUnitPrice')}\n inputMode=\"decimal\"\n maxLength={19}\n aria-invalid={Boolean(errors.targetUnitPrice)}\n aria-describedby={\n errors.targetUnitPrice ? 'targetUnitPrice-error' : 'targetUnitPrice-help'\n }\n placeholder=\"125.50\"\n className={inputClassName}\n />\n {fieldError('targetUnitPrice')}\n {!errors.targetUnitPrice ? (\n <p id=\"targetUnitPrice-help\" className={helpClassName}>\n Positive amount with up to two decimal places.\n </p>\n ) : null}\n </label>\n <div>\n <span className={labelClassName}>Settlement currency</span>\n <div\n className={`${inputClassName} flex items-center bg-surface-sunken font-semibold`}\n >\n USD\n </div>\n <p className={helpClassName}>\n Store sourcing offers, orders, earnings, and payouts currently settle in USD.\n </p>\n </div>\n </div>\n </section>\n\n {submitError ? (\n <div\n role=\"alert\"\n className=\"mt-6 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\n <div className=\"mt-7 flex flex-col-reverse gap-3 border-t border-border-subtle pt-5 sm:flex-row sm:justify-end\">\n <button\n type=\"button\"\n onClick={() => navigate(listPath)}\n disabled={submitting}\n className={secondaryButtonClassName}\n >\n Cancel\n </button>\n <button type=\"submit\" disabled={submitting} className={primaryButtonClassName}>\n {submitting ? (\n <Loader2 className=\"size-4 animate-spin\" aria-hidden=\"true\" />\n ) : (\n <FilePlus2 className=\"size-4\" aria-hidden=\"true\" />\n )}\n {submitting ? 'Creating request…' : 'Create request'}\n </button>\n </div>\n </GlassCard>\n </form>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -43,7 +43,7 @@ var N = () => {
|
|
|
43
43
|
return v(() => {
|
|
44
44
|
$();
|
|
45
45
|
}, [$]), /* @__PURE__ */ O("div", {
|
|
46
|
-
className: "min-h-full bg-surface
|
|
46
|
+
className: "min-h-full bg-surface",
|
|
47
47
|
children: [/* @__PURE__ */ D(s, {
|
|
48
48
|
title: "My sourcing offers",
|
|
49
49
|
description: "Track and update the offers submitted by your verified Store Publisher.",
|
|
@@ -70,7 +70,7 @@ var N = () => {
|
|
|
70
70
|
message: L,
|
|
71
71
|
onRetry: () => void z()
|
|
72
72
|
}) : F ? R ? /* @__PURE__ */ O(E, { children: [/* @__PURE__ */ O("div", {
|
|
73
|
-
className: "mb-5 flex flex-col gap-3 rounded-xl border border-border-
|
|
73
|
+
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",
|
|
74
74
|
children: [/* @__PURE__ */ O("label", {
|
|
75
75
|
className: "block sm:w-64",
|
|
76
76
|
children: [/* @__PURE__ */ D("span", {
|
|
@@ -79,7 +79,7 @@ var N = () => {
|
|
|
79
79
|
}), /* @__PURE__ */ O("select", {
|
|
80
80
|
value: U,
|
|
81
81
|
onChange: (e) => W(M(e.target.value)),
|
|
82
|
-
className: "mt-1.5 w-full rounded-lg border border-border-default bg-surface
|
|
82
|
+
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",
|
|
83
83
|
children: [
|
|
84
84
|
/* @__PURE__ */ D("option", {
|
|
85
85
|
value: "",
|
|
@@ -128,7 +128,7 @@ var N = () => {
|
|
|
128
128
|
}) : /* @__PURE__ */ O(E, { children: [
|
|
129
129
|
Z ? /* @__PURE__ */ D("div", {
|
|
130
130
|
role: "alert",
|
|
131
|
-
className: "mb-4 rounded-lg border border-border
|
|
131
|
+
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",
|
|
132
132
|
children: Z
|
|
133
133
|
}) : null,
|
|
134
134
|
/* @__PURE__ */ D("ul", {
|
|
@@ -141,7 +141,7 @@ var N = () => {
|
|
|
141
141
|
children: [/* @__PURE__ */ O("div", {
|
|
142
142
|
className: "min-w-0",
|
|
143
143
|
children: [/* @__PURE__ */ D("p", {
|
|
144
|
-
className: "truncate text-xs font-semibold uppercase tracking-wide text-
|
|
144
|
+
className: "truncate text-xs font-semibold uppercase tracking-wide text-accent-primary",
|
|
145
145
|
children: e.request?.category ?? "Sourcing request"
|
|
146
146
|
}), /* @__PURE__ */ D("h2", {
|
|
147
147
|
className: "mt-1 line-clamp-2 text-lg font-semibold text-text-primary",
|
|
@@ -155,10 +155,10 @@ var N = () => {
|
|
|
155
155
|
/* @__PURE__ */ O("div", {
|
|
156
156
|
className: "flex gap-2",
|
|
157
157
|
children: [/* @__PURE__ */ D(C, {
|
|
158
|
-
className: "mt-0.5 size-4 shrink-0 text-text-
|
|
158
|
+
className: "mt-0.5 size-4 shrink-0 text-text-muted",
|
|
159
159
|
"aria-hidden": "true"
|
|
160
160
|
}), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
|
|
161
|
-
className: "text-xs text-text-
|
|
161
|
+
className: "text-xs text-text-muted",
|
|
162
162
|
children: "Your unit price"
|
|
163
163
|
}), /* @__PURE__ */ D("dd", {
|
|
164
164
|
className: "font-semibold text-text-primary",
|
|
@@ -168,10 +168,10 @@ var N = () => {
|
|
|
168
168
|
/* @__PURE__ */ O("div", {
|
|
169
169
|
className: "flex gap-2",
|
|
170
170
|
children: [/* @__PURE__ */ D(T, {
|
|
171
|
-
className: "mt-0.5 size-4 shrink-0 text-text-
|
|
171
|
+
className: "mt-0.5 size-4 shrink-0 text-text-muted",
|
|
172
172
|
"aria-hidden": "true"
|
|
173
173
|
}), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
|
|
174
|
-
className: "text-xs text-text-
|
|
174
|
+
className: "text-xs text-text-muted",
|
|
175
175
|
children: "Quantity"
|
|
176
176
|
}), /* @__PURE__ */ O("dd", {
|
|
177
177
|
className: "font-medium text-text-primary",
|
|
@@ -185,10 +185,10 @@ var N = () => {
|
|
|
185
185
|
/* @__PURE__ */ O("div", {
|
|
186
186
|
className: "flex gap-2",
|
|
187
187
|
children: [/* @__PURE__ */ D(S, {
|
|
188
|
-
className: "mt-0.5 size-4 shrink-0 text-text-
|
|
188
|
+
className: "mt-0.5 size-4 shrink-0 text-text-muted",
|
|
189
189
|
"aria-hidden": "true"
|
|
190
190
|
}), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
|
|
191
|
-
className: "text-xs text-text-
|
|
191
|
+
className: "text-xs text-text-muted",
|
|
192
192
|
children: "Promised delivery"
|
|
193
193
|
}), /* @__PURE__ */ D("dd", {
|
|
194
194
|
className: "font-medium text-text-primary",
|
|
@@ -198,10 +198,10 @@ var N = () => {
|
|
|
198
198
|
e.request ? /* @__PURE__ */ O("div", {
|
|
199
199
|
className: "flex gap-2",
|
|
200
200
|
children: [/* @__PURE__ */ D(w, {
|
|
201
|
-
className: "mt-0.5 size-4 shrink-0 text-text-
|
|
201
|
+
className: "mt-0.5 size-4 shrink-0 text-text-muted",
|
|
202
202
|
"aria-hidden": "true"
|
|
203
203
|
}), /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
|
|
204
|
-
className: "text-xs text-text-
|
|
204
|
+
className: "text-xs text-text-muted",
|
|
205
205
|
children: "Destination"
|
|
206
206
|
}), /* @__PURE__ */ D("dd", {
|
|
207
207
|
className: "font-medium text-text-primary",
|
|
@@ -215,7 +215,7 @@ var N = () => {
|
|
|
215
215
|
]
|
|
216
216
|
}),
|
|
217
217
|
e.message ? /* @__PURE__ */ D("p", {
|
|
218
|
-
className: "mt-4 line-clamp-3 rounded-lg bg-surface-
|
|
218
|
+
className: "mt-4 line-clamp-3 rounded-lg bg-surface-sunken p-3 text-sm leading-6 text-text-secondary",
|
|
219
219
|
children: e.message
|
|
220
220
|
}) : null,
|
|
221
221
|
e.order ? /* @__PURE__ */ O("div", {
|
|
@@ -241,9 +241,9 @@ var N = () => {
|
|
|
241
241
|
]
|
|
242
242
|
}) : null,
|
|
243
243
|
/* @__PURE__ */ O("div", {
|
|
244
|
-
className: "mt-auto flex items-center justify-between gap-3 border-t border-border-
|
|
244
|
+
className: "mt-auto flex items-center justify-between gap-3 border-t border-border-subtle pt-4",
|
|
245
245
|
children: [/* @__PURE__ */ O("p", {
|
|
246
|
-
className: "text-xs text-text-
|
|
246
|
+
className: "text-xs text-text-muted",
|
|
247
247
|
children: ["Updated ", l(e.updatedAt)]
|
|
248
248
|
}), /* @__PURE__ */ O("button", {
|
|
249
249
|
type: "button",
|