@appcorp/stellar-solutions-invoice-module 0.1.60 → 0.1.62

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.
@@ -17,57 +17,57 @@ var button_1 = require("@appcorp/shadcn/components/button");
17
17
  var input_1 = require("@appcorp/shadcn/components/input");
18
18
  var context_1 = require("./context");
19
19
  var ServicesSection = function () {
20
- var t = (0, next_intl_1.useTranslations)("invoicePage");
20
+ var t = (0, next_intl_1.useTranslations)("invoice");
21
21
  var _a = (0, context_1.useInvoiceStateContext)(), errors = _a.errors, handleDeleteServiceRow = _a.handleDeleteServiceRow, handleItemChangeServices = _a.handleItemChangeServices, servicesList = _a.servicesList;
22
22
  if (!servicesList || servicesList.length === 0) {
23
23
  return null;
24
24
  }
25
25
  return (react_1.default.createElement("div", { className: "flex flex-col gap-4" },
26
- react_1.default.createElement("h3", { className: "text-lg font-semibold border-b pb-2" }, t("servicesSectionTitle")),
26
+ react_1.default.createElement("h3", { className: "text-lg font-semibold border-b pb-2" }, t("serviceFormSectionTitle")),
27
27
  react_1.default.createElement("div", { className: "flex flex-col gap-4" }, servicesList.map(function (row, index) { return (react_1.default.createElement("div", { key: index, className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-[1fr_1fr_0.75fr_0.75fr_0.75fr_auto] gap-4 items-end p-4 border rounded-lg" },
28
28
  react_1.default.createElement("div", { className: "space-y-2" },
29
- react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-name")], id: "service-name-".concat(index), label: t("formLabelServiceName"), onChange: function (e) {
29
+ react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-name")], id: "service-name-".concat(index), label: t("serviceFormLabelServiceName"), onChange: function (e) {
30
30
  return handleItemChangeServices({
31
31
  index: index,
32
32
  key: "name",
33
33
  value: e.target.value,
34
34
  });
35
- }, placeholder: t("formPlaceholderServiceName"), required: true, type: "text", value: servicesList[index].name || "" })),
35
+ }, placeholder: t("serviceFormPlaceholderServiceName"), required: true, type: "text", value: servicesList[index].name || "", info: t("serviceFormInfoServiceName") })),
36
36
  react_1.default.createElement("div", { className: "space-y-2" },
37
- react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-description")], id: "service-description-".concat(index), label: t("formLabelServiceDescription"), onChange: function (e) {
37
+ react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-description")], id: "service-description-".concat(index), label: t("serviceFormLabelServiceDescription"), onChange: function (e) {
38
38
  return handleItemChangeServices({
39
39
  index: index,
40
40
  key: "description",
41
41
  value: e.target.value,
42
42
  });
43
- }, placeholder: t("formPlaceholderServiceDescription"), type: "text", value: servicesList[index].description || "" })),
43
+ }, placeholder: t("serviceFormPlaceholderServiceDescription"), type: "text", value: servicesList[index].description || "", info: t("serviceFormInfoServiceDescription") })),
44
44
  react_1.default.createElement("div", { className: "space-y-2" },
45
- react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-quantity")], id: "service-quantity-".concat(index), label: t("formLabelQuantity"), onChange: function (e) {
45
+ react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-quantity")], id: "service-quantity-".concat(index), label: t("serviceFormLabelServiceQuantity"), onChange: function (e) {
46
46
  return handleItemChangeServices({
47
47
  index: index,
48
48
  key: "quantity",
49
49
  value: e.target.value,
50
50
  });
51
- }, placeholder: "1", required: true, type: "number", value: servicesList[index].quantity || "" })),
51
+ }, placeholder: t("serviceFormPlaceholderServiceQuantity"), required: true, type: "number", value: servicesList[index].quantity || "", info: t("serviceFormInfoServiceQuantity") })),
52
52
  react_1.default.createElement("div", { className: "space-y-2" },
53
- react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-price")], id: "service-price-".concat(index), label: t("formLabelPrice"), onChange: function (e) {
53
+ react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-price")], id: "service-price-".concat(index), label: t("serviceFormLabelServicePrice"), onChange: function (e) {
54
54
  return handleItemChangeServices({
55
55
  index: index,
56
56
  key: "price",
57
57
  value: e.target.value,
58
58
  });
59
- }, placeholder: "0.00", required: true, type: "number", value: servicesList[index].price || "" })),
59
+ }, placeholder: t("serviceFormPlaceholderServicePrice"), required: true, type: "number", value: servicesList[index].price || "", info: t("serviceFormInfoServicePrice") })),
60
60
  react_1.default.createElement("div", { className: "space-y-2" },
61
- react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-rowTotal")], id: "service-rowTotal-".concat(index), label: t("formLabelRowTotal"), onChange: function (e) {
61
+ react_1.default.createElement(input_1.Input, { error: errors["servicesList-".concat(index, "-rowTotal")], id: "service-rowTotal-".concat(index), label: t("serviceFormLabelServiceRowTotal"), onChange: function (e) {
62
62
  return handleItemChangeServices({
63
63
  index: index,
64
64
  key: "rowTotal",
65
65
  value: e.target.value,
66
66
  });
67
- }, placeholder: "0.00", readOnly: true, required: true, type: "number", value: servicesList[index].rowTotal || "" })),
67
+ }, placeholder: t("serviceFormPlaceholderServiceRowTotal"), readOnly: true, required: true, type: "number", value: servicesList[index].rowTotal || "", info: t("serviceFormInfoServiceRowTotal") })),
68
68
  react_1.default.createElement("div", { className: "flex items-end h-full" },
69
69
  react_1.default.createElement(button_1.Button, { onClick: function () { return handleDeleteServiceRow(index); }, size: "icon", type: "button", variant: "ghost" },
70
70
  react_1.default.createElement(lucide_react_1.Trash2, { className: "h-4 w-4" }),
71
- react_1.default.createElement("span", { className: "sr-only" }, t("buttonDeleteService")))))); }))));
71
+ react_1.default.createElement("span", { className: "sr-only" }, t("serviceFormButtonDeleteService")))))); }))));
72
72
  };
