strapi-plugin-payone-provider 4.6.10 → 4.6.12

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/README.md +64 -0
  2. package/admin/src/pages/App/components/AppHeader.jsx +3 -2
  3. package/admin/src/pages/App/components/AppTabs.jsx +34 -88
  4. package/admin/src/pages/App/components/DocsPanel.jsx +1726 -1726
  5. package/admin/src/pages/App/components/GooglePaybutton.jsx +300 -300
  6. package/admin/src/pages/App/components/StatusBadge.jsx +1 -1
  7. package/admin/src/pages/App/components/common/InfoTooltip.jsx +16 -0
  8. package/admin/src/pages/App/components/{ApplePayConfig.jsx → configuration/ApplePayConfig.jsx} +191 -62
  9. package/admin/src/pages/App/components/{ApplePayConfigPanel.jsx → configuration/ApplePayConfigPanel.jsx} +71 -70
  10. package/admin/src/pages/App/components/configuration/ConfigurationFields.jsx +408 -0
  11. package/admin/src/pages/App/components/configuration/ConfigurationPanel.jsx +67 -0
  12. package/admin/src/pages/App/components/{GooglePayConfig.jsx → configuration/GooglePayConfig.jsx} +254 -254
  13. package/admin/src/pages/App/components/{GooglePayConfigPanel.jsx → configuration/GooglePayConfigPanel.jsx} +82 -82
  14. package/admin/src/pages/App/components/configuration/TestConnection.jsx +129 -0
  15. package/admin/src/pages/App/components/paymentActions/ApplePayPanel.jsx +137 -95
  16. package/admin/src/pages/App/components/paymentActions/CaptureForm.jsx +119 -14
  17. package/admin/src/pages/App/components/paymentActions/CardDetailsInput.jsx +85 -24
  18. package/admin/src/pages/App/components/paymentActions/PaymentActionsPanel.jsx +361 -0
  19. package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.jsx +22 -4
  20. package/admin/src/pages/App/components/paymentActions/RefundForm.jsx +91 -20
  21. package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationForm.jsx +157 -0
  22. package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationFormFields.jsx +308 -0
  23. package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationFormHeader.jsx +27 -0
  24. package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationPaymentButtons.jsx +93 -0
  25. package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationForm.jsx +134 -0
  26. package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationFormFields.jsx +295 -0
  27. package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationFormHeader.jsx +27 -0
  28. package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationPaymentButtons.jsx +53 -0
  29. package/admin/src/pages/App/components/transaction-history/FiltersPanel.jsx +182 -0
  30. package/admin/src/pages/App/components/transaction-history/HistoryPanel.jsx +49 -0
  31. package/admin/src/pages/App/components/transaction-history/TransactionTable.jsx +199 -0
  32. package/admin/src/pages/App/components/transaction-history/TransactionTablePagination.jsx +28 -0
  33. package/admin/src/pages/App/components/transaction-history/details/TransactionDetails.jsx +155 -0
  34. package/admin/src/pages/App/index.jsx +5 -29
  35. package/admin/src/pages/hooks/usePaymentActions.js +87 -11
  36. package/admin/src/pages/hooks/useSettings.js +64 -22
  37. package/admin/src/pages/hooks/useTransactionHistory.js +121 -85
  38. package/admin/src/pages/utils/api.js +31 -3
  39. package/admin/src/pages/utils/countryLanguageUtils.js +236 -0
  40. package/admin/src/pages/utils/transactionTableUtils.js +60 -0
  41. package/package.json +2 -2
  42. package/server/bootstrap.js +6 -6
  43. package/server/content-types/index.js +5 -0
  44. package/server/content-types/transactions/index.js +5 -0
  45. package/server/content-types/transactions/schema.json +87 -0
  46. package/server/controllers/payone.js +29 -3
  47. package/server/index.js +2 -1
  48. package/server/policies/index.js +2 -1
  49. package/server/policies/is-payone-notification.js +31 -0
  50. package/server/routes/index.js +10 -0
  51. package/server/services/applePayService.js +0 -2
  52. package/server/services/payone.js +16 -4
  53. package/server/services/settingsService.js +8 -2
  54. package/server/services/testConnectionService.js +11 -72
  55. package/server/services/transactionService.js +147 -154
  56. package/server/services/transactionStatusService.js +63 -0
  57. package/server/utils/sanitize.js +41 -0
  58. package/admin/src/pages/App/components/ConfigurationPanel.jsx +0 -517
  59. package/admin/src/pages/App/components/CustomerInfoPopover.jsx +0 -147
  60. package/admin/src/pages/App/components/HistoryPanel.jsx +0 -94
  61. package/admin/src/pages/App/components/PaymentActionsPanel.jsx +0 -280
  62. package/admin/src/pages/App/components/RawDataPopover.jsx +0 -113
  63. package/admin/src/pages/App/components/TransactionHistoryItem.jsx +0 -522
  64. package/admin/src/pages/App/components/TransactionHistoryTable/TransactionHistoryTableFilters.jsx +0 -113
  65. package/admin/src/pages/App/components/TransactionHistoryTable/TransactionHistoryTablePagination.jsx +0 -180
  66. package/admin/src/pages/App/components/TransactionHistoryTable/index.jsx +0 -225
  67. package/admin/src/pages/App/components/paymentActions/AuthorizationForm.jsx +0 -197
  68. package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.jsx +0 -142
