@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,159 @@
1
+ <template>
2
+ <v-row no-gutters class="mb-4 pl-4 fill-height" align="center">
3
+ <v-avatar color="surface-variant" size="28">
4
+ <v-img
5
+ v-if="currentUser?.profile"
6
+ :src="profile"
7
+ width="200"
8
+ height="200"
9
+ />
10
+ <span v-else class="text-subtitle-1">{{
11
+ getNameInitials(selectedOrg?.text)
12
+ }}</span>
13
+ </v-avatar>
14
+
15
+ <v-menu
16
+ v-model="menu"
17
+ location="bottom"
18
+ offset="5px"
19
+ :close-on-content-click="false"
20
+ >
21
+ <template #activator="{ props }">
22
+ <v-btn
23
+ variant="text"
24
+ class="text-none ml-2"
25
+ size="large"
26
+ v-bind="props"
27
+ >
28
+ <div class="d-block text-truncate text-start" style="width: 130px">
29
+ {{ selectedOrg?.text || "Select organization" }}
30
+ </div>
31
+ <v-icon class="ml-1">mdi-menu-down</v-icon>
32
+ </v-btn>
33
+ </template>
34
+
35
+ <v-card width="300px" rounded="lg" class="pa-4">
36
+ <span class="text-subtitle-2 font-weight-bold">
37
+ Switch organization context
38
+ </span>
39
+ <v-text-field density="compact" width="100%" hide-details class="mb-2">
40
+ <template #prepend-inner>
41
+ <v-icon>mdi-magnify</v-icon>
42
+ </template>
43
+ </v-text-field>
44
+ <v-divider />
45
+ <v-list class="pa-0 my-2" density="compact" max-height="200px">
46
+ <v-list-item
47
+ density="compact"
48
+ class="text-caption font-weight-bold"
49
+ v-for="item in orgs"
50
+ @click="switchOrg(item.value)"
51
+ >
52
+ <v-icon size="16" class="mr-2">
53
+ {{ currentOrg === item.value ? "mdi-check" : "" }}
54
+ </v-icon>
55
+
56
+ {{ item.text }}
57
+ </v-list-item>
58
+ </v-list>
59
+
60
+ <v-btn
61
+ v-if="isOrg"
62
+ block
63
+ class="text-none mb-1"
64
+ variant="tonal"
65
+ @click="navigateToOrgs"
66
+ >
67
+ Manage Organizations
68
+ </v-btn>
69
+ <v-btn
70
+ v-if="isOrg"
71
+ block
72
+ class="text-none mt-1"
73
+ variant="tonal"
74
+ @click="createOrg"
75
+ >
76
+ Create Organization
77
+ </v-btn>
78
+ </v-card>
79
+ </v-menu>
80
+ </v-row>
81
+ </template>
82
+
83
+ <script setup lang="ts">
84
+ const { currentUser } = useLocalAuth();
85
+
86
+ const menu = ref(false);
87
+ const { getNameInitials } = useUtils();
88
+
89
+ const profile = computed(() => {
90
+ return `/api/public/${currentUser.value?.profile}`;
91
+ });
92
+
93
+ const { getByUserId: _getByUserId, currentOrg } = useOrg();
94
+
95
+ const orgs = ref<Array<Record<string, any>>>([]);
96
+ const page = ref(1);
97
+
98
+ const selectedOrg = ref<Record<string, any> | null>();
99
+
100
+ function setOrg() {
101
+ selectedOrg.value = orgs.value.find((org) => org.value === currentOrg.value);
102
+ }
103
+
104
+ watch(currentOrg, () => {
105
+ menu.value = false;
106
+ setOrg();
107
+ });
108
+
109
+ const { data: userOrgReq } = useLazyAsyncData("orgs-by-user", () => {
110
+ return _getByUserId({ user: currentUser.value?._id });
111
+ });
112
+
113
+ watchEffect(() => {
114
+ if (userOrgReq.value) {
115
+ orgs.value = userOrgReq.value.items;
116
+ page.value = userOrgReq.value.page;
117
+ setOrg();
118
+ }
119
+ });
120
+
121
+ function switchOrg(org: string) {
122
+ navigateTo({
123
+ name: "org-organization",
124
+ params: { organization: org },
125
+ });
126
+ }
127
+
128
+ const APP_NAME = useRuntimeConfig().public.APP_NAME;
129
+ const APP_ORG = useRuntimeConfig().public.APP_ORG;
130
+
131
+ const { redirect } = useLocal();
132
+
133
+ function createOrg() {
134
+ if (APP_NAME.toLowerCase() === "organization") {
135
+ navigateTo({
136
+ name: "organizations-create",
137
+ });
138
+ return;
139
+ }
140
+
141
+ redirect(APP_ORG, "organizations/create");
142
+ }
143
+
144
+ function navigateToOrgs() {
145
+ if (APP_NAME.toLowerCase() === "organization") {
146
+ navigateTo({
147
+ name: "organizations",
148
+ params: { status: "active" },
149
+ });
150
+ return;
151
+ }
152
+
153
+ redirect(APP_ORG, "organizations");
154
+ }
155
+
156
+ const isOrg = computed(() => {
157
+ return APP_NAME.toLowerCase() === "organization";
158
+ });
159
+ </script>
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <v-card
3
+ width="100%"
4
+ variant="outlined"
5
+ border="thin"
6
+ rounded="lg"
7
+ :loading="loading"
8
+ >
9
+ <v-toolbar density="compact" color="grey-lighten-4">
10
+ <template #prepend>
11
+ <v-checkbox v-model="selectAll" hide-details class="mx-1"></v-checkbox>
12
+
13
+ <v-btn fab icon density="comfortable" @click="emit('refresh')">
14
+ <v-icon>mdi-refresh</v-icon>
15
+ </v-btn>
16
+ </template>
17
+
18
+ <template #append>
19
+ <v-row no-gutters justify="end" align="center">
20
+ <span class="mr-2 text-caption text-fontgray">
21
+ {{ props.pageRange }}
22
+ </span>
23
+ <div class="arrow-navigation">
24
+ <v-btn
25
+ icon="mdi-chevron-left"
26
+ variant="text"
27
+ density="comfortable"
28
+ :disabled="page <= 1"
29
+ @click="decrement"
30
+ />
31
+ <v-btn
32
+ icon="mdi-chevron-right"
33
+ variant="text"
34
+ density="comfortable"
35
+ :disabled="page >= props.pages"
36
+ @click="increment"
37
+ />
38
+ </div>
39
+ </v-row>
40
+ </template>
41
+
42
+ <template v-if="$slots.extension" v-slot:extension>
43
+ <slot name="extension"></slot>
44
+ </template>
45
+ </v-toolbar>
46
+ <v-divider></v-divider>
47
+
48
+ <v-data-table
49
+ v-model="selected"
50
+ v-bind="attrs"
51
+ :headers="props.headers"
52
+ :items="props.items"
53
+ item-value="_id"
54
+ items-per-page="10"
55
+ show-select
56
+ fixed-header
57
+ hide-default-footer
58
+ hide-default-header
59
+ :loading="props.loading"
60
+ :style="`max-height: ${props.height};`"
61
+ >
62
+ <template v-if="$slots.item" v-slot:item>
63
+ <slot name="item"></slot>
64
+ </template>
65
+ </v-data-table>
66
+ </v-card>
67
+ </template>
68
+
69
+ <script setup lang="ts">
70
+ const attrs = useAttrs();
71
+ const selected = defineModel({
72
+ type: Array as PropType<Array<string>>,
73
+ default: () => [],
74
+ });
75
+ const page = defineModel("page", { type: Number, default: 0 });
76
+
77
+ const props = defineProps({
78
+ headers: {
79
+ type: Array as PropType<Array<Record<string, string>>>,
80
+ required: true,
81
+ default: () => [],
82
+ },
83
+ items: {
84
+ type: Array as PropType<Array<Record<string, string>>>,
85
+ required: true,
86
+ default: () => [],
87
+ },
88
+ pages: {
89
+ type: Number,
90
+ required: true,
91
+ default: 0,
92
+ },
93
+ pageRange: {
94
+ type: String,
95
+ required: true,
96
+ default: "-- - -- of --",
97
+ },
98
+ loading: {
99
+ type: Boolean,
100
+ required: true,
101
+ default: true,
102
+ },
103
+ height: {
104
+ type: String,
105
+ default: "",
106
+ },
107
+ });
108
+
109
+ const emit = defineEmits(["refresh", "update:pagination"]);
110
+
111
+ function increment() {
112
+ page.value++;
113
+ emit("update:pagination", page.value);
114
+ }
115
+
116
+ function decrement() {
117
+ page.value--;
118
+ emit("update:pagination", page.value);
119
+ }
120
+
121
+ const selectAll = ref(false);
122
+
123
+ watch(selectAll, (curr) => {
124
+ selected.value.splice(0, selected.value.length);
125
+ if (curr) {
126
+ const ids = props.items.map((i) => i._id as string);
127
+ selected.value.push(...ids);
128
+ }
129
+ });
130
+ </script>
@@ -0,0 +1,144 @@
1
+ export default function useAddress() {
2
+ function add({
3
+ type = "",
4
+ user = "",
5
+ org = "",
6
+ country = "",
7
+ countryCode = "",
8
+ phoneNumber = "",
9
+ address = "",
10
+ continuedAddress = "",
11
+ city = "",
12
+ province = "",
13
+ postalCode = "",
14
+ taxId = "",
15
+ } = {}) {
16
+ return useNuxtApp().$api("/api/addresses", {
17
+ method: "POST",
18
+ body: {
19
+ type,
20
+ user,
21
+ org,
22
+ country,
23
+ countryCode,
24
+ phoneNumber,
25
+ address,
26
+ continuedAddress,
27
+ city,
28
+ province,
29
+ postalCode,
30
+ taxId,
31
+ },
32
+ });
33
+ }
34
+
35
+ function updateById({
36
+ id = "",
37
+ country = "",
38
+ address = "",
39
+ continuedAddress = "",
40
+ city = "",
41
+ province = "",
42
+ postalCode = "",
43
+ taxId = "",
44
+ orgId = "",
45
+ } = {}) {
46
+ const payload: Record<string, any> = {
47
+ country,
48
+ address,
49
+ continuedAddress,
50
+ city,
51
+ province,
52
+ postalCode,
53
+ taxId,
54
+ };
55
+
56
+ if (orgId) {
57
+ payload.org = orgId;
58
+ }
59
+
60
+ return useNuxtApp().$api(`/api/addresses/details/${id}`, {
61
+ method: "PUT",
62
+ body: payload,
63
+ });
64
+ }
65
+
66
+ function getByUserId(user = "") {
67
+ return useNuxtApp().$api<TAddress>(`/api/addresses/user/${user}`);
68
+ }
69
+
70
+ function getByOrgId(id = "") {
71
+ return useNuxtApp().$api<TAddress>(`/api/addresses/org/${id}`);
72
+ }
73
+
74
+ const _address = useState("address", (): TAddress => {
75
+ return {
76
+ type: "",
77
+ user: "",
78
+ org: "",
79
+ country: "",
80
+ address: "",
81
+ continuedAddress: "",
82
+ city: "",
83
+ province: "",
84
+ postalCode: "",
85
+ taxId: "",
86
+ };
87
+ });
88
+
89
+ function reset() {
90
+ _address.value.type = "";
91
+ _address.value.user = "";
92
+ _address.value.org = "";
93
+ _address.value.country = "";
94
+ _address.value.address = "";
95
+ _address.value.continuedAddress = "";
96
+ _address.value.city = "";
97
+ _address.value.province = "";
98
+ _address.value.postalCode = "";
99
+ _address.value.taxId = "";
100
+ }
101
+
102
+ function set({
103
+ type = "",
104
+ user = "",
105
+ org = "",
106
+ country = "",
107
+ address = "",
108
+ continuedAddress = "",
109
+ city = "",
110
+ province = "",
111
+ postalCode = "",
112
+ taxId = "",
113
+ } = {}) {
114
+ _address.value.type = type;
115
+ _address.value.user = user;
116
+ _address.value.org = org;
117
+ _address.value.country = country;
118
+ _address.value.address = address;
119
+ _address.value.continuedAddress = continuedAddress;
120
+ _address.value.city = city;
121
+ _address.value.province = province;
122
+ _address.value.postalCode = postalCode;
123
+ _address.value.taxId = taxId;
124
+ }
125
+
126
+ const { address, city, province, postalCode, country } = _address.value;
127
+
128
+ const completeAddress = computed(() => {
129
+ return `${address ? `${address}, ` : ""}${
130
+ city ? `${city}, ` : ""
131
+ } ${province} ${postalCode ? `${postalCode}, ` : ""} ${country}`;
132
+ });
133
+
134
+ return {
135
+ add,
136
+ reset,
137
+ set,
138
+ getByUserId,
139
+ address: _address,
140
+ completeAddress,
141
+ getByOrgId,
142
+ updateById,
143
+ };
144
+ }
@@ -0,0 +1,62 @@
1
+ export default function useChartOfAccount() {
2
+ function getAll(
3
+ { page = 1, status = "active", orgId = "", children = null } = {} as {
4
+ page?: number;
5
+ status?: string;
6
+ orgId?: string;
7
+ children?: number;
8
+ }
9
+ ) {
10
+ return useNuxtApp().$api<Record<string, any>>("/api/chart-of-accounts", {
11
+ method: "GET",
12
+ query: { page, status, orgId, children },
13
+ });
14
+ }
15
+
16
+ type TAddPayload = {
17
+ orgId: string;
18
+ code: string;
19
+ name: string;
20
+ normalBalance: string;
21
+ parent?: string;
22
+ description?: string;
23
+ };
24
+
25
+ function add(value: TAddPayload) {
26
+ return useNuxtApp().$api<TAddPayload>("/api/chart-of-accounts", {
27
+ method: "POST",
28
+ body: value,
29
+ });
30
+ }
31
+
32
+ function getById(id: string) {
33
+ return useNuxtApp().$api<Record<string, any>>(
34
+ `/api/chart-of-accounts/id/${id}`
35
+ );
36
+ }
37
+
38
+ function updateById(
39
+ id: string,
40
+ value: Pick<TAddPayload, "name" | "code" | "normalBalance" | "parent">
41
+ ) {
42
+ return useNuxtApp().$api<TAddPayload>(`/api/chart-of-accounts/id/${id}`, {
43
+ method: "PUT",
44
+ body: value,
45
+ });
46
+ }
47
+
48
+ function deleteById(id: string) {
49
+ return useNuxtApp().$api<Record<string, any>>(
50
+ `/api/chart-of-accounts/id/${id}`,
51
+ { method: "DELETE" }
52
+ );
53
+ }
54
+
55
+ return {
56
+ getAll,
57
+ add,
58
+ getById,
59
+ updateById,
60
+ deleteById,
61
+ };
62
+ }
@@ -0,0 +1,130 @@
1
+ export function useCommonPermissions() {
2
+ const invitationPermissions: Record<string, TPermission> = {
3
+ "create-invitation": {
4
+ check: true,
5
+ description:
6
+ "Allows the user to create a new invitation for a invitation to join the organization.",
7
+ },
8
+ "view-invitations": {
9
+ check: true,
10
+ description:
11
+ "Allows the user to view the list of all invitation in the organization.",
12
+ },
13
+ "cancel-invitation": {
14
+ check: true,
15
+ description:
16
+ "Allows the user to permanently remove a invitation from the organization.",
17
+ },
18
+ };
19
+
20
+ const memberPermissions: Record<string, TPermission> = {
21
+ "view-members": {
22
+ check: true,
23
+ description:
24
+ "Allows the user to view the list of all members in the organization.",
25
+ },
26
+ "assign-member-role": {
27
+ check: true,
28
+ description:
29
+ "Allows the user to assign a specific role to a member in the organization.",
30
+ },
31
+ "suspend-member": {
32
+ check: true,
33
+ description: "Allows the user to suspend a member's account temporarily.",
34
+ },
35
+ "activate-member": {
36
+ check: true,
37
+ description:
38
+ "Allows the user to reactivate a suspended member's account.",
39
+ },
40
+ "delete-member": {
41
+ check: true,
42
+ description:
43
+ "Allows the user to permanently remove a member from the organization.",
44
+ },
45
+ };
46
+
47
+ const rolePermissions: Record<string, TPermission> = {
48
+ "add-role": {
49
+ check: true,
50
+ description: "Allows the user to add a new role to the system.",
51
+ },
52
+ "see-all-roles": {
53
+ check: true,
54
+ description: "Allows the user to view the list of all roles.",
55
+ },
56
+ "see-role-details": {
57
+ check: true,
58
+ description: "Allows the user to view the details of a specific role.",
59
+ },
60
+ "delete-role": {
61
+ check: true,
62
+ description:
63
+ "Allows the user to remove a role from the system permanently.",
64
+ },
65
+ "update-role": {
66
+ check: true,
67
+ description: "Allows the user to update the details of an existing role.",
68
+ },
69
+ };
70
+
71
+ const feedbackPermissions: Record<string, TPermission> = {
72
+ "add-feedback": {
73
+ check: true,
74
+ description: "Allows the user to create a new feedback.",
75
+ },
76
+ "see-all-feedback": {
77
+ check: true,
78
+ description: "Allows the user to view the list of all feedback.",
79
+ },
80
+ "see-feedback-details": {
81
+ check: true,
82
+ description:
83
+ "Allows the user to view the details of a specific feedback.",
84
+ },
85
+ "delete-feedback": {
86
+ check: true,
87
+ description:
88
+ "Allows the user to remove a feedback from the system permanently.",
89
+ },
90
+ "update-feedback": {
91
+ check: true,
92
+ description:
93
+ "Allows the user to update the details of an existing feedback.",
94
+ },
95
+ };
96
+
97
+ const workOrderPermissions: Record<string, TPermission> = {
98
+ "create-work-order": {
99
+ check: true,
100
+ description: "Allows the user to create a new work order.",
101
+ },
102
+ "see-all-work-orders": {
103
+ check: true,
104
+ description: "Allows the user to view the list of all work orders.",
105
+ },
106
+ "see-work-order-details": {
107
+ check: true,
108
+ description:
109
+ "Allows the user to view the details of a specific work order.",
110
+ },
111
+ "delete-work-order": {
112
+ check: true,
113
+ description:
114
+ "Allows the user to remove a work order from the system permanently.",
115
+ },
116
+ "update-work-order": {
117
+ check: true,
118
+ description:
119
+ "Allows the user to update the details of an existing work order.",
120
+ },
121
+ };
122
+
123
+ return {
124
+ invitationPermissions,
125
+ memberPermissions,
126
+ rolePermissions,
127
+ feedbackPermissions,
128
+ workOrderPermissions,
129
+ };
130
+ }
@@ -0,0 +1,29 @@
1
+ export default function useFile() {
2
+ function addFile(file: File | null) {
3
+ if (!file) {
4
+ throw new Error("File not found.");
5
+ }
6
+
7
+ const formData = new FormData();
8
+ formData.append("file", file);
9
+
10
+ return useNuxtApp().$api<Record<string, any>>("/api/files", {
11
+ method: "POST",
12
+ body: formData,
13
+ });
14
+ }
15
+
16
+ function deleteFile(attachmentId: string) {
17
+ return useNuxtApp().$api<Record<string, any>>(
18
+ `/api/files/${attachmentId}`,
19
+ {
20
+ method: "DELETE",
21
+ }
22
+ );
23
+ }
24
+
25
+ return {
26
+ addFile,
27
+ deleteFile,
28
+ };
29
+ }
@@ -0,0 +1,42 @@
1
+ export default function useInvoice() {
2
+ function getBySubscriptionId({ search = "", id = "", page = 1 } = {}) {
3
+ if (!id) {
4
+ throw new Error("Subscription ID is required");
5
+ }
6
+
7
+ return useNuxtApp().$api<Record<string, any>>(
8
+ `/api/invoices/subscription/${id}`,
9
+ {
10
+ method: "GET",
11
+ params: {
12
+ search,
13
+ page,
14
+ },
15
+ }
16
+ );
17
+ }
18
+
19
+ function getByNumber(number: string) {
20
+ return useNuxtApp().$api<Record<string, any>>(
21
+ `/api/invoices/number/${number}`,
22
+ {
23
+ method: "GET",
24
+ }
25
+ );
26
+ }
27
+
28
+ function getByDueDateStatus(date: string, status: string) {
29
+ return useNuxtApp().$api<Record<string, any>>(
30
+ `/api/invoices/due-date/${date}/status/${status}`,
31
+ {
32
+ method: "GET",
33
+ }
34
+ );
35
+ }
36
+
37
+ return {
38
+ getBySubscriptionId,
39
+ getByNumber,
40
+ getByDueDateStatus,
41
+ };
42
+ }