73
73
  exports.ServicesSection = ServicesSection;
@@ -151,7 +151,6 @@ var usePaymentState = function () {
151
151
  }, [theme]);
152
152
  var listCallback = (0, react_1.useCallback)(function (_a) {
153
153
  var data = _a.data, error = _a.error;
154
- console.log("Payment List Callback Data:", data);
155
154
  if (error) {
156
155
  showErrorToast(t("messagesNetworkError"));
157
156
  }
@@ -21,16 +21,14 @@ var next_intl_1 = require("next-intl");
21
21
  var input_1 = require("@appcorp/shadcn/components/input");
22
22
  var textarea_1 = require("@appcorp/shadcn/components/textarea");
23
23
  var combobox_1 = require("@appcorp/shadcn/components/combobox");
24
+ var enhanced_dropzone_1 = require("@appcorp/shadcn/components/enhanced-dropzone");
24
25
  var context_1 = require("./context");
25
- var context_2 = require("@appcorp/stellar-solutions-modules/global-modules/preferences/context");
26
- var context_3 = require("@appcorp/stellar-solutions-modules/global-modules/payment-mode/context");
27
- var types_1 = require("./types");
26
+ var context_2 = require("@appcorp/stellar-solutions-modules/global-modules/payment-mode/context");
28
27
  var PaymentForm = function (_a) {
29
28
  var isRTL = _a.isRTL;
30
29
  var t = (0, next_intl_1.useTranslations)("payment");
31
30
  var _b = (0, context_1.usePaymentStateContext)(), amount = _b.amount, attachment = _b.attachment, balance = _b.balance, currency = _b.currency, date = _b.date, description = _b.description, errors = _b.errors, handleChange = _b.handleChange, paymentModeId = _b.paymentModeId, paymentType = _b.paymentType, ref = _b.ref;
32
- var currencies = (0, context_2.usePreferenceStateContext)().currencies;
33
- var _c = (0, context_3.usePaymentModeStateContext)(), paymentModes = _c.paymentModes, paymentModesLoading = _c.listLoading;
31
+ var _c = (0, context_2.usePaymentModeStateContext)(), paymentModes = _c.paymentModes, paymentModesLoading = _c.listLoading;
34
32
  // Helper function to translate validation error keys
35
33
  var getTranslatedError = function (key) {
36
34
  if (!errors[key])
@@ -54,27 +52,15 @@ var PaymentForm = function (_a) {
54
52
  react_1.default.createElement("div", { className: "space-y-2" },
55
53
  react_1.default.createElement(input_1.Input, { id: "amount", type: "text", label: t("formLabelAmount"), value: amount || "", onChange: function (e) { return handleChange("amount", e.target.value); }, placeholder: t("formPlaceholderAmount"), info: t("formInfoAmount"), error: getTranslatedError("amount"), required: true })),
56
54
  react_1.default.createElement("div", { className: "space-y-2" },
57
- react_1.default.createElement(input_1.Input, { id: "balance", type: "text", label: t("formLabelBalance"), value: balance || "", onChange: function (e) { return handleChange("balance", e.target.value); }, placeholder: t("formPlaceholderBalance"), info: t("formInfoBalance"), error: getTranslatedError("balance") })),
55
+ react_1.default.createElement(input_1.Input, { id: "balance", type: "text", label: t("formLabelBalance"), value: balance || "", onChange: function (e) { return handleChange("balance", e.target.value); }, placeholder: t("formPlaceholderBalance"), info: t("formInfoBalance"), error: getTranslatedError("balance"), required: true })),
58
56
  react_1.default.createElement("div", { className: "space-y-2" },
59
- react_1.default.createElement(combobox_1.Combobox, { id: "paymentType", label: t("formLabelPaymentType"), value: paymentType || types_1.PAYMENT_TYPE.FULL_AMOUNT, onValueChange: function (value) { return handleChange("paymentType", value); }, options: [
60
- {
61
- label: t("paymentTypeFullAmount"),
62
- value: types_1.PAYMENT_TYPE.FULL_AMOUNT,
63
- },
64
- {
65
- label: t("paymentTypePartialAmount"),
66
- value: types_1.PAYMENT_TYPE.PARTIAL_AMOUNT,
67
- },
68
- ], placeholder: t("formPlaceholderPaymentType"), info: t("formInfoPaymentType"), error: getTranslatedError("paymentType"), required: true })),
57
+ react_1.default.createElement(input_1.Input, { id: "paymentType", type: "text", label: t("formLabelPaymentType"), value: paymentType || "", readOnly: true, placeholder: t("formPlaceholderPaymentType"), info: t("formInfoPaymentType"), error: getTranslatedError("paymentType"), required: true })),
69
58
  react_1.default.createElement("div", { className: "space-y-2" },
70
- react_1.default.createElement(combobox_1.Combobox, { id: "currency", label: t("formLabelCurrency"), value: currency || "", onValueChange: function (value) { return handleChange("currency", value); }, options: (currencies || []).map(function (c) { return ({
71
- label: "".concat(c.code, " - ").concat(c.label),
72
- value: c.code,
73
- }); }), placeholder: t("formPlaceholderCurrency"), info: t("formInfoCurrency"), error: getTranslatedError("currency"), required: true })),
59
+ react_1.default.createElement(input_1.Input, { id: "currency", type: "text", label: t("formLabelCurrency"), value: currency || "", readOnly: true, placeholder: t("formPlaceholderCurrency"), info: t("formInfoCurrency"), error: getTranslatedError("currency"), required: true })),
74
60
  react_1.default.createElement("div", { className: "space-y-2" },
75
61
  react_1.default.createElement(combobox_1.Combobox, { id: "paymentModeId", label: t("formLabelPaymentMode"), value: paymentModeId || "", onValueChange: function (value) { return handleChange("paymentModeId", value); }, loading: paymentModesLoading, options: (paymentModes || [])
76
- .slice()
77
- .filter(function (mode) { return mode.enabled; })
62
+ // .slice()
63
+ // .filter((mode) => mode.enabled)
78
64
  .sort(function (a, b) { return a.label.localeCompare(b.label); })
79
65
  .map(function (mode) { return ({
80
66
  label: mode.label,
@@ -83,7 +69,12 @@ var PaymentForm = function (_a) {
83
69
  react_1.default.createElement("div", { className: "space-y-2" },
84
70
  react_1.default.createElement(input_1.Input, { id: "ref", type: "text", label: t("formLabelRef"), value: ref || "", onChange: function (e) { return handleChange("ref", e.target.value); }, placeholder: t("formPlaceholderRef"), info: t("formInfoRef"), error: getTranslatedError("ref") })),
85
71
  react_1.default.createElement("div", { className: "space-y-2" },
86
- react_1.default.createElement(input_1.Input, { id: "attachment", type: "text", label: t("formLabelAttachment"), value: attachment || "", onChange: function (e) { return handleChange("attachment", e.target.value); }, placeholder: t("formPlaceholderAttachment"), info: t("formInfoAttachment"), error: getTranslatedError("attachment") })),
72
+ react_1.default.createElement(enhanced_dropzone_1.EnhancedDropzone, { id: "attachment", label: t("formLabelAttachment"), value: attachment ? [attachment] : [], onChange: function (files) {
73
+ if (files.length > 0) {
74
+ // Handle file upload - you may want to upload to server and get URL
75
+ handleChange("attachment", files[0].name);
76
+ }
77
+ }, onRemoveRemote: function () { return handleChange("attachment", ""); }, info: t("formInfoAttachment"), error: getTranslatedError("attachment"), maxFiles: 1 })),
87
78
  react_1.default.createElement("div", { className: "space-y-2" },
88
79
  react_1.default.createElement(textarea_1.Textarea, { id: "description", label: t("formLabelDescription"), value: description || "", onChange: function (e) { return handleChange("description", e.target.value); }, placeholder: t("formPlaceholderDescription"), info: t("formInfoDescription"), error: getTranslatedError("description"), rows: 3 })))));
89
80
  };
@@ -16,16 +16,16 @@ var lucide_react_1 = require("lucide-react");
16
16
  var button_1 = require("@appcorp/shadcn/components/button");
17
17
  var context_1 = require("./context");
18
18
  var AddServiceProductSection = function () {
19
- var t = (0, next_intl_1.useTranslations)("invoicePage");
19
+ var t = (0, next_intl_1.useTranslations)("quote");
20
20
  var _a = (0, context_1.useQuoteStateContext)(), handleAddItemProduct = _a.handleAddItemProduct, handleAddItemService = _a.handleAddItemService;
21
21
  return (react_1.default.createElement("div", { className: "flex items-center justify-center gap-3 rounded-lg border-2 border-dashed border-muted-foreground/25 p-6 hover:border-muted-foreground/50 transition-colors" },
22
- react_1.default.createElement("span", { className: "text-sm text-muted-foreground" }, t("addItemPrompt")),
22
+ react_1.default.createElement("span", { className: "text-sm text-muted-foreground" }, t("addItem")),
23
23
  react_1.default.createElement(button_1.Button, { onClick: handleAddItemService, size: "sm", type: "button", variant: "outline" },
24
24
  react_1.default.createElement(lucide_react_1.Plus, { className: "h-4 w-4 mr-2" }),
25
- t("buttonAddService")),
25
+ t("addItemService")),
26
26
  react_1.default.createElement("span", { className: "text-sm text-muted-foreground" }, t("addItemOr")),
27
27
  react_1.default.createElement(button_1.Button, { onClick: handleAddItemProduct, size: "sm", type: "button", variant: "outline" },
28
28
  react_1.default.createElement(lucide_react_1.Plus, { className: "h-4 w-4 mr-2" }),
29
- t("buttonAddProduct"))));
29
+ t("addItemProduct"))));
30
30
  };
31
31
  exports.AddServiceProductSection = AddServiceProductSection;
@@ -50,7 +50,7 @@ var context_1 = require("@appcorp/stellar-solutions-modules/global-modules/prefe
50
50
  var actions_1 = require("./actions");
51
51
  var context_2 = require("./context");
52
52
  var CompanySection = function () {
53
- var t = (0, next_intl_1.useTranslations)("invoicePage");
53
+ var t = (0, next_intl_1.useTranslations)("quote");
54
54
  var currencies = (0, context_1.usePreferenceStateContext)().currencies;
55
55
  var _a = (0, context_2.useQuoteStateContext)(), companiesList = _a.companiesList, companyId = _a.companyId, currency = _a.currency, date = _a.date, dispatch = _a.dispatch, errors = _a.errors, expiryDate = _a.expiryDate, note = _a.note, ref = _a.ref;
56
56
  var handleInputChange = (0, react_1.useCallback)(function (key, value) {
@@ -107,19 +107,19 @@ var CompanySection = function () {
107
107
  name: curr.code,
108
108
  }); });
109
109
  return (react_1.default.createElement("div", { className: "flex flex-col gap-4" },
110
- react_1.default.createElement("h3", { className: "text-lg font-semibold border-b pb-2" }, t("companySectionTitle")),
110
+ react_1.default.createElement("h3", { className: "text-lg font-semibold border-b pb-2" }, t("companyFormSectionTitle")),
111
111
  react_1.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" },
112
112
  react_1.default.createElement("div", { className: "space-y-2" },
113
- react_1.default.createElement(combobox_1.CompanyCombobox, { companies: companiesList || [], error: errors.companyId, id: "companyId", label: t("formLabelCompany"), onSearchChange: handleCompanySearch, onValueChange: handleCompanyChange, placeholder: t("formPlaceholderCompany"), required: true, value: companyId || "" })),
113
+ react_1.default.createElement(combobox_1.CompanyCombobox, { companies: companiesList || [], error: errors.companyId, id: "companyId", info: t("companyFormInfoCompany"), label: t("companyFormLabelCompany"), onSearchChange: handleCompanySearch, onValueChange: handleCompanyChange, placeholder: t("companyFormPlaceholderCompany"), required: true, value: companyId || "" })),
114
114
  react_1.default.createElement("div", { className: "space-y-2" },
115
- react_1.default.createElement(input_1.Input, { error: errors.date, id: "date", label: t("formLabelDate"), onChange: function (e) { return handleInputChange("date", e.target.value); }, required: true, type: "date", value: date ? (0, date_fns_1.format)(new Date(date), "yyyy-MM-dd") : "" })),
115
+ react_1.default.createElement(input_1.Input, { error: errors.date, id: "date", info: t("companyFormInfoDate"), label: t("companyFormLabelDate"), onChange: function (e) { return handleInputChange("date", e.target.value); }, placeholder: t("companyFormPlaceholderDate"), required: true, type: "date", value: date ? (0, date_fns_1.format)(new Date(date), "yyyy-MM-dd") : "" })),
116
116
  react_1.default.createElement("div", { className: "space-y-2" },
117
- react_1.default.createElement(input_1.Input, { error: errors.expiryDate, id: "expiryDate", label: t("formLabelExpiryDate"), onChange: function (e) { return handleInputChange("expiryDate", e.target.value); }, required: true, type: "date", value: expiryDate ? (0, date_fns_1.format)(new Date(expiryDate), "yyyy-MM-dd") : "" })),
117
+ react_1.default.createElement(input_1.Input, { error: errors.expiryDate, id: "expiryDate", info: t("companyFormInfoExpiryDate"), label: t("companyFormLabelExpiryDate"), onChange: function (e) { return handleInputChange("expiryDate", e.target.value); }, placeholder: t("companyFormPlaceholderExpiryDate"), required: true, type: "date", value: expiryDate ? (0, date_fns_1.format)(new Date(expiryDate), "yyyy-MM-dd") : "" })),
118
118
  react_1.default.createElement("div", { className: "space-y-2" },
119
- react_1.default.createElement(combobox_1.CompanyCombobox, { companies: currencyOptions, error: errors.currency, id: "currency", label: t("formLabelCurrency"), onSearchChange: function () { }, onValueChange: handleCurrencyChange, placeholder: t("formPlaceholderCurrency"), required: true, value: currency || "" })),
119
+ react_1.default.createElement(combobox_1.CompanyCombobox, { companies: currencyOptions, error: errors.currency, id: "currency", info: t("companyFormInfoCurrency"), label: t("companyFormLabelCurrency"), onSearchChange: function () { }, onValueChange: handleCurrencyChange, placeholder: t("companyFormPlaceholderCurrency"), required: true, value: currency || "" })),
120
120
  react_1.default.createElement("div", { className: "space-y-2" },
121
- react_1.default.createElement(textarea_1.Textarea, { error: errors.note, id: "note", label: t("formLabelNote"), onChange: function (e) { return handleInputChange("note", e.target.value); }, placeholder: t("formPlaceholderNote"), rows: 3, value: note || "" })),
121
+ react_1.default.createElement(textarea_1.Textarea, { error: errors.note, id: "note", info: t("companyFormInfoNote"), label: t("companyFormLabelNote"), onChange: function (e) { return handleInputChange("note", e.target.value); }, placeholder: t("companyFormPlaceholderNote"), rows: 3, value: note || "" })),
122
122
  react_1.default.createElement("div", { className: "space-y-2" },
123
- react_1.default.createElement(input_1.Input, { error: errors.ref, id: "ref", label: t("formLabelRef"), onChange: function (e) { return handleInputChange("ref", e.target.value); }, readOnly: true, required: true, type: "text", value: ref || "" })))));
123
+ react_1.default.createElement(input_1.Input, { error: errors.ref, id: "ref", info: t("companyFormInfoReference"), label: t("companyFormLabelReference"), onChange: function (e) { return handleInputChange("ref", e.target.value); }, placeholder: t("companyFormPlaceholderReference"), readOnly: true, required: true, type: "text", value: ref || "" })))));
124
124
  };
