@eeplatform/nuxt-layer-common 1.0.0

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 (108) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +11 -0
  3. package/.editorconfig +12 -0
  4. package/.github/workflows/main.yml +17 -0
  5. package/.github/workflows/publish.yml +39 -0
  6. package/.nuxtrc +1 -0
  7. package/.playground/app.vue +37 -0
  8. package/.playground/nuxt.config.ts +20 -0
  9. package/CHANGELOG.md +7 -0
  10. package/README.md +73 -0
  11. package/app.vue +3 -0
  12. package/components/AddPaymentMethod.vue +585 -0
  13. package/components/BtnUploadFile.vue +139 -0
  14. package/components/ConfirmDialog.vue +66 -0
  15. package/components/Container/Standard.vue +33 -0
  16. package/components/Input/Date.vue +177 -0
  17. package/components/Input/ListGroupSelection.vue +93 -0
  18. package/components/Input/NewDate.vue +123 -0
  19. package/components/Input/Number.vue +124 -0
  20. package/components/Input/Password.vue +35 -0
  21. package/components/InputLabel.vue +18 -0
  22. package/components/InvitationMain.vue +195 -0
  23. package/components/Layout/Header.vue +285 -0
  24. package/components/Layout/NavigationDrawer.vue +52 -0
  25. package/components/LinkHome.vue +9 -0
  26. package/components/ListItem.vue +35 -0
  27. package/components/LocalPagination.vue +41 -0
  28. package/components/MemberMain.vue +452 -0
  29. package/components/NavigationItem.vue +73 -0
  30. package/components/PlaceholderComponent.vue +34 -0
  31. package/components/RolePermissionFormCreate.vue +179 -0
  32. package/components/RolePermissionFormPreviewUpdate.vue +184 -0
  33. package/components/RolePermissionMain.vue +376 -0
  34. package/components/Snackbar.vue +23 -0
  35. package/components/SpecificAttr.vue +57 -0
  36. package/components/Std/Pagination.vue +52 -0
  37. package/components/SwitchContext.vue +109 -0
  38. package/components/SwitchOrg.vue +159 -0
  39. package/components/TableList.vue +130 -0
  40. package/composables/useAddress.ts +144 -0
  41. package/composables/useChartOfAccount.ts +62 -0
  42. package/composables/useCommonPermission.ts +130 -0
  43. package/composables/useFile.ts +29 -0
  44. package/composables/useInvoice.ts +42 -0
  45. package/composables/useLocal.ts +63 -0
  46. package/composables/useLocalAuth.ts +157 -0
  47. package/composables/useLocalSetup.ts +46 -0
  48. package/composables/useMember.ts +107 -0
  49. package/composables/useOrder.ts +22 -0
  50. package/composables/useOrg.ts +106 -0
  51. package/composables/useOrgPermission.ts +27 -0
  52. package/composables/usePayment.ts +22 -0
  53. package/composables/usePaymentMethod.ts +347 -0
  54. package/composables/usePermission.ts +54 -0
  55. package/composables/usePrice.ts +15 -0
  56. package/composables/usePromoCode.ts +43 -0
  57. package/composables/useRecapPermission.ts +26 -0
  58. package/composables/useRole.ts +89 -0
  59. package/composables/useSchoolPermission.ts +13 -0
  60. package/composables/useSubscription.ts +264 -0
  61. package/composables/useUser.ts +102 -0
  62. package/composables/useUtils.ts +294 -0
  63. package/composables/useVerification.ts +19 -0
  64. package/error.vue +41 -0
  65. package/eslint.config.js +3 -0
  66. package/layouts/plain.vue +7 -0
  67. package/middleware/01.auth.ts +14 -0
  68. package/middleware/org.ts +16 -0
  69. package/nuxt.config.ts +48 -0
  70. package/package.json +35 -0
  71. package/pages/index.vue +3 -0
  72. package/pages/payment-method-cancel-link.vue +31 -0
  73. package/pages/payment-method-failed-link.vue +31 -0
  74. package/pages/payment-method-linked.vue +31 -0
  75. package/pages/require-organization-membership.vue +47 -0
  76. package/pages/unauthorized.vue +29 -0
  77. package/plugins/API.ts +58 -0
  78. package/plugins/iconify.client.ts +5 -0
  79. package/plugins/vuetify.ts +55 -0
  80. package/public/bdo-logo.svg +4 -0
  81. package/public/bpi-logo.svg +74 -0
  82. package/public/chinabank-logo.svg +120 -0
  83. package/public/gcash-logo.png +0 -0
  84. package/public/gcash-logo.svg +65 -0
  85. package/public/grabpay-logo.svg +99 -0
  86. package/public/paymaya-logo.jpg +0 -0
  87. package/public/paymaya-logo.png +0 -0
  88. package/public/paymaya-logo.svg +25 -0
  89. package/public/qrph-c567ff0f-ab6d-4662-86bf-24c6c731d8a8-logo.svg +20 -0
  90. package/public/rcbc-logo.svg +15 -0
  91. package/public/shopeepay-logo.svg +89 -0
  92. package/public/ubp-logo.svg +88 -0
  93. package/tsconfig.json +3 -0
  94. package/types/address.d.ts +13 -0
  95. package/types/invoice.d.ts +28 -0
  96. package/types/local.d.ts +25 -0
  97. package/types/member.d.ts +12 -0
  98. package/types/org.d.ts +13 -0
  99. package/types/payment-method.d.ts +11 -0
  100. package/types/payment.d.ts +18 -0
  101. package/types/permission.d.ts +14 -0
  102. package/types/price.d.ts +17 -0
  103. package/types/promo-code.d.ts +19 -0
  104. package/types/role.d.ts +13 -0
  105. package/types/subscription.d.ts +29 -0
  106. package/types/user.d.ts +21 -0
  107. package/types/verification.d.ts +15 -0
  108. package/types/xendit.d.ts +3 -0
