@burdenoff/microfe-coolandlovely 2026.1028.1 → 2026.1028.3
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/coolandlovely/components/Field.d.ts +1 -0
- package/dist/coolandlovely/components/Field.d.ts.map +1 -1
- package/dist/coolandlovely/components/Field.js +2 -1
- package/dist/coolandlovely/components/Field.js.map +1 -1
- package/dist/coolandlovely/components/RefundPanel.d.ts +4 -0
- package/dist/coolandlovely/components/RefundPanel.d.ts.map +1 -1
- package/dist/coolandlovely/components/RefundPanel.js +163 -97
- package/dist/coolandlovely/components/RefundPanel.js.map +1 -1
- package/dist/coolandlovely/components/ReturnRequests.d.ts +15 -0
- package/dist/coolandlovely/components/ReturnRequests.d.ts.map +1 -0
- package/dist/coolandlovely/components/ReturnRequests.js +218 -0
- package/dist/coolandlovely/components/ReturnRequests.js.map +1 -0
- package/dist/coolandlovely/components/StatusBadge.d.ts.map +1 -1
- package/dist/coolandlovely/components/StatusBadge.js +5 -1
- package/dist/coolandlovely/components/StatusBadge.js.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts +13 -2
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js +113 -33
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts +9 -2
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js +47 -31
- package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.d.ts +3 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js +129 -97
- package/dist/coolandlovely/pages/commerce/BrandOrdersPage.js.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts +2 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.d.ts.map +1 -1
- package/dist/coolandlovely/pages/commerce/OrdersPage.js +124 -122
- package/dist/coolandlovely/pages/commerce/OrdersPage.js.map +1 -1
- package/dist/coolandlovely/types/commerce.d.ts +58 -0
- package/dist/coolandlovely/types/commerce.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/Field.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAe,MAAM,OAAO,CAAC;AAGxD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAqB1C,CAAC;AAKF,UAAU,cAAc;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CAoCxC,CAAC;AAEF,UAAU,kBAAkB;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAqChD,CAAC;AAEF,UAAU,gBAAgB;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/Field.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAe,MAAM,OAAO,CAAC;AAGxD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAqB1C,CAAC;AAKF,UAAU,cAAc;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CAoCxC,CAAC;AAEF,UAAU,kBAAkB;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAqChD,CAAC;AAEF,UAAU,gBAAgB;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAgC5C,CAAC;AAEF,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,gBAAgB;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAyC5C,CAAC"}
|
|
@@ -55,7 +55,7 @@ var r = ({ label: r, htmlFor: i, required: a, hint: o, error: s, children: c, cl
|
|
|
55
55
|
onChange: (e) => s(e.target.value),
|
|
56
56
|
className: e(i, "resize-y", d && "border-status-error-text", p && "cursor-not-allowed opacity-60")
|
|
57
57
|
})
|
|
58
|
-
}), s = ({ id: r, label: i, checked: a, onChange: o, hint: s, disabled: c, className: l }) => /* @__PURE__ */ n("label", {
|
|
58
|
+
}), s = ({ id: r, label: i, checked: a, onChange: o, hint: s, disabled: c, className: l, testId: u }) => /* @__PURE__ */ n("label", {
|
|
59
59
|
htmlFor: r,
|
|
60
60
|
className: e("flex cursor-pointer items-start gap-3 rounded-lg border border-border-seam bg-bg-surface px-3 py-2.5", c && "cursor-not-allowed opacity-60", l),
|
|
61
61
|
children: [/* @__PURE__ */ t("input", {
|
|
@@ -64,6 +64,7 @@ var r = ({ label: r, htmlFor: i, required: a, hint: o, error: s, children: c, cl
|
|
|
64
64
|
checked: a,
|
|
65
65
|
disabled: c,
|
|
66
66
|
onChange: (e) => o(e.target.checked),
|
|
67
|
+
"data-testid": u,
|
|
67
68
|
className: "mt-0.5 h-4 w-4 shrink-0 rounded border-border-seam text-action-primary-bg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]"
|
|
68
69
|
}), /* @__PURE__ */ n("span", {
|
|
69
70
|
className: "min-w-0",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Field.js","names":[],"sources":["../../../src/coolandlovely/components/Field.tsx"],"sourcesContent":["/**\n * Form field primitives\n * @module coolandlovely/components\n *\n * Small, strictly-typed, token-only form controls used across the create/edit\n * forms (no third-party form lib — these wrap native inputs with consistent\n * labels, hints and error styling).\n */\n\nimport type { FC, ReactNode, ChangeEvent } from 'react';\nimport { cn } from '../utils/cn';\n\ninterface FieldShellProps {\n label: string;\n htmlFor?: string;\n required?: boolean;\n hint?: string;\n error?: string;\n children: ReactNode;\n className?: string;\n}\n\nexport const FieldShell: FC<FieldShellProps> = ({\n label,\n htmlFor,\n required,\n hint,\n error,\n children,\n className,\n}) => (\n <div className={cn('flex flex-col gap-1.5', className)}>\n <label htmlFor={htmlFor} className=\"text-sm font-medium text-text-primary\">\n {label}\n {required && <span className=\"ml-0.5 text-status-error-text\">*</span>}\n </label>\n {children}\n {error ? (\n <p className=\"text-xs text-status-error-text\">{error}</p>\n ) : hint ? (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n ) : null}\n </div>\n);\n\nconst baseControl =\n 'w-full rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\n\ninterface TextFieldProps {\n id?: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n required?: boolean;\n hint?: string;\n error?: string;\n type?: 'text' | 'url' | 'number' | 'date';\n disabled?: boolean;\n className?: string;\n}\n\nexport const TextField: FC<TextFieldProps> = ({\n id,\n label,\n value,\n onChange,\n placeholder,\n required,\n hint,\n error,\n type = 'text',\n disabled,\n className,\n}) => (\n <FieldShell\n label={label}\n htmlFor={id}\n required={required}\n hint={hint}\n error={error}\n className={className}\n >\n <input\n id={id}\n type={type}\n value={value}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value)}\n className={cn(\n baseControl,\n error && 'border-status-error-text',\n disabled && 'cursor-not-allowed opacity-60'\n )}\n />\n </FieldShell>\n);\n\ninterface TextAreaFieldProps {\n id?: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n required?: boolean;\n hint?: string;\n error?: string;\n rows?: number;\n disabled?: boolean;\n className?: string;\n}\n\nexport const TextAreaField: FC<TextAreaFieldProps> = ({\n id,\n label,\n value,\n onChange,\n placeholder,\n required,\n hint,\n error,\n rows = 3,\n disabled,\n className,\n}) => (\n <FieldShell\n label={label}\n htmlFor={id}\n required={required}\n hint={hint}\n error={error}\n className={className}\n >\n <textarea\n id={id}\n value={value}\n placeholder={placeholder}\n required={required}\n rows={rows}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)}\n className={cn(\n baseControl,\n 'resize-y',\n error && 'border-status-error-text',\n disabled && 'cursor-not-allowed opacity-60'\n )}\n />\n </FieldShell>\n);\n\ninterface ToggleFieldProps {\n id?: string;\n label: string;\n checked: boolean;\n onChange: (checked: boolean) => void;\n hint?: string;\n disabled?: boolean;\n className?: string;\n}\n\n/** A token-only checkbox row (used for boolean flags e.g. Featured). */\nexport const ToggleField: FC<ToggleFieldProps> = ({\n id,\n label,\n checked,\n onChange,\n hint,\n disabled,\n className,\n}) => (\n <label\n htmlFor={id}\n className={cn(\n 'flex cursor-pointer items-start gap-3 rounded-lg border border-border-seam bg-bg-surface px-3 py-2.5',\n disabled && 'cursor-not-allowed opacity-60',\n className\n )}\n >\n <input\n id={id}\n type=\"checkbox\"\n checked={checked}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.checked)}\n className=\"mt-0.5 h-4 w-4 shrink-0 rounded border-border-seam text-action-primary-bg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium text-text-primary\">{label}</span>\n {hint && <span className=\"mt-0.5 block text-xs text-text-secondary\">{hint}</span>}\n </span>\n </label>\n);\n\ninterface SelectOption {\n value: string;\n label: string;\n}\n\ninterface SelectFieldProps {\n id?: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n options: SelectOption[];\n required?: boolean;\n hint?: string;\n error?: string;\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n}\n\nexport const SelectField: FC<SelectFieldProps> = ({\n id,\n label,\n value,\n onChange,\n options,\n required,\n hint,\n error,\n placeholder,\n disabled,\n className,\n}) => (\n <FieldShell\n label={label}\n htmlFor={id}\n required={required}\n hint={hint}\n error={error}\n className={className}\n >\n <select\n id={id}\n value={value}\n required={required}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => onChange(e.target.value)}\n className={cn(\n baseControl,\n error && 'border-status-error-text',\n disabled && 'cursor-not-allowed opacity-60'\n )}\n >\n {placeholder && <option value=\"\">{placeholder}</option>}\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </FieldShell>\n);\n"],"mappings":";;;AAsBA,IAAa,KAAmC,EAC9C,UACA,YACA,aACA,SACA,UACA,aACA,mBAEA,kBAAC,OAAD;CAAK,WAAW,EAAG,yBAAyB,EAAU;WAAtD;EACE,kBAAC,SAAD;GAAgB;GAAS,WAAU;aAAnC,CACG,GACA,KAAY,kBAAC,QAAD;IAAM,WAAU;cAAgC;IAAQ,CAAA,CAC/D;;EACP;EACA,IACC,kBAAC,KAAD;GAAG,WAAU;aAAkC;GAAU,CAAA,GACvD,IACF,kBAAC,KAAD;GAAG,WAAU;aAA+B;GAAS,CAAA,GACnD;EACA;IAGF,IACJ,sMAgBW,KAAiC,EAC5C,OACA,UACA,UACA,aACA,gBACA,aACA,SACA,UACA,UAAO,QACP,aACA,mBAEA,kBAAC,GAAD;CACS;CACP,SAAS;CACC;CACJ;CACC;CACI;WAEX,kBAAC,SAAD;EACM;EACE;EACC;EACM;EACH;EACA;EACV,WAAW,MAAqC,EAAS,EAAE,OAAO,MAAM;EACxE,WAAW,EACT,GACA,KAAS,4BACT,KAAY,gCACb;EACD,CAAA;CACS,CAAA,EAiBF,KAAyC,EACpD,OACA,UACA,UACA,aACA,gBACA,aACA,SACA,UACA,UAAO,GACP,aACA,mBAEA,kBAAC,GAAD;CACS;CACP,SAAS;CACC;CACJ;CACC;CACI;WAEX,kBAAC,YAAD;EACM;EACG;EACM;EACH;EACJ;EACI;EACV,WAAW,MAAwC,EAAS,EAAE,OAAO,MAAM;EAC3E,WAAW,EACT,GACA,YACA,KAAS,4BACT,KAAY,gCACb;EACD,CAAA;CACS,CAAA,
|
|
1
|
+
{"version":3,"file":"Field.js","names":[],"sources":["../../../src/coolandlovely/components/Field.tsx"],"sourcesContent":["/**\n * Form field primitives\n * @module coolandlovely/components\n *\n * Small, strictly-typed, token-only form controls used across the create/edit\n * forms (no third-party form lib — these wrap native inputs with consistent\n * labels, hints and error styling).\n */\n\nimport type { FC, ReactNode, ChangeEvent } from 'react';\nimport { cn } from '../utils/cn';\n\ninterface FieldShellProps {\n label: string;\n htmlFor?: string;\n required?: boolean;\n hint?: string;\n error?: string;\n children: ReactNode;\n className?: string;\n}\n\nexport const FieldShell: FC<FieldShellProps> = ({\n label,\n htmlFor,\n required,\n hint,\n error,\n children,\n className,\n}) => (\n <div className={cn('flex flex-col gap-1.5', className)}>\n <label htmlFor={htmlFor} className=\"text-sm font-medium text-text-primary\">\n {label}\n {required && <span className=\"ml-0.5 text-status-error-text\">*</span>}\n </label>\n {children}\n {error ? (\n <p className=\"text-xs text-status-error-text\">{error}</p>\n ) : hint ? (\n <p className=\"text-xs text-text-secondary\">{hint}</p>\n ) : null}\n </div>\n);\n\nconst baseControl =\n 'w-full rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\n\ninterface TextFieldProps {\n id?: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n required?: boolean;\n hint?: string;\n error?: string;\n type?: 'text' | 'url' | 'number' | 'date';\n disabled?: boolean;\n className?: string;\n}\n\nexport const TextField: FC<TextFieldProps> = ({\n id,\n label,\n value,\n onChange,\n placeholder,\n required,\n hint,\n error,\n type = 'text',\n disabled,\n className,\n}) => (\n <FieldShell\n label={label}\n htmlFor={id}\n required={required}\n hint={hint}\n error={error}\n className={className}\n >\n <input\n id={id}\n type={type}\n value={value}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value)}\n className={cn(\n baseControl,\n error && 'border-status-error-text',\n disabled && 'cursor-not-allowed opacity-60'\n )}\n />\n </FieldShell>\n);\n\ninterface TextAreaFieldProps {\n id?: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n required?: boolean;\n hint?: string;\n error?: string;\n rows?: number;\n disabled?: boolean;\n className?: string;\n}\n\nexport const TextAreaField: FC<TextAreaFieldProps> = ({\n id,\n label,\n value,\n onChange,\n placeholder,\n required,\n hint,\n error,\n rows = 3,\n disabled,\n className,\n}) => (\n <FieldShell\n label={label}\n htmlFor={id}\n required={required}\n hint={hint}\n error={error}\n className={className}\n >\n <textarea\n id={id}\n value={value}\n placeholder={placeholder}\n required={required}\n rows={rows}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)}\n className={cn(\n baseControl,\n 'resize-y',\n error && 'border-status-error-text',\n disabled && 'cursor-not-allowed opacity-60'\n )}\n />\n </FieldShell>\n);\n\ninterface ToggleFieldProps {\n id?: string;\n label: string;\n checked: boolean;\n onChange: (checked: boolean) => void;\n hint?: string;\n disabled?: boolean;\n className?: string;\n testId?: string;\n}\n\n/** A token-only checkbox row (used for boolean flags e.g. Featured). */\nexport const ToggleField: FC<ToggleFieldProps> = ({\n id,\n label,\n checked,\n onChange,\n hint,\n disabled,\n className,\n testId,\n}) => (\n <label\n htmlFor={id}\n className={cn(\n 'flex cursor-pointer items-start gap-3 rounded-lg border border-border-seam bg-bg-surface px-3 py-2.5',\n disabled && 'cursor-not-allowed opacity-60',\n className\n )}\n >\n <input\n id={id}\n type=\"checkbox\"\n checked={checked}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.checked)}\n data-testid={testId}\n className=\"mt-0.5 h-4 w-4 shrink-0 rounded border-border-seam text-action-primary-bg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n />\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium text-text-primary\">{label}</span>\n {hint && <span className=\"mt-0.5 block text-xs text-text-secondary\">{hint}</span>}\n </span>\n </label>\n);\n\ninterface SelectOption {\n value: string;\n label: string;\n}\n\ninterface SelectFieldProps {\n id?: string;\n label: string;\n value: string;\n onChange: (value: string) => void;\n options: SelectOption[];\n required?: boolean;\n hint?: string;\n error?: string;\n placeholder?: string;\n disabled?: boolean;\n className?: string;\n}\n\nexport const SelectField: FC<SelectFieldProps> = ({\n id,\n label,\n value,\n onChange,\n options,\n required,\n hint,\n error,\n placeholder,\n disabled,\n className,\n}) => (\n <FieldShell\n label={label}\n htmlFor={id}\n required={required}\n hint={hint}\n error={error}\n className={className}\n >\n <select\n id={id}\n value={value}\n required={required}\n disabled={disabled}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => onChange(e.target.value)}\n className={cn(\n baseControl,\n error && 'border-status-error-text',\n disabled && 'cursor-not-allowed opacity-60'\n )}\n >\n {placeholder && <option value=\"\">{placeholder}</option>}\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </FieldShell>\n);\n"],"mappings":";;;AAsBA,IAAa,KAAmC,EAC9C,UACA,YACA,aACA,SACA,UACA,aACA,mBAEA,kBAAC,OAAD;CAAK,WAAW,EAAG,yBAAyB,EAAU;WAAtD;EACE,kBAAC,SAAD;GAAgB;GAAS,WAAU;aAAnC,CACG,GACA,KAAY,kBAAC,QAAD;IAAM,WAAU;cAAgC;IAAQ,CAAA,CAC/D;;EACP;EACA,IACC,kBAAC,KAAD;GAAG,WAAU;aAAkC;GAAU,CAAA,GACvD,IACF,kBAAC,KAAD;GAAG,WAAU;aAA+B;GAAS,CAAA,GACnD;EACA;IAGF,IACJ,sMAgBW,KAAiC,EAC5C,OACA,UACA,UACA,aACA,gBACA,aACA,SACA,UACA,UAAO,QACP,aACA,mBAEA,kBAAC,GAAD;CACS;CACP,SAAS;CACC;CACJ;CACC;CACI;WAEX,kBAAC,SAAD;EACM;EACE;EACC;EACM;EACH;EACA;EACV,WAAW,MAAqC,EAAS,EAAE,OAAO,MAAM;EACxE,WAAW,EACT,GACA,KAAS,4BACT,KAAY,gCACb;EACD,CAAA;CACS,CAAA,EAiBF,KAAyC,EACpD,OACA,UACA,UACA,aACA,gBACA,aACA,SACA,UACA,UAAO,GACP,aACA,mBAEA,kBAAC,GAAD;CACS;CACP,SAAS;CACC;CACJ;CACC;CACI;WAEX,kBAAC,YAAD;EACM;EACG;EACM;EACH;EACJ;EACI;EACV,WAAW,MAAwC,EAAS,EAAE,OAAO,MAAM;EAC3E,WAAW,EACT,GACA,YACA,KAAS,4BACT,KAAY,gCACb;EACD,CAAA;CACS,CAAA,EAeF,KAAqC,EAChD,OACA,UACA,YACA,aACA,SACA,aACA,cACA,gBAEA,kBAAC,SAAD;CACE,SAAS;CACT,WAAW,EACT,wGACA,KAAY,iCACZ,EACD;WANH,CAQE,kBAAC,SAAD;EACM;EACJ,MAAK;EACI;EACC;EACV,WAAW,MAAqC,EAAS,EAAE,OAAO,QAAQ;EAC1E,eAAa;EACb,WAAU;EACV,CAAA,EACF,kBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,kBAAC,QAAD;GAAM,WAAU;aAA+C;GAAa,CAAA,EAC3E,KAAQ,kBAAC,QAAD;GAAM,WAAU;aAA4C;GAAY,CAAA,CAC5E;IACD;IAsBG,KAAqC,EAChD,OACA,UACA,UACA,aACA,YACA,aACA,SACA,UACA,gBACA,aACA,mBAEA,kBAAC,GAAD;CACS;CACP,SAAS;CACC;CACJ;CACC;CACI;WAEX,kBAAC,UAAD;EACM;EACG;EACG;EACA;EACV,WAAW,MAAsC,EAAS,EAAE,OAAO,MAAM;EACzE,WAAW,EACT,GACA,KAAS,4BACT,KAAY,gCACb;YAVH,CAYG,KAAe,kBAAC,UAAD;GAAQ,OAAM;aAAI;GAAqB,CAAA,EACtD,EAAQ,KAAK,MACZ,kBAAC,UAAD;GAAwB,OAAO,EAAI;aAChC,EAAI;GACE,EAFI,EAAI,MAER,CACT,CACK;;CACE,CAAA"}
|
|
@@ -2,6 +2,10 @@ import { CooBrandOrder } from '../types';
|
|
|
2
2
|
|
|
3
3
|
/** Whether the brand can (still) start or retry a refund of this order. */
|
|
4
4
|
export declare function canRefund(order: CooBrandOrder): boolean;
|
|
5
|
+
/** Units of the brand's pieces in this order that took stock at checkout and can be restocked. */
|
|
6
|
+
export declare function restockableUnits(order: CooBrandOrder): number;
|
|
7
|
+
/** Whether a completed refund can still return its pieces to stock afterwards. */
|
|
8
|
+
export declare function canRestockLater(order: CooBrandOrder): boolean;
|
|
5
9
|
export declare function RefundPanel({ order }: {
|
|
6
10
|
order: CooBrandOrder;
|
|
7
11
|
}): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RefundPanel.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/RefundPanel.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"RefundPanel.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/RefundPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAc9C,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAIvD;AAED,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAI7D;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAM7D;AAoCD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,+BAsL9D"}
|
|
@@ -3,111 +3,177 @@ import { useTr as t } from "../hooks/useTr.js";
|
|
|
3
3
|
import "../hooks/index.js";
|
|
4
4
|
import { StatusBadge as n } from "./StatusBadge.js";
|
|
5
5
|
import { formatDate as r, formatPrice as i } from "../utils/formatters.js";
|
|
6
|
-
import { TextAreaField as a } from "./Field.js";
|
|
7
|
-
import { useRefundBrandOrder as
|
|
8
|
-
import { useState as
|
|
9
|
-
import { Loader2 as
|
|
10
|
-
import { jsx as
|
|
6
|
+
import { TextAreaField as a, ToggleField as o } from "./Field.js";
|
|
7
|
+
import { useRefundBrandOrder as s } from "../hooks/useBrandOrdersApi.js";
|
|
8
|
+
import { useState as c } from "react";
|
|
9
|
+
import { Loader2 as l, PackagePlus as u, RotateCcw as d } from "lucide-react";
|
|
10
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
11
11
|
//#region src/coolandlovely/components/RefundPanel.tsx
|
|
12
|
-
var
|
|
13
|
-
function
|
|
12
|
+
var m = 3, h = 1e3, g = "inline-flex w-full items-center justify-center gap-2 rounded-lg border border-status-error-text px-4 py-2.5 text-sm font-semibold text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50", _ = "inline-flex w-full items-center justify-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50";
|
|
13
|
+
function v(e) {
|
|
14
14
|
let t = e.refund?.status;
|
|
15
15
|
return t === "COMPLETED" || t === "PENDING" ? !1 : e.status === "PAID" || e.status === "PARTIALLY_REFUNDED";
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
function y(e) {
|
|
18
|
+
return e.items.filter((e) => e.stockTracked === !0).reduce((e, t) => e + t.quantity, 0);
|
|
19
|
+
}
|
|
20
|
+
function b(e) {
|
|
21
|
+
return e.refund?.status === "COMPLETED" && e.refund.restockStatus === "NONE" && y(e) > 0;
|
|
22
|
+
}
|
|
23
|
+
function x({ order: e }) {
|
|
24
|
+
let n = t(), i = e.refund;
|
|
25
|
+
return !i || i.restockStatus === "NONE" ? null : i.restockStatus === "RESTOCKED" ? /* @__PURE__ */ f("p", {
|
|
26
|
+
className: "text-xs text-status-success-text",
|
|
27
|
+
"data-testid": "brand-refund-restock-status",
|
|
28
|
+
children: n("coolandlovely.refund.restocked", "{{count}} pieces returned to stock {{date}}", {
|
|
29
|
+
count: i.restockedQuantity,
|
|
30
|
+
date: i.restockedAt ? r(i.restockedAt) : ""
|
|
31
|
+
})
|
|
32
|
+
}) : i.restockStatus === "SKIPPED" ? /* @__PURE__ */ f("p", {
|
|
33
|
+
className: "text-xs text-text-secondary",
|
|
34
|
+
"data-testid": "brand-refund-restock-status",
|
|
35
|
+
children: n("coolandlovely.refund.restockSkipped", "Nothing went back to stock: none of these pieces were stock-tracked when they were bought.")
|
|
36
|
+
}) : /* @__PURE__ */ f("p", {
|
|
37
|
+
className: "text-xs text-status-warning-text",
|
|
38
|
+
"data-testid": "brand-refund-restock-status",
|
|
39
|
+
children: n("coolandlovely.refund.restockPending", "The pieces go back to stock once the refund and the sale have settled. Refresh in a moment.")
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function S({ order: S }) {
|
|
43
|
+
let C = t(), w = s(), [T, E] = c(!1), [D, O] = c(""), [k, A] = c(!1), j = S.refund, M = y(S), N = D.trim(), P = N.length >= m && N.length <= h;
|
|
44
|
+
return /* @__PURE__ */ p("div", {
|
|
20
45
|
className: "space-y-3 border-t border-border-seam pt-4",
|
|
21
46
|
"data-testid": "brand-refund-panel",
|
|
22
|
-
children: [
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
47
|
+
children: [
|
|
48
|
+
j && /* @__PURE__ */ p("div", {
|
|
49
|
+
className: "space-y-1 text-sm",
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ p("div", {
|
|
52
|
+
className: "flex items-center justify-between",
|
|
53
|
+
children: [/* @__PURE__ */ f("span", {
|
|
54
|
+
className: "text-text-secondary",
|
|
55
|
+
children: C("coolandlovely.refund.label", "Refund")
|
|
56
|
+
}), /* @__PURE__ */ f("span", {
|
|
57
|
+
"data-testid": "brand-refund-status",
|
|
58
|
+
children: /* @__PURE__ */ f(n, { status: j.status })
|
|
59
|
+
})]
|
|
60
|
+
}),
|
|
61
|
+
/* @__PURE__ */ p("div", {
|
|
62
|
+
className: "flex justify-between",
|
|
63
|
+
children: [/* @__PURE__ */ f("span", {
|
|
64
|
+
className: "text-text-secondary",
|
|
65
|
+
children: C("coolandlovely.refund.amount", "Amount")
|
|
66
|
+
}), /* @__PURE__ */ f("span", {
|
|
67
|
+
className: "font-semibold tabular-nums text-text-primary",
|
|
68
|
+
children: i(j.amount, j.currency)
|
|
69
|
+
})]
|
|
70
|
+
}),
|
|
71
|
+
j.refundedAt && /* @__PURE__ */ f("p", {
|
|
72
|
+
className: "text-xs text-text-secondary",
|
|
73
|
+
children: C("coolandlovely.refund.refundedOn", "Refunded {{date}}", { date: r(j.refundedAt) })
|
|
74
|
+
}),
|
|
75
|
+
/* @__PURE__ */ f("p", {
|
|
76
|
+
className: "text-xs text-text-secondary",
|
|
77
|
+
children: C("coolandlovely.refund.reasonShown", "Reason: {{reason}}", { reason: j.reason })
|
|
78
|
+
}),
|
|
79
|
+
j.status === "PENDING" && /* @__PURE__ */ f("p", {
|
|
80
|
+
className: "text-xs text-status-warning-text",
|
|
81
|
+
children: C("coolandlovely.refund.pendingHint", "The refund is being processed with the payment provider. Refresh in a moment.")
|
|
82
|
+
}),
|
|
83
|
+
j.status === "FAILED" && j.failureReason && /* @__PURE__ */ f("p", {
|
|
84
|
+
className: "text-xs text-status-error-text",
|
|
85
|
+
children: j.failureReason
|
|
86
|
+
}),
|
|
87
|
+
/* @__PURE__ */ f(x, { order: S })
|
|
88
|
+
]
|
|
89
|
+
}),
|
|
90
|
+
b(S) && j && /* @__PURE__ */ p("div", {
|
|
91
|
+
className: "space-y-2",
|
|
92
|
+
children: [
|
|
93
|
+
w.error && /* @__PURE__ */ f("p", {
|
|
94
|
+
className: "text-sm text-status-error-text",
|
|
95
|
+
role: "alert",
|
|
96
|
+
children: w.error.message
|
|
97
|
+
}),
|
|
98
|
+
/* @__PURE__ */ p("button", {
|
|
99
|
+
type: "button",
|
|
100
|
+
disabled: w.isPending,
|
|
101
|
+
onClick: () => w.mutate({
|
|
102
|
+
brandId: S.brandId,
|
|
103
|
+
orderId: S.id,
|
|
104
|
+
reason: j.reason,
|
|
105
|
+
restock: !0
|
|
106
|
+
}),
|
|
107
|
+
className: _,
|
|
108
|
+
"data-testid": "brand-refund-restock-later",
|
|
109
|
+
children: [w.isPending ? /* @__PURE__ */ f(l, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ f(u, { className: "h-4 w-4" }), C("coolandlovely.refund.restockLater", "Return {{count}} pieces to stock", { count: M })]
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ f("p", {
|
|
112
|
+
className: "text-xs text-text-secondary",
|
|
113
|
+
children: C("coolandlovely.refund.restockLaterHint", "Use this once the refunded pieces have come back to you. It can only be done once.")
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
}),
|
|
117
|
+
v(S) && (T ? /* @__PURE__ */ p("div", {
|
|
118
|
+
className: "space-y-3",
|
|
119
|
+
children: [
|
|
120
|
+
/* @__PURE__ */ f("p", {
|
|
121
|
+
className: "text-sm text-text-secondary",
|
|
122
|
+
children: C("coolandlovely.refund.explain", "Refunds {{amount}} plus its share of tax to the shopper, for all of your pieces in this order. Creator commissions on them are reversed. This cannot be undone.", { amount: i(S.brandSubtotal, S.currency) })
|
|
123
|
+
}),
|
|
124
|
+
/* @__PURE__ */ f(a, {
|
|
125
|
+
id: "coo-refund-reason",
|
|
126
|
+
label: C("coolandlovely.refund.reason", "Reason (shown to the shopper)"),
|
|
127
|
+
value: D,
|
|
128
|
+
onChange: O,
|
|
129
|
+
rows: 3
|
|
130
|
+
}),
|
|
131
|
+
M > 0 && /* @__PURE__ */ f(o, {
|
|
132
|
+
id: "coo-refund-restock",
|
|
133
|
+
label: C("coolandlovely.refund.restock", "Return these pieces to stock"),
|
|
134
|
+
hint: C("coolandlovely.refund.restockHint", "Tick this if the {{count}} stock-tracked pieces came back to you. Their sizes and colours go back on sale.", { count: M }),
|
|
135
|
+
checked: k,
|
|
136
|
+
onChange: A,
|
|
137
|
+
disabled: w.isPending,
|
|
138
|
+
testId: "brand-refund-restock"
|
|
139
|
+
}),
|
|
140
|
+
w.error && /* @__PURE__ */ f("p", {
|
|
141
|
+
className: "text-sm text-status-error-text",
|
|
142
|
+
role: "alert",
|
|
143
|
+
children: w.error.message
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ p("button", {
|
|
146
|
+
type: "button",
|
|
147
|
+
disabled: w.isPending || !P,
|
|
148
|
+
onClick: () => w.mutate({
|
|
149
|
+
brandId: S.brandId,
|
|
150
|
+
orderId: S.id,
|
|
151
|
+
reason: N,
|
|
152
|
+
restock: M > 0 && k
|
|
153
|
+
}, { onSuccess: () => E(!1) }),
|
|
154
|
+
className: g,
|
|
155
|
+
"data-testid": "brand-refund-confirm",
|
|
156
|
+
children: [w.isPending ? /* @__PURE__ */ f(l, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ f(d, { className: "h-4 w-4" }), C("coolandlovely.refund.confirm", "Refund my pieces")]
|
|
157
|
+
}),
|
|
158
|
+
/* @__PURE__ */ f("button", {
|
|
159
|
+
type: "button",
|
|
160
|
+
disabled: w.isPending,
|
|
161
|
+
onClick: () => E(!1),
|
|
162
|
+
className: _,
|
|
163
|
+
children: C("coolandlovely.common.cancel", "Cancel")
|
|
164
|
+
})
|
|
165
|
+
]
|
|
166
|
+
}) : /* @__PURE__ */ p("button", {
|
|
167
|
+
type: "button",
|
|
168
|
+
onClick: () => E(!0),
|
|
169
|
+
className: e(_),
|
|
170
|
+
"data-testid": "brand-refund-open",
|
|
171
|
+
children: [/* @__PURE__ */ f(d, { className: "h-4 w-4" }), j?.status === "FAILED" ? C("coolandlovely.refund.retry", "Retry refund") : C("coolandlovely.refund.start", "Refund this order")]
|
|
172
|
+
}))
|
|
173
|
+
]
|
|
108
174
|
});
|
|
109
175
|
}
|
|
110
176
|
//#endregion
|
|
111
|
-
export {
|
|
177
|
+
export { S as RefundPanel };
|
|
112
178
|
|
|
113
179
|
//# sourceMappingURL=RefundPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RefundPanel.js","names":[],"sources":["../../../src/coolandlovely/components/RefundPanel.tsx"],"sourcesContent":["/**\n * Brand refund panel (BOFF-9702)\n * @module coolandlovely/components\n *\n * On the brand's order detail: refund all of the brand's pieces of the order to the shopper\n * (`cooRefundBrandOrder`), or see the refund once it exists. The money goes back through\n * global-billing to the shopper's original payment method, and the creator commissions on the\n * refunded pieces are reversed while they are still unpaid.\n */\n\nimport { useState } from 'react';\nimport { Loader2, RotateCcw } from 'lucide-react';\n\nimport { useTr } from '../hooks';\nimport { useRefundBrandOrder } from '../hooks/useBrandOrdersApi';\nimport type { CooBrandOrder } from '../types';\nimport { cn } from '../utils/cn';\nimport { formatDate, formatPrice } from '../utils/formatters';\nimport { TextAreaField } from './Field';\nimport { StatusBadge } from './StatusBadge';\n\nconst MIN_REASON = 3;\nconst MAX_REASON = 1000;\n\nconst dangerButton =\n 'inline-flex w-full items-center justify-center gap-2 rounded-lg border border-status-error-text px-4 py-2.5 text-sm font-semibold text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50';\nconst secondaryButton =\n 'inline-flex w-full items-center justify-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50';\n\n/** Whether the brand can (still) start or retry a refund of this order. */\nexport function canRefund(order: CooBrandOrder): boolean {\n const status = order.refund?.status;\n if (status === 'COMPLETED' || status === 'PENDING') return false;\n return order.status === 'PAID' || order.status === 'PARTIALLY_REFUNDED';\n}\n\nexport function RefundPanel({ order }: { order: CooBrandOrder }) {\n const tr = useTr();\n const refund = useRefundBrandOrder();\n const [open, setOpen] = useState(false);\n const [reason, setReason] = useState('');\n const existing = order.refund;\n const trimmed = reason.trim();\n const reasonValid = trimmed.length >= MIN_REASON && trimmed.length <= MAX_REASON;\n\n return (\n <div className=\"space-y-3 border-t border-border-seam pt-4\" data-testid=\"brand-refund-panel\">\n {existing && (\n <div className=\"space-y-1 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">\n {tr('coolandlovely.refund.label', 'Refund')}\n </span>\n <span data-testid=\"brand-refund-status\">\n <StatusBadge status={existing.status} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">\n {tr('coolandlovely.refund.amount', 'Amount')}\n </span>\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {formatPrice(existing.amount, existing.currency)}\n </span>\n </div>\n {existing.refundedAt && (\n <p className=\"text-xs text-text-secondary\">\n {tr('coolandlovely.refund.refundedOn', 'Refunded {{date}}', {\n date: formatDate(existing.refundedAt),\n })}\n </p>\n )}\n <p className=\"text-xs text-text-secondary\">\n {tr('coolandlovely.refund.reasonShown', 'Reason: {{reason}}', {\n reason: existing.reason,\n })}\n </p>\n {existing.status === 'PENDING' && (\n <p className=\"text-xs text-status-warning-text\">\n {tr(\n 'coolandlovely.refund.pendingHint',\n 'The refund is being processed with the payment provider. Refresh in a moment.'\n )}\n </p>\n )}\n {existing.status === 'FAILED' && existing.failureReason && (\n <p className=\"text-xs text-status-error-text\">{existing.failureReason}</p>\n )}\n </div>\n )}\n\n {canRefund(order) &&\n (open ? (\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'coolandlovely.refund.explain',\n 'Refunds {{amount}} plus its share of tax to the shopper, for all of your pieces in this order. Creator commissions on them are reversed. This cannot be undone.',\n { amount: formatPrice(order.brandSubtotal, order.currency) }\n )}\n </p>\n <TextAreaField\n id=\"coo-refund-reason\"\n label={tr('coolandlovely.refund.reason', 'Reason (shown to the shopper)')}\n value={reason}\n onChange={setReason}\n rows={3}\n />\n {refund.error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {refund.error.message}\n </p>\n )}\n <button\n type=\"button\"\n disabled={refund.isPending || !reasonValid}\n onClick={() =>\n refund.mutate(\n { brandId: order.brandId, orderId: order.id, reason: trimmed },\n { onSuccess: () => setOpen(false) }\n )\n }\n className={dangerButton}\n data-testid=\"brand-refund-confirm\"\n >\n {refund.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <RotateCcw className=\"h-4 w-4\" />\n )}\n {tr('coolandlovely.refund.confirm', 'Refund my pieces')}\n </button>\n <button\n type=\"button\"\n disabled={refund.isPending}\n onClick={() => setOpen(false)}\n className={secondaryButton}\n >\n {tr('coolandlovely.common.cancel', 'Cancel')}\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className={cn(secondaryButton)}\n data-testid=\"brand-refund-open\"\n >\n <RotateCcw className=\"h-4 w-4\" />\n {existing?.status === 'FAILED'\n ? tr('coolandlovely.refund.retry', 'Retry refund')\n : tr('coolandlovely.refund.start', 'Refund this order')}\n </button>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RefundPanel.js","names":[],"sources":["../../../src/coolandlovely/components/RefundPanel.tsx"],"sourcesContent":["/**\n * Brand refund panel (BOFF-9702)\n * @module coolandlovely/components\n *\n * On the brand's order detail: refund all of the brand's pieces of the order to the shopper\n * (`cooRefundBrandOrder`), or see the refund once it exists. The money goes back through\n * global-billing to the shopper's original payment method, and the creator commissions on the\n * refunded pieces are reversed while they are still unpaid.\n *\n * When some of the pieces were stock-tracked, the brand can return them to stock with the refund\n * (\"Return these pieces to stock\", BOFF-9901), or afterwards once they physically come back.\n */\n\nimport { useState } from 'react';\nimport { Loader2, PackagePlus, RotateCcw } from 'lucide-react';\n\nimport { useTr } from '../hooks';\nimport { useRefundBrandOrder } from '../hooks/useBrandOrdersApi';\nimport type { CooBrandOrder } from '../types';\nimport { cn } from '../utils/cn';\nimport { formatDate, formatPrice } from '../utils/formatters';\nimport { TextAreaField, ToggleField } from './Field';\nimport { StatusBadge } from './StatusBadge';\n\nconst MIN_REASON = 3;\nconst MAX_REASON = 1000;\n\nconst dangerButton =\n 'inline-flex w-full items-center justify-center gap-2 rounded-lg border border-status-error-text px-4 py-2.5 text-sm font-semibold text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50';\nconst secondaryButton =\n 'inline-flex w-full items-center justify-center gap-1.5 rounded-lg border border-border-seam px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50';\n\n/** Whether the brand can (still) start or retry a refund of this order. */\nexport function canRefund(order: CooBrandOrder): boolean {\n const status = order.refund?.status;\n if (status === 'COMPLETED' || status === 'PENDING') return false;\n return order.status === 'PAID' || order.status === 'PARTIALLY_REFUNDED';\n}\n\n/** Units of the brand's pieces in this order that took stock at checkout and can be restocked. */\nexport function restockableUnits(order: CooBrandOrder): number {\n return order.items\n .filter((item) => item.stockTracked === true)\n .reduce((sum, item) => sum + item.quantity, 0);\n}\n\n/** Whether a completed refund can still return its pieces to stock afterwards. */\nexport function canRestockLater(order: CooBrandOrder): boolean {\n return (\n order.refund?.status === 'COMPLETED' &&\n order.refund.restockStatus === 'NONE' &&\n restockableUnits(order) > 0\n );\n}\n\nfunction RestockStatusLine({ order }: { order: CooBrandOrder }) {\n const tr = useTr();\n const refund = order.refund;\n if (!refund || refund.restockStatus === 'NONE') return null;\n if (refund.restockStatus === 'RESTOCKED') {\n return (\n <p className=\"text-xs text-status-success-text\" data-testid=\"brand-refund-restock-status\">\n {tr('coolandlovely.refund.restocked', '{{count}} pieces returned to stock {{date}}', {\n count: refund.restockedQuantity,\n date: refund.restockedAt ? formatDate(refund.restockedAt) : '',\n })}\n </p>\n );\n }\n if (refund.restockStatus === 'SKIPPED') {\n return (\n <p className=\"text-xs text-text-secondary\" data-testid=\"brand-refund-restock-status\">\n {tr(\n 'coolandlovely.refund.restockSkipped',\n 'Nothing went back to stock: none of these pieces were stock-tracked when they were bought.'\n )}\n </p>\n );\n }\n return (\n <p className=\"text-xs text-status-warning-text\" data-testid=\"brand-refund-restock-status\">\n {tr(\n 'coolandlovely.refund.restockPending',\n 'The pieces go back to stock once the refund and the sale have settled. Refresh in a moment.'\n )}\n </p>\n );\n}\n\nexport function RefundPanel({ order }: { order: CooBrandOrder }) {\n const tr = useTr();\n const refund = useRefundBrandOrder();\n const [open, setOpen] = useState(false);\n const [reason, setReason] = useState('');\n const [restock, setRestock] = useState(false);\n const existing = order.refund;\n const units = restockableUnits(order);\n const trimmed = reason.trim();\n const reasonValid = trimmed.length >= MIN_REASON && trimmed.length <= MAX_REASON;\n\n return (\n <div className=\"space-y-3 border-t border-border-seam pt-4\" data-testid=\"brand-refund-panel\">\n {existing && (\n <div className=\"space-y-1 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">\n {tr('coolandlovely.refund.label', 'Refund')}\n </span>\n <span data-testid=\"brand-refund-status\">\n <StatusBadge status={existing.status} />\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span className=\"text-text-secondary\">\n {tr('coolandlovely.refund.amount', 'Amount')}\n </span>\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {formatPrice(existing.amount, existing.currency)}\n </span>\n </div>\n {existing.refundedAt && (\n <p className=\"text-xs text-text-secondary\">\n {tr('coolandlovely.refund.refundedOn', 'Refunded {{date}}', {\n date: formatDate(existing.refundedAt),\n })}\n </p>\n )}\n <p className=\"text-xs text-text-secondary\">\n {tr('coolandlovely.refund.reasonShown', 'Reason: {{reason}}', {\n reason: existing.reason,\n })}\n </p>\n {existing.status === 'PENDING' && (\n <p className=\"text-xs text-status-warning-text\">\n {tr(\n 'coolandlovely.refund.pendingHint',\n 'The refund is being processed with the payment provider. Refresh in a moment.'\n )}\n </p>\n )}\n {existing.status === 'FAILED' && existing.failureReason && (\n <p className=\"text-xs text-status-error-text\">{existing.failureReason}</p>\n )}\n <RestockStatusLine order={order} />\n </div>\n )}\n\n {canRestockLater(order) && existing && (\n <div className=\"space-y-2\">\n {refund.error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {refund.error.message}\n </p>\n )}\n <button\n type=\"button\"\n disabled={refund.isPending}\n onClick={() =>\n refund.mutate({\n brandId: order.brandId,\n orderId: order.id,\n reason: existing.reason,\n restock: true,\n })\n }\n className={secondaryButton}\n data-testid=\"brand-refund-restock-later\"\n >\n {refund.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <PackagePlus className=\"h-4 w-4\" />\n )}\n {tr('coolandlovely.refund.restockLater', 'Return {{count}} pieces to stock', {\n count: units,\n })}\n </button>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'coolandlovely.refund.restockLaterHint',\n 'Use this once the refunded pieces have come back to you. It can only be done once.'\n )}\n </p>\n </div>\n )}\n\n {canRefund(order) &&\n (open ? (\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'coolandlovely.refund.explain',\n 'Refunds {{amount}} plus its share of tax to the shopper, for all of your pieces in this order. Creator commissions on them are reversed. This cannot be undone.',\n { amount: formatPrice(order.brandSubtotal, order.currency) }\n )}\n </p>\n <TextAreaField\n id=\"coo-refund-reason\"\n label={tr('coolandlovely.refund.reason', 'Reason (shown to the shopper)')}\n value={reason}\n onChange={setReason}\n rows={3}\n />\n {units > 0 && (\n <ToggleField\n id=\"coo-refund-restock\"\n label={tr('coolandlovely.refund.restock', 'Return these pieces to stock')}\n hint={tr(\n 'coolandlovely.refund.restockHint',\n 'Tick this if the {{count}} stock-tracked pieces came back to you. Their sizes and colours go back on sale.',\n { count: units }\n )}\n checked={restock}\n onChange={setRestock}\n disabled={refund.isPending}\n testId=\"brand-refund-restock\"\n />\n )}\n {refund.error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {refund.error.message}\n </p>\n )}\n <button\n type=\"button\"\n disabled={refund.isPending || !reasonValid}\n onClick={() =>\n refund.mutate(\n {\n brandId: order.brandId,\n orderId: order.id,\n reason: trimmed,\n restock: units > 0 && restock,\n },\n { onSuccess: () => setOpen(false) }\n )\n }\n className={dangerButton}\n data-testid=\"brand-refund-confirm\"\n >\n {refund.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <RotateCcw className=\"h-4 w-4\" />\n )}\n {tr('coolandlovely.refund.confirm', 'Refund my pieces')}\n </button>\n <button\n type=\"button\"\n disabled={refund.isPending}\n onClick={() => setOpen(false)}\n className={secondaryButton}\n >\n {tr('coolandlovely.common.cancel', 'Cancel')}\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className={cn(secondaryButton)}\n data-testid=\"brand-refund-open\"\n >\n <RotateCcw className=\"h-4 w-4\" />\n {existing?.status === 'FAILED'\n ? tr('coolandlovely.refund.retry', 'Retry refund')\n : tr('coolandlovely.refund.start', 'Refund this order')}\n </button>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CooBrandOrder, CooOrder } from '../types';
|
|
2
|
+
|
|
3
|
+
/** Whether the return window of a paid order is still open. */
|
|
4
|
+
export declare function isReturnWindowOpen(order: Pick<CooOrder, 'returnWindowEndsAt'>, now?: number): boolean;
|
|
5
|
+
/** Whether the shopper can still ask the brand to take back its pieces of this order. */
|
|
6
|
+
export declare function canRequestReturn(order: CooOrder, brandId: string, now?: number): boolean;
|
|
7
|
+
/** The shopper's returns card on a paid order: one row per brand in the order. */
|
|
8
|
+
export declare function OrderReturns({ order }: {
|
|
9
|
+
order: CooOrder;
|
|
10
|
+
}): import("react").JSX.Element | null;
|
|
11
|
+
/** The brand's view of the shopper's return request, with approve and decline. */
|
|
12
|
+
export declare function ReturnRequestPanel({ order }: {
|
|
13
|
+
order: CooBrandOrder;
|
|
14
|
+
}): import("react").JSX.Element | null;
|
|
15
|
+
//# sourceMappingURL=ReturnRequests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReturnRequests.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/components/ReturnRequests.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAoB,MAAM,UAAU,CAAC;AAmB1E,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,GAAG,SAAa,WAG/F;AAED,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,SAAa,GAAG,OAAO,CAM5F;AAuGD,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,sCA0D1D;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,aAAa,CAAA;CAAE,sCAoHrE"}
|