125
125
  exports.CompanySection = CompanySection;
@@ -154,7 +154,7 @@ var useQuoteState = function () {
154
154
  // State & Core Hooks
155
155
  // ---------------------------------------------------------------------------
156
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");
157
+ var t = (0, next_intl_1.useTranslations)("quote");
158
158
  var theme = (0, next_themes_1.useTheme)().theme;
159
159
  var taxes = (0, context_1.useTaxStateContext)().taxes;
160
160
  var currencies = (0, context_2.usePreferenceStateContext)().currencies;
@@ -199,16 +199,16 @@ var useQuoteState = function () {
199
199
  })[0];
200
200
  }, [currencies]);
201
201
  // ---------------------------------------------------------------------------
202
- // API Parameters (Memoized)
202
+ // API PARAMETERS
203
203
  // ---------------------------------------------------------------------------
204
- var listParams = {
204
+ var listParams = (0, react_1.useMemo)(function () { return ({
205
205
  category: types_1.QUOTE_INVOICE_CATEGORY.QUOTE,
206
206
  currentPage: state.currentPage,
207
+ includeCompany: true,
208
+ includeCustomer: true,
207
209
  pageLimit: state.pageLimit,
208
210
  searchQuery: state.searchQuery,
209
- includeCustomer: true,
210
- includeCompany: true,
211
- };
211
+ }); }, [state.currentPage, state.pageLimit, state.searchQuery]);
212
212
  var updateParams = (0, react_1.useMemo)(function () {
213
213
  var _a, _b, _c, _d, _e, _f, _g, _h;
214
214
  return ({
@@ -247,19 +247,16 @@ var useQuoteState = function () {
247
247
  country: (_h = state.customer) === null || _h === void 0 ? void 0 : _h.country,
248
248
  });
249
249
  }, [state]);
250
- var byIdParams = {
251
- id: state.id,
252
- };
253
- var deleteParams = {
254
- id: state.id,
255
- };
250
+ var byIdParams = (0, react_1.useMemo)(function () { return ({ id: state.id }); }, [state.id]);
251
+ var deleteParams = (0, react_1.useMemo)(function () { return ({ id: state.id }); }, [state.id]);
256
252
  // ---------------------------------------------------------------------------
257
- // API Callbacks
253
+ // API CALLBACKS
258
254
  // ---------------------------------------------------------------------------
259
255
  var listCallback = (0, react_1.useCallback)(function (_a) {
260
256
  var data = _a.data, error = _a.error;
261
257
  if (error) {
262
- showErrorToast(t("networkError"));
258
+ showErrorToast(t("messagesNetworkError"));
259
+ return;
263
260
  }
264
261
  if (data === null || data === void 0 ? void 0 : data.items) {
265
262
  dispatch({
@@ -275,16 +272,15 @@ var useQuoteState = function () {
275
272
  var updateCallback = (0, react_1.useCallback)(function (_a) {
276
273
  var data = _a.data, error = _a.error;
277
274
  if (error) {
278
- showErrorToast(t("networkError"));
275
+ showErrorToast(t("messagesNetworkError"));
276
+ return;
279
277
  }
280
278
  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
- });
279
+ showSuccessToast(state.mode === "Edit"
280
+ ? t("messagesQuoteUpdated")
281
+ : t("messagesQuoteCreated"));
282
+ dispatch({ type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM });
283
+ dispatch({ type: actions_1.QUOTE_ACTION_TYPES.RESET_ERRORS });
288
284
  listFetchNow();
289
285
  dispatch({
290
286
  type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
@@ -298,7 +294,8 @@ var useQuoteState = function () {
298
294
  var _b, _c, _d, _e, _f;
299
295
  var data = _a.data, error = _a.error;
300
296
  if (error) {
301
- showErrorToast(t("invoiceFetchError"));
297
+ showErrorToast(t("messagesQuoteFetchError"));
298
+ return;
302
299
  }
303
300
  if (data) {
304
301
  var updatedServices = __spreadArray([], data === null || data === void 0 ? void 0 : data.services, true).map(function (item) {
@@ -345,13 +342,12 @@ var useQuoteState = function () {
345
342
  var deleteCallback = (0, react_1.useCallback)(function (_a) {
346
343
  var data = _a.data, error = _a.error;
347
344
  if (error) {
348
- showErrorToast(t("networkError"));
345
+ showErrorToast(t("messagesNetworkError"));
346
+ return;
349
347
  }
350
348
  if (data) {
351
- showSuccessToast(t("invoiceUpdated"));
352
- dispatch({
353
- type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM,
354
- });
349
+ showSuccessToast(t("messagesQuoteDeleted"));
350
+ dispatch({ type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM });
355
351
  listFetchNow();
356
352
  }
357
353
  },
@@ -552,7 +548,12 @@ var useQuoteState = function () {
552
548
  var handleCreate = (0, react_1.useCallback)(function (text) {
553
549
  dispatch({
554
550
  type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
555
- payload: { key: "ref", value: (0, util_functions_1.generateRef)({ refLength: 5 }) },
551
+ payload: {
552
+ key: "ref",
553
+ value: (0, util_functions_1.generateRef)({
554
+ refLength: Number(process.env.NEXT_PUBLIC_QUOTE_INVOICE_REF_LENGTH) || 5,
555
+ }),
556
+ },
556
557
  });
557
558
  if (text === "company") {
558
559
  dispatch({
@@ -733,56 +734,69 @@ var useQuoteState = function () {
733
734
  payload: { key: "productsList", value: updatedItems },
734
735
  });
735
736
  }, [state.servicesList, state.productsList, state.getProducts]);
736
- var handleNextClick = function () {
737
+ // ---------------------------------------------------------------------------
738
+ // PAGINATION HANDLERS
739
+ // ---------------------------------------------------------------------------
740
+ var handleNextClick = (0, react_1.useCallback)(function () {
737
741
  dispatch({
738
742
  type: actions_1.QUOTE_ACTION_TYPES.SET_CURRENT_PAGE,
739
743
  payload: { currentPage: state.currentPage + 1 },
740
744
  });
741
- };
742
- var handlePreviousClick = function () {
745
+ }, [state.currentPage]);
746
+ var handlePreviousClick = (0, react_1.useCallback)(function () {
743
747
  dispatch({
744
748
  type: actions_1.QUOTE_ACTION_TYPES.SET_CURRENT_PAGE,
745
749
  payload: { currentPage: state.currentPage - 1 },
746
750
  });
747
- };
748
- var handlePageLimit = function (k, value) {
751
+ }, [state.currentPage]);
752
+ var handlePageLimit = (0, react_1.useCallback)(function (k, value) {
749
753
  var val = __assign({}, value);
750
754
  dispatch({
751
755
  type: actions_1.QUOTE_ACTION_TYPES.SET_PAGE_LIMIT,
752
756
  payload: { pageLimit: Number(val.option) },
753
757
  });
754
- };
755
- var searchOnChange = function (k, v) {
758
+ // Reset to page 1 when page limit changes
759
+ dispatch({
760
+ type: actions_1.QUOTE_ACTION_TYPES.SET_CURRENT_PAGE,
761
+ payload: { currentPage: 1 },
762
+ });
763
+ }, []);
764
+ var searchOnChange = (0, react_1.useCallback)(function (k, v) {
756
765
  dispatch({
757
766
  type: actions_1.QUOTE_ACTION_TYPES.SET_SEARCH_QUERY,
758
767
  payload: { searchQuery: v },
759
768
  });
760
- };
761
- var clearSearch = function () {
769
+ }, []);
770
+ var clearSearch = (0, react_1.useCallback)(function () {
762
771
  dispatch({
763
772
  type: actions_1.QUOTE_ACTION_TYPES.SET_SEARCH_QUERY,
764
773
  payload: { searchQuery: "" },
765
774
  });
766
- };
767
- var handleTaxSearch = function (searchQuery) {
775
+ }, []);
776
+ // ---------------------------------------------------------------------------
777
+ // SEARCH HANDLERS
778
+ // ---------------------------------------------------------------------------
779
+ var handleTaxSearch = (0, react_1.useCallback)(function (searchQuery) {
768
780
  dispatch({
769
781
  type: actions_1.QUOTE_ACTION_TYPES.SET_INPUT_FIELD,
770
782
  payload: { key: "taxQuery", value: searchQuery },
771
783
  });
772
- };
773
- var closeDrawer = function () {
784
+ }, []);
785
+ // ---------------------------------------------------------------------------
786
+ // DRAWER & MODAL HANDLERS
787
+ // ---------------------------------------------------------------------------
788
+ var closeDrawer = (0, react_1.useCallback)(function () {
774
789
  dispatch({
775
790
  type: actions_1.QUOTE_ACTION_TYPES.SET_DRAWER,
776
791
  payload: { drawer: null },
777
792
  });
778
- dispatch({
779
- type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM,
780
- });
781
- dispatch({
782
- type: actions_1.QUOTE_ACTION_TYPES.RESET_ERRORS,
783
- });
784
- };
785
- var handleDeleteServiceRow = function (i) {
793
+ dispatch({ type: actions_1.QUOTE_ACTION_TYPES.RESET_FORM });
794
+ dispatch({ type: actions_1.QUOTE_ACTION_TYPES.RESET_ERRORS });
795
+ }, []);
796
+ // ---------------------------------------------------------------------------
797
+ // FORM HANDLERS
798
+ // ---------------------------------------------------------------------------
799
+ var handleDeleteServiceRow = (0, react_1.useCallback)(function (i) {
786
800
  if (state.servicesList.length > 1) {
787
801
  var res = state.servicesList.splice(i, 1);
788
802
  dispatch({
@@ -790,8 +804,8 @@ var useQuoteState = function () {
790
804
  payload: { servicesList: __spreadArray([], res, true) },
791
805
  });
792
806
  }
793
- };
794
- var handleDeleteProductRow = function (i) {
807
+ }, [state.servicesList]);
808
+ var handleDeleteProductRow = (0, react_1.useCallback)(function (i) {
795
809
  if (state.productsList.length > 1) {
796
810
  var res = state.productsList.splice(i, 1);
797
811
  dispatch({
@@ -799,35 +813,41 @@ var useQuoteState = function () {
799
813
  payload: { productsList: __spreadArray([], res, true) },
800
814
  });
801
815
  }
802
- };
803
- var headerActions = [
816
+ }, [state.productsList]);
817
+ // ---------------------------------------------------------------------------
818
+ // TABLE ACTIONS
819
+ // ---------------------------------------------------------------------------
820
+ var headerActions = (0, react_1.useMemo)(function () { return [
804
821
  {
805
822
  enabled: true,
806
823
  handleOnClick: function () { return handleCreate("company"); },
807
- label: "Quote for Company",
824
+ label: t("actionsQuoteCompany"),
808
825
  order: 1,
809
826
  },
810
827
  {
811
828
  enabled: true,
812
829
  handleOnClick: function () { return handleCreate("customer"); },
813
- label: "Quote for Customer",
830
+ label: t("actionsQuoteCustomer"),
814
831
  order: 2,
815
832
  },
816
- ];
817
- var rowActions = [
833
+ ]; }, [t, handleCreate]);
834
+ var rowActions = (0, react_1.useMemo)(function () { return [
818
835
  {
819
836
  enabled: true,
820
837
  handleAction: function (id) { return handleEdit(id); },
821
- label: "Edit",
838
+ label: t("actionsButtonEdit"),
822
839
  order: 1,
823
840
  },
824
841
  {
825
842
  enabled: true,
826
843
  handleAction: function (id) { return handleDelete(id); },
827
- label: "Delete",
844
+ label: t("actionsButtonDelete"),
828
845
  order: 2,
829
846
  },
830
- ];
847
+ ]; }, [t, handleEdit, handleDelete]);
848
+ // ---------------------------------------------------------------------------
849
+ // RETURN STATE
850
+ // ---------------------------------------------------------------------------
831
851
  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, handleTaxSearch: handleTaxSearch, headerActions: headerActions, listError: listError, listFetchNow: listFetchNow, listLoading: listLoading, rowActions: rowActions, searchOnChange: searchOnChange, updateError: updateError, updateLoading: updateLoading });
832
852
  };
833
853
  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; }, handleTaxSearch: function () { return void 0; }, headerActions: [], listError: undefined, listFetchNow: function () { return void 0; }, listLoading: false, rowActions: [], searchOnChange: function () { return void 0; }, updateError: undefined, updateLoading: false }));
@@ -48,7 +48,7 @@ var input_1 = require("@appcorp/shadcn/components/input");
48
48
  var context_1 = require("./context");
49
49
  var actions_1 = require("./actions");
50
50
  var CustomerSection = function () {
51
- var t = (0, next_intl_1.useTranslations)("invoicePage");
51
+ var t = (0, next_intl_1.useTranslations)("quote");
52
52
  var _a = (0, context_1.useQuoteStateContext)(), customer = _a.customer, errors = _a.errors, dispatch = _a.dispatch;
53
53
  var handleCustomerChange = (0, react_1.useCallback)(function (key, value) {
54
54
  if (key === "phone") {
@@ -79,21 +79,21 @@ var CustomerSection = function () {
79
79
  handleCustomerChange("country", country);
80
80
  };
81
81
  return (react_1.default.createElement("div", { className: "flex flex-col gap-4" },
82
- react_1.default.createElement("h3", { className: "text-lg font-semibold border-b pb-2" }, t("customerSectionTitle")),
82
+ react_1.default.createElement("h3", { className: "text-lg font-semibold border-b pb-2" }, t("customerFormSectionTitle")),
83
83
  react_1.default.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4" },
84
84
  react_1.default.createElement("div", { className: "space-y-2" },
85
- react_1.default.createElement(input_1.Input, { id: "phone", type: "tel", label: t("formLabelPhone"), value: (customer === null || customer === void 0 ? void 0 : customer.phone) || "", onChange: function (e) { return handleCustomerChange("phone", e.target.value); }, placeholder: "+92 300 0000000", error: errors.phone, required: true })),
85
+ react_1.default.createElement(input_1.Input, { error: errors.phone, id: "phone", info: t("customerFormInfoPhone"), label: t("customerFormLabelPhone"), onChange: function (e) { return handleCustomerChange("phone", e.target.value); }, placeholder: t("customerFormPlaceholderPhone"), required: true, type: "tel", value: (customer === null || customer === void 0 ? void 0 : customer.phone) || "" })),
86
86
  react_1.default.createElement("div", { className: "space-y-2" },
87
- react_1.default.createElement(input_1.Input, { id: "firstName", type: "text", label: t("formLabelFirstName"), value: (customer === null || customer === void 0 ? void 0 : customer.firstName) || "", onChange: function (e) { return handleInputChange("firstName", e.target.value); }, placeholder: "John", error: errors.firstName, required: true })),
87
+ react_1.default.createElement(input_1.Input, { error: errors.firstName, id: "firstName", info: t("customerFormInfoFirstName"), label: t("customerFormLabelFirstName"), onChange: function (e) { return handleInputChange("firstName", e.target.value); }, placeholder: t("customerFormPlaceholderFirstName"), required: true, type: "text", value: (customer === null || customer === void 0 ? void 0 : customer.firstName) || "" })),
88
88
  react_1.default.createElement("div", { className: "space-y-2" },
89
- react_1.default.createElement(input_1.Input, { id: "lastName", type: "text", label: t("formLabelLastName"), value: (customer === null || customer === void 0 ? void 0 : customer.lastName) || "", onChange: function (e) { return handleInputChange("lastName", e.target.value); }, placeholder: "Doe", error: errors.lastName, required: true })),
89
+ react_1.default.createElement(input_1.Input, { error: errors.lastName, id: "lastName", info: t("customerFormInfoLastName"), label: t("customerFormLabelLastName"), onChange: function (e) { return handleInputChange("lastName", e.target.value); }, placeholder: t("customerFormPlaceholderLastName"), required: true, type: "text", value: (customer === null || customer === void 0 ? void 0 : customer.lastName) || "" })),
90
90
  react_1.default.createElement("div", { className: "space-y-2" },
91
- react_1.default.createElement(input_1.Input, { id: "email", type: "email", label: t("formLabelEmail"), value: (customer === null || customer === void 0 ? void 0 : customer.email) || "", onChange: function (e) { return handleInputChange("email", e.target.value); }, placeholder: "name@company.com", error: errors.email })),
91
+ react_1.default.createElement(input_1.Input, { error: errors.email, id: "email", info: t("customerFormInfoEmail"), label: t("customerFormLabelEmail"), onChange: function (e) { return handleInputChange("email", e.target.value); }, placeholder: t("customerFormPlaceholderEmail"), type: "email", value: (customer === null || customer === void 0 ? void 0 : customer.email) || "" })),
92
92
  react_1.default.createElement("div", { className: "space-y-2" },
93
- react_1.default.createElement(input_1.Input, { id: "address", type: "text", label: t("formLabelAddress"), value: (customer === null || customer === void 0 ? void 0 : customer.address) || "", onChange: function (e) { return handleInputChange("address", e.target.value); }, placeholder: "123 Street", error: errors.address })),
93
+ react_1.default.createElement(input_1.Input, { error: errors.address, id: "address", info: t("customerFormInfoAddress"), label: t("customerFormLabelAddress"), onChange: function (e) { return handleInputChange("address", e.target.value); }, placeholder: t("customerFormPlaceholderAddress"), type: "text", value: (customer === null || customer === void 0 ? void 0 : customer.address) || "" })),
94
94
  react_1.default.createElement("div", { className: "space-y-2" },
95
- react_1.default.createElement(input_1.Input, { id: "city", type: "text", label: t("formLabelCity"), value: (customer === null || customer === void 0 ? void 0 : customer.city) || "", onChange: function (e) { return handleInputChange("city", e.target.value); }, placeholder: "New York", error: errors.city, required: true })),
95
+ react_1.default.createElement(input_1.Input, { error: errors.city, id: "city", info: t("customerFormInfoCity"), label: t("customerFormLabelCity"), onChange: function (e) { return handleInputChange("city", e.target.value); }, placeholder: t("customerFormPlaceholderCity"), required: true, type: "text", value: (customer === null || customer === void 0 ? void 0 : customer.city) || "" })),
96
96
  react_1.default.createElement("div", { className: "space-y-2" },
97
- react_1.default.createElement(combobox_1.CountryCombobox, { countries: util_functions_1.countriesTimeZones, id: "country", label: t("formLabelCountry"), value: (customer === null || customer === void 0 ? void 0 : customer.country) || "", onValueChange: handleCountryChange, placeholder: t("formPlaceholderCountry"), error: errors.country, required: true })))));
97
+ react_1.default.createElement(combobox_1.CountryCombobox, { countries: util_functions_1.countriesTimeZones, error: errors.country, id: "country", info: t("customerFormInfoCountry"), label: t("customerFormLabelCountry"), onValueChange: handleCountryChange, placeholder: t("customerFormPlaceholderCountry"), required: true, value: (customer === null || customer === void 0 ? void 0 : customer.country) || "" })))));
98
98
  };
99
99
  exports.CustomerSection = CustomerSection;
@@ -21,11 +21,11 @@ var form_1 = require("./form");
21
21
  var types_1 = require("./types");
22
22
  var Drawer = function (_a) {
23
23
  var isRTL = _a.isRTL;
24
- var t = (0, next_intl_1.useTranslations)("invoicePage");
24
+ var t = (0, next_intl_1.useTranslations)("quote");
25
25
  var _b = (0, context_1.useQuoteStateContext)(), closeDrawer = _b.closeDrawer, disableSaveButton = _b.disableSaveButton, drawer = _b.drawer, handleSubmit = _b.handleSubmit;
26
26
  var isFormDrawer = drawer === types_1.QUOTE_DRAWER.QUOTE_COMPANY_FORM_DRAWER ||
27
27
  drawer === types_1.QUOTE_DRAWER.QUOTE_CUSTOMER_FORM_DRAWER;
28
- var drawerTitle = t("drawerTitleInvoice");
28
+ var drawerTitle = t("drawerTitleQuote");
29
29
  var drawerWidth = "data-[vaul-drawer-direction=right]:sm:max-w-5xl";
30
30
  var drawerDirection = isRTL ? "left" : "right";
31
31
  return (react_1.default.createElement(drawer_1.Drawer, { open: !!drawer, onOpenChange: function (open) { return !open && closeDrawer(); }, direction: drawerDirection },