@pisell/private-materials 6.3.220 → 6.3.222

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.
Files changed (125) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.css +1 -1
  6. package/build/lowcode/render/default/view.js +13 -13
  7. package/build/lowcode/view.css +1 -1
  8. package/build/lowcode/view.js +13 -13
  9. package/es/components/kioskSkuDetail/index.js +7 -7
  10. package/es/components/pay/toC/PaymentMethods/MWCreditCard/tds2.js +53 -26
  11. package/es/components/scanOrder/components/Content/index.js +14 -2
  12. package/es/components/scanOrder/components/ExitConfirmModal/index.js +84 -0
  13. package/es/components/scanOrder/components/ExitConfirmModal/index.less +182 -0
  14. package/es/components/scanOrder/locales.js +20 -0
  15. package/es/index.d.ts +9 -1
  16. package/es/index.js +6 -2
  17. package/es/plus/inventory/BindingModal.js +94 -0
  18. package/es/plus/inventory/InventoryItemManagement.d.ts +7 -0
  19. package/es/plus/inventory/InventoryItemManagement.js +204 -0
  20. package/es/plus/inventory/InventoryLocationManagement.d.ts +7 -0
  21. package/es/plus/inventory/InventoryLocationManagement.js +296 -0
  22. package/es/plus/inventory/InventoryUnitManagement.d.ts +7 -0
  23. package/es/plus/inventory/InventoryUnitManagement.js +144 -0
  24. package/es/plus/inventory/ItemDrawer.js +266 -0
  25. package/es/plus/inventory/RecordDialog.js +141 -0
  26. package/es/plus/inventory/StockList.js +132 -0
  27. package/es/plus/inventory/api.js +66 -0
  28. package/es/plus/inventory/components.js +172 -0
  29. package/es/plus/inventory/context.js +118 -0
  30. package/es/plus/inventory/forms.js +46 -0
  31. package/es/plus/inventory/hooks.js +235 -0
  32. package/es/plus/inventory/index.less +559 -0
  33. package/es/plus/inventory/locales.js +277 -0
  34. package/es/plus/inventory/types.d.ts +10 -0
  35. package/es/plus/inventory/utils.js +24 -0
  36. package/es/plus/panpacificTask/JobCard.js +22 -0
  37. package/es/plus/panpacificTask/JobDrawer.js +366 -0
  38. package/es/plus/panpacificTask/JobForm.js +312 -0
  39. package/es/plus/panpacificTask/JobStatus.js +29 -0
  40. package/es/plus/panpacificTask/PanpacificTask.d.ts +7 -0
  41. package/es/plus/panpacificTask/PanpacificTask.js +552 -0
  42. package/es/plus/panpacificTask/PhotoPreview.js +37 -0
  43. package/es/plus/panpacificTask/README.md +114 -0
  44. package/es/plus/panpacificTask/attachments.js +64 -0
  45. package/es/plus/panpacificTask/index.d.ts +2 -0
  46. package/es/plus/panpacificTask/index.less +539 -0
  47. package/es/plus/panpacificTask/locales.js +586 -0
  48. package/es/plus/panpacificTask/model.js +260 -0
  49. package/es/plus/panpacificTask/saveJob.js +68 -0
  50. package/es/plus/panpacificTask/serve.js +243 -0
  51. package/es/plus/panpacificTask/tenant.js +16 -0
  52. package/es/plus/panpacificTask/types.d.ts +19 -0
  53. package/es/plus/pisellReservation/data/bookingToReservationTables.js +1 -1
  54. package/es/plus/pisellReservation/floorMap/floorPlanApi.js +1 -1
  55. package/es/plus/pisellReservation/floorMap/reservationMock.js +1 -1
  56. package/es/plus/pisellSupersetDashboard/README.md +291 -0
  57. package/es/plus/pisellSupersetDashboard/index.d.ts +15 -0
  58. package/es/plus/pisellSupersetDashboard/index.js +187 -0
  59. package/es/plus/pisellSupersetDashboard/index.less +83 -0
  60. package/es/plus/pisellSupersetDashboard/locales.js +36 -0
  61. package/es/plus/pisellSupersetDashboard/serve.js +51 -0
  62. package/es/plus/pisellSupersetDashboard/types.d.ts +17 -0
  63. package/es/plus/skuOptionsSelection/store/createStore.js +2 -2
  64. package/es/private-materials/lowcode/authmodal/meta.d.ts +1 -0
  65. package/es/pro/Login2.0/AuthModal.d.ts +1 -1
  66. package/es/pro/Login2.0/index.d.ts +1 -2
  67. package/es/pro/Login2.0/shared/types.d.ts +1 -1
  68. package/lib/components/kioskSkuDetail/index.js +7 -7
  69. package/lib/components/pay/toC/PaymentMethods/MWCreditCard/tds2.js +53 -26
  70. package/lib/components/scanOrder/components/Content/index.js +14 -2
  71. package/lib/components/scanOrder/components/ExitConfirmModal/index.js +86 -0
  72. package/lib/components/scanOrder/components/ExitConfirmModal/index.less +182 -0
  73. package/lib/components/scanOrder/locales.js +20 -0
  74. package/lib/index.d.ts +9 -1
  75. package/lib/index.js +136 -126
  76. package/lib/plus/inventory/BindingModal.js +96 -0
  77. package/lib/plus/inventory/InventoryItemManagement.d.ts +7 -0
  78. package/lib/plus/inventory/InventoryItemManagement.js +206 -0
  79. package/lib/plus/inventory/InventoryLocationManagement.d.ts +7 -0
  80. package/lib/plus/inventory/InventoryLocationManagement.js +298 -0
  81. package/lib/plus/inventory/InventoryUnitManagement.d.ts +7 -0
  82. package/lib/plus/inventory/InventoryUnitManagement.js +146 -0
  83. package/lib/plus/inventory/ItemDrawer.js +268 -0
  84. package/lib/plus/inventory/RecordDialog.js +143 -0
  85. package/lib/plus/inventory/StockList.js +134 -0
  86. package/lib/plus/inventory/api.js +66 -0
  87. package/lib/plus/inventory/components.js +181 -0
  88. package/lib/plus/inventory/context.js +121 -0
  89. package/lib/plus/inventory/forms.js +50 -0
  90. package/lib/plus/inventory/hooks.js +240 -0
  91. package/lib/plus/inventory/index.less +559 -0
  92. package/lib/plus/inventory/locales.js +277 -0
  93. package/lib/plus/inventory/types.d.ts +10 -0
  94. package/lib/plus/inventory/utils.js +30 -0
  95. package/lib/plus/panpacificTask/JobCard.js +24 -0
  96. package/lib/plus/panpacificTask/JobDrawer.js +368 -0
  97. package/lib/plus/panpacificTask/JobForm.js +314 -0
  98. package/lib/plus/panpacificTask/JobStatus.js +33 -0
  99. package/lib/plus/panpacificTask/PanpacificTask.d.ts +7 -0
  100. package/lib/plus/panpacificTask/PanpacificTask.js +555 -0
  101. package/lib/plus/panpacificTask/PhotoPreview.js +39 -0
  102. package/lib/plus/panpacificTask/README.md +114 -0
  103. package/lib/plus/panpacificTask/attachments.js +66 -0
  104. package/lib/plus/panpacificTask/index.d.ts +2 -0
  105. package/lib/plus/panpacificTask/index.less +539 -0
  106. package/lib/plus/panpacificTask/locales.js +586 -0
  107. package/lib/plus/panpacificTask/model.js +289 -0
  108. package/lib/plus/panpacificTask/saveJob.js +68 -0
  109. package/lib/plus/panpacificTask/serve.js +260 -0
  110. package/lib/plus/panpacificTask/tenant.js +17 -0
  111. package/lib/plus/panpacificTask/types.d.ts +19 -0
  112. package/lib/plus/pisellSupersetDashboard/README.md +291 -0
  113. package/lib/plus/pisellSupersetDashboard/index.d.ts +15 -0
  114. package/lib/plus/pisellSupersetDashboard/index.js +189 -0
  115. package/lib/plus/pisellSupersetDashboard/index.less +83 -0
  116. package/lib/plus/pisellSupersetDashboard/locales.js +36 -0
  117. package/lib/plus/pisellSupersetDashboard/serve.js +52 -0
  118. package/lib/plus/pisellSupersetDashboard/types.d.ts +17 -0
  119. package/lowcode/inventory-item-management/meta.ts +20 -0
  120. package/lowcode/inventory-location-management/meta.ts +20 -0
  121. package/lowcode/inventory-unit-management/meta.ts +20 -0
  122. package/lowcode/panpacific-task/meta.ts +51 -0
  123. package/lowcode/pisell-superset-dashboard/meta.ts +75 -0
  124. package/package.json +4 -2
  125. package/es/plus/pisellReservation/index.js +0 -17
