@appcorp/stellar-solutions-invoice-module 0.1.55 → 0.1.57

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 (68) hide show
  1. package/base-modules/invoice/add-service-product-section.d.ts +12 -2
  2. package/base-modules/invoice/add-service-product-section.js +20 -10
  3. package/base-modules/invoice/company-form-section.d.ts +12 -2
  4. package/base-modules/invoice/company-form-section.js +118 -10
  5. package/base-modules/invoice/constants.d.ts +18 -25
  6. package/base-modules/invoice/constants.js +66 -548
  7. package/base-modules/invoice/context.d.ts +42 -2
  8. package/base-modules/invoice/context.js +259 -317
  9. package/base-modules/invoice/customer-form-section.d.ts +12 -2
  10. package/base-modules/invoice/customer-form-section.js +91 -9
  11. package/base-modules/invoice/drawer.d.ts +9 -4
  12. package/base-modules/invoice/drawer.js +32 -6
  13. package/base-modules/invoice/form.d.ts +2 -4
  14. package/base-modules/invoice/form.js +7 -6
  15. package/base-modules/invoice/invoice.d.ts +2 -2
  16. package/base-modules/invoice/invoice.js +33 -42
  17. package/base-modules/invoice/pricing-form-section.d.ts +12 -2
  18. package/base-modules/invoice/pricing-form-section.js +65 -9
  19. package/base-modules/invoice/products-form-section.d.ts +12 -2
  20. package/base-modules/invoice/products-form-section.js +57 -31
  21. package/base-modules/invoice/reducer.d.ts +2 -2
  22. package/base-modules/invoice/reducer.js +57 -56
  23. package/base-modules/invoice/services-form-section.d.ts +12 -2
  24. package/base-modules/invoice/services-form-section.js +61 -14
  25. package/base-modules/invoice/types.d.ts +43 -23
  26. package/base-modules/invoice/validate.d.ts +869 -17
  27. package/base-modules/invoice/validate.js +94 -35
  28. package/base-modules/quote/actions.d.ts +215 -0
  29. package/base-modules/quote/actions.js +38 -0
  30. package/base-modules/quote/add-service-product-section.d.ts +12 -0
  31. package/base-modules/quote/add-service-product-section.js +31 -0
  32. package/base-modules/quote/calculate-subtotal.d.ts +1 -0
  33. package/base-modules/quote/calculate-subtotal.js +6 -0
  34. package/base-modules/quote/calculate-total.d.ts +1 -0
  35. package/base-modules/quote/calculate-total.js +6 -0
  36. package/base-modules/quote/company-form-section.d.ts +12 -0
  37. package/base-modules/quote/company-form-section.js +125 -0
  38. package/base-modules/quote/constants.d.ts +64 -0
  39. package/base-modules/quote/constants.js +107 -0
  40. package/base-modules/quote/context.d.ts +50 -0
  41. package/base-modules/quote/context.js +822 -0
  42. package/base-modules/quote/customer-form-section.d.ts +12 -0
  43. package/base-modules/quote/customer-form-section.js +99 -0
  44. package/base-modules/quote/drawer.d.ts +13 -0
  45. package/base-modules/quote/drawer.js +45 -0
  46. package/base-modules/quote/form.d.ts +6 -0
  47. package/base-modules/quote/form.js +27 -0
  48. package/base-modules/quote/pricing-form-section.d.ts +12 -0
  49. package/base-modules/quote/pricing-form-section.js +76 -0
  50. package/base-modules/quote/products-form-section.d.ts +12 -0
  51. package/base-modules/quote/products-form-section.js +71 -0
  52. package/base-modules/quote/quote.d.ts +8 -0
  53. package/base-modules/quote/quote.js +69 -0
  54. package/base-modules/quote/reducer.d.ts +4 -0
  55. package/base-modules/quote/reducer.js +181 -0
  56. package/base-modules/quote/services-form-section.d.ts +12 -0
  57. package/base-modules/quote/services-form-section.js +73 -0
  58. package/base-modules/quote/types.d.ts +126 -0
  59. package/base-modules/quote/types.js +35 -0
  60. package/base-modules/quote/validate.d.ts +856 -0
  61. package/base-modules/quote/validate.js +85 -0
  62. package/package.json +23 -8
  63. package/base-modules/invoice/company-form-elements.d.ts +0 -3
  64. package/base-modules/invoice/company-form-elements.js +0 -41
  65. package/base-modules/invoice/customer-form-elements.d.ts +0 -3
  66. package/base-modules/invoice/customer-form-elements.js +0 -41
  67. package/base-modules/invoice/pricing-form-elements.d.ts +0 -3
  68. package/base-modules/invoice/pricing-form-elements.js +0 -41