@@ -1,4 +1,4 @@
1
- import { useState, useEffect } from "react";
1
+ import { useState, useEffect, useRef } from "react";
2
2
  import { useNotification } from "@strapi/helper-plugin";
3
3
  import payoneRequests from "../utils/api";
4
4
 
@@ -11,15 +11,31 @@ const useSettings = () => {
11
11
  key: "",
12
12
  mode: "test",
13
13
  api_version: "3.10",
14
- enable3DSecure: false
14
+ merchantName: "",
15
+ displayName: "",
16
+ domainName: "",
17
+ merchantIdentifier: "",
18
+ enable3DSecure: false,
19
+ enableCreditCard: false,
20
+ enablePayPal: false,
21
+ enableGooglePay: false,
22
+ enableApplePay: false,
23
+ enableSepaDirectDebit: false
15
24
  });
25
+
16
26
  const [isLoading, setIsLoading] = useState(false);
17
27
  const [isSaving, setIsSaving] = useState(false);
18
28
  const [isTesting, setIsTesting] = useState(false);
19
29
  const [testResult, setTestResult] = useState(null);
30
+ const saveTimeoutRef = useRef(null);
20
31
 
21
32
  useEffect(() => {
22
33
  loadSettings();
34
+ return () => {
35
+ if (saveTimeoutRef.current) {
36
+ clearTimeout(saveTimeoutRef.current);
37
+ }
38
+ };
23
39
  }, []);
24
40
 
