@burdenoff/microfe-devportal 2026.915.5 → 2026.915.7

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.
@@ -3,20 +3,26 @@ import { FC } from 'react';
3
3
  export interface RegisterPickupLocationModalProps {
4
4
  open: boolean;
5
5
  onOpenChange: (open: boolean) => void;
6
- /** The pincode being registered — the one already typed in the Fulfillment field. */
7
- postalCode: string;
6
+ /** Pre-fills the pincode field with the org's currently-saved pincode, if
7
+ * any — the seller can still change it here, this is just a starting
8
+ * point, not a fixed value decided elsewhere. */
9
+ initialPostalCode: string;
8
10
  /** Which carrier to register with — only carriers that support registration
9
11
  * should ever open this modal (currently just "shiprocket"). */
10
12
  carrier: string;
11
- onRegistered: () => void;
13
+ /** Called with the pincode that was actually registered, so the caller can
14
+ * persist it as the org's pickup pincode in the same action. */
15
+ onRegistered: (postalCode: string) => void;
12
16
  }
13
17
  /**
14
- * Lets a seller submit their real pickup address and have it registered as a
15
- * new, bookable location directly with the shipping carrier — a real,
18
+ * Lets a seller submit their real pickup address — the ONE way to set up
19
+ * fulfillment, no separate bare-pincode field — and have it registered as a
20
+ * new, bookable location directly with the shipping carrier. A real,
16
21
  * permanent write to the carrier's own account (see
17
- * ShiprocketAdapter.registerPickupLocation). We never maintain our own list
18
- * of "valid" pincodes; whatever address the carrier itself accepts here is
19
- * supported, full stop.
22
+ * ShiprocketAdapter.registerPickupLocation), free of charge on Shiprocket's
23
+ * side (no per-address fee — they bill per shipment, not per pickup point).
24
+ * We never maintain our own list of "valid" pincodes; whatever address the
25
+ * carrier itself accepts here is supported, full stop.
20
26
  */
21
27
  export declare const RegisterPickupLocationModal: FC<RegisterPickupLocationModalProps>;
22
28
  //# sourceMappingURL=RegisterPickupLocationModal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RegisterPickupLocationModal.d.ts","sourceRoot":"","sources":["../../../src/devportal/components/RegisterPickupLocationModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAsCzD,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;IACnB;oEACgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,EAAE,CAC1C,gCAAgC,CA4NjC,CAAC"}
