@burdenoff/microfe-coolandlovely 2026.1028.2 → 2026.1028.4
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.map +1 -1
- package/dist/coolandlovely/components/ReturnRequests.js +1 -1
- package/dist/coolandlovely/components/ReturnRequests.js.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts +3 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js +14 -3
- package/dist/coolandlovely/hooks/useBrandOrdersApi.js.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.d.ts.map +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js +1 -1
- package/dist/coolandlovely/hooks/useCommerceApi.js.map +1 -1
- package/dist/coolandlovely/types/commerce.d.ts +13 -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":"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"}
|
|
@@ -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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"}
|
|
@@ -1 +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;
|
|
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;AA2GD,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"}
|
|
@@ -33,7 +33,7 @@ function C({ request: t }) {
|
|
|
33
33
|
"data-testid": "return-decision-note",
|
|
34
34
|
children: r("coolandlovely.returns.brandNote", "Brand’s note: {{note}}", { note: t.decisionNote })
|
|
35
35
|
}),
|
|
36
|
-
t.status !== "REQUESTED" && t.decidedAt && /* @__PURE__ */ f("p", { children: t.status === "APPROVED" ? r("coolandlovely.returns.approvedOn", "Approved {{date}}.
|
|
36
|
+
t.status !== "REQUESTED" && t.decidedAt && /* @__PURE__ */ f("p", { children: t.status === "APPROVED" ? r("coolandlovely.returns.approvedOn", "Approved {{date}}. The pieces were refunded.", { date: n(t.decidedAt) }) : r("coolandlovely.returns.declinedOn", "Declined {{date}}.", { date: n(t.decidedAt) }) })
|
|
37
37
|
]
|
|
38
38
|
});
|
|
39
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReturnRequests.js","names":[],"sources":["../../../src/coolandlovely/components/ReturnRequests.tsx"],"sourcesContent":["/**\n * Shopper return requests (BOFF-9900)\n * @module coolandlovely/components\n *\n * `OrderReturns` sits on the shopper's order detail: for each brand in a paid order the shopper\n * can ask for a return (`cooRequestReturn`) inside the return window, and sees the request and\n * the brand's decision once it exists. `ReturnRequestPanel` sits on the brand's order detail: the\n * brand approves the request, which refunds its pieces through the brand refund\n * (`cooApproveReturnRequest`), or declines it with a note (`cooDeclineReturnRequest`).\n */\n\nimport { useState } from 'react';\nimport { CheckCircle2, Loader2, Undo2, XCircle } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\n\nimport { useTr } from '../hooks';\nimport { useApproveReturnRequest, useDeclineReturnRequest } from '../hooks/useBrandOrdersApi';\nimport { useRequestReturn } from '../hooks/useCommerceApi';\nimport type { CooBrandOrder, CooOrder, CooReturnRequest } from '../types';\nimport { formatDate } from '../utils/formatters';\nimport { TextAreaField } from './Field';\nimport { StatusBadge } from './StatusBadge';\n\nconst MIN_TEXT = 3;\nconst MAX_TEXT = 1000;\nconst RETURNABLE_ORDER_STATUSES = ['PAID', 'PARTIALLY_REFUNDED'];\n\nconst isValidText = (value: string): boolean => {\n const trimmed = value.trim();\n return trimmed.length >= MIN_TEXT && trimmed.length <= MAX_TEXT;\n};\n\nconst primaryButton =\n 'inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50';\nconst secondaryButton =\n 'inline-flex 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 return window of a paid order is still open. */\nexport function isReturnWindowOpen(order: Pick<CooOrder, 'returnWindowEndsAt'>, now = Date.now()) {\n if (!order.returnWindowEndsAt) return false;\n return new Date(order.returnWindowEndsAt).getTime() > now;\n}\n\n/** Whether the shopper can still ask the brand to take back its pieces of this order. */\nexport function canRequestReturn(order: CooOrder, brandId: string, now = Date.now()): boolean {\n if (!RETURNABLE_ORDER_STATUSES.includes(order.status)) return false;\n if (order.returnRequests?.some((request) => request.brandId === brandId)) return false;\n const refund = order.refunds?.find((entry) => entry.brandId === brandId);\n if (refund && (refund.status === 'COMPLETED' || refund.status === 'PENDING')) return false;\n return isReturnWindowOpen(order, now);\n}\n\nfunction RequestDetails({ request }: { request: CooReturnRequest }) {\n const tr = useTr();\n return (\n <div className=\"space-y-1 text-xs text-text-secondary\">\n <p>\n {tr('coolandlovely.returns.reasonShown', 'Reason: {{reason}}', { reason: request.reason })}\n </p>\n {request.status === 'REQUESTED' && (\n <p>\n {tr(\n 'coolandlovely.returns.awaitingBrand',\n 'Asked {{date}}. The brand will approve or decline it.',\n { date: formatDate(request.createdAt) }\n )}\n </p>\n )}\n {request.status !== 'REQUESTED' && request.decisionNote && (\n <p data-testid=\"return-decision-note\">\n {tr('coolandlovely.returns.brandNote', 'Brand’s note: {{note}}', {\n note: request.decisionNote,\n })}\n </p>\n )}\n {request.status !== 'REQUESTED' && request.decidedAt && (\n <p>\n {request.status === 'APPROVED'\n ? tr('coolandlovely.returns.approvedOn', 'Approved {{date}}. See the refund above.', {\n date: formatDate(request.decidedAt),\n })\n : tr('coolandlovely.returns.declinedOn', 'Declined {{date}}.', {\n date: formatDate(request.decidedAt),\n })}\n </p>\n )}\n </div>\n );\n}\n\nfunction RequestReturnForm({ orderId, brandId }: { orderId: string; brandId: string }) {\n const tr = useTr();\n const request = useRequestReturn();\n const [open, setOpen] = useState(false);\n const [reason, setReason] = useState('');\n\n if (!open) {\n return (\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className={secondaryButton}\n data-testid=\"order-return-open\"\n >\n <Undo2 className=\"h-4 w-4\" />\n {tr('coolandlovely.returns.request', 'Request a return')}\n </button>\n );\n }\n return (\n <div className=\"space-y-2\">\n <TextAreaField\n id={`coo-return-reason-${brandId}`}\n label={tr('coolandlovely.returns.reason', 'Why are you returning these pieces?')}\n hint={tr('coolandlovely.returns.reasonHint', 'Shown to the brand.')}\n value={reason}\n onChange={setReason}\n rows={3}\n />\n {request.error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {request.error.message}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n disabled={request.isPending || !isValidText(reason)}\n onClick={() =>\n request.mutate(\n { orderId, brandId, reason: reason.trim() },\n { onSuccess: () => setOpen(false) }\n )\n }\n className={primaryButton}\n data-testid=\"order-return-submit\"\n >\n {request.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr('coolandlovely.returns.send', 'Send return request')}\n </button>\n <button\n type=\"button\"\n disabled={request.isPending}\n onClick={() => setOpen(false)}\n className={secondaryButton}\n >\n {tr('coolandlovely.common.cancel', 'Cancel')}\n </button>\n </div>\n </div>\n );\n}\n\n/** The shopper's returns card on a paid order: one row per brand in the order. */\nexport function OrderReturns({ order }: { order: CooOrder }) {\n const tr = useTr();\n const paid = order.status === 'PAID' || order.status === 'PARTIALLY_REFUNDED';\n const requests = order.returnRequests ?? [];\n if (!paid && requests.length === 0) return null;\n\n const brandIds = [...new Set(order.items.map((item) => item.brandId))];\n const brandName = (brandId: string): string =>\n requests.find((request) => request.brandId === brandId)?.brandName ??\n order.fulfilments?.find((fulfilment) => fulfilment.brandId === brandId)?.brandName ??\n order.refunds?.find((refund) => refund.brandId === brandId)?.brandName ??\n tr('coolandlovely.orders.brand', 'Brand');\n const windowOpen = isReturnWindowOpen(order);\n\n return (\n <GlassCard treatment=\"plain\" className=\"space-y-4 p-4\" data-testid=\"order-returns\">\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.returns.title', 'Returns')}\n </p>\n {paid && order.returnWindowEndsAt && (\n <p className=\"text-xs text-text-secondary\" data-testid=\"order-return-window\">\n {windowOpen\n ? tr(\n 'coolandlovely.returns.windowOpen',\n 'You can ask a brand to take back its pieces until {{date}}.',\n { date: formatDate(order.returnWindowEndsAt) }\n )\n : tr('coolandlovely.returns.windowClosed', 'The return window closed on {{date}}.', {\n date: formatDate(order.returnWindowEndsAt),\n })}\n </p>\n )}\n </div>\n {brandIds.map((brandId) => {\n const request = requests.find((entry) => entry.brandId === brandId);\n const eligible = canRequestReturn(order, brandId);\n if (!request && !eligible) return null;\n return (\n <div key={brandId} className=\"space-y-2\" data-testid=\"order-return\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{brandName(brandId)}</span>\n {request && (\n <span data-testid=\"order-return-status\">\n <StatusBadge status={request.status} />\n </span>\n )}\n </div>\n {request ? (\n <RequestDetails request={request} />\n ) : (\n <RequestReturnForm orderId={order.id} brandId={brandId} />\n )}\n </div>\n );\n })}\n </GlassCard>\n );\n}\n\n/** The brand's view of the shopper's return request, with approve and decline. */\nexport function ReturnRequestPanel({ order }: { order: CooBrandOrder }) {\n const tr = useTr();\n const approve = useApproveReturnRequest();\n const decline = useDeclineReturnRequest();\n const [mode, setMode] = useState<'idle' | 'approve' | 'decline'>('idle');\n const [note, setNote] = useState('');\n const request = order.returnRequest;\n if (!request) return null;\n\n const busy = approve.isPending || decline.isPending;\n const error = approve.error ?? decline.error;\n const noteOk = mode === 'approve' ? note.trim() === '' || isValidText(note) : isValidText(note);\n const reset = () => {\n setMode('idle');\n setNote('');\n };\n const submit = () => {\n const input = { brandId: order.brandId, orderId: order.id };\n if (mode === 'approve') {\n approve.mutate({ ...input, note: note.trim() || null }, { onSuccess: reset });\n } else {\n decline.mutate({ ...input, note: note.trim() }, { onSuccess: reset });\n }\n };\n\n return (\n <div className=\"space-y-3 border-t border-border-seam pt-4\" data-testid=\"brand-return-panel\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {tr('coolandlovely.returns.brandTitle', 'Return request')}\n </span>\n <span data-testid=\"brand-return-status\">\n <StatusBadge status={request.status} />\n </span>\n </div>\n <RequestDetails request={request} />\n\n {request.status === 'REQUESTED' &&\n (mode === 'idle' ? (\n <div className=\"grid grid-cols-2 gap-2\">\n <button\n type=\"button\"\n onClick={() => setMode('approve')}\n className={primaryButton}\n data-testid=\"brand-return-approve-open\"\n >\n <CheckCircle2 className=\"h-4 w-4\" />\n {tr('coolandlovely.returns.approve', 'Approve')}\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('decline')}\n className={secondaryButton}\n data-testid=\"brand-return-decline-open\"\n >\n <XCircle className=\"h-4 w-4\" />\n {tr('coolandlovely.returns.decline', 'Decline')}\n </button>\n </div>\n ) : (\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {mode === 'approve'\n ? tr(\n 'coolandlovely.returns.approveExplain',\n 'Approving refunds all of your pieces in this order to the shopper, with their share of tax, and reverses the creator commissions on them. This cannot be undone.'\n )\n : tr(\n 'coolandlovely.returns.declineExplain',\n 'The shopper sees your note. A declined return cannot be reopened.'\n )}\n </p>\n <TextAreaField\n id=\"coo-return-decision-note\"\n label={\n mode === 'approve'\n ? tr('coolandlovely.returns.approveNote', 'Note to the shopper (optional)')\n : tr('coolandlovely.returns.declineNote', 'Why are you declining?')\n }\n value={note}\n onChange={setNote}\n rows={3}\n />\n {error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {error.message}\n </p>\n )}\n <button\n type=\"button\"\n disabled={busy || !noteOk}\n onClick={submit}\n className={\n mode === 'approve'\n ? `${primaryButton} w-full`\n : `${secondaryButton} w-full text-status-error-text`\n }\n data-testid=\"brand-return-confirm\"\n >\n {busy && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {mode === 'approve'\n ? tr('coolandlovely.returns.approveConfirm', 'Approve and refund')\n : tr('coolandlovely.returns.declineConfirm', 'Decline return')}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={reset}\n className={`${secondaryButton} w-full`}\n >\n {tr('coolandlovely.common.cancel', 'Cancel')}\n </button>\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ReturnRequests.js","names":[],"sources":["../../../src/coolandlovely/components/ReturnRequests.tsx"],"sourcesContent":["/**\n * Shopper return requests (BOFF-9900)\n * @module coolandlovely/components\n *\n * `OrderReturns` sits on the shopper's order detail: for each brand in a paid order the shopper\n * can ask for a return (`cooRequestReturn`) inside the return window, and sees the request and\n * the brand's decision once it exists. `ReturnRequestPanel` sits on the brand's order detail: the\n * brand approves the request, which refunds its pieces through the brand refund\n * (`cooApproveReturnRequest`), or declines it with a note (`cooDeclineReturnRequest`).\n */\n\nimport { useState } from 'react';\nimport { CheckCircle2, Loader2, Undo2, XCircle } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\n\nimport { useTr } from '../hooks';\nimport { useApproveReturnRequest, useDeclineReturnRequest } from '../hooks/useBrandOrdersApi';\nimport { useRequestReturn } from '../hooks/useCommerceApi';\nimport type { CooBrandOrder, CooOrder, CooReturnRequest } from '../types';\nimport { formatDate } from '../utils/formatters';\nimport { TextAreaField } from './Field';\nimport { StatusBadge } from './StatusBadge';\n\nconst MIN_TEXT = 3;\nconst MAX_TEXT = 1000;\nconst RETURNABLE_ORDER_STATUSES = ['PAID', 'PARTIALLY_REFUNDED'];\n\nconst isValidText = (value: string): boolean => {\n const trimmed = value.trim();\n return trimmed.length >= MIN_TEXT && trimmed.length <= MAX_TEXT;\n};\n\nconst primaryButton =\n 'inline-flex items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text transition-colors hover:bg-action-primary-bg/90 disabled:opacity-50';\nconst secondaryButton =\n 'inline-flex 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 return window of a paid order is still open. */\nexport function isReturnWindowOpen(order: Pick<CooOrder, 'returnWindowEndsAt'>, now = Date.now()) {\n if (!order.returnWindowEndsAt) return false;\n return new Date(order.returnWindowEndsAt).getTime() > now;\n}\n\n/** Whether the shopper can still ask the brand to take back its pieces of this order. */\nexport function canRequestReturn(order: CooOrder, brandId: string, now = Date.now()): boolean {\n if (!RETURNABLE_ORDER_STATUSES.includes(order.status)) return false;\n if (order.returnRequests?.some((request) => request.brandId === brandId)) return false;\n const refund = order.refunds?.find((entry) => entry.brandId === brandId);\n if (refund && (refund.status === 'COMPLETED' || refund.status === 'PENDING')) return false;\n return isReturnWindowOpen(order, now);\n}\n\nfunction RequestDetails({ request }: { request: CooReturnRequest }) {\n const tr = useTr();\n return (\n <div className=\"space-y-1 text-xs text-text-secondary\">\n <p>\n {tr('coolandlovely.returns.reasonShown', 'Reason: {{reason}}', { reason: request.reason })}\n </p>\n {request.status === 'REQUESTED' && (\n <p>\n {tr(\n 'coolandlovely.returns.awaitingBrand',\n 'Asked {{date}}. The brand will approve or decline it.',\n { date: formatDate(request.createdAt) }\n )}\n </p>\n )}\n {request.status !== 'REQUESTED' && request.decisionNote && (\n <p data-testid=\"return-decision-note\">\n {tr('coolandlovely.returns.brandNote', 'Brand’s note: {{note}}', {\n note: request.decisionNote,\n })}\n </p>\n )}\n {request.status !== 'REQUESTED' && request.decidedAt && (\n <p>\n {request.status === 'APPROVED'\n ? tr(\n 'coolandlovely.returns.approvedOn',\n 'Approved {{date}}. The pieces were refunded.',\n {\n date: formatDate(request.decidedAt),\n }\n )\n : tr('coolandlovely.returns.declinedOn', 'Declined {{date}}.', {\n date: formatDate(request.decidedAt),\n })}\n </p>\n )}\n </div>\n );\n}\n\nfunction RequestReturnForm({ orderId, brandId }: { orderId: string; brandId: string }) {\n const tr = useTr();\n const request = useRequestReturn();\n const [open, setOpen] = useState(false);\n const [reason, setReason] = useState('');\n\n if (!open) {\n return (\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className={secondaryButton}\n data-testid=\"order-return-open\"\n >\n <Undo2 className=\"h-4 w-4\" />\n {tr('coolandlovely.returns.request', 'Request a return')}\n </button>\n );\n }\n return (\n <div className=\"space-y-2\">\n <TextAreaField\n id={`coo-return-reason-${brandId}`}\n label={tr('coolandlovely.returns.reason', 'Why are you returning these pieces?')}\n hint={tr('coolandlovely.returns.reasonHint', 'Shown to the brand.')}\n value={reason}\n onChange={setReason}\n rows={3}\n />\n {request.error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {request.error.message}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n disabled={request.isPending || !isValidText(reason)}\n onClick={() =>\n request.mutate(\n { orderId, brandId, reason: reason.trim() },\n { onSuccess: () => setOpen(false) }\n )\n }\n className={primaryButton}\n data-testid=\"order-return-submit\"\n >\n {request.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr('coolandlovely.returns.send', 'Send return request')}\n </button>\n <button\n type=\"button\"\n disabled={request.isPending}\n onClick={() => setOpen(false)}\n className={secondaryButton}\n >\n {tr('coolandlovely.common.cancel', 'Cancel')}\n </button>\n </div>\n </div>\n );\n}\n\n/** The shopper's returns card on a paid order: one row per brand in the order. */\nexport function OrderReturns({ order }: { order: CooOrder }) {\n const tr = useTr();\n const paid = order.status === 'PAID' || order.status === 'PARTIALLY_REFUNDED';\n const requests = order.returnRequests ?? [];\n if (!paid && requests.length === 0) return null;\n\n const brandIds = [...new Set(order.items.map((item) => item.brandId))];\n const brandName = (brandId: string): string =>\n requests.find((request) => request.brandId === brandId)?.brandName ??\n order.fulfilments?.find((fulfilment) => fulfilment.brandId === brandId)?.brandName ??\n order.refunds?.find((refund) => refund.brandId === brandId)?.brandName ??\n tr('coolandlovely.orders.brand', 'Brand');\n const windowOpen = isReturnWindowOpen(order);\n\n return (\n <GlassCard treatment=\"plain\" className=\"space-y-4 p-4\" data-testid=\"order-returns\">\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr('coolandlovely.returns.title', 'Returns')}\n </p>\n {paid && order.returnWindowEndsAt && (\n <p className=\"text-xs text-text-secondary\" data-testid=\"order-return-window\">\n {windowOpen\n ? tr(\n 'coolandlovely.returns.windowOpen',\n 'You can ask a brand to take back its pieces until {{date}}.',\n { date: formatDate(order.returnWindowEndsAt) }\n )\n : tr('coolandlovely.returns.windowClosed', 'The return window closed on {{date}}.', {\n date: formatDate(order.returnWindowEndsAt),\n })}\n </p>\n )}\n </div>\n {brandIds.map((brandId) => {\n const request = requests.find((entry) => entry.brandId === brandId);\n const eligible = canRequestReturn(order, brandId);\n if (!request && !eligible) return null;\n return (\n <div key={brandId} className=\"space-y-2\" data-testid=\"order-return\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{brandName(brandId)}</span>\n {request && (\n <span data-testid=\"order-return-status\">\n <StatusBadge status={request.status} />\n </span>\n )}\n </div>\n {request ? (\n <RequestDetails request={request} />\n ) : (\n <RequestReturnForm orderId={order.id} brandId={brandId} />\n )}\n </div>\n );\n })}\n </GlassCard>\n );\n}\n\n/** The brand's view of the shopper's return request, with approve and decline. */\nexport function ReturnRequestPanel({ order }: { order: CooBrandOrder }) {\n const tr = useTr();\n const approve = useApproveReturnRequest();\n const decline = useDeclineReturnRequest();\n const [mode, setMode] = useState<'idle' | 'approve' | 'decline'>('idle');\n const [note, setNote] = useState('');\n const request = order.returnRequest;\n if (!request) return null;\n\n const busy = approve.isPending || decline.isPending;\n const error = approve.error ?? decline.error;\n const noteOk = mode === 'approve' ? note.trim() === '' || isValidText(note) : isValidText(note);\n const reset = () => {\n setMode('idle');\n setNote('');\n };\n const submit = () => {\n const input = { brandId: order.brandId, orderId: order.id };\n if (mode === 'approve') {\n approve.mutate({ ...input, note: note.trim() || null }, { onSuccess: reset });\n } else {\n decline.mutate({ ...input, note: note.trim() }, { onSuccess: reset });\n }\n };\n\n return (\n <div className=\"space-y-3 border-t border-border-seam pt-4\" data-testid=\"brand-return-panel\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {tr('coolandlovely.returns.brandTitle', 'Return request')}\n </span>\n <span data-testid=\"brand-return-status\">\n <StatusBadge status={request.status} />\n </span>\n </div>\n <RequestDetails request={request} />\n\n {request.status === 'REQUESTED' &&\n (mode === 'idle' ? (\n <div className=\"grid grid-cols-2 gap-2\">\n <button\n type=\"button\"\n onClick={() => setMode('approve')}\n className={primaryButton}\n data-testid=\"brand-return-approve-open\"\n >\n <CheckCircle2 className=\"h-4 w-4\" />\n {tr('coolandlovely.returns.approve', 'Approve')}\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('decline')}\n className={secondaryButton}\n data-testid=\"brand-return-decline-open\"\n >\n <XCircle className=\"h-4 w-4\" />\n {tr('coolandlovely.returns.decline', 'Decline')}\n </button>\n </div>\n ) : (\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {mode === 'approve'\n ? tr(\n 'coolandlovely.returns.approveExplain',\n 'Approving refunds all of your pieces in this order to the shopper, with their share of tax, and reverses the creator commissions on them. This cannot be undone.'\n )\n : tr(\n 'coolandlovely.returns.declineExplain',\n 'The shopper sees your note. A declined return cannot be reopened.'\n )}\n </p>\n <TextAreaField\n id=\"coo-return-decision-note\"\n label={\n mode === 'approve'\n ? tr('coolandlovely.returns.approveNote', 'Note to the shopper (optional)')\n : tr('coolandlovely.returns.declineNote', 'Why are you declining?')\n }\n value={note}\n onChange={setNote}\n rows={3}\n />\n {error && (\n <p className=\"text-sm text-status-error-text\" role=\"alert\">\n {error.message}\n </p>\n )}\n <button\n type=\"button\"\n disabled={busy || !noteOk}\n onClick={submit}\n className={\n mode === 'approve'\n ? `${primaryButton} w-full`\n : `${secondaryButton} w-full text-status-error-text`\n }\n data-testid=\"brand-return-confirm\"\n >\n {busy && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {mode === 'approve'\n ? tr('coolandlovely.returns.approveConfirm', 'Approve and refund')\n : tr('coolandlovely.returns.declineConfirm', 'Decline return')}\n </button>\n <button\n type=\"button\"\n disabled={busy}\n onClick={reset}\n className={`${secondaryButton} w-full`}\n >\n {tr('coolandlovely.common.cancel', 'Cancel')}\n </button>\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -6,7 +6,9 @@ export declare const useBrandOrder: (brandId: string | undefined, id: string | u
|
|
|
6
6
|
export declare const useUpdateOrderFulfilment: () => import('@tanstack/react-query').UseMutationResult<CooBrandOrder, Error, CooUpdateOrderFulfilmentInput, unknown>;
|
|
7
7
|
/**
|
|
8
8
|
* Refund the brand's pieces of an order (BOFF-9702). global-billing returns the money to the
|
|
9
|
-
* shopper, and the creator commissions on the refunded lines are reversed.
|
|
9
|
+
* shopper, and the creator commissions on the refunded lines are reversed. With `restock: true`
|
|
10
|
+
* the refunded stock-tracked pieces go back into stock (BOFF-9901); sending it on a completed
|
|
11
|
+
* refund restocks it afterwards.
|
|
10
12
|
*/
|
|
11
13
|
export declare const useRefundBrandOrder: () => import('@tanstack/react-query').UseMutationResult<CooBrandOrder, Error, CooRefundBrandOrderInput, unknown>;
|
|
12
14
|
/** The brand's return requests, newest first, optionally by status (BOFF-9900). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBrandOrdersApi.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/hooks/useBrandOrdersApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,4BAA4B,EAC5B,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAC9B,MAAM,UAAU,CAAC;AAkBlB,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,GAAG,SAAS,EAC3B,mBAAmB,mBAAmB,4FAoBvC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,GAAG,SAAS,yFAkB/D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,GAAG,SAAS,EAAE,IAAI,MAAM,GAAG,SAAS,yFAchF,CAAC;AAEF,eAAO,MAAM,wBAAwB,uHAoBpC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"useBrandOrdersApi.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/hooks/useBrandOrdersApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,4BAA4B,EAC5B,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,6BAA6B,EAC9B,MAAM,UAAU,CAAC;AAkBlB,eAAO,MAAM,cAAc,GACzB,SAAS,MAAM,GAAG,SAAS,EAC3B,mBAAmB,mBAAmB,4FAoBvC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,GAAG,SAAS,yFAkB/D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,GAAG,SAAS,EAAE,IAAI,MAAM,GAAG,SAAS,yFAchF,CAAC;AAEF,eAAO,MAAM,wBAAwB,uHAoBpC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,kHAoC/B,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,sBAAsB,GACjC,SAAS,MAAM,GAAG,SAAS,EAC3B,SAAS,sBAAsB,+FAoBhC,CAAC;AAaF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,sHAiBnC,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,sHAgBnC,CAAC"}
|
|
@@ -9,7 +9,7 @@ var c = "coolandlovely", l = `
|
|
|
9
9
|
shippingName shippingAddress buyerNote paidAt createdAt
|
|
10
10
|
items {
|
|
11
11
|
id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal
|
|
12
|
-
lookId isCreatorAttributed
|
|
12
|
+
lookId isCreatorAttributed stockTracked
|
|
13
13
|
}
|
|
14
14
|
fulfilment { ${n} }
|
|
15
15
|
refund { ${r} }
|
|
@@ -94,7 +94,7 @@ var c = "coolandlovely", l = `
|
|
|
94
94
|
cooRefundBrandOrder(input: $input) { ${l} }
|
|
95
95
|
}`, { input: e }, n)).cooRefundBrandOrder,
|
|
96
96
|
onSuccess: (e) => {
|
|
97
|
-
r.setQueryData([
|
|
97
|
+
if (r.setQueryData([
|
|
98
98
|
c,
|
|
99
99
|
"brand-order",
|
|
100
100
|
e.brandId,
|
|
@@ -107,7 +107,18 @@ var c = "coolandlovely", l = `
|
|
|
107
107
|
c,
|
|
108
108
|
"brand-order-summary",
|
|
109
109
|
e.brandId
|
|
110
|
-
] })
|
|
110
|
+
] }), e.refund?.restockStatus === "RESTOCKED") {
|
|
111
|
+
for (let t of new Set(e.items.map((e) => e.styleItemId))) r.invalidateQueries({ queryKey: [
|
|
112
|
+
c,
|
|
113
|
+
"style-item-inventory",
|
|
114
|
+
t
|
|
115
|
+
] }), r.invalidateQueries({ queryKey: [
|
|
116
|
+
c,
|
|
117
|
+
"style-item",
|
|
118
|
+
t
|
|
119
|
+
] });
|
|
120
|
+
r.invalidateQueries({ queryKey: [c, "style-items"] });
|
|
121
|
+
}
|
|
111
122
|
},
|
|
112
123
|
onError: (e, t) => {
|
|
113
124
|
r.invalidateQueries({ queryKey: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBrandOrdersApi.js","names":[],"sources":["../../../src/coolandlovely/hooks/useBrandOrdersApi.ts"],"sourcesContent":["/**\n * Brand order hooks (BOFF-9636)\n * @module coolandlovely/hooks\n *\n * React Query layer over the brand-side order fields of `wspace-coolandlovely-svc`: the paid\n * orders that contain a brand's pieces (only that brand's lines), counts per fulfilment state,\n * and the fulfilment mutation (confirm, ship with tracking, mark delivered). Also the brand's\n * refunds (BOFF-9702) and the shopper return requests it approves or declines (BOFF-9900).\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { useCoolAndLovely } from '../context';\nimport type {\n CooApproveReturnRequestInput,\n CooBrandOrder,\n CooBrandOrderConnection,\n CooBrandOrderSummary,\n CooDeclineReturnRequestInput,\n CooFulfilmentStatus,\n CooRefundBrandOrderInput,\n CooReturnRequestConnection,\n CooReturnRequestStatus,\n CooUpdateOrderFulfilmentInput,\n} from '../types';\nimport { FULFILMENT_FIELDS, REFUND_FIELDS, RETURN_REQUEST_FIELDS } from './useCommerceApi';\nimport { coolQuery } from './useCoolAndLovelyApi';\n\nconst QK = 'coolandlovely';\n\nconst BRAND_ORDER_FIELDS = `\n id orderNumber status brandId currency brandSubtotal itemCount\n shippingName shippingAddress buyerNote paidAt createdAt\n items {\n id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal\n lookId isCreatorAttributed\n }\n fulfilment { ${FULFILMENT_FIELDS} }\n refund { ${REFUND_FIELDS} }\n returnRequest { ${RETURN_REQUEST_FIELDS} }\n`;\n\nexport const useBrandOrders = (\n brandId: string | undefined,\n fulfilmentStatus?: CooFulfilmentStatus\n) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-orders', brandId, fulfilmentStatus ?? 'ALL'],\n enabled: !!brandId,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandOrders: CooBrandOrderConnection }>(\n `query CooBrandOrders($brandId: ID!, $fulfilmentStatus: CooFulfilmentStatus, $pagination: PaginationInput) {\n cooBrandOrders(brandId: $brandId, fulfilmentStatus: $fulfilmentStatus, pagination: $pagination) {\n items { ${BRAND_ORDER_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { brandId, fulfilmentStatus, pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooBrandOrders;\n },\n });\n};\n\nexport const useBrandOrderSummary = (brandId: string | undefined) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-order-summary', brandId],\n enabled: !!brandId,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandOrderSummary: CooBrandOrderSummary }>(\n `query CooBrandOrderSummary($brandId: ID!) {\n cooBrandOrderSummary(brandId: $brandId) {\n brandId unfulfilled confirmed shipped delivered refunded total\n }\n }`,\n { brandId },\n apiGatewayUrl\n );\n return data.cooBrandOrderSummary;\n },\n });\n};\n\nexport const useBrandOrder = (brandId: string | undefined, id: string | undefined) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-order', brandId, id],\n enabled: !!brandId && !!id,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandOrder: CooBrandOrder | null }>(\n `query CooBrandOrder($brandId: ID!, $id: ID!) { cooBrandOrder(brandId: $brandId, id: $id) { ${BRAND_ORDER_FIELDS} } }`,\n { brandId, id },\n apiGatewayUrl\n );\n return data.cooBrandOrder;\n },\n });\n};\n\nexport const useUpdateOrderFulfilment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: CooUpdateOrderFulfilmentInput) => {\n const data = await coolQuery<{ cooUpdateOrderFulfilment: CooBrandOrder }>(\n `mutation CooUpdateOrderFulfilment($input: CooUpdateOrderFulfilmentInput!) {\n cooUpdateOrderFulfilment(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooUpdateOrderFulfilment;\n },\n onSuccess: (order) => {\n queryClient.setQueryData([QK, 'brand-order', order.brandId, order.id], order);\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-orders', order.brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order-summary', order.brandId] });\n },\n });\n};\n\n/**\n * Refund the brand's pieces of an order (BOFF-9702). global-billing returns the money to the\n * shopper, and the creator commissions on the refunded lines are reversed.\n */\nexport const useRefundBrandOrder = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: CooRefundBrandOrderInput) => {\n const data = await coolQuery<{ cooRefundBrandOrder: CooBrandOrder }>(\n `mutation CooRefundBrandOrder($input: CooRefundBrandOrderInput!) {\n cooRefundBrandOrder(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooRefundBrandOrder;\n },\n onSuccess: (order) => {\n queryClient.setQueryData([QK, 'brand-order', order.brandId, order.id], order);\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-orders', order.brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order-summary', order.brandId] });\n },\n // A failed refund is recorded on the order; refetch so the page shows why.\n onError: (_error, input) => {\n void queryClient.invalidateQueries({\n queryKey: [QK, 'brand-order', input.brandId, input.orderId],\n });\n },\n });\n};\n\n/** The brand's return requests, newest first, optionally by status (BOFF-9900). */\nexport const useBrandReturnRequests = (\n brandId: string | undefined,\n status?: CooReturnRequestStatus\n) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-return-requests', brandId, status ?? 'ALL'],\n enabled: !!brandId,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandReturnRequests: CooReturnRequestConnection }>(\n `query CooBrandReturnRequests($brandId: ID!, $status: CooReturnRequestStatus, $pagination: PaginationInput) {\n cooBrandReturnRequests(brandId: $brandId, status: $status, pagination: $pagination) {\n items { ${RETURN_REQUEST_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { brandId, status, pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooBrandReturnRequests;\n },\n });\n};\n\nconst useReturnDecisionSettled = () => {\n const queryClient = useQueryClient();\n return (brandId: string, orderId: string, order?: CooBrandOrder) => {\n if (order) queryClient.setQueryData([QK, 'brand-order', brandId, orderId], order);\n else void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order', brandId, orderId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-orders', brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order-summary', brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-return-requests', brandId] });\n };\n};\n\n/**\n * Approve a shopper's return (BOFF-9900): refunds the brand's pieces through the brand refund and\n * marks the request approved. On an error the order is refetched so a failed refund shows why.\n */\nexport const useApproveReturnRequest = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useReturnDecisionSettled();\n return useMutation({\n mutationFn: async (input: CooApproveReturnRequestInput) => {\n const data = await coolQuery<{ cooApproveReturnRequest: CooBrandOrder }>(\n `mutation CooApproveReturnRequest($input: CooApproveReturnRequestInput!) {\n cooApproveReturnRequest(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooApproveReturnRequest;\n },\n onSuccess: (order, input) => settle(input.brandId, input.orderId, order),\n onError: (_error, input) => settle(input.brandId, input.orderId),\n });\n};\n\n/** Decline a shopper's return with a note the shopper sees (BOFF-9900). */\nexport const useDeclineReturnRequest = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useReturnDecisionSettled();\n return useMutation({\n mutationFn: async (input: CooDeclineReturnRequestInput) => {\n const data = await coolQuery<{ cooDeclineReturnRequest: CooBrandOrder }>(\n `mutation CooDeclineReturnRequest($input: CooDeclineReturnRequestInput!) {\n cooDeclineReturnRequest(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooDeclineReturnRequest;\n },\n onSuccess: (order, input) => settle(input.brandId, input.orderId, order),\n });\n};\n"],"mappings":";;;;;;AA4BA,IAAM,IAAK,iBAEL,IAAqB;;;;;;;iBAOV,EAAkB;aACtB,EAAc;oBACP,EAAsB;GAG7B,KACX,GACA,MACG;CACH,IAAM,EAAE,qBAAkB,GAAkB;AAC5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAI;GAAgB;GAAS,KAAoB;GAAM;EAClE,SAAS,CAAC,CAAC;EACX,SAAS,aACM,MAAM,EACjB;;sBAEc,EAAmB;;;YAIjC;GAAE;GAAS;GAAkB,YAAY;IAAE,OAAO;IAAI,QAAQ;IAAG;GAAE,EACnE,EACD,EACW;EAEf,CAAC;GAGS,KAAwB,MAAgC;CACnE,IAAM,EAAE,qBAAkB,GAAkB;AAC5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAI;GAAuB;GAAQ;EAC9C,SAAS,CAAC,CAAC;EACX,SAAS,aACM,MAAM,EACjB,wMAKA,EAAE,YAAS,EACX,EACD,EACW;EAEf,CAAC;GAGS,KAAiB,GAA6B,MAA2B;CACpF,IAAM,EAAE,qBAAkB,GAAkB;AAC5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAI;GAAe;GAAS;GAAG;EAC1C,SAAS,CAAC,CAAC,KAAW,CAAC,CAAC;EACxB,SAAS,aACM,MAAM,EACjB,8FAA8F,EAAmB,OACjH;GAAE;GAAS;GAAI,EACf,EACD,EACW;EAEf,CAAC;GAGS,UAAiC;CAC5C,IAAM,EAAE,qBAAkB,GAAkB,EACtC,IAAc,GAAgB;AACpC,QAAO,EAAY;EACjB,YAAY,OAAO,OACJ,MAAM,EACjB;sDAC8C,EAAmB;YAEjE,EAAE,UAAO,EACT,EACD,EACW;EAEd,YAAY,MAAU;AAGf,GAFL,EAAY,aAAa;IAAC;IAAI;IAAe,EAAM;IAAS,EAAM;IAAG,EAAE,EAAM,EACxE,EAAY,kBAAkB,EAAE,UAAU;IAAC;IAAI;IAAgB,EAAM;IAAQ,EAAE,CAAC,EAChF,EAAY,kBAAkB,EAAE,UAAU;IAAC;IAAI;IAAuB,EAAM;IAAQ,EAAE,CAAC;;EAE/F,CAAC;GAOS,UAA4B;CACvC,IAAM,EAAE,qBAAkB,GAAkB,EACtC,IAAc,GAAgB;AACpC,QAAO,EAAY;EACjB,YAAY,OAAO,OACJ,MAAM,EACjB;iDACyC,EAAmB;YAE5D,EAAE,UAAO,EACT,EACD,EACW;EAEd,YAAY,MAAU;AAGf,GAFL,EAAY,aAAa;IAAC;IAAI;IAAe,EAAM;IAAS,EAAM;IAAG,EAAE,EAAM,EACxE,EAAY,kBAAkB,EAAE,UAAU;IAAC;IAAI;IAAgB,EAAM;IAAQ,EAAE,CAAC,EAChF,EAAY,kBAAkB,EAAE,UAAU;IAAC;IAAI;IAAuB,EAAM;IAAQ,EAAE,CAAC;;EAG9F,UAAU,GAAQ,MAAU;AACrB,KAAY,kBAAkB,EACjC,UAAU;IAAC;IAAI;IAAe,EAAM;IAAS,EAAM;IAAQ,EAC5D,CAAC;;EAEL,CAAC;GAIS,KACX,GACA,MACG;CACH,IAAM,EAAE,qBAAkB,GAAkB;AAC5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAI;GAAyB;GAAS,KAAU;GAAM;EACjE,SAAS,CAAC,CAAC;EACX,SAAS,aACM,MAAM,EACjB;;sBAEc,EAAsB;;;YAIpC;GAAE;GAAS;GAAQ,YAAY;IAAE,OAAO;IAAI,QAAQ;IAAG;GAAE,EACzD,EACD,EACW;EAEf,CAAC;GAGE,UAAiC;CACrC,IAAM,IAAc,GAAgB;AACpC,SAAQ,GAAiB,GAAiB,MAA0B;AAK7D,EAJD,IAAO,EAAY,aAAa;GAAC;GAAI;GAAe;GAAS;GAAQ,EAAE,EAAM,GACvE,EAAY,kBAAkB,EAAE,UAAU;GAAC;GAAI;GAAe;GAAS;GAAQ,EAAE,CAAC,EACvF,EAAY,kBAAkB,EAAE,UAAU;GAAC;GAAI;GAAgB;GAAQ,EAAE,CAAC,EAC1E,EAAY,kBAAkB,EAAE,UAAU;GAAC;GAAI;GAAuB;GAAQ,EAAE,CAAC,EACjF,EAAY,kBAAkB,EAAE,UAAU;GAAC;GAAI;GAAyB;GAAQ,EAAE,CAAC;;GAQ/E,UAAgC;CAC3C,IAAM,EAAE,qBAAkB,GAAkB,EACtC,IAAS,GAA0B;AACzC,QAAO,EAAY;EACjB,YAAY,OAAO,OACJ,MAAM,EACjB;qDAC6C,EAAmB;YAEhE,EAAE,UAAO,EACT,EACD,EACW;EAEd,YAAY,GAAO,MAAU,EAAO,EAAM,SAAS,EAAM,SAAS,EAAM;EACxE,UAAU,GAAQ,MAAU,EAAO,EAAM,SAAS,EAAM,QAAQ;EACjE,CAAC;GAIS,UAAgC;CAC3C,IAAM,EAAE,qBAAkB,GAAkB,EACtC,IAAS,GAA0B;AACzC,QAAO,EAAY;EACjB,YAAY,OAAO,OACJ,MAAM,EACjB;qDAC6C,EAAmB;YAEhE,EAAE,UAAO,EACT,EACD,EACW;EAEd,YAAY,GAAO,MAAU,EAAO,EAAM,SAAS,EAAM,SAAS,EAAM;EACzE,CAAC"}
|
|
1
|
+
{"version":3,"file":"useBrandOrdersApi.js","names":[],"sources":["../../../src/coolandlovely/hooks/useBrandOrdersApi.ts"],"sourcesContent":["/**\n * Brand order hooks (BOFF-9636)\n * @module coolandlovely/hooks\n *\n * React Query layer over the brand-side order fields of `wspace-coolandlovely-svc`: the paid\n * orders that contain a brand's pieces (only that brand's lines), counts per fulfilment state,\n * and the fulfilment mutation (confirm, ship with tracking, mark delivered). Also the brand's\n * refunds (BOFF-9702) and the shopper return requests it approves or declines (BOFF-9900).\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { useCoolAndLovely } from '../context';\nimport type {\n CooApproveReturnRequestInput,\n CooBrandOrder,\n CooBrandOrderConnection,\n CooBrandOrderSummary,\n CooDeclineReturnRequestInput,\n CooFulfilmentStatus,\n CooRefundBrandOrderInput,\n CooReturnRequestConnection,\n CooReturnRequestStatus,\n CooUpdateOrderFulfilmentInput,\n} from '../types';\nimport { FULFILMENT_FIELDS, REFUND_FIELDS, RETURN_REQUEST_FIELDS } from './useCommerceApi';\nimport { coolQuery } from './useCoolAndLovelyApi';\n\nconst QK = 'coolandlovely';\n\nconst BRAND_ORDER_FIELDS = `\n id orderNumber status brandId currency brandSubtotal itemCount\n shippingName shippingAddress buyerNote paidAt createdAt\n items {\n id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal\n lookId isCreatorAttributed stockTracked\n }\n fulfilment { ${FULFILMENT_FIELDS} }\n refund { ${REFUND_FIELDS} }\n returnRequest { ${RETURN_REQUEST_FIELDS} }\n`;\n\nexport const useBrandOrders = (\n brandId: string | undefined,\n fulfilmentStatus?: CooFulfilmentStatus\n) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-orders', brandId, fulfilmentStatus ?? 'ALL'],\n enabled: !!brandId,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandOrders: CooBrandOrderConnection }>(\n `query CooBrandOrders($brandId: ID!, $fulfilmentStatus: CooFulfilmentStatus, $pagination: PaginationInput) {\n cooBrandOrders(brandId: $brandId, fulfilmentStatus: $fulfilmentStatus, pagination: $pagination) {\n items { ${BRAND_ORDER_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { brandId, fulfilmentStatus, pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooBrandOrders;\n },\n });\n};\n\nexport const useBrandOrderSummary = (brandId: string | undefined) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-order-summary', brandId],\n enabled: !!brandId,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandOrderSummary: CooBrandOrderSummary }>(\n `query CooBrandOrderSummary($brandId: ID!) {\n cooBrandOrderSummary(brandId: $brandId) {\n brandId unfulfilled confirmed shipped delivered refunded total\n }\n }`,\n { brandId },\n apiGatewayUrl\n );\n return data.cooBrandOrderSummary;\n },\n });\n};\n\nexport const useBrandOrder = (brandId: string | undefined, id: string | undefined) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-order', brandId, id],\n enabled: !!brandId && !!id,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandOrder: CooBrandOrder | null }>(\n `query CooBrandOrder($brandId: ID!, $id: ID!) { cooBrandOrder(brandId: $brandId, id: $id) { ${BRAND_ORDER_FIELDS} } }`,\n { brandId, id },\n apiGatewayUrl\n );\n return data.cooBrandOrder;\n },\n });\n};\n\nexport const useUpdateOrderFulfilment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: CooUpdateOrderFulfilmentInput) => {\n const data = await coolQuery<{ cooUpdateOrderFulfilment: CooBrandOrder }>(\n `mutation CooUpdateOrderFulfilment($input: CooUpdateOrderFulfilmentInput!) {\n cooUpdateOrderFulfilment(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooUpdateOrderFulfilment;\n },\n onSuccess: (order) => {\n queryClient.setQueryData([QK, 'brand-order', order.brandId, order.id], order);\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-orders', order.brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order-summary', order.brandId] });\n },\n });\n};\n\n/**\n * Refund the brand's pieces of an order (BOFF-9702). global-billing returns the money to the\n * shopper, and the creator commissions on the refunded lines are reversed. With `restock: true`\n * the refunded stock-tracked pieces go back into stock (BOFF-9901); sending it on a completed\n * refund restocks it afterwards.\n */\nexport const useRefundBrandOrder = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: CooRefundBrandOrderInput) => {\n const data = await coolQuery<{ cooRefundBrandOrder: CooBrandOrder }>(\n `mutation CooRefundBrandOrder($input: CooRefundBrandOrderInput!) {\n cooRefundBrandOrder(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooRefundBrandOrder;\n },\n onSuccess: (order) => {\n queryClient.setQueryData([QK, 'brand-order', order.brandId, order.id], order);\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-orders', order.brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order-summary', order.brandId] });\n // A restock (BOFF-9901) changes the pieces' stock and can put a sold-out piece back on sale.\n if (order.refund?.restockStatus === 'RESTOCKED') {\n for (const styleItemId of new Set(order.items.map((item) => item.styleItemId))) {\n void queryClient.invalidateQueries({\n queryKey: [QK, 'style-item-inventory', styleItemId],\n });\n void queryClient.invalidateQueries({ queryKey: [QK, 'style-item', styleItemId] });\n }\n void queryClient.invalidateQueries({ queryKey: [QK, 'style-items'] });\n }\n },\n // A failed refund is recorded on the order; refetch so the page shows why.\n onError: (_error, input) => {\n void queryClient.invalidateQueries({\n queryKey: [QK, 'brand-order', input.brandId, input.orderId],\n });\n },\n });\n};\n\n/** The brand's return requests, newest first, optionally by status (BOFF-9900). */\nexport const useBrandReturnRequests = (\n brandId: string | undefined,\n status?: CooReturnRequestStatus\n) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'brand-return-requests', brandId, status ?? 'ALL'],\n enabled: !!brandId,\n queryFn: async () => {\n const data = await coolQuery<{ cooBrandReturnRequests: CooReturnRequestConnection }>(\n `query CooBrandReturnRequests($brandId: ID!, $status: CooReturnRequestStatus, $pagination: PaginationInput) {\n cooBrandReturnRequests(brandId: $brandId, status: $status, pagination: $pagination) {\n items { ${RETURN_REQUEST_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { brandId, status, pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooBrandReturnRequests;\n },\n });\n};\n\nconst useReturnDecisionSettled = () => {\n const queryClient = useQueryClient();\n return (brandId: string, orderId: string, order?: CooBrandOrder) => {\n if (order) queryClient.setQueryData([QK, 'brand-order', brandId, orderId], order);\n else void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order', brandId, orderId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-orders', brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-order-summary', brandId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'brand-return-requests', brandId] });\n };\n};\n\n/**\n * Approve a shopper's return (BOFF-9900): refunds the brand's pieces through the brand refund and\n * marks the request approved. On an error the order is refetched so a failed refund shows why.\n */\nexport const useApproveReturnRequest = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useReturnDecisionSettled();\n return useMutation({\n mutationFn: async (input: CooApproveReturnRequestInput) => {\n const data = await coolQuery<{ cooApproveReturnRequest: CooBrandOrder }>(\n `mutation CooApproveReturnRequest($input: CooApproveReturnRequestInput!) {\n cooApproveReturnRequest(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooApproveReturnRequest;\n },\n onSuccess: (order, input) => settle(input.brandId, input.orderId, order),\n onError: (_error, input) => settle(input.brandId, input.orderId),\n });\n};\n\n/** Decline a shopper's return with a note the shopper sees (BOFF-9900). */\nexport const useDeclineReturnRequest = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useReturnDecisionSettled();\n return useMutation({\n mutationFn: async (input: CooDeclineReturnRequestInput) => {\n const data = await coolQuery<{ cooDeclineReturnRequest: CooBrandOrder }>(\n `mutation CooDeclineReturnRequest($input: CooDeclineReturnRequestInput!) {\n cooDeclineReturnRequest(input: $input) { ${BRAND_ORDER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooDeclineReturnRequest;\n },\n onSuccess: (order, input) => settle(input.brandId, input.orderId, order),\n });\n};\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { CooAddToCartInput, CooCart, CooCheckoutInput, CooCollaborationPaymentCh
|
|
|
3
3
|
/** Per-brand fulfilment (BOFF-9636): shared by the shopper's order detail and the brand view. */
|
|
4
4
|
export declare const FULFILMENT_FIELDS = "\n id orderId brandId brandName status refunded carrier trackingNumber trackingUrl note\n confirmedAt shippedAt deliveredAt updatedAt\n";
|
|
5
5
|
/** A brand's refund of its pieces (BOFF-9702): the shopper's order detail and the brand view. */
|
|
6
|
-
export declare const REFUND_FIELDS = "\n id orderId brandId brandName amount currency reason status failureReason refundedAt createdAt\n";
|
|
6
|
+
export declare const REFUND_FIELDS = "\n id orderId brandId brandName amount currency reason status failureReason refundedAt\n restockStatus restockedQuantity restockedAt createdAt\n";
|
|
7
7
|
/** A shopper's return request (BOFF-9900): the shopper's order detail and the brand view. */
|
|
8
8
|
export declare const RETURN_REQUEST_FIELDS = "\n id orderId orderNumber brandId brandName reason status decisionNote decidedAt refundId\n createdAt updatedAt\n";
|
|
9
9
|
export declare const useMyCart: () => import('@tanstack/react-query').UseQueryResult<NoInfer<CooCart>, Error>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCommerceApi.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/hooks/useCommerceApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,iBAAiB,EACjB,OAAO,EACP,gBAAgB,EAChB,+BAA+B,EAC/B,sBAAsB,EACtB,gCAAgC,EAChC,2BAA2B,EAC3B,yBAAyB,EACzB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAwBlB,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,8IAG7B,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"useCommerceApi.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/hooks/useCommerceApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,iBAAiB,EACjB,OAAO,EACP,gBAAgB,EAChB,+BAA+B,EAC/B,sBAAsB,EACtB,gCAAgC,EAChC,2BAA2B,EAC3B,yBAAyB,EACzB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAwBlB,iGAAiG;AACjG,eAAO,MAAM,iBAAiB,8IAG7B,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,aAAa,uJAGzB,CAAC;AAEF,6FAA6F;AAC7F,eAAO,MAAM,qBAAqB,wHAGjC,CAAC;AAoBF,eAAO,MAAM,SAAS,+EAarB,CAAC;AAuBF,eAAO,MAAM,YAAY;WACE,iBAAiB;WAGzC,CAAC;AAEJ,eAAO,MAAM,iBAAiB;QACN,MAAM;cAAY,MAAM;WAK7C,CAAC;AAEJ,eAAO,MAAM,iBAAiB;QACN,MAAM;WAG3B,CAAC;AAMJ,eAAO,MAAM,WAAW,GAAI,SAAS,cAAc,uFAkBlD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,IAAI,MAAM,GAAG,SAAS,oFAchD,CAAC;AAWF,eAAO,MAAM,WAAW,6GAcvB,CAAC;AAEF,eAAO,MAAM,qBAAqB,mGAcjC,CAAC;AAEF,eAAO,MAAM,mBAAmB,2FAc/B,CAAC;AAEF,eAAO,MAAM,cAAc,2FAc1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,kHAkB5B,CAAC;AAMF,eAAO,MAAM,oBAAoB,mGAqBhC,CAAC;AAEF,eAAO,MAAM,2BAA2B,iGAkBvC,CAAC;AAEF,eAAO,MAAM,uBAAuB;YAII,MAAM;cAAY,MAAM;YAAU,MAAM,GAAG,IAAI;WActF,CAAC;AAWF,uFAAuF;AACvF,eAAO,MAAM,yBAAyB,wGAkBrC,CAAC;AAWF,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,kHAgBlC,CAAC;AAEF,6FAA6F;AAC7F,eAAO,MAAM,2BAA2B,yGAgBvC,CAAC"}
|
|
@@ -3,7 +3,7 @@ import "../context/index.js";
|
|
|
3
3
|
import { COLLABORATION_PAYOUT_FIELDS as t, coolQuery as n } from "./useCoolAndLovelyApi.js";
|
|
4
4
|
import { useMutation as r, useQuery as i, useQueryClient as a } from "@tanstack/react-query";
|
|
5
5
|
//#region src/coolandlovely/hooks/useCommerceApi.ts
|
|
6
|
-
var o = "coolandlovely", s = "\n items {\n id styleItemId quantity size colour lookId unitPrice currency lineTotal isPurchasable\n availableQuantity\n styleItem { id name status image { id } brand { id name } }\n }\n itemCount subtotal currency canCheckout blockedReason\n", c = "\n id orderNumber status currency subtotal taxAmount total itemCount\n shippingName shippingAddress buyerNote paymentProvider paidAt cancelledAt refundedAmount refundedAt\n createdAt updatedAt\n items {\n id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal\n lookId isCreatorAttributed\n }\n", l = "\n id orderId brandId brandName status refunded carrier trackingNumber trackingUrl note\n confirmedAt shippedAt deliveredAt updatedAt\n", u = "\n id orderId brandId brandName amount currency reason status failureReason refundedAt createdAt\n", d = "\n id orderId orderNumber brandId brandName reason status decisionNote decidedAt refundId\n createdAt updatedAt\n", f = `
|
|
6
|
+
var o = "coolandlovely", s = "\n items {\n id styleItemId quantity size colour lookId unitPrice currency lineTotal isPurchasable\n availableQuantity\n styleItem { id name status image { id } brand { id name } }\n }\n itemCount subtotal currency canCheckout blockedReason\n", c = "\n id orderNumber status currency subtotal taxAmount total itemCount\n shippingName shippingAddress buyerNote paymentProvider paidAt cancelledAt refundedAmount refundedAt\n createdAt updatedAt\n items {\n id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal\n lookId isCreatorAttributed\n }\n", l = "\n id orderId brandId brandName status refunded carrier trackingNumber trackingUrl note\n confirmedAt shippedAt deliveredAt updatedAt\n", u = "\n id orderId brandId brandName amount currency reason status failureReason refundedAt\n restockStatus restockedQuantity restockedAt createdAt\n", d = "\n id orderId orderNumber brandId brandName reason status decisionNote decidedAt refundId\n createdAt updatedAt\n", f = `
|
|
7
7
|
${c}
|
|
8
8
|
fulfilmentStatus
|
|
9
9
|
fulfilments { ${l} }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCommerceApi.js","names":[],"sources":["../../../src/coolandlovely/hooks/useCommerceApi.ts"],"sourcesContent":["/**\n * Commerce API hooks (BOFF-3370)\n * @module coolandlovely/hooks\n *\n * React Query layer over the self-scoped commerce fields of `wspace-coolandlovely-svc`:\n * the shopper's cart, checkout and orders, and the creator's look commissions + payouts.\n * The client never decides that an order is paid — it opens the provider's checkout that\n * global-billing prepared and then asks the backend to settle against billing's record.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { useCoolAndLovely } from '../context';\nimport type {\n CooAddToCartInput,\n CooCart,\n CooCheckoutInput,\n CooCollaborationPaymentCheckout,\n CooCollaborationPayout,\n CooCollaborationPayoutConnection,\n CooCreatorEarningConnection,\n CooCreatorEarningsSummary,\n CooCreatorPayout,\n CooOrder,\n CooOrderCheckout,\n CooOrderConnection,\n CooOrderStatus,\n CooRequestReturnInput,\n CooReturnRequest,\n} from '../types';\nimport { COLLABORATION_PAYOUT_FIELDS, coolQuery } from './useCoolAndLovelyApi';\n\nconst QK = 'coolandlovely';\n\nconst CART_FIELDS = `\n items {\n id styleItemId quantity size colour lookId unitPrice currency lineTotal isPurchasable\n availableQuantity\n styleItem { id name status image { id } brand { id name } }\n }\n itemCount subtotal currency canCheckout blockedReason\n`;\n\nconst ORDER_FIELDS = `\n id orderNumber status currency subtotal taxAmount total itemCount\n shippingName shippingAddress buyerNote paymentProvider paidAt cancelledAt refundedAmount refundedAt\n createdAt updatedAt\n items {\n id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal\n lookId isCreatorAttributed\n }\n`;\n\n/** Per-brand fulfilment (BOFF-9636): shared by the shopper's order detail and the brand view. */\nexport const FULFILMENT_FIELDS = `\n id orderId brandId brandName status refunded carrier trackingNumber trackingUrl note\n confirmedAt shippedAt deliveredAt updatedAt\n`;\n\n/** A brand's refund of its pieces (BOFF-9702): the shopper's order detail and the brand view. */\nexport const REFUND_FIELDS = `\n id orderId brandId brandName amount currency reason status failureReason refundedAt createdAt\n`;\n\n/** A shopper's return request (BOFF-9900): the shopper's order detail and the brand view. */\nexport const RETURN_REQUEST_FIELDS = `\n id orderId orderNumber brandId brandName reason status decisionNote decidedAt refundId\n createdAt updatedAt\n`;\n\nconst ORDER_DETAIL_FIELDS = `\n ${ORDER_FIELDS}\n fulfilmentStatus\n fulfilments { ${FULFILMENT_FIELDS} }\n refunds { ${REFUND_FIELDS} }\n returnRequests { ${RETURN_REQUEST_FIELDS} }\n returnWindowEndsAt\n`;\n\nconst CHECKOUT_FIELDS = `\n order { ${ORDER_FIELDS} }\n provider providerOrderId razorpayKeyId clientSecret stripePublishableKey subtotal taxAmount total currency\n`;\n\n// ---------------------------------------------------------------------------\n// Cart\n// ---------------------------------------------------------------------------\n\nexport const useMyCart = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'cart'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCart: CooCart }>(\n `query CooMyCart { cooMyCart { ${CART_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return data.cooMyCart;\n },\n });\n};\n\n/** Every cart mutation answers with the fresh cart, which is written straight into the cache. */\nconst useCartMutation = <TVars>(document: string, field: string) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (variables: TVars) => {\n const data = await coolQuery<Record<string, CooCart>>(\n document,\n variables as Record<string, unknown>,\n apiGatewayUrl\n );\n const cart = data[field];\n if (!cart) throw new Error('The cart could not be updated');\n return cart;\n },\n onSuccess: (cart) => {\n queryClient.setQueryData([QK, 'cart'], cart);\n },\n });\n};\n\nexport const useAddToCart = () =>\n useCartMutation<{ input: CooAddToCartInput }>(\n `mutation CooAddToCart($input: CooAddToCartInput!) { cooAddToCart(input: $input) { ${CART_FIELDS} } }`,\n 'cooAddToCart'\n );\n\nexport const useUpdateCartItem = () =>\n useCartMutation<{ id: string; quantity: number }>(\n `mutation CooUpdateCartItem($id: ID!, $quantity: Int!) {\n cooUpdateCartItem(id: $id, quantity: $quantity) { ${CART_FIELDS} }\n }`,\n 'cooUpdateCartItem'\n );\n\nexport const useRemoveCartItem = () =>\n useCartMutation<{ id: string }>(\n `mutation CooRemoveCartItem($id: ID!) { cooRemoveCartItem(id: $id) { ${CART_FIELDS} } }`,\n 'cooRemoveCartItem'\n );\n\n// ---------------------------------------------------------------------------\n// Orders + checkout\n// ---------------------------------------------------------------------------\n\nexport const useMyOrders = (status?: CooOrderStatus) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'orders', status ?? 'ALL'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyOrders: CooOrderConnection }>(\n `query CooMyOrders($status: CooOrderStatus, $pagination: PaginationInput) {\n cooMyOrders(status: $status, pagination: $pagination) {\n items { ${ORDER_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status, pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooMyOrders;\n },\n });\n};\n\nexport const useMyOrder = (id: string | undefined) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'order', id],\n enabled: !!id,\n queryFn: async () => {\n const data = await coolQuery<{ cooMyOrder: CooOrder | null }>(\n `query CooMyOrder($id: ID!) { cooMyOrder(id: $id) { ${ORDER_DETAIL_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooMyOrder;\n },\n });\n};\n\nconst useOrderInvalidation = () => {\n const queryClient = useQueryClient();\n return (order: CooOrder) => {\n queryClient.setQueryData([QK, 'order', order.id], order);\n void queryClient.invalidateQueries({ queryKey: [QK, 'orders'] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'cart'] });\n };\n};\n\nexport const useCheckout = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (input: CooCheckoutInput) => {\n const data = await coolQuery<{ cooCheckout: CooOrderCheckout }>(\n `mutation CooCheckout($input: CooCheckoutInput!) { cooCheckout(input: $input) { ${CHECKOUT_FIELDS} } }`,\n { input },\n apiGatewayUrl\n );\n return data.cooCheckout;\n },\n onSuccess: (checkout) => settle(checkout.order),\n });\n};\n\nexport const useResumeOrderPayment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await coolQuery<{ cooResumeOrderPayment: CooOrderCheckout }>(\n `mutation CooResumeOrderPayment($id: ID!) { cooResumeOrderPayment(id: $id) { ${CHECKOUT_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooResumeOrderPayment;\n },\n onSuccess: (checkout) => settle(checkout.order),\n });\n};\n\nexport const useSyncOrderPayment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await coolQuery<{ cooSyncOrderPayment: CooOrder }>(\n `mutation CooSyncOrderPayment($id: ID!) { cooSyncOrderPayment(id: $id) { ${ORDER_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooSyncOrderPayment;\n },\n onSuccess: settle,\n });\n};\n\nexport const useCancelOrder = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await coolQuery<{ cooCancelOrder: CooOrder }>(\n `mutation CooCancelOrder($id: ID!) { cooCancelOrder(id: $id) { ${ORDER_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooCancelOrder;\n },\n onSuccess: settle,\n });\n};\n\n/**\n * Ask a brand to take back its pieces of one of the caller's paid orders (BOFF-9900). The brand\n * approves (which refunds them) or declines; the order detail is refetched to show the request.\n */\nexport const useRequestReturn = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: CooRequestReturnInput) => {\n const data = await coolQuery<{ cooRequestReturn: CooReturnRequest }>(\n `mutation CooRequestReturn($input: CooRequestReturnInput!) {\n cooRequestReturn(input: $input) { ${RETURN_REQUEST_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooRequestReturn;\n },\n onSettled: (_request, _error, input) => {\n void queryClient.invalidateQueries({ queryKey: [QK, 'order', input.orderId] });\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// Creator earnings + payouts\n// ---------------------------------------------------------------------------\n\nexport const useMyCreatorEarnings = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'creator-earnings'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCreatorEarnings: CooCreatorEarningConnection }>(\n `query CooMyCreatorEarnings($pagination: PaginationInput) {\n cooMyCreatorEarnings(pagination: $pagination) {\n items {\n id orderId orderNumber lookId collaborationId commissionRate saleAmount amount currency\n availableAt billingSyncStatus reversalStatus reversedAt createdAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooMyCreatorEarnings;\n },\n });\n};\n\nexport const useMyCreatorEarningsSummary = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'creator-earnings-summary'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCreatorEarningsSummary: CooCreatorEarningsSummary }>(\n `query CooMyCreatorEarningsSummary {\n cooMyCreatorEarningsSummary {\n commissionRate holdDays currency totalLifetimeAmount availableAmount pendingAmount\n reservedAmount paidAmount pendingPayoutCount unsyncedCount billingAvailable\n }\n }`,\n {},\n apiGatewayUrl\n );\n return data.cooMyCreatorEarningsSummary;\n },\n });\n};\n\nexport const useRequestCreatorPayout = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: { amount: number; currency: string; notes?: string | null }) => {\n const data = await coolQuery<{ cooRequestCreatorPayout: CooCreatorPayout }>(\n `mutation CooRequestCreatorPayout($input: CooRequestCreatorPayoutInput!) {\n cooRequestCreatorPayout(input: $input) { id status requestedAmount currency createdAt }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooRequestCreatorPayout;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [QK, 'creator-earnings-summary'] });\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// Collaboration fees (BOFF-9637)\n// ---------------------------------------------------------------------------\n\nconst COLLABORATION_PAYMENT_FIELDS = `\n payout { ${COLLABORATION_PAYOUT_FIELDS} }\n provider providerOrderId razorpayKeyId clientSecret stripePublishableKey subtotal taxAmount total currency\n`;\n\n/** The calling creator's collaboration fees: awaiting the brand's payment, or paid. */\nexport const useMyCollaborationPayouts = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'collaboration-payouts'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCollaborationPayouts: CooCollaborationPayoutConnection }>(\n `query CooMyCollaborationPayouts($pagination: PaginationInput) {\n cooMyCollaborationPayouts(pagination: $pagination) {\n items { ${COLLABORATION_PAYOUT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooMyCollaborationPayouts;\n },\n });\n};\n\nconst useCollaborationPayoutInvalidation = () => {\n const queryClient = useQueryClient();\n return (collaborationId: string) => {\n void queryClient.invalidateQueries({ queryKey: [QK, 'collaboration', collaborationId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'collaboration-payouts'] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'creator-earnings-summary'] });\n };\n};\n\n/** Start (or re-open) the brand owner's payment of a collaboration fee. */\nexport const usePayCollaborationFee = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const refresh = useCollaborationPayoutInvalidation();\n return useMutation({\n mutationFn: async (collaborationId: string) => {\n const data = await coolQuery<{ cooPayCollaborationFee: CooCollaborationPaymentCheckout }>(\n `mutation CooPayCollaborationFee($id: ID!) {\n cooPayCollaborationFee(id: $id) { ${COLLABORATION_PAYMENT_FIELDS} }\n }`,\n { id: collaborationId },\n apiGatewayUrl\n );\n return data.cooPayCollaborationFee;\n },\n onSuccess: (checkout) => refresh(checkout.payout.collaborationId),\n });\n};\n\n/** Ask the backend to settle a collaboration fee against global-billing's payment record. */\nexport const useSyncCollaborationPayment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const refresh = useCollaborationPayoutInvalidation();\n return useMutation({\n mutationFn: async (collaborationId: string) => {\n const data = await coolQuery<{ cooSyncCollaborationPayment: CooCollaborationPayout }>(\n `mutation CooSyncCollaborationPayment($id: ID!) {\n cooSyncCollaborationPayment(id: $id) { ${COLLABORATION_PAYOUT_FIELDS} }\n }`,\n { id: collaborationId },\n apiGatewayUrl\n );\n return data.cooSyncCollaborationPayment;\n },\n onSuccess: (payout) => refresh(payout.collaborationId),\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useCommerceApi.js","names":[],"sources":["../../../src/coolandlovely/hooks/useCommerceApi.ts"],"sourcesContent":["/**\n * Commerce API hooks (BOFF-3370)\n * @module coolandlovely/hooks\n *\n * React Query layer over the self-scoped commerce fields of `wspace-coolandlovely-svc`:\n * the shopper's cart, checkout and orders, and the creator's look commissions + payouts.\n * The client never decides that an order is paid — it opens the provider's checkout that\n * global-billing prepared and then asks the backend to settle against billing's record.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { useCoolAndLovely } from '../context';\nimport type {\n CooAddToCartInput,\n CooCart,\n CooCheckoutInput,\n CooCollaborationPaymentCheckout,\n CooCollaborationPayout,\n CooCollaborationPayoutConnection,\n CooCreatorEarningConnection,\n CooCreatorEarningsSummary,\n CooCreatorPayout,\n CooOrder,\n CooOrderCheckout,\n CooOrderConnection,\n CooOrderStatus,\n CooRequestReturnInput,\n CooReturnRequest,\n} from '../types';\nimport { COLLABORATION_PAYOUT_FIELDS, coolQuery } from './useCoolAndLovelyApi';\n\nconst QK = 'coolandlovely';\n\nconst CART_FIELDS = `\n items {\n id styleItemId quantity size colour lookId unitPrice currency lineTotal isPurchasable\n availableQuantity\n styleItem { id name status image { id } brand { id name } }\n }\n itemCount subtotal currency canCheckout blockedReason\n`;\n\nconst ORDER_FIELDS = `\n id orderNumber status currency subtotal taxAmount total itemCount\n shippingName shippingAddress buyerNote paymentProvider paidAt cancelledAt refundedAmount refundedAt\n createdAt updatedAt\n items {\n id styleItemId brandId name sku image { id } size colour unitPrice quantity lineTotal\n lookId isCreatorAttributed\n }\n`;\n\n/** Per-brand fulfilment (BOFF-9636): shared by the shopper's order detail and the brand view. */\nexport const FULFILMENT_FIELDS = `\n id orderId brandId brandName status refunded carrier trackingNumber trackingUrl note\n confirmedAt shippedAt deliveredAt updatedAt\n`;\n\n/** A brand's refund of its pieces (BOFF-9702): the shopper's order detail and the brand view. */\nexport const REFUND_FIELDS = `\n id orderId brandId brandName amount currency reason status failureReason refundedAt\n restockStatus restockedQuantity restockedAt createdAt\n`;\n\n/** A shopper's return request (BOFF-9900): the shopper's order detail and the brand view. */\nexport const RETURN_REQUEST_FIELDS = `\n id orderId orderNumber brandId brandName reason status decisionNote decidedAt refundId\n createdAt updatedAt\n`;\n\nconst ORDER_DETAIL_FIELDS = `\n ${ORDER_FIELDS}\n fulfilmentStatus\n fulfilments { ${FULFILMENT_FIELDS} }\n refunds { ${REFUND_FIELDS} }\n returnRequests { ${RETURN_REQUEST_FIELDS} }\n returnWindowEndsAt\n`;\n\nconst CHECKOUT_FIELDS = `\n order { ${ORDER_FIELDS} }\n provider providerOrderId razorpayKeyId clientSecret stripePublishableKey subtotal taxAmount total currency\n`;\n\n// ---------------------------------------------------------------------------\n// Cart\n// ---------------------------------------------------------------------------\n\nexport const useMyCart = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'cart'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCart: CooCart }>(\n `query CooMyCart { cooMyCart { ${CART_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return data.cooMyCart;\n },\n });\n};\n\n/** Every cart mutation answers with the fresh cart, which is written straight into the cache. */\nconst useCartMutation = <TVars>(document: string, field: string) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (variables: TVars) => {\n const data = await coolQuery<Record<string, CooCart>>(\n document,\n variables as Record<string, unknown>,\n apiGatewayUrl\n );\n const cart = data[field];\n if (!cart) throw new Error('The cart could not be updated');\n return cart;\n },\n onSuccess: (cart) => {\n queryClient.setQueryData([QK, 'cart'], cart);\n },\n });\n};\n\nexport const useAddToCart = () =>\n useCartMutation<{ input: CooAddToCartInput }>(\n `mutation CooAddToCart($input: CooAddToCartInput!) { cooAddToCart(input: $input) { ${CART_FIELDS} } }`,\n 'cooAddToCart'\n );\n\nexport const useUpdateCartItem = () =>\n useCartMutation<{ id: string; quantity: number }>(\n `mutation CooUpdateCartItem($id: ID!, $quantity: Int!) {\n cooUpdateCartItem(id: $id, quantity: $quantity) { ${CART_FIELDS} }\n }`,\n 'cooUpdateCartItem'\n );\n\nexport const useRemoveCartItem = () =>\n useCartMutation<{ id: string }>(\n `mutation CooRemoveCartItem($id: ID!) { cooRemoveCartItem(id: $id) { ${CART_FIELDS} } }`,\n 'cooRemoveCartItem'\n );\n\n// ---------------------------------------------------------------------------\n// Orders + checkout\n// ---------------------------------------------------------------------------\n\nexport const useMyOrders = (status?: CooOrderStatus) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'orders', status ?? 'ALL'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyOrders: CooOrderConnection }>(\n `query CooMyOrders($status: CooOrderStatus, $pagination: PaginationInput) {\n cooMyOrders(status: $status, pagination: $pagination) {\n items { ${ORDER_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status, pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooMyOrders;\n },\n });\n};\n\nexport const useMyOrder = (id: string | undefined) => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'order', id],\n enabled: !!id,\n queryFn: async () => {\n const data = await coolQuery<{ cooMyOrder: CooOrder | null }>(\n `query CooMyOrder($id: ID!) { cooMyOrder(id: $id) { ${ORDER_DETAIL_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooMyOrder;\n },\n });\n};\n\nconst useOrderInvalidation = () => {\n const queryClient = useQueryClient();\n return (order: CooOrder) => {\n queryClient.setQueryData([QK, 'order', order.id], order);\n void queryClient.invalidateQueries({ queryKey: [QK, 'orders'] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'cart'] });\n };\n};\n\nexport const useCheckout = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (input: CooCheckoutInput) => {\n const data = await coolQuery<{ cooCheckout: CooOrderCheckout }>(\n `mutation CooCheckout($input: CooCheckoutInput!) { cooCheckout(input: $input) { ${CHECKOUT_FIELDS} } }`,\n { input },\n apiGatewayUrl\n );\n return data.cooCheckout;\n },\n onSuccess: (checkout) => settle(checkout.order),\n });\n};\n\nexport const useResumeOrderPayment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await coolQuery<{ cooResumeOrderPayment: CooOrderCheckout }>(\n `mutation CooResumeOrderPayment($id: ID!) { cooResumeOrderPayment(id: $id) { ${CHECKOUT_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooResumeOrderPayment;\n },\n onSuccess: (checkout) => settle(checkout.order),\n });\n};\n\nexport const useSyncOrderPayment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await coolQuery<{ cooSyncOrderPayment: CooOrder }>(\n `mutation CooSyncOrderPayment($id: ID!) { cooSyncOrderPayment(id: $id) { ${ORDER_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooSyncOrderPayment;\n },\n onSuccess: settle,\n });\n};\n\nexport const useCancelOrder = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const settle = useOrderInvalidation();\n return useMutation({\n mutationFn: async (id: string) => {\n const data = await coolQuery<{ cooCancelOrder: CooOrder }>(\n `mutation CooCancelOrder($id: ID!) { cooCancelOrder(id: $id) { ${ORDER_FIELDS} } }`,\n { id },\n apiGatewayUrl\n );\n return data.cooCancelOrder;\n },\n onSuccess: settle,\n });\n};\n\n/**\n * Ask a brand to take back its pieces of one of the caller's paid orders (BOFF-9900). The brand\n * approves (which refunds them) or declines; the order detail is refetched to show the request.\n */\nexport const useRequestReturn = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: CooRequestReturnInput) => {\n const data = await coolQuery<{ cooRequestReturn: CooReturnRequest }>(\n `mutation CooRequestReturn($input: CooRequestReturnInput!) {\n cooRequestReturn(input: $input) { ${RETURN_REQUEST_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooRequestReturn;\n },\n onSettled: (_request, _error, input) => {\n void queryClient.invalidateQueries({ queryKey: [QK, 'order', input.orderId] });\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// Creator earnings + payouts\n// ---------------------------------------------------------------------------\n\nexport const useMyCreatorEarnings = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'creator-earnings'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCreatorEarnings: CooCreatorEarningConnection }>(\n `query CooMyCreatorEarnings($pagination: PaginationInput) {\n cooMyCreatorEarnings(pagination: $pagination) {\n items {\n id orderId orderNumber lookId collaborationId commissionRate saleAmount amount currency\n availableAt billingSyncStatus reversalStatus reversedAt createdAt\n }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooMyCreatorEarnings;\n },\n });\n};\n\nexport const useMyCreatorEarningsSummary = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'creator-earnings-summary'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCreatorEarningsSummary: CooCreatorEarningsSummary }>(\n `query CooMyCreatorEarningsSummary {\n cooMyCreatorEarningsSummary {\n commissionRate holdDays currency totalLifetimeAmount availableAmount pendingAmount\n reservedAmount paidAmount pendingPayoutCount unsyncedCount billingAvailable\n }\n }`,\n {},\n apiGatewayUrl\n );\n return data.cooMyCreatorEarningsSummary;\n },\n });\n};\n\nexport const useRequestCreatorPayout = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: async (input: { amount: number; currency: string; notes?: string | null }) => {\n const data = await coolQuery<{ cooRequestCreatorPayout: CooCreatorPayout }>(\n `mutation CooRequestCreatorPayout($input: CooRequestCreatorPayoutInput!) {\n cooRequestCreatorPayout(input: $input) { id status requestedAmount currency createdAt }\n }`,\n { input },\n apiGatewayUrl\n );\n return data.cooRequestCreatorPayout;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [QK, 'creator-earnings-summary'] });\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// Collaboration fees (BOFF-9637)\n// ---------------------------------------------------------------------------\n\nconst COLLABORATION_PAYMENT_FIELDS = `\n payout { ${COLLABORATION_PAYOUT_FIELDS} }\n provider providerOrderId razorpayKeyId clientSecret stripePublishableKey subtotal taxAmount total currency\n`;\n\n/** The calling creator's collaboration fees: awaiting the brand's payment, or paid. */\nexport const useMyCollaborationPayouts = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n return useQuery({\n queryKey: [QK, 'collaboration-payouts'],\n queryFn: async () => {\n const data = await coolQuery<{ cooMyCollaborationPayouts: CooCollaborationPayoutConnection }>(\n `query CooMyCollaborationPayouts($pagination: PaginationInput) {\n cooMyCollaborationPayouts(pagination: $pagination) {\n items { ${COLLABORATION_PAYOUT_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: { limit: 50, offset: 0 } },\n apiGatewayUrl\n );\n return data.cooMyCollaborationPayouts;\n },\n });\n};\n\nconst useCollaborationPayoutInvalidation = () => {\n const queryClient = useQueryClient();\n return (collaborationId: string) => {\n void queryClient.invalidateQueries({ queryKey: [QK, 'collaboration', collaborationId] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'collaboration-payouts'] });\n void queryClient.invalidateQueries({ queryKey: [QK, 'creator-earnings-summary'] });\n };\n};\n\n/** Start (or re-open) the brand owner's payment of a collaboration fee. */\nexport const usePayCollaborationFee = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const refresh = useCollaborationPayoutInvalidation();\n return useMutation({\n mutationFn: async (collaborationId: string) => {\n const data = await coolQuery<{ cooPayCollaborationFee: CooCollaborationPaymentCheckout }>(\n `mutation CooPayCollaborationFee($id: ID!) {\n cooPayCollaborationFee(id: $id) { ${COLLABORATION_PAYMENT_FIELDS} }\n }`,\n { id: collaborationId },\n apiGatewayUrl\n );\n return data.cooPayCollaborationFee;\n },\n onSuccess: (checkout) => refresh(checkout.payout.collaborationId),\n });\n};\n\n/** Ask the backend to settle a collaboration fee against global-billing's payment record. */\nexport const useSyncCollaborationPayment = () => {\n const { apiGatewayUrl } = useCoolAndLovely();\n const refresh = useCollaborationPayoutInvalidation();\n return useMutation({\n mutationFn: async (collaborationId: string) => {\n const data = await coolQuery<{ cooSyncCollaborationPayment: CooCollaborationPayout }>(\n `mutation CooSyncCollaborationPayment($id: ID!) {\n cooSyncCollaborationPayment(id: $id) { ${COLLABORATION_PAYOUT_FIELDS} }\n }`,\n { id: collaborationId },\n apiGatewayUrl\n );\n return data.cooSyncCollaborationPayment;\n },\n onSuccess: (payout) => refresh(payout.collaborationId),\n });\n};\n"],"mappings":"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"}
|
|
@@ -3,6 +3,8 @@ import { CooFileRef, CooStyleItem } from './index';
|
|
|
3
3
|
export type CooOrderStatus = 'PENDING_PAYMENT' | 'PAID' | 'PARTIALLY_REFUNDED' | 'REFUNDED' | 'CANCELLED';
|
|
4
4
|
/** A brand's refund of its pieces of an order (BOFF-9702). */
|
|
5
5
|
export type CooRefundStatus = 'PENDING' | 'COMPLETED' | 'FAILED';
|
|
6
|
+
/** Whether a brand refund returned its pieces to stock (BOFF-9901). */
|
|
7
|
+
export type CooRestockStatus = 'NONE' | 'PENDING' | 'RESTOCKED' | 'SKIPPED';
|
|
6
8
|
/** Whether a creator commission was reversed because its line was refunded (BOFF-9702). */
|
|
7
9
|
export type CooCommissionReversalStatus = 'NONE' | 'PENDING' | 'REVERSED' | 'NOT_REVERSIBLE' | 'FAILED';
|
|
8
10
|
export type CooEarningSyncStatus = 'PENDING' | 'SYNCED' | 'FAILED';
|
|
@@ -36,6 +38,10 @@ export interface CooOrderRefund {
|
|
|
36
38
|
status: CooRefundStatus;
|
|
37
39
|
failureReason: string | null;
|
|
38
40
|
refundedAt: string | null;
|
|
41
|
+
/** Whether the refunded pieces went back on sale (BOFF-9901). */
|
|
42
|
+
restockStatus: CooRestockStatus;
|
|
43
|
+
restockedQuantity: number;
|
|
44
|
+
restockedAt: string | null;
|
|
39
45
|
createdAt: string;
|
|
40
46
|
}
|
|
41
47
|
/** A shopper's request to return one brand's pieces of an order (BOFF-9900). */
|
|
@@ -119,6 +125,11 @@ export interface CooOrderItem {
|
|
|
119
125
|
lineTotal: number;
|
|
120
126
|
lookId: string | null;
|
|
121
127
|
isCreatorAttributed: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* True when the piece took stock from a tracked variant at checkout, so a refund can return it
|
|
130
|
+
* to stock (BOFF-9901). Only fetched on the brand's order views.
|
|
131
|
+
*/
|
|
132
|
+
stockTracked?: boolean;
|
|
122
133
|
}
|
|
123
134
|
export interface CooOrder {
|
|
124
135
|
id: string;
|
|
@@ -193,6 +204,8 @@ export interface CooRefundBrandOrderInput {
|
|
|
193
204
|
brandId: string;
|
|
194
205
|
orderId: string;
|
|
195
206
|
reason: string;
|
|
207
|
+
/** Return the refunded stock-tracked pieces to stock (BOFF-9901). */
|
|
208
|
+
restock?: boolean;
|
|
196
209
|
}
|
|
197
210
|
export interface CooUpdateOrderFulfilmentInput {
|
|
198
211
|
brandId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/types/commerce.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../../src/coolandlovely/types/commerce.ts"],"names":[],"mappings":"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"}
|