@@ -0,0 +1,29 @@
1
+ import { displayStatus, displayStatuses, hasInvoice, jobStyle, statusColors } from "./model.js";
2
+ import React from "react";
3
+ //#region src/plus/panpacificTask/JobStatus.tsx
4
+ function JobStatus({ job, getText }) {
5
+ const status = displayStatus(job);
6
+ return /* @__PURE__ */ React.createElement("span", {
7
+ className: "pp-task-status",
8
+ "data-status": status,
9
+ style: jobStyle(job)
10
+ }, getText(`pisell2.panpacific.task.${status}`), hasInvoice(job) && /* @__PURE__ */ React.createElement(InvoiceMark, { getText }));
11
+ }
12
+ function InvoiceMark({ getText }) {
13
+ return /* @__PURE__ */ React.createElement("svg", {
14
+ className: "pp-task-invoice",
15
+ width: "12",
16
+ height: "12",
17
+ viewBox: "0 0 16 16",
18
+ role: "img",
19
+ "aria-label": getText("pisell2.panpacific.task.invoice")
20
+ }, /* @__PURE__ */ React.createElement("path", {
21
+ fill: "currentColor",
22
+ d: "M3 1h10a1 1 0 0 1 1 1v12l-2-1.5L10 14l-2-1.5L6 14l-2-1.5L2 14V2a1 1 0 0 1 1-1zm1 3v1h8V4H4zm0 2v1h5V6H4zm0 2v1h8V8H4z"
23
+ }));
24
+ }
25
+ function StatusLegend({ getText }) {
26
+ return /* @__PURE__ */ React.createElement("div", { className: "pp-task-legend" }, displayStatuses.map((status) => /* @__PURE__ */ React.createElement("span", { key: status }, /* @__PURE__ */ React.createElement("i", { style: { background: statusColors[status] } }), getText(`pisell2.panpacific.task.${status}`), status === "invoice" && /* @__PURE__ */ React.createElement(InvoiceMark, { getText }))));
27
+ }
28
+ //#endregion
29
+ export { InvoiceMark, JobStatus, StatusLegend };
@@ -0,0 +1,7 @@
1
+ import { PanpacificTaskProps } from "./types.js";
2
+ import React from "react";
3
+ //#region src/plus/panpacificTask/PanpacificTask.d.ts
4
+ /** Complete #task workspace. All UI state belongs to this component, including its overlays. */
5
+ declare function PanpacificTask(props: PanpacificTaskProps): React.JSX.Element;
6
+ //#endregion
7
+ export { PanpacificTask };
@@ -0,0 +1,552 @@
1
+ import { _objectSpread2 } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
+ import { _asyncToGenerator } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js";
3
+ import useEngineContext from "../../hooks/useEngineContext.js";
4
+ import { request } from "../../utils/index.js";
5
+ import { defaultPhotoUploader } from "./attachments.js";
6
+ import { calendarItems, companyName, dateText, displayStatuses, draftFor, emptyBase, filterJobs, hasInvoice, jobRange, jobStyle, jobsOnDate, paymentTerm, scheduleText, shiftDates, statuses } from "./model.js";
7
+ import { errorText, getJobBaseData, getJobs, removeJob, updateJob } from "./serve.js";
8
+ import { JobForm } from "./JobForm.js";
9
+ import { InvoiceMark, JobStatus, StatusLegend } from "./JobStatus.js";
10
+ import { JobDrawer } from "./JobDrawer.js";
11
+ import { JobCard } from "./JobCard.js";
12
+ import locales$1 from "./locales.js";
13
+ import dayjs from "dayjs";
14
+ import React, { useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from "react";
15
+ import { Button, ConfigProvider, DatePicker, Empty, Input, Modal, Select, Switch, Table, Tabs } from "antd";
16
+ import { locales } from "@pisell/utils";
17
+ import { PisellCalendar, PisellGantt } from "@pisell/materials";
18
+ import "./index.less";
19
+ //#region src/plus/panpacificTask/PanpacificTask.tsx
20
+ /** Complete #task workspace. All UI state belongs to this component, including its overlays. */
21
+ function PanpacificTask(props) {
22
+ return /* @__PURE__ */ React.createElement(ConfigProvider, {
23
+ prefixCls: "pisell-lowcode",
24
+ componentSize: "middle",
25
+ theme: { token: {
26
+ colorPrimary: "#634db3",
27
+ controlHeight: 38,
28
+ controlHeightSM: 38
29
+ } }
30
+ }, /* @__PURE__ */ React.createElement(TaskWorkspace, props));
31
+ }
32
+ function TaskWorkspace(props) {
33
+ var _context$appHelper, _context$engine, _context$appHelper2;
34
+ const context = useEngineContext();
35
+ const utils = (context === null || context === void 0 || (_context$appHelper = context.appHelper) === null || _context$appHelper === void 0 ? void 0 : _context$appHelper.utils) || {};
36
+ if (utils.request) request.setRequest(utils.request);
37
+ const locale = (context === null || context === void 0 || (_context$engine = context.engine) === null || _context$engine === void 0 || (_context$engine = _context$engine.props) === null || _context$engine === void 0 ? void 0 : _context$engine.locale) || "en";
38
+ locales.init(locales$1, locale);
39
+ const getText = locales.getText;
40
+ const client = useMemo(() => utils.request || request.getRequest(), [utils.request]);
41
+ const { mediaUploadUrl, getHeaders } = (context === null || context === void 0 || (_context$appHelper2 = context.appHelper) === null || _context$appHelper2 === void 0 ? void 0 : _context$appHelper2.constants) || {};
42
+ const uploadPhoto = useMemo(() => props.uploadPhoto || defaultPhotoUploader({
43
+ mediaUploadUrl,
44
+ getHeaders
45
+ }), [
46
+ props.uploadPhoto,
47
+ mediaUploadUrl,
48
+ getHeaders
49
+ ]);
50
+ const [modal, modalContext] = Modal.useModal();
51
+ const [tab, setTab] = useState(props.defaultTab || "calendar");
52
+ const [jobs, setJobs] = useState([]);
53
+ const [base, setBase] = useState(emptyBase);
54
+ const [loading, setLoading] = useState(false);
55
+ const [busyId, setBusyId] = useState();
56
+ const [month, setMonth] = useState(dayjs().format("YYYY-MM"));
57
+ const [selectedDate, setSelectedDate] = useState(dateText(dayjs()));
58
+ const [period, setPeriod] = useState(false);
59
+ const [viewport, setViewport] = useState({
60
+ mode: "month",
61
+ month
62
+ });
63
+ const [ganttStatus, setGanttStatus] = useState();
64
+ const [hoveredJob, setHoveredJob] = useState();
65
+ const [collapsed, setCollapsed] = useState([]);
66
+ const [filters, setFilters] = useState({
67
+ search: "",
68
+ due: ""
69
+ });
70
+ const [page, setPage] = useState(1);
71
+ const [pageSize, setPageSize] = useState(10);
72
+ const [drawer, setDrawer] = useState();
73
+ const [draft, setDraft] = useState();
74
+ const [editorKey, setEditorKey] = useState(0);
75
+ const editorRef = useRef(null);
76
+ const disposed = useRef(false);
77
+ const readSequence = useRef(0);
78
+ const writing = useRef(false);
79
+ const changeCallback = useRef(props.onJobChange);
80
+ changeCallback.current = props.onJobChange;
81
+ const load = useCallback(_asyncToGenerator(function* () {
82
+ const token = ++readSequence.current;
83
+ setLoading(true);
84
+ try {
85
+ const result = yield getJobs(client);
86
+ if (!disposed.current && token === readSequence.current) setJobs(result);
87
+ } catch (error) {
88
+ console.warn("[PanpacificTask] Job list load failed", error);
89
+ } finally {
90
+ if (!disposed.current && token === readSequence.current) setLoading(false);
91
+ }
92
+ }), [client]);
93
+ useEffect(() => {
94
+ disposed.current = false;
95
+ let cancelled = false;
96
+ load();
97
+ getJobBaseData(client).then((result) => {
98
+ if (!cancelled) setBase((previous) => _objectSpread2(_objectSpread2({}, previous), result));
99
+ });
100
+ return () => {
101
+ cancelled = true;
102
+ disposed.current = true;
103
+ readSequence.current++;
104
+ };
105
+ }, [client, load]);
106
+ const confirm = (key) => new Promise((resolve) => modal.confirm({
107
+ title: getText(`pisell2.panpacific.task.${key}`),
108
+ okText: getText(`pisell2.panpacific.task.${key === "discardConfirm" ? "discard" : key === "removeConfirm" ? "remove" : "cancelJob"}`),
109
+ cancelText: getText("pisell2.panpacific.task.cancelAction"),
110
+ okButtonProps: { danger: true },
111
+ onOk: () => resolve(true),
112
+ onCancel: () => resolve(false)
113
+ }));
114
+ const changed = (id) => {
115
+ var _changeCallback$curre;
116
+ load();
117
+ (_changeCallback$curre = changeCallback.current) === null || _changeCallback$curre === void 0 || _changeCallback$curre.call(changeCallback, id);
118
+ };
119
+ const openCreate = (initial = draftFor(void 0, selectedDate)) => {
120
+ setEditorKey((value) => value + 1);
121
+ setDraft(initial);
122
+ };
123
+ const openJob = (job, edit = false) => {
124
+ if (!writing.current && !draft) setDrawer({
125
+ id: job.id,
126
+ edit
127
+ });
128
+ };
129
+ const mutate = function() {
130
+ var _ref = _asyncToGenerator(function* (job, operation, patch) {
131
+ if (writing.current) return false;
132
+ writing.current = true;
133
+ setBusyId(job.id);
134
+ try {
135
+ yield operation();
136
+ if (!disposed.current) {
137
+ var _changeCallback$curre2;
138
+ if (patch) setJobs((previous) => previous.map((row) => String(row.id) === String(job.id) ? _objectSpread2(_objectSpread2({}, row), patch) : row));
139
+ yield load();
140
+ (_changeCallback$curre2 = changeCallback.current) === null || _changeCallback$curre2 === void 0 || _changeCallback$curre2.call(changeCallback, job.id);
141
+ }
142
+ return true;
143
+ } catch (error) {
144
+ if (!disposed.current) modal.error({ title: getText(errorText(error)) });
145
+ return false;
146
+ } finally {
147
+ writing.current = false;
148
+ if (!disposed.current) setBusyId(void 0);
149
+ }
150
+ });
151
+ return function mutate(_x, _x2, _x3) {
152
+ return _ref.apply(this, arguments);
153
+ };
154
+ }();
155
+ const remove = function() {
156
+ var _ref2 = _asyncToGenerator(function* (job) {
157
+ if (yield confirm("removeConfirm")) {
158
+ if (yield mutate(job, () => removeJob(client, job.id))) setJobs((previous) => previous.filter((row) => String(row.id) !== String(job.id)));
159
+ }
160
+ });
161
+ return function remove(_x4) {
162
+ return _ref2.apply(this, arguments);
163
+ };
164
+ }();
165
+ const cancel = function() {
166
+ var _ref3 = _asyncToGenerator(function* (job) {
167
+ if (yield confirm("cancelConfirm")) yield mutate(job, () => updateJob(client, job.id, { status: "cancel" }), { status: "cancel" });
168
+ });
169
+ return function cancel(_x5) {
170
+ return _ref3.apply(this, arguments);
171
+ };
172
+ }();
173
+ const requestDates = function() {
174
+ var _ref4 = _asyncToGenerator(function* (change) {
175
+ const job = jobs.find((row) => String(row.id) === change.item.id);
176
+ if (!job || writing.current) return {
177
+ accepted: false,
178
+ reason: getText("pisell2.panpacific.task.requestFailed")
179
+ };
180
+ const currentRange = jobRange(job);
181
+ if (!currentRange || currentRange.start !== change.before.start || currentRange.endExclusive !== change.before.endExclusive) return {
182
+ accepted: false,
183
+ reason: getText("pisell2.panpacific.task.requestFailed")
184
+ };
185
+ const patch = shiftDates(job, change.after, change.action);
186
+ const accepted = yield mutate(job, () => updateJob(client, job.id, patch), patch);
187
+ return _objectSpread2({ accepted }, accepted ? {} : { reason: getText("pisell2.panpacific.task.requestFailed") });
188
+ });
189
+ return function requestDates(_x6) {
190
+ return _ref4.apply(this, arguments);
191
+ };
192
+ }();
193
+ const statusOptions = displayStatuses.map((value) => ({
194
+ value,
195
+ label: getText(`pisell2.panpacific.task.${value}`)
196
+ }));
197
+ const statusSelect = (value, onChange) => /* @__PURE__ */ React.createElement(Select, {
198
+ size: "small",
199
+ allowClear: true,
200
+ showSearch: true,
201
+ optionFilterProp: "label",
202
+ className: "pp-task-filter-status",
203
+ "aria-label": getText("pisell2.panpacific.task.status"),
204
+ placeholder: getText("pisell2.panpacific.task.allStatuses"),
205
+ options: [{
206
+ value: "",
207
+ label: getText("pisell2.panpacific.task.allStatuses")
208
+ }, ...statusOptions],
209
+ value: value || "",
210
+ onChange: (next) => onChange(next || void 0)
211
+ });
212
+ const deferredFilters = useDeferredValue(filters);
213
+ const filtered = useMemo(() => filterJobs(jobs, deferredFilters, base), [
214
+ jobs,
215
+ deferredFilters,
216
+ base
217
+ ]);
218
+ useEffect(() => {
219
+ const last = Math.max(1, Math.ceil(filtered.length / pageSize));
220
+ if (page > last) setPage(last);
221
+ }, [
222
+ filtered.length,
223
+ page,
224
+ pageSize
225
+ ]);
226
+ const updateFilter = (patch) => {
227
+ setFilters((previous) => Object.keys(patch).every((key) => previous[key] === patch[key]) ? previous : _objectSpread2(_objectSpread2({}, previous), patch));
228
+ setPage(1);
229
+ };
230
+ const columns = [
231
+ {
232
+ key: "code",
233
+ title: getText("pisell2.panpacific.task.code"),
234
+ width: 230,
235
+ render: (_, job) => /* @__PURE__ */ React.createElement(Button, {
236
+ type: "link",
237
+ className: "pp-task-code-link",
238
+ onClick: () => openJob(job)
239
+ }, job.job_number)
240
+ },
241
+ {
242
+ key: "supplier",
243
+ title: getText("pisell2.panpacific.task.supplier"),
244
+ width: 210,
245
+ render: (_, job) => companyName(job) || "—"
246
+ },
247
+ {
248
+ key: "schedule",
249
+ title: getText("pisell2.panpacific.task.schedule"),
250
+ width: 310,
251
+ render: (_, job) => `${scheduleText(job)} · ${getText("pisell2.panpacific.task.due")} ${dateText(job.due_date)}`
252
+ },
253
+ {
254
+ key: "due",
255
+ title: getText("pisell2.panpacific.task.due"),
256
+ width: 130,
257
+ render: (_, job) => dateText(job.due_date) || "—"
258
+ },
259
+ {
260
+ key: "status",
261
+ title: getText("pisell2.panpacific.task.status"),
262
+ width: 140,
263
+ render: (_, job) => /* @__PURE__ */ React.createElement(JobStatus, {
264
+ job,
265
+ getText
266
+ })
267
+ },
268
+ {
269
+ key: "items",
270
+ title: getText("pisell2.panpacific.task.items"),
271
+ width: 90,
272
+ render: (_, job) => {
273
+ var _job$job_materials$fi, _job$job_materials;
274
+ return (_job$job_materials$fi = (_job$job_materials = job.job_materials) === null || _job$job_materials === void 0 ? void 0 : _job$job_materials.filter((row) => row.deleted_at == null).length) !== null && _job$job_materials$fi !== void 0 ? _job$job_materials$fi : "—";
275
+ }
276
+ },
277
+ {
278
+ key: "payment",
279
+ title: getText("pisell2.panpacific.task.payment"),
280
+ width: 170,
281
+ render: (_, job) => [paymentTerm(job, base), job.payment_term_days != null ? `${job.payment_term_days} ${getText("pisell2.panpacific.task.dayUnit")}` : ""].filter(Boolean).join(" · ") || "—"
282
+ },
283
+ {
284
+ key: "actions",
285
+ fixed: "right",
286
+ title: getText("pisell2.panpacific.task.actions"),
287
+ width: 260,
288
+ render: (_, job) => /* @__PURE__ */ React.createElement("div", {
289
+ className: "pp-task-row-actions",
290
+ onClick: (event) => event.stopPropagation()
291
+ }, /* @__PURE__ */ React.createElement(Button, {
292
+ size: "small",
293
+ onClick: () => openJob(job)
294
+ }, getText("pisell2.panpacific.task.view")), /* @__PURE__ */ React.createElement(Button, {
295
+ size: "small",
296
+ onClick: () => openJob(job, true)
297
+ }, getText("pisell2.panpacific.task.edit")), /* @__PURE__ */ React.createElement(Button, {
298
+ size: "small",
299
+ disabled: job.status === "cancel" || busyId != null,
300
+ onClick: () => cancel(job)
301
+ }, getText("pisell2.panpacific.task.cancelJob")), /* @__PURE__ */ React.createElement(Button, {
302
+ size: "small",
303
+ danger: true,
304
+ disabled: busyId != null,
305
+ onClick: () => remove(job)
306
+ }, getText("pisell2.panpacific.task.remove")))
307
+ }
308
+ ];
309
+ const selectedJobs = useMemo(() => jobsOnDate(jobs, selectedDate, period), [
310
+ jobs,
311
+ selectedDate,
312
+ period
313
+ ]);
314
+ const items = useMemo(() => calendarItems(jobs), [jobs]);
315
+ const ganttStart = viewport.mode === "month" ? viewport.month + "-01" : viewport.range.start;
316
+ const ganttEnd = viewport.mode === "month" ? dayjs(ganttStart).add(1, "month").format("YYYY-MM-DD") : viewport.range.endExclusive;
317
+ const ganttItems = useMemo(() => calendarItems(filterJobs(jobs, { status: ganttStatus }, base)).filter((item) => item.range.start < ganttEnd && item.range.endExclusive > ganttStart), [
318
+ jobs,
319
+ ganttStatus,
320
+ base,
321
+ ganttStart,
322
+ ganttEnd
323
+ ]);
324
+ const calendar = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusLegend, { getText }), /* @__PURE__ */ React.createElement("div", { className: "pp-task-calendar-layout" }, /* @__PURE__ */ React.createElement("div", { className: "pp-task-calendar-main" }, /* @__PURE__ */ React.createElement(PisellCalendar, {
325
+ items,
326
+ today: dateText(dayjs()),
327
+ month,
328
+ onMonthChange: setMonth,
329
+ selectedDate,
330
+ onSelectedDateChange: setSelectedDate,
331
+ displayMode: period ? "range" : "custom-date",
332
+ getDisplayDate: (item) => {
333
+ var _item$data;
334
+ return dateText((_item$data = item.data) === null || _item$data === void 0 ? void 0 : _item$data.due_date);
335
+ },
336
+ loading,
337
+ interaction: { move: true },
338
+ moveAnchor: "grabbed-date",
339
+ canStartInteraction: () => ({ allowed: !writing.current }),
340
+ onRequestChange: requestDates,
341
+ onChangeCommitted: (change) => setSelectedDate(change.target.date),
342
+ onItemClick: ({ item }) => item.data && openJob(item.data),
343
+ onDateDoubleClick: ({ date }) => {
344
+ setSelectedDate(date);
345
+ openCreate(draftFor(void 0, date));
346
+ },
347
+ selectedItemId: drawer && String(drawer.id),
348
+ density: "compact",
349
+ maxEventsPerDay: 4,
350
+ classNames: { overflowPanel: "pp-task-calendar-popup" },
351
+ locale,
352
+ toolbarExtra: /* @__PURE__ */ React.createElement("label", { className: "pp-task-period" }, /* @__PURE__ */ React.createElement(Switch, {
353
+ size: "small",
354
+ checked: period,
355
+ onChange: setPeriod
356
+ }), getText("pisell2.panpacific.task.period")),
357
+ styles: { event: (ctx) => _objectSpread2(_objectSpread2({}, jobStyle((ctx === null || ctx === void 0 ? void 0 : ctx.item.data) || {})), (ctx === null || ctx === void 0 ? void 0 : ctx.item.id) === hoveredJob ? {
358
+ outline: "2px solid #634db3",
359
+ outlineOffset: "-2px"
360
+ } : {}) },
361
+ renderEventContent: ({ item }) => /* @__PURE__ */ React.createElement("span", { className: "pp-task-event-content" }, /* @__PURE__ */ React.createElement("span", { title: item.title }, item.title), hasInvoice(item.data || {}) && /* @__PURE__ */ React.createElement(InvoiceMark, { getText }))
362
+ })), /* @__PURE__ */ React.createElement("aside", { className: "pp-task-calendar-side" }, /* @__PURE__ */ React.createElement("h2", null, selectedDate), /* @__PURE__ */ React.createElement("p", null, selectedJobs.length, " ", getText("pisell2.panpacific.task.job")), /* @__PURE__ */ React.createElement(Button, {
363
+ block: true,
364
+ type: "primary",
365
+ onClick: () => openCreate()
366
+ }, "+ ", getText("pisell2.panpacific.task.createJob")), /* @__PURE__ */ React.createElement("div", {
367
+ className: "pp-task-job-cards pp-job-list",
368
+ role: "list"
369
+ }, selectedJobs.length ? selectedJobs.map((job) => /* @__PURE__ */ React.createElement("div", {
370
+ role: "listitem",
371
+ key: String(job.id)
372
+ }, /* @__PURE__ */ React.createElement(JobCard, {
373
+ job,
374
+ getText,
375
+ selected: String(drawer === null || drawer === void 0 ? void 0 : drawer.id) === String(job.id),
376
+ onOpen: () => openJob(job),
377
+ onHover: setHoveredJob
378
+ }))) : /* @__PURE__ */ React.createElement(Empty, {
379
+ image: Empty.PRESENTED_IMAGE_SIMPLE,
380
+ description: getText("pisell2.panpacific.task.noJobs")
381
+ })))));
382
+ const timeline = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusLegend, { getText }), /* @__PURE__ */ React.createElement(PisellGantt, {
383
+ items: ganttItems,
384
+ today: dateText(dayjs()),
385
+ viewport,
386
+ onViewportChange: setViewport,
387
+ loading,
388
+ locale,
389
+ rowHeight: 60,
390
+ getGroupKey: (item) => {
391
+ var _item$data2;
392
+ return ((_item$data2 = item.data) === null || _item$data2 === void 0 ? void 0 : _item$data2.status) || "create";
393
+ },
394
+ groups: statuses.filter((id) => ganttItems.some((item) => item.data.status === id)).map((id) => ({
395
+ id,
396
+ title: getText(`pisell2.panpacific.task.${id}`)
397
+ })),
398
+ collapsedGroupIds: collapsed,
399
+ onCollapsedGroupIdsChange: setCollapsed,
400
+ toolbarExtra: /* @__PURE__ */ React.createElement("label", { className: "pp-task-timeline-filter" }, /* @__PURE__ */ React.createElement("span", null, getText("pisell2.panpacific.task.status")), statusSelect(ganttStatus, setGanttStatus)),
401
+ selectedItemId: drawer && String(drawer.id),
402
+ onItemClick: ({ item }) => item.data && openJob(item.data),
403
+ interaction: {
404
+ move: true,
405
+ resizeStart: true,
406
+ resizeEnd: true
407
+ },
408
+ canStartInteraction: () => ({ allowed: !writing.current }),
409
+ onRequestChange: requestDates,
410
+ renderRowLabel: ({ item }) => /* @__PURE__ */ React.createElement(Button, {
411
+ type: "text",
412
+ onClick: () => item.data && openJob(item.data)
413
+ }, item.title),
414
+ styles: { taskBar: (ctx) => _objectSpread2(_objectSpread2({}, jobStyle((ctx === null || ctx === void 0 ? void 0 : ctx.item.data) || {})), {}, { border: "1px solid #d1d5db" }) },
415
+ renderTaskContent: ({ item }) => {
416
+ var _item$data3, _item$data4;
417
+ return /* @__PURE__ */ React.createElement("div", { className: "pp-task-gantt-content" }, /* @__PURE__ */ React.createElement("strong", null, item.title), /* @__PURE__ */ React.createElement("small", null, ((_item$data3 = item.data) === null || _item$data3 === void 0 ? void 0 : _item$data3.company_contact) || "—", " · ", dateText((_item$data4 = item.data) === null || _item$data4 === void 0 ? void 0 : _item$data4.due_date), hasInvoice(item.data || {}) && /* @__PURE__ */ React.createElement(InvoiceMark, { getText })));
418
+ }
419
+ }));
420
+ const list = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "pp-task-filters" }, /* @__PURE__ */ React.createElement("label", null, /* @__PURE__ */ React.createElement("span", null, getText("pisell2.panpacific.task.search")), /* @__PURE__ */ React.createElement(Input, {
421
+ allowClear: true,
422
+ placeholder: getText("pisell2.panpacific.task.searchHint"),
423
+ value: filters.search,
424
+ "aria-label": getText("pisell2.panpacific.task.search"),
425
+ onInput: (event) => updateFilter({ search: event.currentTarget.value }),
426
+ onChange: (event) => updateFilter({ search: event.target.value })
427
+ })), /* @__PURE__ */ React.createElement("label", null, /* @__PURE__ */ React.createElement("span", null, getText("pisell2.panpacific.task.due")), /* @__PURE__ */ React.createElement(DatePicker, {
428
+ allowClear: true,
429
+ placeholder: getText("pisell2.panpacific.task.allDates"),
430
+ value: filters.due ? dayjs(filters.due) : null,
431
+ onChange: (value) => updateFilter({ due: dateText(value) })
432
+ })), /* @__PURE__ */ React.createElement("label", null, /* @__PURE__ */ React.createElement("span", null, getText("pisell2.panpacific.task.status")), statusSelect(filters.status, (status) => updateFilter({ status }))), /* @__PURE__ */ React.createElement(Button, { onClick: () => {
433
+ setFilters({
434
+ search: "",
435
+ due: ""
436
+ });
437
+ setPage(1);
438
+ } }, getText("pisell2.panpacific.task.reset")), /* @__PURE__ */ React.createElement(Button, {
439
+ type: "primary",
440
+ onClick: () => openCreate()
441
+ }, "+ ", getText("pisell2.panpacific.task.createJob"))), /* @__PURE__ */ React.createElement(Table, {
442
+ size: "small",
443
+ rowKey: (job) => String(job.id),
444
+ columns,
445
+ dataSource: filtered,
446
+ loading,
447
+ scroll: { x: 1640 },
448
+ locale: { emptyText: getText("pisell2.panpacific.task.noJobs") },
449
+ pagination: {
450
+ current: page,
451
+ pageSize,
452
+ showSizeChanger: true,
453
+ onChange: (next, size) => {
454
+ setPage(size !== pageSize ? 1 : next);
455
+ setPageSize(size);
456
+ }
457
+ },
458
+ onRow: (job) => ({ onClick: (event) => {
459
+ if (!event.target.closest("button, a, input")) openJob(job);
460
+ } })
461
+ }));
462
+ return /* @__PURE__ */ React.createElement("div", {
463
+ className: ["pp-task", props.className].filter(Boolean).join(" "),
464
+ style: props.style
465
+ }, modalContext, /* @__PURE__ */ React.createElement("header", { className: "pp-task-heading" }, /* @__PURE__ */ React.createElement("h1", null, getText("pisell2.panpacific.task.job"))), /* @__PURE__ */ React.createElement(Tabs, {
466
+ activeKey: tab,
467
+ onChange: (value) => setTab(value),
468
+ destroyInactiveTabPane: true,
469
+ items: [
470
+ {
471
+ key: "calendar",
472
+ label: getText("pisell2.panpacific.task.calendar"),
473
+ children: calendar
474
+ },
475
+ {
476
+ key: "timeline",
477
+ label: getText("pisell2.panpacific.task.timeline"),
478
+ children: timeline
479
+ },
480
+ {
481
+ key: "list",
482
+ label: getText("pisell2.panpacific.task.list"),
483
+ children: list
484
+ }
485
+ ]
486
+ }), /* @__PURE__ */ React.createElement(Modal, {
487
+ open: !!draft,
488
+ title: getText("pisell2.panpacific.task.createJob"),
489
+ width: "min(1100px, 96vw)",
490
+ wrapClassName: "pp-task-overlay pp-task-modal",
491
+ footer: null,
492
+ destroyOnClose: true,
493
+ maskClosable: false,
494
+ onCancel: () => {
495
+ var _editorRef$current;
496
+ return (_editorRef$current = editorRef.current) === null || _editorRef$current === void 0 ? void 0 : _editorRef$current.close();
497
+ },
498
+ bodyStyle: {
499
+ maxHeight: "76vh",
500
+ overflowY: "auto",
501
+ position: "relative"
502
+ }
503
+ }, draft && /* @__PURE__ */ React.createElement(JobForm, {
504
+ key: editorKey,
505
+ ref: editorRef,
506
+ initial: draft,
507
+ jobs,
508
+ base,
509
+ request: client,
510
+ getText,
511
+ confirmDiscard: () => confirm("discardConfirm"),
512
+ onCancel: () => {
513
+ setDraft(void 0);
514
+ load();
515
+ },
516
+ onSaved: (id, values) => {
517
+ var _jobRange;
518
+ const date = period ? (_jobRange = jobRange(values)) === null || _jobRange === void 0 ? void 0 : _jobRange.start : dateText(values.due_date);
519
+ if (date) {
520
+ setSelectedDate(date);
521
+ setMonth(date.slice(0, 7));
522
+ setViewport({
523
+ mode: "month",
524
+ month: date.slice(0, 7)
525
+ });
526
+ }
527
+ setDraft(void 0);
528
+ changed(id);
529
+ }
530
+ })), drawer && /* @__PURE__ */ React.createElement(JobDrawer, {
531
+ key: `${drawer.id}:${!!drawer.edit}`,
532
+ id: drawer.id,
533
+ startEditing: drawer.edit,
534
+ jobs,
535
+ base,
536
+ request: client,
537
+ getText,
538
+ uploadPhoto,
539
+ confirm,
540
+ onClose: () => {
541
+ setDrawer(void 0);
542
+ load();
543
+ },
544
+ onChanged: changed,
545
+ onDuplicate: (initial) => {
546
+ setDrawer(void 0);
547
+ openCreate(initial);
548
+ }
549
+ }));
550
+ }
551
+ //#endregion
552
+ export { PanpacificTask as default };
@@ -0,0 +1,37 @@
1
+ import { attachments } from "./attachments.js";
2
+ import React, { useState } from "react";
3
+ import { Button, Image } from "antd";
4
+ import { DeleteOutlined } from "@ant-design/icons";
5
+ //#region src/plus/panpacificTask/PhotoPreview.tsx
6
+ function PhotoPreview({ value, label, compact, disabled, getText, onRemove }) {
7
+ const [visible, setVisible] = useState(false);
8
+ const images = attachments(value);
9
+ const remove = (index) => {
10
+ if (disabled || !onRemove) return;
11
+ setVisible(false);
12
+ onRemove(index);
13
+ };
14
+ const removeLabel = getText("pisell2.panpacific.task.removePhoto");
15
+ return /* @__PURE__ */ React.createElement(Image.PreviewGroup, { preview: {
16
+ visible,
17
+ onVisibleChange: setVisible,
18
+ rootClassName: "pp-task-photo-preview",
19
+ toolbarRender: (toolbar, { current }) => /* @__PURE__ */ React.createElement(React.Fragment, null, toolbar, onRemove && /* @__PURE__ */ React.createElement(Button, {
20
+ className: "pp-task-photo-preview-remove",
21
+ danger: true,
22
+ icon: /* @__PURE__ */ React.createElement(DeleteOutlined, null),
23
+ disabled,
24
+ onClick: () => remove(current)
25
+ }, removeLabel))
26
+ } }, images.map((item, index) => /* @__PURE__ */ React.createElement("figure", {
27
+ className: "pp-task-photo",
28
+ key: `${item.url}-${index}`
29
+ }, /* @__PURE__ */ React.createElement(Image, {
30
+ width: compact ? 38 : 92,
31
+ height: compact ? 38 : 72,
32
+ src: item.url,
33
+ alt: item.name || label || getText("pisell2.panpacific.task.photo")
34
+ }), !compact && /* @__PURE__ */ React.createElement("figcaption", null, label || item.name))));
35
+ }
36
+ //#endregion
37
+ export { PhotoPreview };