25
41
  const loadSettings = async () => {
@@ -39,6 +55,37 @@ const useSettings = () => {
39
55
 
40
56
  const handleInputChange = (field, value) => {
41
57
  setSettings((prev) => ({ ...prev, [field]: value }));
58
+
59
+ if (saveTimeoutRef.current) {
60
+ clearTimeout(saveTimeoutRef.current);
61
+ }
62
+
63
+ saveTimeoutRef.current = setTimeout(async () => {
64
+ let updatedSettings;
65
+ setSettings((prev) => {
66
+ updatedSettings = { ...prev };
67
+ return prev;
68
+ });
69
+
70
+ setIsSaving(true);
71
+ try {
72
+ await payoneRequests.updateSettings(updatedSettings);
73
+ await loadSettings();
74
+ } catch (error) {
75
+ setSettings((prev) => {
76
+ const previousValue = prev[field];
77
+ return { ...prev, [field]: previousValue };
78
+ });
79
+
80
+ toggleNotification({
81
+ type: "warning",
82
+ message: "Failed to update settings"
83
+ });
84
+
85
+ } finally {
86
+ setIsSaving(false);
87
+ }
88
+ }, 1000);
42
89
  };
43
90
 
44
91
  const handlePaymentMethodToggle = async (field, value) => {
@@ -90,31 +137,26 @@ const useSettings = () => {
90
137
  setTestResult(null);
91
138
  try {
92
139
  const response = await payoneRequests.testConnection();
93
- if (response.data) {
94
- const result = response.data;
95
- setTestResult(result);
96
- if (result.success !== undefined) {
97
- toggleNotification({
98
- type: Boolean(result.success) ? "success" : "warning",
99
- message: result.message || "Test completed"
100
- });
101
- }
140
+ console.log("response test connection", response?.data, response?.data?.error?.ErrorMessage);
141
+ if (response?.data && response?.data?.success) {
142
+ setTestResult(response?.data);
143
+ toggleNotification({
144
+ type: "success",
145
+ message: response?.data?.message || "Test completed"
146
+ });
102
147
  } else {
103
- throw new Error("Invalid response format from server");
148
+ setTestResult(response?.data);
149
+ toggleNotification({
150
+ type: "warning",
151
+ message: response?.data?.error?.ErrorMessage
152
+ });
153
+
154
+ throw new Error(response?.data?.error?.ErrorMessage);
104
155
  }
105
156
  } catch (error) {
106
157
  toggleNotification({
107
158
  type: "warning",
108
- message: "Failed to test connection"
109
- });
110
- setTestResult({
111
- success: false,
112
- message:
113
- "Failed to test connection. Please check your network and server logs for details.",
114
- details: {
115
- errorCode: "NETWORK",
116
- rawResponse: error.message || "Network error"
117
- }
159
+ message: error?.message
118
160
  });
119
161
  } finally {
120
162
  setIsTesting(false);
@@ -1,17 +1,15 @@
1
1
  import { useState, useEffect } from "react";
2
+ import { useLocation, useHistory } from "react-router-dom";
2
3
  import { useNotification } from "@strapi/helper-plugin";
3
4
  import payoneRequests from "../utils/api";
4
5
 
5
- const DEFAULT_PAGE_SIZE = 10;
6
+ const PAGE_SIZE = 10;
6
7
 
7
8
  const useTransactionHistory = () => {
8
9
  const toggleNotification = useNotification();
9
- const [transactionHistory, setTransactionHistory] = useState([]);
10
- const [isLoadingHistory, setIsLoadingHistory] = useState(false);
11
- const [selectedTransaction, setSelectedTransaction] = useState(null);
12
- const [currentPage, setCurrentPage] = useState(1);
13
- const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE);
14
- // Calculate default dates
10
+ const location = useLocation();
11
+ const history = useHistory();
12
+
15
13
  const getDefaultDateFrom = () => {
16
14
  const date = new Date();
17
15
  date.setDate(date.getDate() - 30);
@@ -20,130 +18,168 @@ const useTransactionHistory = () => {
20
18
 
21
19
  const getDefaultDateTo = () => {
22
20
  const date = new Date();
23
- date.setDate(date.getDate() + 1); // Add 1 day to include today's transactions
21
+ date.setDate(date.getDate() + 1);
24
22
  return date.toISOString().split('T')[0];
25
23
  };
26
24
 
25
+ const getQueryParams = () => {
26
+ const searchParams = new URLSearchParams(location.search);
27
+ const page = parseInt(searchParams.get("page") || "1", 10);
28
+ const pageSize = parseInt(searchParams.get("pageSize") || String(PAGE_SIZE), 10);
29
+ const sort_by = searchParams.get("sort_by") || "createdAt";
30
+ const sort_order = searchParams.get("sort_order") || "desc";
31
+
32
+ return { page, pageSize, sort_by, sort_order };
33
+ };
34
+
27
35
  const [filters, setFilters] = useState({
28
36
  search: "",
37
+ status: "",
29
38
  request_type: "",
30
39
  payment_method: "",
31
40
  date_from: getDefaultDateFrom(),
32
41
  date_to: getDefaultDateTo(),
33
- status: ""
34
42
  });
35
43
 
36
- const [sorting, setSorting] = useState({
37
- sortBy: null,
38
- sortOrder: null // 'asc' or 'desc'
44
+ const initialQueryParams = getQueryParams();
45
+ const [pagination, setPagination] = useState({
46
+ page: initialQueryParams.page,
47
+ pageSize: initialQueryParams.pageSize,
48
+ pageCount: 1,
49
+ total: 0,
39
50
  });
40
51
 
41
- useEffect(() => {
42
- loadTransactionHistory();
43
- }, []);
52
+ const [sort, setSort] = useState({
53
+ sort_by: initialQueryParams.sort_by,
54
+ sort_order: initialQueryParams.sort_order,
55
+ });
56
+
57
+ const [transactionHistory, setTransactionHistory] = useState([]);
58
+ const [isLoadingHistory, setIsLoadingHistory] = useState(false);
59
+ const [selectedTransaction, setSelectedTransaction] = useState(null);
44
60
 
45
61
  const loadTransactionHistory = async () => {
46
62
  setIsLoadingHistory(true);
47
63
  try {
48
- const params = { ...filters };
49
- if (sorting.sortBy && sorting.sortOrder) {
50
- params.sort_by = sorting.sortBy;
51
- params.sort_order = sorting.sortOrder;
64
+ const response = await payoneRequests.getTransactionHistory({
65
+ filters,
66
+ pagination,
67
+ sort_by: sort.sort_by,
68
+ sort_order: sort.sort_order,
69
+ });
70
+
71
+ if (response && response.data && response.pagination) {
72
+ setTransactionHistory(response.data);
73
+ setPagination(response.pagination);
74
+ } else {
75
+ setTransactionHistory([]);
76
+ setPagination((prev) => ({
77
+ ...prev,
78
+ pageCount: 1,
79
+ total: 0,
80
+ }));
52
81
  }
53
- const result = await payoneRequests.getTransactionHistory(params);
54
- setTransactionHistory(result.data || []);
55
- setCurrentPage(1);
56
82
  } catch (error) {
83
+ console.error("Error loading transaction history:", error);
84
+ setTransactionHistory([]);
85
+ setPagination((prev) => ({
86
+ ...prev,
87
+ pageCount: 1,
88
+ total: 0,
89
+ }));
57
90
  toggleNotification({
58
91
  type: "warning",
59
- message: "Failed to load transaction history"
92
+ message: "Failed to load transaction history",
60
93
  });
61
94
  } finally {
62
95
  setIsLoadingHistory(false);
63
96
  }
64
97
  };
65
98
 
66
- const handleFilterChange = (field, value) => {
67
- setFilters((prev) => ({ ...prev, [field]: value }));
68
- };
99
+ useEffect(() => {
100
+ const params = getQueryParams();
101
+ setPagination((prev) => ({
102
+ ...prev,
103
+ page: params.page,
104
+ pageSize: params.pageSize,
105
+ }));
106
+ setSort({ sort_by: params.sort_by, sort_order: params.sort_order });
107
+ }, [location.search]);
69
108
 
70
- const handleFilterApply = () => {
109
+ useEffect(() => {
71
110
  loadTransactionHistory();
72
- };
111
+ }, [
112
+ filters.search,
113
+ filters.status,
114
+ filters.request_type,
115
+ filters.payment_method,
116
+ filters.date_from,
117
+ filters.date_to,
118
+ pagination.page,
119
+ pagination.pageSize,
120
+ sort.sort_by,
121
+ sort.sort_order,
122
+ ]);
73
123
 
74
- const handleSort = (column) => {
75
- setSorting((prev) => {
76
- // If clicking the same column, cycle through: null -> asc -> desc -> null
77
- if (prev.sortBy === column) {
78
- if (!prev.sortOrder) {
79
- return { sortBy: column, sortOrder: "asc" };
80
- } else if (prev.sortOrder === "asc") {
81
- return { sortBy: column, sortOrder: "desc" };
82
- } else {
83
- return { sortBy: null, sortOrder: null };
84
- }
85
- } else {
86
- // If clicking a different column, reset and set new column to asc
87
- return { sortBy: column, sortOrder: "asc" };
88
- }
89
- });
124
+ const handleTransactionSelect = (transaction) => {
125
+ setSelectedTransaction(
126
+ selectedTransaction?.id === transaction?.id ? null : transaction
127
+ );
90
128
  };
91
129
 
92
- // Reload when sorting changes (but not on initial mount)
93
- const [isInitialMount, setIsInitialMount] = useState(true);
94
-
95
- useEffect(() => {
96
- if (isInitialMount) {
97
- setIsInitialMount(false);
98
- return;
130
+ const handlePaginationChange = (newPagination) => {
131
+ if (newPagination && typeof newPagination === "object") {
132
+ const updatedQuery = new URLSearchParams(location.search);
133
+ if (newPagination.page !== undefined) {
134
+ updatedQuery.set('page', String(newPagination.page));
135
+ }
136
+ if (newPagination.pageSize !== undefined) {
137
+ updatedQuery.set('pageSize', String(newPagination.pageSize));
138
+ updatedQuery.set('page', '1');
139
+ }
140
+ history.push({ search: updatedQuery.toString() });
99
141
  }
100
- // Only reload if sorting is actually set or cleared
101
- loadTransactionHistory();
102
- // eslint-disable-next-line react-hooks/exhaustive-deps
103
- }, [sorting.sortBy, sorting.sortOrder]);
142
+ };
104
143
 
105
- const handleTransactionSelect = (transaction) => {
106
- if (selectedTransaction?.id === transaction?.id) {
107
- setSelectedTransaction(null);
108
- } else {
109
- setSelectedTransaction(transaction);
144
+ const handleFiltersChange = (newFilters) => {
145
+ if (newFilters && typeof newFilters === "object") {
146
+ setFilters((prev) => ({
147
+ ...prev,
148
+ ...newFilters,
149
+ }));
150
+ const updatedQuery = new URLSearchParams(location.search);
151
+ updatedQuery.set("page", "1");
152
+ history.push({ search: updatedQuery.toString() });
110
153
  }
111
154
  };
112
155
 
113
- const handlePageChange = (page) => {
114
- setCurrentPage(page);
115
- setSelectedTransaction(null);
156
+ const handleSort = (sortBy) => {
157
+ const nextOrder =
158
+ sort.sort_by === sortBy && sort.sort_order === "asc" ? "desc" : "asc";
159
+ setSort({ sort_by: sortBy, sort_order: nextOrder });
160
+ const updatedQuery = new URLSearchParams(location.search);
161
+ updatedQuery.set("sort_by", sortBy);
162
+ updatedQuery.set("sort_order", nextOrder);
163
+ updatedQuery.set("page", "1");
164
+ history.push({ search: updatedQuery.toString() });
116
165
  };
117
166
 
118
- const handlePageSizeChange = (newPageSize) => {
119
- setPageSize(newPageSize);
120
- setCurrentPage(1); // Reset to first page when page size changes
167
+ useEffect(() => {
121
168
  setSelectedTransaction(null);
122
- };
123
-
124
- // Pagination calculations
125
- const totalPages = Math.ceil(transactionHistory.length / pageSize);
126
- const startIndex = (currentPage - 1) * pageSize;
127
- const endIndex = startIndex + pageSize;
128
- const paginatedTransactions = transactionHistory.slice(startIndex, endIndex);
169
+ }, [filters, pagination.page]);
129
170
 
130
171
  return {
131
- transactionHistory,
132
- paginatedTransactions,
172
+ transactions: Array.isArray(transactionHistory) ? transactionHistory : [],
133
173
  isLoadingHistory,
134
174
  selectedTransaction,
175
+ handleTransactionSelect,
176
+ loadTransactionHistory,
135
177
  filters,
136
- sorting,
137
- currentPage,
138
- totalPages,
139
- pageSize,
140
- handleFilterChange,
141
- handleFilterApply,
178
+ handleFiltersChange,
179
+ pagination,
180
+ handlePaginationChange,
181
+ sort,
142
182
  handleSort,
143
- handleTransactionSelect,
144
- handlePageChange,
145
- handlePageSizeChange,
146
- loadTransactionHistory
147
183
  };
148
184
  };
149
185
 
@@ -15,14 +15,42 @@ const payoneRequests = {
15
15
  });
16
16
  },
17
17
 
18
- getTransactionHistory: (params = {}) => {
19
- const queryString = new URLSearchParams(params).toString();
20
- return request(
18
+ getTransactionHistory: async (params = {}) => {
19
+ const queryParams = new URLSearchParams();
20
+
21
+ if (params.filters) {
22
+ Object.keys(params.filters).forEach((key) => {
23
+ const value = params.filters[key];
24
+ if (value !== undefined && value !== null && value !== '') {
25
+ queryParams.append(`filters[${key}]`, String(value));
26
+ }
27
+ });
28
+ }
29
+
30
+ if (params.pagination) {
31
+ if (params.pagination.page) {
32
+ queryParams.append('pagination[page]', String(params.pagination.page));
33
+ }
34
+ if (params.pagination.pageSize) {
35
+ queryParams.append('pagination[pageSize]', String(params.pagination.pageSize));
36
+ }
37
+ }
38
+
39
+ if (params.sort_by) {
40
+ queryParams.append('sort_by', String(params.sort_by));
41
+ }
42
+ if (params.sort_order) {
43
+ queryParams.append('sort_order', String(params.sort_order));
44
+ }
45
+
46
+ const queryString = queryParams.toString();
47
+ const response = await request(
21
48
  `/${pluginId}/transaction-history${queryString ? `?${queryString}` : ""}`,
22
49
  {
23
50
  method: "GET"
24
51
  }
25
52
  );
53
+ return response;
26
54
  },
27
55
 
28
56
  testConnection: () => {
@@ -0,0 +1,236 @@
1
+ export const COUNTRY_LANGUAGE_MAP = {
2
+ US: "en",
3
+ GB: "en",
4
+ CA: "en",
5
+ AU: "en",
6
+ NZ: "en",
7
+ IE: "en",
8
+ DE: "de",
9
+ AT: "de",
10
+ CH: "de",
11
+ FR: "fr",
12
+ BE: "fr",
13
+ IT: "it",
14
+ ES: "es",
15
+ PT: "pt",
16
+ NL: "nl",
17
+ PL: "pl",
18
+ CZ: "cs",
19
+ HU: "hu",
20
+ SE: "sv",
21
+ NO: "no",
22
+ DK: "da",
23
+ FI: "fi",
24
+ GR: "el",
25
+ JP: "ja",
26
+ CN: "zh",
27
+ HK: "zh",
28
+ TW: "zh",
29
+ SG: "en",
30
+ BR: "pt",
31
+ MX: "es",
32
+ AE: "ar",
33
+ SA: "ar",
34
+ RU: "ru",
35
+ UA: "uk",
36
+ TR: "tr",
37
+ ZA: "en",
38
+ IN: "en",
39
+ };
40
+
41
+ export const COUNTRIES = [
42
+ { code: "US", name: "United States" },
43
+ { code: "GB", name: "United Kingdom" },
44
+ { code: "CA", name: "Canada" },
45
+ { code: "AU", name: "Australia" },
46
+ { code: "DE", name: "Germany" },
47
+ { code: "FR", name: "France" },
48
+ { code: "IT", name: "Italy" },
49
+ { code: "ES", name: "Spain" },
50
+ { code: "NL", name: "Netherlands" },
51
+ { code: "BE", name: "Belgium" },
52
+ { code: "CH", name: "Switzerland" },
53
+ { code: "AT", name: "Austria" },
54
+ { code: "IE", name: "Ireland" },
55
+ { code: "SE", name: "Sweden" },
56
+ { code: "NO", name: "Norway" },
57
+ { code: "DK", name: "Denmark" },
58
+ { code: "FI", name: "Finland" },
59
+ { code: "PL", name: "Poland" },
60
+ { code: "CZ", name: "Czech Republic" },
61
+ { code: "HU", name: "Hungary" },
62
+ { code: "PT", name: "Portugal" },
63
+ { code: "GR", name: "Greece" },
64
+ { code: "JP", name: "Japan" },
65
+ { code: "CN", name: "China" },
66
+ { code: "HK", name: "Hong Kong" },
67
+ { code: "TW", name: "Taiwan" },
68
+ { code: "SG", name: "Singapore" },
69
+ { code: "NZ", name: "New Zealand" },
70
+ { code: "BR", name: "Brazil" },
71
+ { code: "MX", name: "Mexico" },
72
+ { code: "AE", name: "United Arab Emirates" },
73
+ { code: "SA", name: "Saudi Arabia" },
74
+ { code: "RU", name: "Russia" },
75
+ { code: "UA", name: "Ukraine" },
76
+ { code: "TR", name: "Turkey" },
77
+ { code: "ZA", name: "South Africa" },
78
+ { code: "IN", name: "India" },
79
+ ];
80
+
81
+ export const getLanguageForCountry = (countryCode) => {
82
+ return COUNTRY_LANGUAGE_MAP[countryCode] || "en";
83
+ };
84
+
85
+ export const SALUTATION_OPTIONS = {
86
+ en: [
87
+ { value: "Mr", label: "Mr" },
88
+ { value: "Mrs", label: "Mrs" },
89
+ { value: "Ms", label: "Ms" },
90
+ { value: "Dr", label: "Dr" },
91
+ ],
92
+ de: [
93
+ { value: "Herr", label: "Herr" },
94
+ { value: "Frau", label: "Frau" },
95
+ { value: "Dr", label: "Dr" },
96
+ ],
97
+ fr: [
98
+ { value: "Monsieur", label: "Monsieur" },
99
+ { value: "Madame", label: "Madame" },
100
+ { value: "Mademoiselle", label: "Mademoiselle" },
101
+ ],
102
+ it: [
103
+ { value: "Signore", label: "Signore" },
104
+ { value: "Signora", label: "Signora" },
105
+ { value: "Signorina", label: "Signorina" },
106
+ ],
107
+ es: [
108
+ { value: "Señor", label: "Señor" },
109
+ { value: "Señora", label: "Señora" },
110
+ { value: "Señorita", label: "Señorita" },
111
+ ],
112
+ nl: [
113
+ { value: "Dhr", label: "Dhr" },
114
+ { value: "Mevr", label: "Mevr" },
115
+ ],
116
+ pt: [
117
+ { value: "Senhor", label: "Senhor" },
118
+ { value: "Senhora", label: "Senhora" },
119
+ ],
120
+ default: [
121
+ { value: "Mr", label: "Mr" },
122
+ { value: "Mrs", label: "Mrs" },
123
+ { value: "Ms", label: "Ms" },
124
+ ],
125
+ };
126
+
127
+ export const GENDER_OPTIONS = {
128
+ en: [
129
+ { value: "m", label: "Male" },
130
+ { value: "f", label: "Female" },
131
+ ],
132
+ de: [
133
+ { value: "m", label: "Männlich" },
134
+ { value: "f", label: "Weiblich" },
135
+ ],
136
+ fr: [
137
+ { value: "m", label: "Masculin" },
138
+ { value: "f", label: "Féminin" },
139
+ ],
140
+ it: [
141
+ { value: "m", label: "Maschio" },
142
+ { value: "f", label: "Femmina" },
143
+ ],
144
+ es: [
145
+ { value: "m", label: "Masculino" },
146
+ { value: "f", label: "Femenino" },
147
+ ],
148
+ nl: [
149
+ { value: "m", label: "Man" },
150
+ { value: "f", label: "Vrouw" },
151
+ ],
152
+ pt: [
153
+ { value: "m", label: "Masculino" },
154
+ { value: "f", label: "Feminino" },
155
+ ],
156
+ default: [
157
+ { value: "m", label: "Male" },
158
+ { value: "f", label: "Female" },
159
+ ],
160
+ };
161
+
162
+ export const getSalutationOptions = (countryCode) => {
163
+ const language = getLanguageForCountry(countryCode);
164
+ return SALUTATION_OPTIONS[language] || SALUTATION_OPTIONS.default;
165
+ };
166
+
167
+ export const getGenderOptions = (countryCode) => {
168
+ const language = getLanguageForCountry(countryCode);
169
+ return GENDER_OPTIONS[language] || GENDER_OPTIONS.default;
170
+ };
171
+
172
+ export const CURRENCIES = [
173
+ { code: "USD", name: "US Dollar", symbol: "$" },
174
+ { code: "EUR", name: "Euro", symbol: "€" },
175
+ { code: "GBP", name: "British Pound", symbol: "£" },
176
+ { code: "CAD", name: "Canadian Dollar", symbol: "C$" },
177
+ { code: "AUD", name: "Australian Dollar", symbol: "A$" },
178
+ { code: "JPY", name: "Japanese Yen", symbol: "¥" },
179
+ { code: "CNY", name: "Chinese Yuan", symbol: "¥" },
180
+ { code: "HKD", name: "Hong Kong Dollar", symbol: "HK$" },
181
+ { code: "TWD", name: "Taiwan Dollar", symbol: "NT$" },
182
+ { code: "SGD", name: "Singapore Dollar", symbol: "S$" },
183
+ { code: "NZD", name: "New Zealand Dollar", symbol: "NZ$" },
184
+ { code: "BRL", name: "Brazilian Real", symbol: "R$" },
185
+ { code: "MXN", name: "Mexican Peso", symbol: "Mex$" },
186
+ { code: "AED", name: "UAE Dirham", symbol: "د.إ" },
187
+ { code: "SAR", name: "Saudi Riyal", symbol: "﷼" },
188
+ { code: "RUB", name: "Russian Ruble", symbol: "₽" },
189
+ { code: "UAH", name: "Ukrainian Hryvnia", symbol: "₴" },
190
+ { code: "TRY", name: "Turkish Lira", symbol: "₺" },
191
+ { code: "ZAR", name: "South African Rand", symbol: "R" },
192
+ { code: "CHF", name: "Swiss Franc", symbol: "CHF" },
193
+ { code: "SEK", name: "Swedish Krona", symbol: "kr" },
194
+ { code: "NOK", name: "Norwegian Krone", symbol: "kr" },
195
+ { code: "DKK", name: "Danish Krone", symbol: "kr" },
196
+ { code: "PLN", name: "Polish Zloty", symbol: "zł" },
197
+ { code: "CZK", name: "Czech Koruna", symbol: "Kč" },
198
+ { code: "HUF", name: "Hungarian Forint", symbol: "Ft" },
199
+ { code: "INR", name: "Indian Rupee", symbol: "₹" },
200
+ ];
201
+
202
+ export const getCurrencyOptions = () => {
203
+ return CURRENCIES.map((c) => ({
204
+ value: c.code,
205
+ label: `${c.name} (${c.code}) ${c.symbol}`,
206
+ }));
207
+ };
208
+
209
+ export const getCountryOptions = (paymentMethod) => {
210
+ let supportedCountryCodes = [];
211
+
212
+ if (paymentMethod === "apl") {
213
+ supportedCountryCodes = [
214
+ "US", "GB", "CA", "AU", "DE", "FR", "IT", "ES", "NL", "BE", "CH", "AT", "IE",
215
+ "SE", "NO", "DK", "FI", "PL", "CZ", "HU", "PT", "GR", "JP", "CN", "HK", "TW",
216
+ "SG", "NZ", "BR", "MX", "AE", "SA", "RU", "UA", "TR", "ZA"
217
+ ];
218
+ } else if (paymentMethod === "gpp") {
219
+ supportedCountryCodes = [
220
+ "US", "GB", "CA", "AU", "DE", "FR", "IT", "ES", "NL", "BE", "CH", "AT", "IE",
221
+ "SE", "NO", "DK", "FI", "PL", "BR", "MX", "JP", "SG", "NZ", "IN"
222
+ ];
223
+ }
224
+
225
+ const hasRestriction = supportedCountryCodes.length > 0;
226
+
227
+ return COUNTRIES.map((country) => {
228
+ const isSupported = !hasRestriction || supportedCountryCodes.includes(country.code);
229
+ return {
230
+ value: country.code,
231
+ label: `${country.name} (${country.code})`,
232
+ disabled: hasRestriction && !isSupported,
233
+ };
234
+ });
235
+ };
236
+