1
+ {"version":3,"file":"RegisterPickupLocationModal.d.ts","sourceRoot":"","sources":["../../../src/devportal/components/RegisterPickupLocationModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AA0CpE,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC;;qDAEiD;IACjD,iBAAiB,EAAE,MAAM,CAAC;IAC1B;oEACgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB;oEACgE;IAChE,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,EAAE,EAAE,CAC1C,gCAAgC,CAyOjC,CAAC"}
@@ -1,190 +1,200 @@
1
1
  import { useTr as e } from "../utils/i18n.js";
2
2
  import { InputField as t } from "./FormField.js";
3
- import { useId as n, useRef as r, useState as i } from "react";
4
- import { Loader2 as a, Truck as o, X as s } from "lucide-react";
5
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
- import { graphqlFetch as u } from "@burdenoff/fe-libs/shared/graphql";
3
+ import { useEffect as n, useId as r, useRef as i, useState as a } from "react";
4
+ import { Loader2 as o, Truck as s, X as c } from "lucide-react";
5
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
6
+ import { graphqlFetch as d } from "@burdenoff/fe-libs/shared/graphql";
7
7
  //#region src/devportal/components/RegisterPickupLocationModal.tsx
8
- var d = "\n mutation RegisterCarrierPickupLocation($input: RegisterCarrierPickupLocationInput!) {\n registerCarrierPickupLocation(input: $input) {\n label\n postalCode\n carrier\n }\n }\n", f = {
9
- name: "",
10
- email: "",
11
- phone: "",
12
- address: "",
13
- addressLine2: "",
14
- city: "",
15
- state: "",
16
- country: "India"
17
- }, p = ({ open: p, onOpenChange: m, postalCode: h, carrier: g, onRegistered: _ }) => {
18
- let v = e(), y = n(), b = r(null), [x, S] = i(f), [C, w] = i(!1), [T, E] = i(null);
19
- if (!p) return null;
20
- let D = (e, t) => S((n) => ({
8
+ var f = "\n mutation RegisterCarrierPickupLocation($input: RegisterCarrierPickupLocationInput!) {\n registerCarrierPickupLocation(input: $input) {\n label\n postalCode\n carrier\n }\n }\n";
9
+ function p(e) {
10
+ return {
11
+ name: "",
12
+ email: "",
13
+ phone: "",
14
+ address: "",
15
+ addressLine2: "",
16
+ city: "",
17
+ state: "",
18
+ country: "India",
19
+ postalCode: e
20
+ };
21
+ }
22
+ var m = ({ open: m, onOpenChange: h, initialPostalCode: g, carrier: _, onRegistered: v }) => {
23
+ let y = e(), b = r(), x = i(null), [S, C] = a(() => p(g)), [w, T] = a(!1), [E, D] = a(null);
24
+ if (n(() => {
25
+ m && C(p(g));
26
+ }, [m]), !m) return null;
27
+ let O = (e, t) => C((n) => ({
21
28
  ...n,
22
29
  [e]: t
23
- })), O = () => {
24
- C || (S(f), E(null), m(!1));
25
- }, k = x.name.trim() && x.email.trim() && x.phone.trim() && x.address.trim() && x.city.trim() && x.state.trim() && x.country.trim(), A = async () => {
26
- if (k) {
27
- w(!0), E(null);
30
+ })), k = () => {
31
+ w || (D(null), h(!1));
32
+ }, A = S.name.trim() && S.email.trim() && S.phone.trim() && S.address.trim() && S.city.trim() && S.state.trim() && S.country.trim() && S.postalCode.trim(), j = async () => {
33
+ if (A) {
34
+ T(!0), D(null);
28
35
  try {
29
- let e = await u({
36
+ let e = S.postalCode.trim(), t = await d({
30
37
  gateway: "global",
31
- query: d,
38
+ query: f,
32
39
  variables: { input: {
33
- carrier: g,
34
- name: x.name.trim(),
35
- email: x.email.trim(),
36
- phone: x.phone.trim(),
37
- address: x.address.trim(),
38
- addressLine2: x.addressLine2.trim() || void 0,
39
- city: x.city.trim(),
40
- state: x.state.trim(),
41
- country: x.country.trim(),
42
- postalCode: h
40
+ carrier: _,
41
+ name: S.name.trim(),
42
+ email: S.email.trim(),
43
+ phone: S.phone.trim(),
44
+ address: S.address.trim(),
45
+ addressLine2: S.addressLine2.trim() || void 0,
46
+ city: S.city.trim(),
47
+ state: S.state.trim(),
48
+ country: S.country.trim(),
49
+ postalCode: e
43
50
  } }
44
51
  });
45
- if (e.errors?.length) throw Error(e.errors[0]?.message ?? "Failed to register pickup address");
46
- _(), O();
52
+ if (t.errors?.length) throw Error(t.errors[0]?.message ?? "Failed to register pickup address");
53
+ v(e), h(!1);
47
54
  } catch (e) {
48
- E(e instanceof Error ? e.message : "Failed to register pickup address");
55
+ D(e instanceof Error ? e.message : "Failed to register pickup address");
49
56
  } finally {
50
- w(!1);
57
+ T(!1);
51
58
  }
52
59
  }
53
60
  };
54
- return /* @__PURE__ */ l("div", {
61
+ return /* @__PURE__ */ u("div", {
55
62
  className: "fixed inset-0 z-50 flex items-center justify-center",
56
- children: [/* @__PURE__ */ c("button", {
63
+ children: [/* @__PURE__ */ l("button", {
57
64
  type: "button",
58
65
  "aria-label": "Close register pickup address dialog backdrop",
59
66
  className: "absolute inset-0 bg-bg-overlay",
60
- onClick: O
61
- }), /* @__PURE__ */ l("div", {
62
- ref: b,
67
+ onClick: k
68
+ }), /* @__PURE__ */ u("div", {
69
+ ref: x,
63
70
  role: "dialog",
64
71
  "aria-modal": "true",
65
- "aria-labelledby": y,
72
+ "aria-labelledby": b,
66
73
  tabIndex: -1,
67
74
  className: "relative z-10 max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-lg bg-bg-surface shadow-xl",
68
75
  children: [
69
- /* @__PURE__ */ l("div", {
76
+ /* @__PURE__ */ u("div", {
70
77
  className: "flex items-start gap-4 border-b p-6",
71
78
  children: [
72
- /* @__PURE__ */ c("div", {
79
+ /* @__PURE__ */ l("div", {
73
80
  className: "rounded-full bg-status-info-bg-subtle p-2",
74
- children: /* @__PURE__ */ c(o, { className: "h-6 w-6 text-status-info-text" })
81
+ children: /* @__PURE__ */ l(s, { className: "h-6 w-6 text-status-info-text" })
75
82
  }),
76
- /* @__PURE__ */ l("div", {
83
+ /* @__PURE__ */ u("div", {
77
84
  className: "flex-1",
78
- children: [/* @__PURE__ */ c("h3", {
79
- id: y,
85
+ children: [/* @__PURE__ */ l("h3", {
86
+ id: b,
80
87
  className: "text-lg font-semibold",
81
- children: v("devportal.registerPickupAddress", "Register Pickup Address")
82
- }), /* @__PURE__ */ c("p", {
88
+ children: y("devportal.registerPickupAddress", "Pickup Address")
89
+ }), /* @__PURE__ */ l("p", {
83
90
  className: "mt-1 text-sm text-text-secondary",
84
- children: v("devportal.registerPickupAddressDesc", "This registers a real pickup point on our shipping carrier so orders can actually be booked from it.")
91
+ children: y("devportal.registerPickupAddressDesc", "This is the real address your physical orders ship from. It's free to register — Shiprocket doesn't charge per pickup point, only per shipment.")
85
92
  })]
86
93
  }),
87
- /* @__PURE__ */ c("button", {
94
+ /* @__PURE__ */ l("button", {
88
95
  type: "button",
89
- onClick: O,
90
- disabled: C,
96
+ onClick: k,
97
+ disabled: w,
91
98
  className: "rounded-md p-1 text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50",
92
- children: /* @__PURE__ */ c(s, { className: "h-5 w-5" })
99
+ children: /* @__PURE__ */ l(c, { className: "h-5 w-5" })
93
100
  })
94
101
  ]
95
102
  }),
96
- /* @__PURE__ */ l("div", {
103
+ /* @__PURE__ */ u("div", {
97
104
  className: "space-y-4 p-6",
98
105
  children: [
99
- /* @__PURE__ */ c(t, {
100
- label: v("devportal.pickupContactName", "Contact name"),
101
- value: x.name,
102
- onChange: (e) => D("name", e.target.value),
106
+ /* @__PURE__ */ l(t, {
107
+ label: y("devportal.pickupContactName", "Contact name"),
108
+ value: S.name,
109
+ onChange: (e) => O("name", e.target.value),
103
110
  required: !0,
104
- disabled: C
111
+ disabled: w
105
112
  }),
106
- /* @__PURE__ */ l("div", {
113
+ /* @__PURE__ */ u("div", {
107
114
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
108
- children: [/* @__PURE__ */ c(t, {
109
- label: v("devportal.pickupContactEmail", "Contact email"),
115
+ children: [/* @__PURE__ */ l(t, {
116
+ label: y("devportal.pickupContactEmail", "Contact email"),
110
117
  type: "email",
111
- value: x.email,
112
- onChange: (e) => D("email", e.target.value),
118
+ value: S.email,
119
+ onChange: (e) => O("email", e.target.value),
113
120
  required: !0,
114
- disabled: C
115
- }), /* @__PURE__ */ c(t, {
116
- label: v("devportal.pickupContactPhone", "Contact phone"),
121
+ disabled: w
122
+ }), /* @__PURE__ */ l(t, {
123
+ label: y("devportal.pickupContactPhone", "Contact phone"),
117
124
  type: "tel",
118
- value: x.phone,
119
- onChange: (e) => D("phone", e.target.value),
125
+ value: S.phone,
126
+ onChange: (e) => O("phone", e.target.value),
120
127
  required: !0,
121
- disabled: C
128
+ disabled: w
122
129
  })]
123
130
  }),
124
- /* @__PURE__ */ c(t, {
125
- label: v("devportal.pickupAddressLine1", "Address"),
126
- value: x.address,
127
- onChange: (e) => D("address", e.target.value),
131
+ /* @__PURE__ */ l(t, {
132
+ label: y("devportal.pickupAddressLine1", "Address"),
133
+ value: S.address,
134
+ onChange: (e) => O("address", e.target.value),
128
135
  required: !0,
129
- disabled: C
136
+ disabled: w,
137
+ placeholder: "12 Farm Road",
138
+ hint: y("devportal.pickupAddressLine1Hint", "Must include a house/flat/building or road number — our carrier rejects area names alone (e.g. \"Pitampura\" on its own won't work, \"12 Pitampura Road\" will).")
130
139
  }),
131
- /* @__PURE__ */ c(t, {
132
- label: v("devportal.pickupAddressLine2", "Apartment, suite, etc. (optional)"),
133
- value: x.addressLine2,
134
- onChange: (e) => D("addressLine2", e.target.value),
135
- disabled: C
140
+ /* @__PURE__ */ l(t, {
141
+ label: y("devportal.pickupAddressLine2", "Apartment, suite, building number, etc. (optional)"),
142
+ value: S.addressLine2,
143
+ onChange: (e) => O("addressLine2", e.target.value),
144
+ disabled: w
136
145
  }),
137
- /* @__PURE__ */ l("div", {
146
+ /* @__PURE__ */ u("div", {
138
147
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
139
- children: [/* @__PURE__ */ c(t, {
140
- label: v("devportal.pickupCity", "City"),
141
- value: x.city,
142
- onChange: (e) => D("city", e.target.value),
148
+ children: [/* @__PURE__ */ l(t, {
149
+ label: y("devportal.pickupCity", "City"),
150
+ value: S.city,
151
+ onChange: (e) => O("city", e.target.value),
143
152
  required: !0,
144
- disabled: C
145
- }), /* @__PURE__ */ c(t, {
146
- label: v("devportal.pickupState", "State"),
147
- value: x.state,
148
- onChange: (e) => D("state", e.target.value),
153
+ disabled: w
154
+ }), /* @__PURE__ */ l(t, {
155
+ label: y("devportal.pickupState", "State"),
156
+ value: S.state,
157
+ onChange: (e) => O("state", e.target.value),
149
158
  required: !0,
150
- disabled: C
159
+ disabled: w
151
160
  })]
152
161
  }),
153
- /* @__PURE__ */ l("div", {
162
+ /* @__PURE__ */ u("div", {
154
163
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
155
- children: [/* @__PURE__ */ c(t, {
156
- label: v("devportal.pickupCountry", "Country"),
157
- value: x.country,
158
- onChange: (e) => D("country", e.target.value),
164
+ children: [/* @__PURE__ */ l(t, {
165
+ label: y("devportal.pickupCountry", "Country"),
166
+ value: S.country,
167
+ onChange: (e) => O("country", e.target.value),
168
+ required: !0,
169
+ disabled: w
170
+ }), /* @__PURE__ */ l(t, {
171
+ label: y("devportal.pickupPincode", "Pincode"),
172
+ value: S.postalCode,
173
+ onChange: (e) => O("postalCode", e.target.value),
159
174
  required: !0,
160
- disabled: C
161
- }), /* @__PURE__ */ c(t, {
162
- label: v("devportal.pickupPincodeReadonly", "Pincode"),
163
- value: h,
164
- disabled: !0,
165
- hint: v("devportal.pickupPincodeReadonlyHint", "The pincode you entered above.")
175
+ disabled: w
166
176
  })]
167
177
  }),
168
- T && /* @__PURE__ */ c("p", {
178
+ E && /* @__PURE__ */ l("p", {
169
179
  className: "text-sm text-status-error-text",
170
- children: T
180
+ children: E
171
181
  })
172
182
  ]
173
183
  }),
174
- /* @__PURE__ */ l("div", {
184
+ /* @__PURE__ */ u("div", {
175
185
  className: "flex items-center justify-end gap-3 border-t p-6",
176
- children: [/* @__PURE__ */ c("button", {
186
+ children: [/* @__PURE__ */ l("button", {
177
187
  type: "button",
178
- onClick: O,
179
- disabled: C,
188
+ onClick: k,
189
+ disabled: w,
180
190
  className: "rounded-md px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50",
181
- children: v("devportal.cancel", "Cancel")
182
- }), /* @__PURE__ */ l("button", {
191
+ children: y("devportal.cancel", "Cancel")
192
+ }), /* @__PURE__ */ u("button", {
183
193
  type: "button",
184
- onClick: () => void A(),
185
- disabled: C || !k,
194
+ onClick: () => void j(),
195
+ disabled: w || !A,
186
196
  className: "flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50",
187
- children: [C && /* @__PURE__ */ c(a, { className: "h-4 w-4 animate-spin" }), v("devportal.registerPickupAddressSubmit", "Register Address")]
197
+ children: [w && /* @__PURE__ */ l(o, { className: "h-4 w-4 animate-spin" }), y("devportal.registerPickupAddressSubmit", "Save Pickup Address")]
188
198
  })]
189
199
  })
190
200
  ]
@@ -192,6 +202,6 @@ var d = "\n mutation RegisterCarrierPickupLocation($input: RegisterCarrierPicku
192
202
  });
193
203
  };
194
204
  //#endregion
195
- export { p as RegisterPickupLocationModal };
205
+ export { m as RegisterPickupLocationModal };
196
206
 
197
207
  //# sourceMappingURL=RegisterPickupLocationModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RegisterPickupLocationModal.js","names":[],"sources":["../../../src/devportal/components/RegisterPickupLocationModal.tsx"],"sourcesContent":["import { useId, useRef, useState, type FC } from \"react\";\nimport { Truck, X, Loader2 } from \"lucide-react\";\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { InputField } from \"./FormField\";\nimport { useTr } from \"../utils/i18n\";\n\nconst REGISTER_CARRIER_PICKUP_LOCATION_MUTATION = `\n mutation RegisterCarrierPickupLocation($input: RegisterCarrierPickupLocationInput!) {\n registerCarrierPickupLocation(input: $input) {\n label\n postalCode\n carrier\n }\n }\n`;\n\ninterface AddressForm {\n name: string;\n email: string;\n phone: string;\n address: string;\n addressLine2: string;\n city: string;\n state: string;\n country: string;\n}\n\nconst EMPTY_FORM: AddressForm = {\n name: \"\",\n email: \"\",\n phone: \"\",\n address: \"\",\n addressLine2: \"\",\n city: \"\",\n state: \"\",\n country: \"India\",\n};\n\nexport interface RegisterPickupLocationModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** The pincode being registered — the one already typed in the Fulfillment field. */\n postalCode: string;\n /** Which carrier to register with — only carriers that support registration\n * should ever open this modal (currently just \"shiprocket\"). */\n carrier: string;\n onRegistered: () => void;\n}\n\n/**\n * Lets a seller submit their real pickup address and have it registered as a\n * new, bookable location directly with the shipping carrier — a real,\n * permanent write to the carrier's own account (see\n * ShiprocketAdapter.registerPickupLocation). We never maintain our own list\n * of \"valid\" pincodes; whatever address the carrier itself accepts here is\n * supported, full stop.\n */\nexport const RegisterPickupLocationModal: FC<\n RegisterPickupLocationModalProps\n> = ({ open, onOpenChange, postalCode, carrier, onRegistered }) => {\n const tr = useTr();\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const [form, setForm] = useState<AddressForm>(EMPTY_FORM);\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n if (!open) return null;\n\n const setField = (field: keyof AddressForm, value: string) =>\n setForm((prev) => ({ ...prev, [field]: value }));\n\n const handleClose = () => {\n if (submitting) return;\n setForm(EMPTY_FORM);\n setError(null);\n onOpenChange(false);\n };\n\n const canSubmit =\n form.name.trim() &&\n form.email.trim() &&\n form.phone.trim() &&\n form.address.trim() &&\n form.city.trim() &&\n form.state.trim() &&\n form.country.trim();\n\n const handleSubmit = async () => {\n if (!canSubmit) return;\n setSubmitting(true);\n setError(null);\n try {\n const result = await graphqlFetch<{\n registerCarrierPickupLocation: {\n label: string;\n postalCode: string;\n carrier: string;\n };\n }>({\n gateway: \"global\",\n query: REGISTER_CARRIER_PICKUP_LOCATION_MUTATION,\n variables: {\n input: {\n carrier,\n name: form.name.trim(),\n email: form.email.trim(),\n phone: form.phone.trim(),\n address: form.address.trim(),\n addressLine2: form.addressLine2.trim() || undefined,\n city: form.city.trim(),\n state: form.state.trim(),\n country: form.country.trim(),\n postalCode,\n },\n },\n });\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ?? \"Failed to register pickup address\",\n );\n }\n onRegistered();\n handleClose();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to register pickup address\",\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <button\n type=\"button\"\n aria-label=\"Close register pickup address dialog backdrop\"\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={handleClose}\n />\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n className=\"relative z-10 max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-lg bg-bg-surface shadow-xl\"\n >\n <div className=\"flex items-start gap-4 border-b p-6\">\n <div className=\"rounded-full bg-status-info-bg-subtle p-2\">\n <Truck className=\"h-6 w-6 text-status-info-text\" />\n </div>\n <div className=\"flex-1\">\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {tr(\"devportal.registerPickupAddress\", \"Register Pickup Address\")}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.registerPickupAddressDesc\",\n \"This registers a real pickup point on our shipping carrier so orders can actually be booked from it.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md p-1 text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4 p-6\">\n <InputField\n label={tr(\"devportal.pickupContactName\", \"Contact name\")}\n value={form.name}\n onChange={(e) => setField(\"name\", e.target.value)}\n required\n disabled={submitting}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.pickupContactEmail\", \"Contact email\")}\n type=\"email\"\n value={form.email}\n onChange={(e) => setField(\"email\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\"devportal.pickupContactPhone\", \"Contact phone\")}\n type=\"tel\"\n value={form.phone}\n onChange={(e) => setField(\"phone\", e.target.value)}\n required\n disabled={submitting}\n />\n </div>\n <InputField\n label={tr(\"devportal.pickupAddressLine1\", \"Address\")}\n value={form.address}\n onChange={(e) => setField(\"address\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\n \"devportal.pickupAddressLine2\",\n \"Apartment, suite, etc. (optional)\",\n )}\n value={form.addressLine2}\n onChange={(e) => setField(\"addressLine2\", e.target.value)}\n disabled={submitting}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.pickupCity\", \"City\")}\n value={form.city}\n onChange={(e) => setField(\"city\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\"devportal.pickupState\", \"State\")}\n value={form.state}\n onChange={(e) => setField(\"state\", e.target.value)}\n required\n disabled={submitting}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.pickupCountry\", \"Country\")}\n value={form.country}\n onChange={(e) => setField(\"country\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\"devportal.pickupPincodeReadonly\", \"Pincode\")}\n value={postalCode}\n disabled\n hint={tr(\n \"devportal.pickupPincodeReadonlyHint\",\n \"The pincode you entered above.\",\n )}\n />\n </div>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <div className=\"flex items-center justify-end gap-3 border-t p-6\">\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleSubmit()}\n disabled={submitting || !canSubmit}\n className=\"flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr(\"devportal.registerPickupAddressSubmit\", \"Register Address\")}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"RegisterPickupLocationModal.js","names":[],"sources":["../../../src/devportal/components/RegisterPickupLocationModal.tsx"],"sourcesContent":["import { useEffect, useId, useRef, useState, type FC } from \"react\";\nimport { Truck, X, Loader2 } from \"lucide-react\";\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { InputField } from \"./FormField\";\nimport { useTr } from \"../utils/i18n\";\n\nconst REGISTER_CARRIER_PICKUP_LOCATION_MUTATION = `\n mutation RegisterCarrierPickupLocation($input: RegisterCarrierPickupLocationInput!) {\n registerCarrierPickupLocation(input: $input) {\n label\n postalCode\n carrier\n }\n }\n`;\n\ninterface AddressForm {\n name: string;\n email: string;\n phone: string;\n address: string;\n addressLine2: string;\n city: string;\n state: string;\n country: string;\n postalCode: string;\n}\n\nfunction emptyForm(initialPostalCode: string): AddressForm {\n return {\n name: \"\",\n email: \"\",\n phone: \"\",\n address: \"\",\n addressLine2: \"\",\n city: \"\",\n state: \"\",\n country: \"India\",\n postalCode: initialPostalCode,\n };\n}\n\nexport interface RegisterPickupLocationModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Pre-fills the pincode field with the org's currently-saved pincode, if\n * any — the seller can still change it here, this is just a starting\n * point, not a fixed value decided elsewhere. */\n initialPostalCode: string;\n /** Which carrier to register with — only carriers that support registration\n * should ever open this modal (currently just \"shiprocket\"). */\n carrier: string;\n /** Called with the pincode that was actually registered, so the caller can\n * persist it as the org's pickup pincode in the same action. */\n onRegistered: (postalCode: string) => void;\n}\n\n/**\n * Lets a seller submit their real pickup address — the ONE way to set up\n * fulfillment, no separate bare-pincode field — and have it registered as a\n * new, bookable location directly with the shipping carrier. A real,\n * permanent write to the carrier's own account (see\n * ShiprocketAdapter.registerPickupLocation), free of charge on Shiprocket's\n * side (no per-address fee — they bill per shipment, not per pickup point).\n * We never maintain our own list of \"valid\" pincodes; whatever address the\n * carrier itself accepts here is supported, full stop.\n */\nexport const RegisterPickupLocationModal: FC<\n RegisterPickupLocationModalProps\n> = ({ open, onOpenChange, initialPostalCode, carrier, onRegistered }) => {\n const tr = useTr();\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const [form, setForm] = useState<AddressForm>(() =>\n emptyForm(initialPostalCode),\n );\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Re-seed the pincode whenever the modal is (re)opened for a different\n // saved value — e.g. opening \"Change pickup address\" after a save.\n useEffect(() => {\n if (open) setForm(emptyForm(initialPostalCode));\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only re-seed on open, not on every initialPostalCode identity change while open\n }, [open]);\n\n if (!open) return null;\n\n const setField = (field: keyof AddressForm, value: string) =>\n setForm((prev) => ({ ...prev, [field]: value }));\n\n const handleClose = () => {\n if (submitting) return;\n setError(null);\n onOpenChange(false);\n };\n\n const canSubmit =\n form.name.trim() &&\n form.email.trim() &&\n form.phone.trim() &&\n form.address.trim() &&\n form.city.trim() &&\n form.state.trim() &&\n form.country.trim() &&\n form.postalCode.trim();\n\n const handleSubmit = async () => {\n if (!canSubmit) return;\n setSubmitting(true);\n setError(null);\n try {\n const postalCode = form.postalCode.trim();\n const result = await graphqlFetch<{\n registerCarrierPickupLocation: {\n label: string;\n postalCode: string;\n carrier: string;\n };\n }>({\n gateway: \"global\",\n query: REGISTER_CARRIER_PICKUP_LOCATION_MUTATION,\n variables: {\n input: {\n carrier,\n name: form.name.trim(),\n email: form.email.trim(),\n phone: form.phone.trim(),\n address: form.address.trim(),\n addressLine2: form.addressLine2.trim() || undefined,\n city: form.city.trim(),\n state: form.state.trim(),\n country: form.country.trim(),\n postalCode,\n },\n },\n });\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ?? \"Failed to register pickup address\",\n );\n }\n onRegistered(postalCode);\n onOpenChange(false);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to register pickup address\",\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <button\n type=\"button\"\n aria-label=\"Close register pickup address dialog backdrop\"\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={handleClose}\n />\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n className=\"relative z-10 max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-lg bg-bg-surface shadow-xl\"\n >\n <div className=\"flex items-start gap-4 border-b p-6\">\n <div className=\"rounded-full bg-status-info-bg-subtle p-2\">\n <Truck className=\"h-6 w-6 text-status-info-text\" />\n </div>\n <div className=\"flex-1\">\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {tr(\"devportal.registerPickupAddress\", \"Pickup Address\")}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.registerPickupAddressDesc\",\n \"This is the real address your physical orders ship from. It's free to register — Shiprocket doesn't charge per pickup point, only per shipment.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md p-1 text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4 p-6\">\n <InputField\n label={tr(\"devportal.pickupContactName\", \"Contact name\")}\n value={form.name}\n onChange={(e) => setField(\"name\", e.target.value)}\n required\n disabled={submitting}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.pickupContactEmail\", \"Contact email\")}\n type=\"email\"\n value={form.email}\n onChange={(e) => setField(\"email\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\"devportal.pickupContactPhone\", \"Contact phone\")}\n type=\"tel\"\n value={form.phone}\n onChange={(e) => setField(\"phone\", e.target.value)}\n required\n disabled={submitting}\n />\n </div>\n <InputField\n label={tr(\"devportal.pickupAddressLine1\", \"Address\")}\n value={form.address}\n onChange={(e) => setField(\"address\", e.target.value)}\n required\n disabled={submitting}\n placeholder=\"12 Farm Road\"\n hint={tr(\n \"devportal.pickupAddressLine1Hint\",\n 'Must include a house/flat/building or road number — our carrier rejects area names alone (e.g. \"Pitampura\" on its own won\\'t work, \"12 Pitampura Road\" will).',\n )}\n />\n <InputField\n label={tr(\n \"devportal.pickupAddressLine2\",\n \"Apartment, suite, building number, etc. (optional)\",\n )}\n value={form.addressLine2}\n onChange={(e) => setField(\"addressLine2\", e.target.value)}\n disabled={submitting}\n />\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.pickupCity\", \"City\")}\n value={form.city}\n onChange={(e) => setField(\"city\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\"devportal.pickupState\", \"State\")}\n value={form.state}\n onChange={(e) => setField(\"state\", e.target.value)}\n required\n disabled={submitting}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.pickupCountry\", \"Country\")}\n value={form.country}\n onChange={(e) => setField(\"country\", e.target.value)}\n required\n disabled={submitting}\n />\n <InputField\n label={tr(\"devportal.pickupPincode\", \"Pincode\")}\n value={form.postalCode}\n onChange={(e) => setField(\"postalCode\", e.target.value)}\n required\n disabled={submitting}\n />\n </div>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <div className=\"flex items-center justify-end gap-3 border-t p-6\">\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleSubmit()}\n disabled={submitting || !canSubmit}\n className=\"flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr(\"devportal.registerPickupAddressSubmit\", \"Save Pickup Address\")}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReportOrderIssueModal.d.ts","sourceRoot":"","sources":["../../../src/devportal/components/ReportOrderIssueModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAIzD,MAAM,MAAM,kBAAkB,GAC1B,cAAc,GACd,gBAAgB,GAChB,eAAe,GACf,OAAO,CAAC;AAqBZ,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CA8KhE,CAAC"}
1
+ {"version":3,"file":"ReportOrderIssueModal.d.ts","sourceRoot":"","sources":["../../../src/devportal/components/ReportOrderIssueModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAIzD,MAAM,MAAM,kBAAkB,GAC5B,cAAc,GAAG,gBAAgB,GAAG,eAAe,GAAG,OAAO,CAAC;AAqBhE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,0BAA0B,CA0KhE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReportOrderIssueModal.js","names":[],"sources":["../../../src/devportal/components/ReportOrderIssueModal.tsx"],"sourcesContent":["import { useId, useRef, useState, type FC } from \"react\";\nimport { AlertTriangle, X, Loader2 } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\n\nexport type OrderIssueCategory =\n | \"OUT_OF_STOCK\"\n | \"CANNOT_FULFILL\"\n | \"WRONG_ADDRESS\"\n | \"OTHER\";\n\nconst CATEGORY_OPTIONS: { value: OrderIssueCategory; label: string }[] = [\n { value: \"OUT_OF_STOCK\", label: \"Out of stock\" },\n { value: \"CANNOT_FULFILL\", label: \"Cannot fulfill\" },\n { value: \"WRONG_ADDRESS\", label: \"Wrong address / pincode\" },\n { value: \"OTHER\", label: \"Other\" },\n];\n\nconst FLAG_ORDER_ISSUE_MUTATION = `\n mutation FlagOrderIssue($orderId: ID!, $organizationId: ID!, $category: OrderIssueCategory!, $note: String) {\n flagOrderIssue(orderId: $orderId, organizationId: $organizationId, category: $category, note: $note) {\n id\n category\n note\n status\n createdAt\n }\n }\n`;\n\nexport interface ReportOrderIssueModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n orderId: string;\n organizationId: string;\n gqlUrl: string;\n headers: Record<string, string>;\n onReported: () => void;\n}\n\n/**\n * Small modal for a seller to report a problem fulfilling a physical order\n * (out of stock, cannot fulfill, wrong address, etc). Purely informational —\n * visible to admin on the fulfillment console; does not cancel or refund\n * anything (that stays manual for now, see BOFF-7192 follow-up).\n */\nexport const ReportOrderIssueModal: FC<ReportOrderIssueModalProps> = ({\n open,\n onOpenChange,\n orderId,\n organizationId,\n gqlUrl,\n headers,\n onReported,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const [category, setCategory] = useState<OrderIssueCategory>(\"OUT_OF_STOCK\");\n const [note, setNote] = useState(\"\");\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n if (!open) return null;\n\n const handleClose = () => {\n if (submitting) return;\n setNote(\"\");\n setCategory(\"OUT_OF_STOCK\");\n setError(null);\n onOpenChange(false);\n };\n\n const handleSubmit = async () => {\n setSubmitting(true);\n setError(null);\n try {\n const res = await fetch(gqlUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n query: FLAG_ORDER_ISSUE_MUTATION,\n variables: {\n orderId,\n organizationId,\n category,\n note: note.trim() || null,\n },\n }),\n });\n const json = (await res.json()) as { errors?: { message: string }[] };\n if (json.errors?.length) {\n throw new Error(json.errors[0]?.message ?? \"Failed to report issue\");\n }\n onReported();\n handleClose();\n } catch (err) {\n setError(\n err instanceof Error ? err.message : \"Failed to report issue\",\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <button\n type=\"button\"\n aria-label=\"Close report issue dialog backdrop\"\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={handleClose}\n />\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n className=\"relative z-10 w-full max-w-md rounded-lg bg-bg-surface shadow-xl\"\n >\n <div className=\"flex items-start gap-4 border-b p-6\">\n <div className=\"rounded-full bg-status-warning-bg-subtle p-2\">\n <AlertTriangle className=\"h-6 w-6 text-status-warning-text\" />\n </div>\n <div className=\"flex-1\">\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {tr(\"devportal.reportOrderIssue\", \"Report an Issue\")}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.reportOrderIssueDesc\",\n \"Let admin know about a problem fulfilling this order.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md p-1 text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4 p-6\">\n <div>\n <label className=\"mb-2 block text-sm font-medium\">\n {tr(\"devportal.issueCategory\", \"What's the problem?\")}\n </label>\n <div className=\"space-y-2\">\n {CATEGORY_OPTIONS.map((opt) => (\n <label\n key={opt.value}\n className=\"flex items-center gap-2 rounded-md border border-border-seam px-3 py-2 text-sm cursor-pointer hover:bg-bg-sunken transition-colors has-[:checked]:border-primary has-[:checked]:bg-primary/5\"\n >\n <input\n type=\"radio\"\n name=\"issue-category\"\n value={opt.value}\n checked={category === opt.value}\n onChange={() => setCategory(opt.value)}\n className=\"text-primary\"\n />\n {opt.label}\n </label>\n ))}\n </div>\n </div>\n\n <div>\n <label className=\"mb-2 block text-sm font-medium\">\n {tr(\"devportal.issueNote\", \"Additional details (optional)\")}\n </label>\n <textarea\n value={note}\n onChange={(e) => setNote(e.target.value)}\n rows={3}\n maxLength={500}\n placeholder={tr(\n \"devportal.issueNotePlaceholder\",\n \"Anything admin should know…\",\n )}\n className=\"w-full resize-none rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </div>\n\n {error && (\n <p className=\"text-sm text-status-error-text\">{error}</p>\n )}\n </div>\n\n <div className=\"flex items-center justify-end gap-3 border-t p-6\">\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleSubmit()}\n disabled={submitting}\n className=\"flex items-center gap-2 rounded-md bg-status-warning-bg px-4 py-2 text-sm font-medium text-status-warning-text hover:opacity-90 transition-opacity disabled:opacity-50\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr(\"devportal.submitReport\", \"Report Issue\")}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ReportOrderIssueModal.js","names":[],"sources":["../../../src/devportal/components/ReportOrderIssueModal.tsx"],"sourcesContent":["import { useId, useRef, useState, type FC } from \"react\";\nimport { AlertTriangle, X, Loader2 } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\n\nexport type OrderIssueCategory =\n \"OUT_OF_STOCK\" | \"CANNOT_FULFILL\" | \"WRONG_ADDRESS\" | \"OTHER\";\n\nconst CATEGORY_OPTIONS: { value: OrderIssueCategory; label: string }[] = [\n { value: \"OUT_OF_STOCK\", label: \"Out of stock\" },\n { value: \"CANNOT_FULFILL\", label: \"Cannot fulfill\" },\n { value: \"WRONG_ADDRESS\", label: \"Wrong address / pincode\" },\n { value: \"OTHER\", label: \"Other\" },\n];\n\nconst FLAG_ORDER_ISSUE_MUTATION = `\n mutation FlagOrderIssue($orderId: ID!, $organizationId: ID!, $category: OrderIssueCategory!, $note: String) {\n flagOrderIssue(orderId: $orderId, organizationId: $organizationId, category: $category, note: $note) {\n id\n category\n note\n status\n createdAt\n }\n }\n`;\n\nexport interface ReportOrderIssueModalProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n orderId: string;\n organizationId: string;\n gqlUrl: string;\n headers: Record<string, string>;\n onReported: () => void;\n}\n\n/**\n * Small modal for a seller to report a problem fulfilling a physical order\n * (out of stock, cannot fulfill, wrong address, etc). Purely informational —\n * visible to admin on the fulfillment console; does not cancel or refund\n * anything (that stays manual for now, see BOFF-7192 follow-up).\n */\nexport const ReportOrderIssueModal: FC<ReportOrderIssueModalProps> = ({\n open,\n onOpenChange,\n orderId,\n organizationId,\n gqlUrl,\n headers,\n onReported,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const [category, setCategory] = useState<OrderIssueCategory>(\"OUT_OF_STOCK\");\n const [note, setNote] = useState(\"\");\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n if (!open) return null;\n\n const handleClose = () => {\n if (submitting) return;\n setNote(\"\");\n setCategory(\"OUT_OF_STOCK\");\n setError(null);\n onOpenChange(false);\n };\n\n const handleSubmit = async () => {\n setSubmitting(true);\n setError(null);\n try {\n const res = await fetch(gqlUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n query: FLAG_ORDER_ISSUE_MUTATION,\n variables: {\n orderId,\n organizationId,\n category,\n note: note.trim() || null,\n },\n }),\n });\n const json = (await res.json()) as { errors?: { message: string }[] };\n if (json.errors?.length) {\n throw new Error(json.errors[0]?.message ?? \"Failed to report issue\");\n }\n onReported();\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to report issue\");\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <button\n type=\"button\"\n aria-label=\"Close report issue dialog backdrop\"\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={handleClose}\n />\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n className=\"relative z-10 w-full max-w-md rounded-lg bg-bg-surface shadow-xl\"\n >\n <div className=\"flex items-start gap-4 border-b p-6\">\n <div className=\"rounded-full bg-status-warning-bg-subtle p-2\">\n <AlertTriangle className=\"h-6 w-6 text-status-warning-text\" />\n </div>\n <div className=\"flex-1\">\n <h3 id={titleId} className=\"text-lg font-semibold\">\n {tr(\"devportal.reportOrderIssue\", \"Report an Issue\")}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.reportOrderIssueDesc\",\n \"Let admin know about a problem fulfilling this order.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md p-1 text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4 p-6\">\n <div>\n <label className=\"mb-2 block text-sm font-medium\">\n {tr(\"devportal.issueCategory\", \"What's the problem?\")}\n </label>\n <div className=\"space-y-2\">\n {CATEGORY_OPTIONS.map((opt) => (\n <label\n key={opt.value}\n className=\"flex items-center gap-2 rounded-md border border-border-seam px-3 py-2 text-sm cursor-pointer hover:bg-bg-sunken transition-colors has-[:checked]:border-primary has-[:checked]:bg-primary/5\"\n >\n <input\n type=\"radio\"\n name=\"issue-category\"\n value={opt.value}\n checked={category === opt.value}\n onChange={() => setCategory(opt.value)}\n className=\"text-primary\"\n />\n {opt.label}\n </label>\n ))}\n </div>\n </div>\n\n <div>\n <label className=\"mb-2 block text-sm font-medium\">\n {tr(\"devportal.issueNote\", \"Additional details (optional)\")}\n </label>\n <textarea\n value={note}\n onChange={(e) => setNote(e.target.value)}\n rows={3}\n maxLength={500}\n placeholder={tr(\n \"devportal.issueNotePlaceholder\",\n \"Anything admin should know…\",\n )}\n className=\"w-full resize-none rounded-md border border-border-seam bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </div>\n\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <div className=\"flex items-center justify-end gap-3 border-t p-6\">\n <button\n type=\"button\"\n onClick={handleClose}\n disabled={submitting}\n className=\"rounded-md px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleSubmit()}\n disabled={submitting}\n className=\"flex items-center gap-2 rounded-md bg-status-warning-bg px-4 py-2 text-sm font-medium text-status-warning-text hover:opacity-90 transition-opacity disabled:opacity-50\"\n >\n {submitting && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {tr(\"devportal.submitReport\", \"Report Issue\")}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CreateOrganizationPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/CreateOrganizationPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAmDhC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,EA0mBpC,CAAC"}
1
+ {"version":3,"file":"CreateOrganizationPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/CreateOrganizationPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAoDhC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,EA8rBpC,CAAC"}