@@ -0,0 +1,822 @@
1
+ /**
2
+ * Invoice State Context
3
+ *
4
+ * This module provides comprehensive state management for the Invoice feature including:
5
+ * - CRUD operations (create, read, update, delete)
6
+ * - Form validation and error handling
7
+ * - Multi-section forms (company, customer, pricing, products, services)
8
+ * - Complex calculations (subtotal, tax, discount, total)
9
+ * - Dynamic product and service row management
10
+ * - Search and filtering functionality
11
+ * - Pagination controls
12
+ * - Company and customer integration
13
+ * - Currency and tax management
14
+ * - Internationalization support
15
+ * - Theme-aware toast notifications
16
+ *
17
+ * Organization:
18
+ * - Types & Interfaces
19
+ * - Main Hook (useInvoiceState)
20
+ * - State & Core Hooks
21
+ * - Theme Support
22
+ * - Toast Helpers
23
+ * - Debounced Values
24
+ * - Tax & Currency Defaults
25
+ * - API Parameters (memoized)
26
+ * - API Callbacks (with error handling)
27
+ * - Module Entity Hook
28
+ * - Effects (list refresh, defaults, calculations)
29
+ * - Drawer & Modal Handlers
30
+ * - CRUD Operation Handlers
31
+ * - Form Handlers (products, services, pricing)
32
+ * - Calculation Handlers
33
+ * - Pagination Handlers
34
+ * - Search Handlers
35
+ * - Table Actions (memoized)
36
+ * - Return State
37
+ * - Context Setup
38
+ * - Provider Component
39
+ * - Custom Hook
40
+ */
41
+ "use client";
42
+ "use strict";
43
+ var __assign = (this && this.__assign) || function () {
44
+ __assign = Object.assign || function(t) {
45
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
46
+ s = arguments[i];
47
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
48
+ t[p] = s[p];
49
+ }
50
+ return t;
51
+ };
52
+ return __assign.apply(this, arguments);
53
+ };
54
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
55
+ if (k2 === undefined) k2 = k;
56
+ var desc = Object.getOwnPropertyDescriptor(m, k);
57
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
58
+ desc = { enumerable: true, get: function() { return m[k]; } };
59
+ }
60
+ Object.defineProperty(o, k2, desc);
61
+ }) : (function(o, m, k, k2) {
62
+ if (k2 === undefined) k2 = k;
63
+ o[k2] = m[k];
64
+ }));
65
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
66
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
67
+ }) : function(o, v) {
68
+ o["default"] = v;
69
+ });
70
+ var __importStar = (this && this.__importStar) || (function () {
71
+ var ownKeys = function(o) {
72
+ ownKeys = Object.getOwnPropertyNames || function (o) {
73
+ var ar = [];
74
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
75
+ return ar;
76
+ };
77
+ return ownKeys(o);
78
+ };
79
+ return function (mod) {
80
+ if (mod && mod.__esModule) return mod;
81
+ var result = {};
82
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
83
+ __setModuleDefault(result, mod);
84
+ return result;
85
+ };
86
+ })();
87
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
88
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
89
+ return new (P || (P = Promise))(function (resolve, reject) {
90
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
91
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
92
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
93
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
94
+ });
95
+ };
96
+ var __generator = (this && this.__generator) || function (thisArg, body) {
97
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
98
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
99
+ function verb(n) { return function (v) { return step([n, v]); }; }
100
+ function step(op) {
101
+ if (f) throw new TypeError("Generator is already executing.");
102
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
103
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
104
+ if (y = 0, t) op = [op[0] & 2, t.value];
105
+ switch (op[0]) {
106
+ case 0: case 1: t = op; break;
107
+ case 4: _.label++; return { value: op[1], done: false };
108
+ case 5: _.label++; y = op[1]; op = [0]; continue;
109
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
110
+ default:
111
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
112
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
113
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
114
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
115
+ if (t[2]) _.ops.pop();
116
+ _.trys.pop(); continue;
117
+ }
118
+ op = body.call(thisArg, _);
119
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
120
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
121
+ }
122
+ };
123
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
124
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
125
+ if (ar || !(i in from)) {
126
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
127
+ ar[i] = from[i];
128
+ }
129
+ }
130
+ return to.concat(ar || Array.prototype.slice.call(from));
131
+ };
132
+ Object.defineProperty(exports, "__esModule", { value: true });
133
+ exports.useQuoteStateContext = exports.QuoteStateContextProvider = exports.QuoteStateContext = void 0;
134
+ var react_1 = __importStar(require("react"));
135
+ var next_themes_1 = require("next-themes");
136
+ var next_intl_1 = require("next-intl");
137
+ var util_functions_1 = require("@react-pakistan/util-functions");
138
+ var toast_utils_1 = require("@appcorp/shadcn/lib/toast-utils");
139
+ var actions_1 = require("./actions");
140
+ var constants_1 = require("./constants");
141
+ var reducer_1 = require("./reducer");
142
+ var types_1 = require("./types");
143
+ var validate_1 = require("./validate");
144
+ var calculate_subtotal_1 = require("./calculate-subtotal");
145
+ var calculate_total_1 = require("./calculate-total");
146
+ var context_1 = require("@appcorp/stellar-solutions-modules/global-modules/tax/context");
147
+ var context_2 = require("@appcorp/stellar-solutions-modules/global-modules/preferences/context");
148
+ // ============================================================================
149
+ // MAIN HOOK
150
+ // ============================================================================
151
+ var useQuoteState = function () {
152
+ var _a;
153
+ // ---------------------------------------------------------------------------
154
+ // State & Core Hooks
155
+ // ---------------------------------------------------------------------------
156
+ var _b = (0, react_1.useReducer)(reducer_1.quoteReducer, reducer_1.initialQuoteState), state = _b[0], dispatch = _b[1];
157
+ var t = (0, next_intl_1.useTranslations)("toastMessages");
158
+ var theme = (0, next_themes_1.useTheme)().theme;
159
+ var taxes = (0, context_1.useTaxStateContext)().taxes;
160
+ var currencies = (0, context_2.usePreferenceStateContext)().currencies;
161
+ // ---------------------------------------------------------------------------
162
+ // Toast Helpers
163
+ // ---------------------------------------------------------------------------
164
+ var showErrorToast = (0, react_1.useCallback)(function (description) {
165
+ (0, toast_utils_1.generateThemeToast)({
166
+ variant: toast_utils_1.TOAST_VARIANT.ERROR,
167
+ description: description,
168
+ theme: theme,
169
+ });
170
+ }, [theme]);
171
+ var showSuccessToast = (0, react_1.useCallback)(function (description) {
172
+ (0, toast_utils_1.generateThemeToast)({
173
+ variant: toast_utils_1.TOAST_VARIANT.SUCCESS,
174
+ description: description,
175
+ theme: theme,
176
+ });
177
+ }, [theme]);
178
+ // ---------------------------------------------------------------------------
179
+ // Debounced Values
180
+ // ---------------------------------------------------------------------------
181
+ var debouncedQuery = (0, util_functions_1.useDebounce)(state.searchQuery, 800);
182
+ var debouncedProductList = (0, util_functions_1.useDebounce)(state.productQuery, 800);
183
+ var debouncedCustomer = (0, util_functions_1.useDebounce)((_a = state === null || state === void 0 ? void 0 : state.customer) === null || _a === void 0 ? void 0 : _a.phone, 800);
184
+ var debouncedTaxList = (0, util_functions_1.useDebounce)(state.taxQuery, 800);
185
+ var debouncedCompanyList = (0, util_functions_1.useDebounce)(state.companyQuery, 800);
186
+ // ---------------------------------------------------------------------------
187
+ // Tax & Currency Defaults
188
+ // ---------------------------------------------------------------------------
189
+ var defaultTax = (0, react_1.useMemo)(function () {
190
+ return taxes.filter(function (_a) {
191
+ var isDefault = _a.isDefault;
192
+ return isDefault;
193
+ })[0];
194
+ }, [taxes]);
195
+ var defaultCurrency = (0, react_1.useMemo)(function () {
196
+ return currencies.filter(function (_a) {
197
+ var isDefault = _a.isDefault;
198
+ return isDefault;
199
+ })[0];
200
+ }, [currencies]);
201
+ // ---------------------------------------------------------------------------
202
+ // API Parameters (Memoized)
203
+ // ---------------------------------------------------------------------------
204
+ var listParams = {
205
+ category: types_1.QUOTE_INVOICE_CATEGORY.QUOTE,
206
+ currentPage: state.currentPage,
207
+ pageLimit: state.pageLimit,
208
+ searchQuery: state.searchQuery,
209
+ includeCustomer: true,
210
+ includeCompany: true,
211
+ };
212
+ var updateParams = (0, react_1.useMemo)(function () {
213
+ var _a, _b, _c, _d, _e, _f, _g, _h;
214
+ return ({
215
+ category: state.category,
216
+ companyId: state.companyId,
217
+ currency: state.currency,
218
+ customerId: state.customerId,
219
+ date: state.date,
220
+ discount: (_a = state === null || state === void 0 ? void 0 : state.discount) === null || _a === void 0 ? void 0 : _a.trim(),
221
+ discountUnit: state.discountUnit,
222
+ drawer: state.drawer,
223
+ expiryDate: state.expiryDate,
224
+ id: state.id,
225
+ invoiceStatus: state.invoiceStatus,
226
+ mode: state.mode,
227
+ note: state.note.trim(),
228
+ productsList: state.productsList.filter(function (_a) {
229
+ var id = _a.id;
230
+ return id;
231
+ }),
232
+ quoteStatus: state.quoteStatus,
233
+ ref: state.ref,
234
+ servicesList: state.servicesList.filter(function (_a) {
235
+ var name = _a.name;
236
+ return name;
237
+ }),
238
+ subTotal: state.subTotal,
239
+ taxRate: state.taxRate,
240
+ total: state.total,
241
+ phone: (_b = state.customer) === null || _b === void 0 ? void 0 : _b.phone,
242
+ firstName: (_c = state.customer) === null || _c === void 0 ? void 0 : _c.firstName,
243
+ lastName: (_d = state.customer) === null || _d === void 0 ? void 0 : _d.lastName,
244
+ email: (_e = state.customer) === null || _e === void 0 ? void 0 : _e.email,
245
+ address: (_f = state.customer) === null || _f === void 0 ? void 0 : _f.address,
246
+ city: (_g = state.customer) === null || _g === void 0 ? void 0 : _g.city,
247
+ country: (_h = state.customer) === null || _h === void 0 ? void 0 : _h.country,
248
+ });
249
+ }, [state]);
250
+ var byIdParams = {
251
+ id: state.id,
252
+ };
253
+ var deleteParams = {
254
+ id: state.id,
255
+ };
256
+ // ---------------------------------------------------------------------------
257
+ // API Callbacks
258
+ // ---------------------------------------------------------------------------
259
+ var listCallback = (0, react_1.useCallback)(function (_a) {
260
+ var data = _a.data, error = _a.error;
261
+ if (error) {
262
+ showErrorToast(t("networkError"));
263
+ }
264
+ if (data === null || data === void 0 ? void 0 : data.items) {
265
+ dispatch({
266
+ type: actions_1.QUOTE_ACTION_TYPES.SET_QUOTES,
267
+ payload: { quotes: data.items },
268
+ });
269
+ dispatch({
270
+ type: actions_1.QUOTE_ACTION_TYPES.SET_COUNT,
271
+ payload: { count: data === null || data === void 0 ? void 0 : data.count },
272
+ });
273
+ }
274
+ }, [t, showErrorToast]);
275
+ var updateCallback = (0, react_1.useCallback)(function (_a) {
276
+ var data = _a.data, error = _a.error;
277
+ if (error) {
278
+ showErrorToast(t("networkError"));
279
+ }
280
+ if (data) {
281
+ showSuccessToast(state.mode === "Edit" ? t("invoiceUpdated") : t("invoiceCreated"));
282
+ dispatch({
283
+ type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM,
284
+ });
285
+ dispatch({
286
+ type: actions_1.QUOTE_ACTION_TYPES.RESET_ERRORS,
287
+ });
288
+ listFetchNow();
289
+ dispatch({
290
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
291
+ payload: { drawer: null },
292
+ });
293
+ }
294
+ },
295
+ // eslint-disable-next-line react-hooks/exhaustive-deps
296
+ [t, state.mode, showErrorToast, showSuccessToast]);
297
+ var byIdCallback = (0, react_1.useCallback)(function (_a) {
298
+ var _b, _c, _d, _e, _f;
299
+ var data = _a.data, error = _a.error;
300
+ if (error) {
301
+ showErrorToast(t("invoiceFetchError"));
302
+ }
303
+ if (data) {
304
+ var updatedServices = __spreadArray([], data === null || data === void 0 ? void 0 : data.services, true).map(function (item) {
305
+ delete item.quoteInvoiceId;
306
+ return __assign(__assign({}, item), { rowTotal: Number(item.quantity) * Number(item.price) });
307
+ });
308
+ var updatedProducts = __spreadArray([], data === null || data === void 0 ? void 0 : data.products, true).map(function (item) {
309
+ var _a, _b;
310
+ return (__assign(__assign({}, item), { price: (_a = item === null || item === void 0 ? void 0 : item.product) === null || _a === void 0 ? void 0 : _a.salePrice, id: item === null || item === void 0 ? void 0 : item.productId, quantity: item === null || item === void 0 ? void 0 : item.quantity, rowTotal: parseFloat((_b = item === null || item === void 0 ? void 0 : item.product) === null || _b === void 0 ? void 0 : _b.salePrice) * parseInt(item.quantity) }));
311
+ });
312
+ var updatedData = __assign(__assign(__assign(__assign({}, data), { mode: "Edit", companyId: (data === null || data === void 0 ? void 0 : data.companyId) || "", customerId: (data === null || data === void 0 ? void 0 : data.customerId) || "" }), (((_b = data === null || data === void 0 ? void 0 : data.customer) === null || _b === void 0 ? void 0 : _b.id) && {
313
+ customer: __assign({}, data.customer),
314
+ })), { servicesList: __spreadArray([], updatedServices, true).filter(function (item) { return item.name; }), productsList: __spreadArray([], updatedProducts, true).filter(function (item) { return item.id; }), companiesList: [__assign({}, data.company)] });
315
+ if ((_c = updatedData === null || updatedData === void 0 ? void 0 : updatedData.company) === null || _c === void 0 ? void 0 : _c.name) {
316
+ dispatch({
317
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
318
+ payload: { drawer: types_1.QUOTE_DRAWER.QUOTE_COMPANY_FORM_DRAWER },
319
+ });
320
+ }
321
+ if ((_d = updatedData === null || updatedData === void 0 ? void 0 : updatedData.customer) === null || _d === void 0 ? void 0 : _d.firstName) {
322
+ dispatch({
323
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
324
+ payload: { drawer: types_1.QUOTE_DRAWER.QUOTE_CUSTOMER_FORM_DRAWER },
325
+ });
326
+ }
327
+ dispatch({
328
+ type: actions_1.QUOTE_ACTION_TYPES.SET_FORM,
329
+ payload: { form: updatedData },
330
+ });
331
+ if ((_e = updatedData === null || updatedData === void 0 ? void 0 : updatedData.company) === null || _e === void 0 ? void 0 : _e.name) {
332
+ dispatch({
333
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
334
+ payload: { drawer: types_1.QUOTE_DRAWER.QUOTE_COMPANY_FORM_DRAWER },
335
+ });
336
+ }
337
+ if ((_f = updatedData === null || updatedData === void 0 ? void 0 : updatedData.customer) === null || _f === void 0 ? void 0 : _f.firstName) {
338
+ dispatch({
339
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
340
+ payload: { drawer: types_1.QUOTE_DRAWER.QUOTE_CUSTOMER_FORM_DRAWER },
341
+ });
342
+ }
343
+ }
344
+ }, [t, showErrorToast]);
345
+ var deleteCallback = (0, react_1.useCallback)(function (_a) {
346
+ var data = _a.data, error = _a.error;
347
+ if (error) {
348
+ showErrorToast(t("networkError"));
349
+ }
350
+ if (data) {
351
+ showSuccessToast(t("invoiceUpdated"));
352
+ dispatch({
353
+ type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM,
354
+ });
355
+ listFetchNow();
356
+ }
357
+ },
358
+ // eslint-disable-next-line react-hooks/exhaustive-deps
359
+ [t, showErrorToast, showSuccessToast]);
360
+ // ---------------------------------------------------------------------------
361
+ // Module Entity Hook
362
+ // ---------------------------------------------------------------------------
363
+ var _c = (0, util_functions_1.useModuleEntity)({
364
+ byIdCallback: byIdCallback,
365
+ byIdParams: byIdParams,
366
+ deleteCallback: deleteCallback,
367
+ deleteParams: deleteParams,
368
+ listCallback: listCallback,
369
+ listParams: listParams,
370
+ listUrl: constants_1.QUOTE_API_ROUTES.QUOTES,
371
+ searchQuery: debouncedQuery,
372
+ unitByIdUrl: constants_1.QUOTE_API_ROUTES.QUOTE_BY_ID,
373
+ unitUrl: constants_1.QUOTE_API_ROUTES.QUOTE,
374
+ updateCallback: updateCallback,
375
+ updateDeps: [state],
376
+ listDeps: [debouncedQuery, state.currentPage, state.pageLimit],
377
+ updateParams: __assign(__assign({}, updateParams), { mode: "Create" }),
378
+ }), byIdError = _c.byIdError, byIdFetchNow = _c.byIdFetchNow, byIdLoading = _c.byIdLoading, deleteError = _c.deleteError, deleteFetchNow = _c.deleteFetchNow, deleteLoading = _c.deleteLoading, listError = _c.listError, listFetchNow = _c.listFetchNow, listLoading = _c.listLoading, updateError = _c.updateError, updateFetchNow = _c.updateFetchNow, updateLoading = _c.updateLoading;
379
+ // ---------------------------------------------------------------------------
380
+ // Effects
381
+ // ---------------------------------------------------------------------------
382
+ (0, react_1.useEffect)(function () {
383
+ listFetchNow();
384
+ // eslint-disable-next-line
385
+ }, [debouncedQuery, state.currentPage, state.pageLimit]);
386
+ (0, react_1.useEffect)(function () {
387
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
388
+ var data;
389
+ return __generator(this, function (_a) {
390
+ switch (_a.label) {
391
+ case 0: return [4 /*yield*/, (0, util_functions_1.fetchData)({
392
+ url: constants_1.QUOTE_API_ROUTES.PRODUCTS,
393
+ method: util_functions_1.API_METHODS.POST,
394
+ body: JSON.stringify({
395
+ searchQuery: debouncedProductList,
396
+ pageLimit: 100,
397
+ currentPage: 1,
398
+ }),
399
+ })];
400
+ case 1:
401
+ data = (_a.sent()).data;
402
+ if (data === null || data === void 0 ? void 0 : data.items) {
403
+ dispatch({
404
+ type: actions_1.QUOTE_ACTION_TYPES.SET_PRODUCTS_LIST,
405
+ payload: { list: data.items },
406
+ });
407
+ }
408
+ return [2 /*return*/];
409
+ }
410
+ });
411
+ }); })();
412
+ }, [debouncedProductList]);
413
+ (0, react_1.useEffect)(function () {
414
+ if (state.drawer === types_1.QUOTE_DRAWER.QUOTE_CUSTOMER_FORM_DRAWER &&
415
+ debouncedCustomer) {
416
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
417
+ var data;
418
+ return __generator(this, function (_a) {
419
+ switch (_a.label) {
420
+ case 0: return [4 /*yield*/, (0, util_functions_1.fetchData)({
421
+ url: constants_1.QUOTE_API_ROUTES.CUSTOMER_BY_PHONE,
422
+ method: util_functions_1.API_METHODS.POST,
423
+ body: JSON.stringify({
424
+ phone: debouncedCustomer,
425
+ }),
426
+ })];
427
+ case 1:
428
+ data = (_a.sent()).data;
429
+ if (data) {
430
+ dispatch({
431
+ type: actions_1.QUOTE_ACTION_TYPES.SET_CUSTOMER,
432
+ payload: { customer: __assign({}, data), customerId: data.id },
433
+ });
434
+ }
435
+ return [2 /*return*/];
436
+ }
437
+ });
438
+ }); })();
439
+ }
440
+ }, [debouncedCustomer, state.drawer]);
441
+ (0, react_1.useEffect)(function () {
442
+ if (state.drawer === types_1.QUOTE_DRAWER.QUOTE_COMPANY_FORM_DRAWER &&
443
+ debouncedCompanyList) {
444
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
445
+ var data;
446
+ return __generator(this, function (_a) {
447
+ switch (_a.label) {
448
+ case 0: return [4 /*yield*/, (0, util_functions_1.fetchData)({
449
+ url: constants_1.QUOTE_API_ROUTES.COMPANIES,
450
+ method: util_functions_1.API_METHODS.POST,
451
+ body: JSON.stringify({
452
+ searchQuery: debouncedCompanyList,
453
+ pageLimit: 100,
454
+ currentPage: 1,
455
+ }),
456
+ })];
457
+ case 1:
458
+ data = (_a.sent()).data;
459
+ if (data === null || data === void 0 ? void 0 : data.items) {
460
+ dispatch({
461
+ type: actions_1.QUOTE_ACTION_TYPES.SET_COMPANIES_LIST,
462
+ payload: { companiesList: data.items },
463
+ });
464
+ }
465
+ return [2 /*return*/];
466
+ }
467
+ });
468
+ }); })();
469
+ }
470
+ }, [debouncedCompanyList, state.drawer]);
471
+ (0, react_1.useEffect)(function () {
472
+ (function () { return __awaiter(void 0, void 0, void 0, function () {
473
+ var data;
474
+ return __generator(this, function (_a) {
475
+ switch (_a.label) {
476
+ case 0:
477
+ if (!debouncedTaxList) return [3 /*break*/, 2];
478
+ return [4 /*yield*/, (0, util_functions_1.fetchData)({
479
+ url: constants_1.QUOTE_API_ROUTES.TAXES,
480
+ method: util_functions_1.API_METHODS.POST,
481
+ body: JSON.stringify({
482
+ searchQuery: debouncedTaxList,
483
+ pageLimit: 100,
484
+ currentPage: 1,
485
+ }),
486
+ })];
487
+ case 1:
488
+ data = (_a.sent()).data;
489
+ if (data.items) {
490
+ dispatch({
491
+ type: actions_1.QUOTE_ACTION_TYPES.SET_TAXES,
492
+ payload: { taxes: data.items },
493
+ });
494
+ }
495
+ _a.label = 2;
496
+ case 2: return [2 /*return*/];
497
+ }
498
+ });
499
+ }); })();
500
+ }, [debouncedTaxList]);
501
+ (0, react_1.useEffect)(function () {
502
+ var _a = (0, calculate_total_1.calculateTotal)(state.subTotal, state.taxRate, state.discountUnit, state.discount || "0"), afterDiscount = _a.afterDiscount, tax = _a.tax, total = _a.total;
503
+ dispatch({
504
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
505
+ payload: {
506
+ key: "total",
507
+ value: total,
508
+ },
509
+ });
510
+ dispatch({
511
+ type: actions_1.QUOTE_ACTION_TYPES.SET_TAX,
512
+ payload: { tax: tax },
513
+ });
514
+ dispatch({
515
+ type: actions_1.QUOTE_ACTION_TYPES.SET_AFTER_DISCOUNT,
516
+ payload: { afterDiscount: String(afterDiscount) },
517
+ });
518
+ }, [state.discountUnit, state.discount, state.subTotal, state.taxRate]);
519
+ // ---------------------------------------------------------------------------
520
+ // Item Management Handlers
521
+ // ---------------------------------------------------------------------------
522
+ var handleAddItemService = (0, react_1.useCallback)(function () {
523
+ var newItem = {
524
+ mode: "Create",
525
+ name: "",
526
+ description: "",
527
+ quantity: "1",
528
+ price: "",
529
+ rowTotal: "",
530
+ };
531
+ dispatch({
532
+ type: actions_1.QUOTE_ACTION_TYPES.ADD_ITEM_SERVICE,
533
+ payload: { servicesList: __spreadArray(__spreadArray([], state.servicesList, true), [newItem], false) },
534
+ });
535
+ }, [state.servicesList]);
536
+ var handleAddItemProduct = (0, react_1.useCallback)(function () {
537
+ var newItem = {
538
+ id: "",
539
+ mode: "Create",
540
+ price: "",
541
+ quantity: "1",
542
+ rowTotal: "",
543
+ };
544
+ dispatch({
545
+ type: actions_1.QUOTE_ACTION_TYPES.ADD_ITEM_PRODUCT,
546
+ payload: { productsList: __spreadArray(__spreadArray([], state.productsList, true), [newItem], false) },
547
+ });
548
+ }, [state.productsList]);
549
+ // ---------------------------------------------------------------------------
550
+ // Drawer & Modal Handlers
551
+ // ---------------------------------------------------------------------------
552
+ var handleCreate = (0, react_1.useCallback)(function (text) {
553
+ dispatch({
554
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
555
+ payload: { key: "ref", value: (0, util_functions_1.generateRef)({ refLength: 5 }) },
556
+ });
557
+ if (text === "company") {
558
+ dispatch({
559
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
560
+ payload: { drawer: types_1.QUOTE_DRAWER.QUOTE_COMPANY_FORM_DRAWER },
561
+ });
562
+ }
563
+ if (text === "customer") {
564
+ dispatch({
565
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
566
+ payload: { drawer: types_1.QUOTE_DRAWER.QUOTE_CUSTOMER_FORM_DRAWER },
567
+ });
568
+ }
569
+ }, []);
570
+ // ---------------------------------------------------------------------------
571
+ // CRUD Operation Handlers
572
+ // ---------------------------------------------------------------------------
573
+ var handleEdit = (0, react_1.useCallback)(function (id) {
574
+ byIdFetchNow(undefined, {
575
+ body: JSON.stringify({
576
+ id: id,
577
+ includeCompany: true,
578
+ includeCustomer: true,
579
+ includePayments: true,
580
+ includeProducts: true,
581
+ includeServices: true,
582
+ }),
583
+ });
584
+ // eslint-disable-next-line react-hooks/exhaustive-deps
585
+ }, []);
586
+ var handleDelete = (0, react_1.useCallback)(function (id) {
587
+ deleteFetchNow === null || deleteFetchNow === void 0 ? void 0 : deleteFetchNow(undefined, {
588
+ body: JSON.stringify({ id: id }),
589
+ });
590
+ // eslint-disable-next-line react-hooks/exhaustive-deps
591
+ }, []);
592
+ // ---------------------------------------------------------------------------
593
+ // Form Submission Handler
594
+ // ---------------------------------------------------------------------------
595
+ var handleSubmit = (0, react_1.useCallback)(function () {
596
+ if (!state.servicesList[0].name && !state.productsList[0].id) {
597
+ dispatch({
598
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
599
+ payload: { disableSaveButton: true },
600
+ });
601
+ return;
602
+ }
603
+ dispatch({
604
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
605
+ payload: { disableSaveButton: true },
606
+ });
607
+ (0, util_functions_1.validateForm)({
608
+ params: __assign(__assign({}, updateParams), { currency: updateParams.currency || defaultCurrency.code, taxRate: updateParams.taxRate || defaultTax.taxRate }),
609
+ schema: validate_1.formValid,
610
+ successCallback: function () {
611
+ updateFetchNow(undefined, {
612
+ body: JSON.stringify(__assign(__assign({}, updateParams), { products: state.productsList.filter(function (item) { return item.id; }), services: state.servicesList.filter(function (item) { return item.name; }), currency: updateParams.currency || defaultCurrency.code, taxRate: updateParams.taxRate || defaultTax.taxRate })),
613
+ });
614
+ },
615
+ errorCallback: function (e) {
616
+ dispatch({
617
+ type: actions_1.QUOTE_ACTION_TYPES.SET_ERRORS,
618
+ payload: { errors: e },
619
+ });
620
+ },
621
+ });
622
+ }, [
623
+ updateFetchNow,
624
+ updateParams,
625
+ defaultCurrency,
626
+ defaultTax,
627
+ state.productsList,
628
+ state.servicesList,
629
+ ]);
630
+ // ---------------------------------------------------------------------------
631
+ // Form Change Handlers
632
+ // ---------------------------------------------------------------------------
633
+ var handleChange = (0, react_1.useCallback)(function (key, value) {
634
+ if (key === "companyQuery") {
635
+ dispatch({
636
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
637
+ payload: { key: key, value: value },
638
+ });
639
+ return;
640
+ }
641
+ dispatch({
642
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
643
+ payload: { disableSaveButton: false },
644
+ });
645
+ dispatch({
646
+ type: actions_1.QUOTE_ACTION_TYPES.RESET_ERRORS,
647
+ });
648
+ }, []);
649
+ var handleItemChangeServices = (0, react_1.useCallback)(function (_a) {
650
+ var _b;
651
+ var index = _a.index, key = _a.key, value = _a.value;
652
+ dispatch({
653
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
654
+ payload: { disableSaveButton: false },
655
+ });
656
+ var updatedItems = __spreadArray([], state.servicesList, true);
657
+ updatedItems[index] = __assign(__assign({}, updatedItems[index]), (_b = {}, _b[key] = value, _b.mode = updatedItems[index].mode === "Create" ? "Create" : "Edit", _b));
658
+ var quantity = parseFloat(updatedItems[index].quantity) || 0;
659
+ var price = parseFloat(updatedItems[index].price) || 0;
660
+ var rowTotal = (quantity * price).toFixed(2);
661
+ updatedItems[index].rowTotal = rowTotal;
662
+ var allProducts = state.productsList;
663
+ var subtotal = (0, calculate_subtotal_1.calculateSubtotal)(updatedItems, allProducts);
664
+ dispatch({
665
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
666
+ payload: { key: "subTotal", value: subtotal },
667
+ });
668
+ dispatch({
669
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
670
+ payload: { key: "servicesList", value: updatedItems },
671
+ });
672
+ }, [state.productsList, state.servicesList]);
673
+ var handleItemChangeProducts = (0, react_1.useCallback)(function (_a) {
674
+ var _b, _c, _d;
675
+ var _e;
676
+ var index = _a.index, key = _a.key, value = _a.value;
677
+ dispatch({
678
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
679
+ payload: { disableSaveButton: false },
680
+ });
681
+ var updatedItems = __spreadArray([], state.productsList, true);
682
+ if (key === "id" && typeof value === "string") {
683
+ var matchingProduct = (_e = state.getProducts) === null || _e === void 0 ? void 0 : _e.find(function (product) { return product.id === value; });
684
+ if (matchingProduct) {
685
+ var quantity = parseFloat(String(updatedItems[index].quantity)) || 0;
686
+ var rowTotal = (quantity * parseFloat(matchingProduct.salePrice)).toFixed(2);
687
+ updatedItems[index] = __assign(__assign({}, updatedItems[index]), (_b = {}, _b[key] = value, _b.price = matchingProduct.salePrice, _b.mode = updatedItems[index].mode === "Create" ? "Create" : "Edit", _b.rowTotal = rowTotal, _b));
688
+ var allServices = state.servicesList;
689
+ var subtotal = (0, calculate_subtotal_1.calculateSubtotal)(allServices, updatedItems);
690
+ dispatch({
691
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
692
+ payload: { key: "subTotal", value: subtotal },
693
+ });
694
+ }
695
+ else {
696
+ updatedItems[index] = __assign(__assign({}, updatedItems[index]), (_c = {}, _c[key] = value, _c.mode = updatedItems[index].mode === "Create" ? "Create" : "Edit", _c));
697
+ }
698
+ }
699
+ else {
700
+ updatedItems[index] = __assign(__assign({}, updatedItems[index]), (_d = {}, _d[key] = value, _d.mode = updatedItems[index].mode === "Create" ? "Create" : "Edit", _d));
701
+ var quantity = parseFloat(String(updatedItems[index].quantity)) || 0;
702
+ var price = parseFloat(updatedItems[index].price) || 0;
703
+ var rowTotal = (quantity * price).toFixed(2);
704
+ updatedItems[index] = __assign(__assign({}, updatedItems[index]), { rowTotal: rowTotal });
705
+ var allServices = state.servicesList;
706
+ var subtotal = (0, calculate_subtotal_1.calculateSubtotal)(allServices, updatedItems);
707
+ dispatch({
708
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
709
+ payload: { key: "subTotal", value: subtotal },
710
+ });
711
+ }
712
+ dispatch({
713
+ type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
714
+ payload: { key: "productsList", value: updatedItems },
715
+ });
716
+ }, [state.servicesList, state.productsList, state.getProducts]);
717
+ var handleNextClick = function () {
718
+ dispatch({
719
+ type: actions_1.QUOTE_ACTION_TYPES.SET_CURRENT_PAGE,
720
+ payload: { currentPage: state.currentPage + 1 },
721
+ });
722
+ };
723
+ var handlePreviousClick = function () {
724
+ dispatch({
725
+ type: actions_1.QUOTE_ACTION_TYPES.SET_CURRENT_PAGE,
726
+ payload: { currentPage: state.currentPage - 1 },
727
+ });
728
+ };
729
+ var handlePageLimit = function (k, value) {
730
+ var val = __assign({}, value);
731
+ dispatch({
732
+ type: actions_1.QUOTE_ACTION_TYPES.SET_PAGE_LIMIT,
733
+ payload: { pageLimit: Number(val.option) },
734
+ });
735
+ };
736
+ var searchOnChange = function (k, v) {
737
+ dispatch({
738
+ type: actions_1.QUOTE_ACTION_TYPES.SET_SEARCH_QUERY,
739
+ payload: { searchQuery: v },
740
+ });
741
+ };
742
+ var clearSearch = function () {
743
+ dispatch({
744
+ type: actions_1.QUOTE_ACTION_TYPES.SET_SEARCH_QUERY,
745
+ payload: { searchQuery: "" },
746
+ });
747
+ };
748
+ var closeDrawer = function () {
749
+ dispatch({
750
+ type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
751
+ payload: { drawer: null },
752
+ });
753
+ dispatch({
754
+ type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM,
755
+ });
756
+ dispatch({
757
+ type: actions_1.QUOTE_ACTION_TYPES.RESET_ERRORS,
758
+ });
759
+ };
760
+ var handleDeleteServiceRow = function (i) {
761
+ if (state.servicesList.length > 1) {
762
+ var res = state.servicesList.splice(i, 1);
763
+ dispatch({
764
+ type: actions_1.QUOTE_ACTION_TYPES.DELETE_ITEM_SERVICE,
765
+ payload: { servicesList: __spreadArray([], res, true) },
766
+ });
767
+ }
768
+ };
769
+ var handleDeleteProductRow = function (i) {
770
+ if (state.productsList.length > 1) {
771
+ var res = state.productsList.splice(i, 1);
772
+ dispatch({
773
+ type: actions_1.QUOTE_ACTION_TYPES.DELETE_ITEM_PRODUCT,
774
+ payload: { productsList: __spreadArray([], res, true) },
775
+ });
776
+ }
777
+ };
778
+ var headerActions = [
779
+ {
780
+ enabled: true,
781
+ handleOnClick: function () { return handleCreate("company"); },
782
+ label: "Quote for Company",
783
+ order: 1,
784
+ },
785
+ {
786
+ enabled: true,
787
+ handleOnClick: function () { return handleCreate("customer"); },
788
+ label: "Quote for Customer",
789
+ order: 2,
790
+ },
791
+ ];
792
+ var rowActions = [
793
+ {
794
+ enabled: true,
795
+ handleAction: function (id) { return handleEdit(id); },
796
+ label: "Edit",
797
+ order: 1,
798
+ },
799
+ {
800
+ enabled: true,
801
+ handleAction: function (id) { return handleDelete(id); },
802
+ label: "Delete",
803
+ order: 2,
804
+ },
805
+ ];
806
+ return __assign(__assign({}, state), { byIdError: byIdError, byIdLoading: byIdLoading, clearSearch: clearSearch, closeDrawer: closeDrawer, deleteError: deleteError, deleteLoading: deleteLoading, dispatch: dispatch, handleAddItemProduct: handleAddItemProduct, handleAddItemService: handleAddItemService, handleChange: handleChange, handleDeleteProductRow: handleDeleteProductRow, handleDeleteServiceRow: handleDeleteServiceRow, handleItemChangeProducts: handleItemChangeProducts, handleItemChangeServices: handleItemChangeServices, handleNextClick: handleNextClick, handlePageLimit: handlePageLimit, handlePreviousClick: handlePreviousClick, handleSubmit: handleSubmit, headerActions: headerActions, listError: listError, listFetchNow: listFetchNow, listLoading: listLoading, rowActions: rowActions, searchOnChange: searchOnChange, updateError: updateError, updateLoading: updateLoading });
807
+ };
808
+ exports.QuoteStateContext = (0, react_1.createContext)(__assign(__assign({}, reducer_1.initialQuoteState), { byIdError: undefined, byIdLoading: false, clearSearch: function () { return void 0; }, closeDrawer: function () { return void 0; }, deleteError: undefined, deleteLoading: false, dispatch: function () { return void 0; }, handleAddItemProduct: function () { return void 0; }, handleAddItemService: function () { return void 0; }, handleChange: function () { return void 0; }, handleDeleteProductRow: function () { return void 0; }, handleDeleteServiceRow: function () { return void 0; }, handleItemChangeProducts: function () { return void 0; }, handleItemChangeServices: function () { return void 0; }, handleNextClick: function () { return void 0; }, handlePageLimit: function () { return void 0; }, handlePreviousClick: function () { return void 0; }, handleSubmit: function () { return void 0; }, headerActions: [], listError: undefined, listFetchNow: function () { return void 0; }, listLoading: false, rowActions: [], searchOnChange: function () { return void 0; }, updateError: undefined, updateLoading: false }));
809
+ var QuoteStateContextProvider = function (_a) {
810
+ var children = _a.children;
811
+ var state = useQuoteState();
812
+ return (react_1.default.createElement(exports.QuoteStateContext.Provider, { value: state }, children));
813
+ };
814
+ exports.QuoteStateContextProvider = QuoteStateContextProvider;
815
+ var useQuoteStateContext = function () {
816
+ var state = (0, react_1.useContext)(exports.QuoteStateContext);
817
+ if (state === undefined) {
818
+ throw new Error("useQuoteStateContext must be used within a QuoteContextProvider");
819
+ }
820
+ return state;
821
+ };
822
+ exports.useQuoteStateContext = useQuoteStateContext;