@@ -0,0 +1,347 @@
1
+ import { z } from "zod";
2
+
3
+ export default function usePaymentMethod() {
4
+ function linkEWallet({
5
+ type = "GCASH",
6
+ customer_id = "",
7
+ success_return_url = "",
8
+ failure_return_url = "",
9
+ cancel_return_url = "",
10
+ category = "individual",
11
+ } = {}) {
12
+ return useNuxtApp().$api<Record<string, any>>(
13
+ "/api/payment-methods/e-wallet",
14
+ {
15
+ method: "POST",
16
+ body: {
17
+ customer_id,
18
+ type,
19
+ success_return_url,
20
+ failure_return_url,
21
+ cancel_return_url,
22
+ category,
23
+ },
24
+ }
25
+ );
26
+ }
27
+
28
+ function linkCard({
29
+ cardType = "",
30
+ cardNumber = "",
31
+ expiryMonth = "",
32
+ expiryYear = "",
33
+ cvv = "",
34
+ cardholderName = "",
35
+ currency = "",
36
+ success_return_url = "",
37
+ failure_return_url = "",
38
+ subscriptionData = {},
39
+ } = {}) {
40
+ return useNuxtApp().$api<Record<string, any>>("/api/payment-methods/card", {
41
+ method: "POST",
42
+ body: {
43
+ cardType,
44
+ cardNumber,
45
+ expiryMonth,
46
+ expiryYear,
47
+ cvv,
48
+ cardholderName,
49
+ currency,
50
+ success_return_url,
51
+ failure_return_url,
52
+ subscriptionData,
53
+ },
54
+ });
55
+ }
56
+
57
+ function getByUser(user = "") {
58
+ return useNuxtApp().$api<Array<Record<string, any>>>(
59
+ `/api/payment-methods/user/${user}`,
60
+ {
61
+ method: "GET",
62
+ }
63
+ );
64
+ }
65
+
66
+ function getByOrg(org = "") {
67
+ return useNuxtApp().$api<Array<Record<string, any>>>(
68
+ `/api/payment-methods/org/${org}`,
69
+ {
70
+ method: "GET",
71
+ }
72
+ );
73
+ }
74
+
75
+ function getById(id = "") {
76
+ return useNuxtApp().$api<Record<string, any>>(
77
+ `/api/payment-methods/id/${id}`
78
+ );
79
+ }
80
+
81
+ function getByCustomerId(id = "") {
82
+ return useNuxtApp().$api<Record<string, any>>(
83
+ `/api/payment-methods/customer/${id}`
84
+ );
85
+ }
86
+
87
+ const eWalletNumber = useState("eWalletNumber", () => "");
88
+ const cardNumber = useState("cardNumber", () => "");
89
+ const cardExpiration = useState("cardExpiration", () => "");
90
+ const cardSecurityCode = useState("cardSecurityCode", () => "");
91
+ const cardholderName = useState("cardholderName", () => "");
92
+ const cardholderMobileNumber = useState("cardholderMobileNumber", () => "");
93
+ const cardholderEmail = useState("cardholderEmail", () => "");
94
+ const selectedPaymentMethod = useState("selectedPaymentMethod", () => "");
95
+
96
+ function linkOnly(value: Record<string, any>) {
97
+ return useNuxtApp().$api<Record<string, any>>(
98
+ "/api/payment-methods/link-only",
99
+ {
100
+ method: "POST",
101
+ body: value,
102
+ }
103
+ );
104
+ }
105
+
106
+ const supportedEwallets = [
107
+ {
108
+ channel: "GCASH",
109
+ logo: "/gcash-logo.svg",
110
+ type: "EWALLET",
111
+ text: "GCash",
112
+ },
113
+ {
114
+ channel: "PAYMAYA",
115
+ logo: "/paymaya-logo.svg",
116
+ type: "EWALLET",
117
+ text: "PayMaya",
118
+ },
119
+ {
120
+ channel: "GRABPAY",
121
+ logo: "/grabpay-logo.svg",
122
+ type: "EWALLET",
123
+ text: "GrabPay",
124
+ },
125
+ {
126
+ channel: "SHOPEEPAY",
127
+ logo: "/shopeepay-logo.svg",
128
+ type: "EWALLET",
129
+ text: "ShopeePay",
130
+ },
131
+ ];
132
+
133
+ const supportedDirectDebit = [
134
+ {
135
+ channel: "UBP",
136
+ logo: "/ubp-logo.svg",
137
+ type: "DIRECT_DEBIT",
138
+ text: "BA_UBP",
139
+ },
140
+ {
141
+ channel: "BDO",
142
+ logo: "/bdo-logo.svg",
143
+ type: "DIRECT_DEBIT",
144
+ text: "BDO",
145
+ },
146
+ {
147
+ channel: "BPI",
148
+ logo: "/bpi-logo.svg",
149
+ type: "DIRECT_DEBIT",
150
+ text: "BA_BPI",
151
+ },
152
+ {
153
+ channel: "RCBC",
154
+ logo: "/rcbc-logo.svg",
155
+ type: "DIRECT_DEBIT",
156
+ text: "RCBC",
157
+ },
158
+ {
159
+ channel: "Chinabank",
160
+ logo: "/chinabank-logo.svg",
161
+ type: "DIRECT_DEBIT",
162
+ text: "Chinabank",
163
+ },
164
+ ];
165
+
166
+ const supportedPaymentMethods = [
167
+ ...supportedEwallets,
168
+ ...supportedDirectDebit,
169
+ ];
170
+
171
+ const { updatePaymentMethodById } = useSubscription();
172
+
173
+ const linkingOverlay = useState("linkingOverlay", () => false);
174
+ const updatingPaymentMethod = useState("updatingPaymentMethod", () => false);
175
+ const linkingMessage = useState("linkingMessage", () => "");
176
+ const paymentMethod = useState(
177
+ "paymentMethod",
178
+ (): Record<string, any> | null => null
179
+ );
180
+
181
+ function reset() {
182
+ eWalletNumber.value = "";
183
+ cardNumber.value = "";
184
+ cardExpiration.value = "";
185
+ cardSecurityCode.value = "";
186
+ cardholderName.value = "";
187
+ paymentMethod.value = null;
188
+ }
189
+
190
+ async function initLink(value: TLinkParams, callback?: Function) {
191
+ const validation = z.object({
192
+ subscriptionId: z.string().min(1).optional(),
193
+ paymentMethodType: z.enum(["EWALLET", "DIRECT_DEBIT", "CREDIT_CARD"]),
194
+ paymentMethodChannel: z.string().min(1),
195
+ customerId: z.string().min(1),
196
+ card_number: z.string().optional(),
197
+ expiry_month: z.string().optional(),
198
+ expiry_year: z.string().optional(),
199
+ card_security_code: z.string().optional(),
200
+ cardholder_name: z.string().optional(),
201
+ });
202
+
203
+ const parsed = validation.safeParse(value);
204
+
205
+ if (!parsed.success) {
206
+ throw new Error(
207
+ `Validation failed: ${parsed.error.issues
208
+ .map((issue) => `${issue.path.join(".")}: ${issue.message}`)
209
+ .join(", ")}`
210
+ );
211
+ }
212
+
213
+ linkingOverlay.value = true;
214
+ const success_return_url = `${window.origin}/payment-method-linked`;
215
+ const failure_return_url = `${window.origin}/payment-method-failed-link`;
216
+ const cancel_return_url = `${window.origin}/payment-method-cancel-link`;
217
+
218
+ const payload: Record<string, any> = {
219
+ type: value.paymentMethodType,
220
+ reusability: "MULTIPLE_USE",
221
+ };
222
+
223
+ if (payload.type === "EWALLET") {
224
+ payload.country = "PH";
225
+ payload.ewallet = {
226
+ channel_code: value.paymentMethodChannel,
227
+ channel_properties: {
228
+ success_return_url,
229
+ failure_return_url,
230
+ cancel_return_url,
231
+ },
232
+ };
233
+
234
+ payload.customer_id = value.customerId;
235
+ } else if (payload.type === "DIRECT_DEBIT") {
236
+ payload.direct_debit = {
237
+ channel_code: value.paymentMethodChannel,
238
+ channel_properties: {
239
+ success_return_url,
240
+ failure_return_url,
241
+ },
242
+ };
243
+ payload.customer_id = value.customerId;
244
+ } else if (payload.type === "CARD") {
245
+ payload.card = {
246
+ currency: "PHP",
247
+ channel_properties: {
248
+ success_return_url,
249
+ failure_return_url,
250
+ skip_three_d_secure: true,
251
+ },
252
+ card_information: {
253
+ card_number: value.card_number,
254
+ expiry_month: value.expiry_month,
255
+ expiry_year: value.expiry_year,
256
+ cvv: value.card_security_code,
257
+ cardholder_name: value.cardholder_name,
258
+ },
259
+ };
260
+ }
261
+
262
+ try {
263
+ const _paymentMethod = await linkOnly(payload);
264
+
265
+ // Open a small popup window
266
+ const popupWidth = 500;
267
+ const popupHeight = 600;
268
+ const left = (screen.width - popupWidth) / 2;
269
+ const top = (screen.height - popupHeight) / 2;
270
+
271
+ const popup = window.open(
272
+ _paymentMethod.actions[0].url,
273
+ "eWalletPopup",
274
+ `width=${popupWidth},height=${popupHeight},top=${top},left=${left},resizable=yes,scrollbars=yes`
275
+ );
276
+
277
+ // Check every 500ms if the popup is closed
278
+ const checkPopupClosed = setInterval(async () => {
279
+ if (!popup || popup.closed) {
280
+ clearInterval(checkPopupClosed);
281
+ console.log(
282
+ "Popup closed. Proceeding with subscription automation..."
283
+ );
284
+ // Call your function to handle subscription
285
+
286
+ const temp = await getById(_paymentMethod.id);
287
+
288
+ if (temp.status === "ACTIVE" && value.subscriptionId) {
289
+ await updatePaymentMethodById(
290
+ value.subscriptionId,
291
+ _paymentMethod.id as string
292
+ );
293
+
294
+ paymentMethod.value = await getById(_paymentMethod.id);
295
+ }
296
+
297
+ if (callback) {
298
+ callback();
299
+ }
300
+
301
+ updatingPaymentMethod.value = false;
302
+ linkingOverlay.value = false;
303
+ }
304
+ }, 500);
305
+ } catch (error: any) {
306
+ linkingMessage.value = error.response._data.message;
307
+ }
308
+ }
309
+
310
+ function updateStatusById(id: string, status: string) {
311
+ return useNuxtApp().$api<Record<string, any>>(
312
+ `/api/payment-methods/status/${id}`,
313
+ {
314
+ method: "PATCH",
315
+ body: { status },
316
+ }
317
+ );
318
+ }
319
+
320
+ return {
321
+ linkEWallet,
322
+ linkCard,
323
+ getByUser,
324
+ getByOrg,
325
+ eWalletNumber,
326
+ cardNumber,
327
+ cardExpiration,
328
+ cardSecurityCode,
329
+ cardholderName,
330
+ cardholderMobileNumber,
331
+ cardholderEmail,
332
+ selectedPaymentMethod,
333
+ reset,
334
+ linkOnly,
335
+ getById,
336
+ supportedPaymentMethods,
337
+ supportedDirectDebit,
338
+ supportedEwallets,
339
+ initLink,
340
+ linkingOverlay,
341
+ updatingPaymentMethod,
342
+ linkingMessage,
343
+ paymentMethod,
344
+ getByCustomerId,
345
+ updateStatusById,
346
+ };
347
+ }
@@ -0,0 +1,54 @@
1
+ export default function usePermission() {
2
+ // Permission-Based Access Control with Dynamic Role Creation
3
+
4
+ // Utility to list all resources and their actions
5
+ function listPermissions(permissions: TPermissions): {
6
+ resource: string;
7
+ actions: { title: string; description: string }[];
8
+ }[] {
9
+ return Object.entries(permissions).map(([resource, actions]) => ({
10
+ resource,
11
+ actions: Object.entries(actions).map(([action, { description }]) => ({
12
+ title: action,
13
+ description,
14
+ })),
15
+ }));
16
+ }
17
+
18
+ // Utility to check if a user has permission
19
+ function hasPermission(
20
+ user: TRole,
21
+ permissions: TPermissions,
22
+ resource: string,
23
+ action: string,
24
+ data?: any
25
+ ): boolean {
26
+ const permissionKey = `${resource}:${action}`;
27
+
28
+ // Check if the permission exists in the user's permission array
29
+ if (!user.permissions?.includes(permissionKey)) {
30
+ return false;
31
+ }
32
+
33
+ const resourcePermissions = permissions[resource];
34
+ if (!resourcePermissions || !resourcePermissions[action]) {
35
+ return false;
36
+ }
37
+
38
+ const permissionCheck = resourcePermissions[action].check;
39
+
40
+ // Evaluate the permission check
41
+ if (typeof permissionCheck === "boolean") {
42
+ return permissionCheck;
43
+ } else if (typeof permissionCheck === "function") {
44
+ return permissionCheck(user, data);
45
+ }
46
+
47
+ return false;
48
+ }
49
+
50
+ return {
51
+ listPermissions,
52
+ hasPermission,
53
+ };
54
+ }
@@ -0,0 +1,15 @@
1
+ export default function usePrice() {
2
+ function getByNameType(name: string, type: string) {
3
+ return useNuxtApp().$api<Record<string, any>>("/api/prices/price", {
4
+ method: "GET",
5
+ params: {
6
+ name,
7
+ type,
8
+ },
9
+ });
10
+ }
11
+
12
+ return {
13
+ getByNameType,
14
+ };
15
+ }
@@ -0,0 +1,43 @@
1
+ export default function usePromoCode() {
2
+ function add(value: TPromoCode) {
3
+ return useNuxtApp().$api<Record<string, any>>("/api/promo-codes", {
4
+ method: "POST",
5
+ body: value,
6
+ });
7
+ }
8
+
9
+ function getPromoCodes({ search = "", page = 1, status = "active" } = {}) {
10
+ return useNuxtApp().$api<Record<string, any>>("/api/promo-codes", {
11
+ method: "GET",
12
+ query: {
13
+ search,
14
+ page,
15
+ status,
16
+ },
17
+ });
18
+ }
19
+
20
+ function getByCode(code: string, type?: string, assigned?: boolean) {
21
+ return useNuxtApp().$api<TPromoCode>("/api/promo-codes/code", {
22
+ method: "GET",
23
+ params: {
24
+ code,
25
+ type,
26
+ assigned,
27
+ },
28
+ });
29
+ }
30
+
31
+ function getById(id: string) {
32
+ return useNuxtApp().$api<TPromoCode>(`/api/promo-codes/id/${id}`, {
33
+ method: "GET",
34
+ });
35
+ }
36
+
37
+ return {
38
+ add,
39
+ getPromoCodes,
40
+ getByCode,
41
+ getById,
42
+ };
43
+ }
@@ -0,0 +1,26 @@
1
+ export default function useRecapPermission() {
2
+ const permissions: TPermissions = {
3
+ request: {
4
+ "create-request": {
5
+ check: true,
6
+ description: "Create a new request.",
7
+ },
8
+ "review-request": {
9
+ check: true,
10
+ description: "Review a request.",
11
+ },
12
+ "approve-request": {
13
+ check: true,
14
+ description: "Approve a request.",
15
+ },
16
+ "delete-request": {
17
+ check: true,
18
+ description: "Delete authored request.",
19
+ },
20
+ },
21
+ };
22
+
23
+ return {
24
+ permissions,
25
+ };
26
+ }
@@ -0,0 +1,89 @@
1
+ export default function useRole() {
2
+ function createRole(
3
+ { name, permissions, type, org } = {} as {
4
+ name: string;
5
+ permissions: Array<string>;
6
+ type: string;
7
+ org: string;
8
+ }
9
+ ) {
10
+ return useNuxtApp().$api("/api/roles", {
11
+ method: "POST",
12
+ body: { name, permissions, type, org },
13
+ });
14
+ }
15
+
16
+ function getRoles({
17
+ search = "",
18
+ page = 1,
19
+ limit = 20,
20
+ type = "",
21
+ org = "",
22
+ } = {}) {
23
+ return useNuxtApp().$api<Record<string, any>>("/api/roles", {
24
+ method: "GET",
25
+ query: { search, page, limit, type, org },
26
+ });
27
+ }
28
+
29
+ function getRoleById(id: string) {
30
+ return useNuxtApp().$api<Record<string, any>>(`/api/roles/id/${id}`, {
31
+ method: "GET",
32
+ });
33
+ }
34
+
35
+ function updateRoleById(
36
+ _id: string,
37
+ name?: string,
38
+ permissions?: Array<string>
39
+ ) {
40
+ return useNuxtApp().$api(`/api/roles/id/${_id}`, {
41
+ method: "PATCH",
42
+ body: { name, permissions },
43
+ });
44
+ }
45
+
46
+ function updatePermissionById(_id: string, permissions?: Array<string>) {
47
+ return useNuxtApp().$api(`/api/roles/permissions/id/${_id}`, {
48
+ method: "PATCH",
49
+ body: { permissions },
50
+ });
51
+ }
52
+
53
+ function updateRoleFieldById(_id: string, field: string, value: string) {
54
+ return useNuxtApp().$api(`/api/roles/${_id}`, {
55
+ method: "PATCH",
56
+ body: { field, value },
57
+ });
58
+ }
59
+
60
+ function deleteRole(_id: string) {
61
+ return useNuxtApp().$api<Record<string, any>>(`/api/roles/${_id}`, {
62
+ method: "DELETE",
63
+ });
64
+ }
65
+
66
+ const role = useState("userRole", (): TRole => {
67
+ return {
68
+ _id: "",
69
+ name: "",
70
+ org: "",
71
+ permissions: [],
72
+ createdAt: "",
73
+ updatedAt: "",
74
+ deletedAt: "",
75
+ default: false,
76
+ };
77
+ });
78
+
79
+ return {
80
+ role,
81
+ createRole,
82
+ getRoles,
83
+ getRoleById,
84
+ updateRoleById,
85
+ updateRoleFieldById,
86
+ deleteRole,
87
+ updatePermissionById,
88
+ };
89
+ }
@@ -0,0 +1,13 @@
1
+ export function useSchoolPermission() {
2
+ const { memberPermissions, rolePermissions, invitationPermission } =
3
+ useCommonPermissions();
4
+ const permissions: TPermissions = {
5
+ members: memberPermissions,
6
+ invitations: invitationPermission,
7
+ roles: rolePermissions,
8
+ };
9
+
10
+ return {
11
+ permissions,
12
+ };
13
+ }