@goweekdays/layer-common 0.0.13 → 0.1.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.
@@ -10,7 +10,7 @@ const inputRef = ref<HTMLInputElement | null>(null);
10
10
  const attrs = useAttrs();
11
11
 
12
12
  let cursorPosition = 0;
13
- let forceCursorToEnd = false;
13
+ let forceCursorToEnd = true;
14
14
 
15
15
  // Computed property to format value with commas or infinity sign
16
16
  const formattedValue = computed({
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <v-app-bar scroll-behavior="elevate" scroll-threshold="200">
3
- <div style="width: 264px" class="ml-4">
3
+ <v-app-bar-nav-icon @click="drawer = !drawer" />
4
+ <div style="width: 206px" class="ml-4">
4
5
  <nuxt-link
5
6
  class="text-h6 font-weight-medium text-decoration-none APP_NAME"
6
7
  :to="{ name: APP_NAME_ROUTE }"
@@ -172,7 +173,7 @@ import { useTheme } from "vuetify";
172
173
 
173
174
  const search = defineModel("search", { type: String });
174
175
 
175
- const { redirect, apps } = useLocal();
176
+ const { redirect, apps, drawer } = useLocal();
176
177
 
177
178
  const {
178
179
  APP_MAIN,
@@ -220,7 +221,7 @@ const name = computed(() => {
220
221
 
221
222
  const { getNameInitials } = useUtils();
222
223
 
223
- const defaultApps = [
224
+ const defaultApps = computed(() => [
224
225
  {
225
226
  title: "Account",
226
227
  icon: "mdi-account",
@@ -231,7 +232,9 @@ const defaultApps = [
231
232
  title: "Organization",
232
233
  icon: "mdi-domain",
233
234
  link: APP_ORG,
234
- landingPage: `org/${currentUser.value?.defaultOrg}`,
235
+ landingPage: currentUser.value?.defaultOrg
236
+ ? `org/${currentUser.value?.defaultOrg}`
237
+ : "index",
235
238
  },
236
239
  {
237
240
  title: "Admin",
@@ -245,7 +248,7 @@ const defaultApps = [
245
248
  link: APP_AFFILIATE,
246
249
  landingPage: "home",
247
250
  },
248
- ];
251
+ ]);
249
252
  </script>
250
253
 
251
254
  <style scoped>
@@ -1,16 +1,17 @@
1
1
  <template>
2
- <v-navigation-drawer permanent floating class="pr-2">
3
- <v-list>
2
+ <v-navigation-drawer v-model="drawer" permanent floating class="pr-2">
3
+ <v-list class="py-1">
4
4
  <slot name="action"></slot>
5
5
  <template
6
6
  v-for="(navigationItem, navigationIndex) in props.navigationItems"
7
- :key="`${navigationItem.route.name}-${navigationIndex}`"
7
+ :key="`${navigationItem.title}-${navigationIndex}`"
8
8
  >
9
9
  <NavigationItem
10
10
  :title="navigationItem.title"
11
11
  :icon="navigationItem.icon"
12
12
  :route="navigationItem.route"
13
13
  :children="navigationItem.children"
14
+ :disabled="navigationItem.disabled"
14
15
  />
15
16
  </template>
16
17
  </v-list>
@@ -21,4 +22,6 @@
21
22
  const props = defineProps({
22
23
  navigationItems: { type: Array<TNavigationItem>, required: true },
23
24
  });
25
+
26
+ const { drawer } = useLocal();
24
27
  </script>
@@ -1,31 +1,41 @@
1
1
  <template>
2
- <div class="arrow-navigation">
3
- <v-btn icon="mdi-chevron-left" variant="text" density="comfortable" :disabled="page <= 1" @click="decrement" />
4
- <v-btn
5
- icon="mdi-chevron-right" variant="text" density="comfortable" :disabled="page >= props.length"
6
- @click="increment" />
7
- </div>
2
+ <div class="arrow-navigation">
3
+ <v-btn
4
+ icon="mdi-chevron-left"
5
+ variant="text"
6
+ density="comfortable"
7
+ :disabled="page <= 1"
8
+ @click="decrement"
9
+ />
10
+ <v-btn
11
+ icon="mdi-chevron-right"
12
+ variant="text"
13
+ density="comfortable"
14
+ :disabled="page >= props.length"
15
+ @click="increment"
16
+ />
17
+ </div>
8
18
  </template>
9
19
 
10
20
  <script setup lang="ts">
11
21
  const page = defineModel({ type: Number, default: 0 });
12
22
  function increment() {
13
- page.value++;
23
+ page.value++;
14
24
  }
15
25
 
16
26
  function decrement() {
17
- page.value--;
27
+ page.value--;
18
28
  }
19
- const emit = defineEmits(['update:value']);
29
+ const emit = defineEmits(["update:value"]);
20
30
  watch(page, () => {
21
- emit('update:value', page.value);
31
+ emit("update:value", page.value);
22
32
  });
23
33
 
24
34
  const props = defineProps({
25
- length: {
26
- type: Number,
27
- required: true,
28
- default: 0
29
- }
35
+ length: {
36
+ type: Number,
37
+ required: true,
38
+ default: 0,
39
+ },
30
40
  });
31
- </script>
41
+ </script>
@@ -18,6 +18,7 @@
18
18
  :icon="child.icon"
19
19
  :route="child.route"
20
20
  :children="child.children"
21
+ :disabled="child.disabled"
21
22
  />
22
23
  </v-list-group>
23
24
 
@@ -27,6 +28,7 @@
27
28
  :to="props.route"
28
29
  rounded="e-pill"
29
30
  class="text-subtitle-2"
31
+ :disabled="props.disabled"
30
32
  >
31
33
  {{ title }}
32
34
  </v-list-item>
@@ -55,5 +57,10 @@ const props = defineProps({
55
57
  required: false,
56
58
  default: () => [],
57
59
  },
60
+ disabled: {
61
+ type: Boolean,
62
+ required: false,
63
+ default: false,
64
+ },
58
65
  });
59
66
  </script>
@@ -19,8 +19,13 @@
19
19
  :close-on-content-click="false"
20
20
  >
21
21
  <template #activator="{ props }">
22
- <v-btn variant="text" class="text-none ml-2" v-bind="props">
23
- <div class="d-block text-truncate" style="width: 130px">
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">
24
29
  {{ selectedOrg?.text || "Select organization" }}
25
30
  </div>
26
31
  <v-icon class="ml-1">mdi-menu-down</v-icon>
@@ -42,7 +47,6 @@
42
47
  density="compact"
43
48
  class="text-caption font-weight-bold"
44
49
  v-for="item in orgs"
45
- :key="item.value"
46
50
  @click="switchOrg(item.value)"
47
51
  >
48
52
  <v-icon size="16" class="mr-2">
@@ -54,18 +58,20 @@
54
58
  </v-list>
55
59
 
56
60
  <v-btn
61
+ v-if="isOrg"
57
62
  block
58
63
  class="text-none mb-1"
59
64
  variant="tonal"
60
- :to="{ name: 'organizations' }"
65
+ @click="navigateToOrgs"
61
66
  >
62
67
  Manage Organizations
63
68
  </v-btn>
64
69
  <v-btn
70
+ v-if="isOrg"
65
71
  block
66
72
  class="text-none mt-1"
67
73
  variant="tonal"
68
- :to="{ name: 'organizations-create' }"
74
+ @click="createOrg"
69
75
  >
70
76
  Create Organization
71
77
  </v-btn>
@@ -119,4 +125,36 @@ function switchOrg(org: string) {
119
125
  params: { organization: org },
120
126
  });
121
127
  }
128
+
129
+ const APP_NAME = useRuntimeConfig().public.APP_NAME;
130
+ const APP_ORG = useRuntimeConfig().public.APP_ORG;
131
+
132
+ const { redirect } = useLocal();
133
+
134
+ function createOrg() {
135
+ if (APP_NAME.toLowerCase() === "organization") {
136
+ navigateTo({
137
+ name: "organizations-create",
138
+ });
139
+ return;
140
+ }
141
+
142
+ redirect(APP_ORG, "organizations/create");
143
+ }
144
+
145
+ function navigateToOrgs() {
146
+ if (APP_NAME.toLowerCase() === "organization") {
147
+ navigateTo({
148
+ name: "organizations",
149
+ params: { status: "active" },
150
+ });
151
+ return;
152
+ }
153
+
154
+ redirect(APP_ORG, "organizations");
155
+ }
156
+
157
+ const isOrg = computed(() => {
158
+ return APP_NAME.toLowerCase() === "organization";
159
+ });
122
160
  </script>
@@ -41,18 +41,25 @@ export default function useAddress() {
41
41
  province = "",
42
42
  postalCode = "",
43
43
  taxId = "",
44
+ orgId = "",
44
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
+
45
60
  return useNuxtApp().$api(`/api/addresses/details/${id}`, {
46
61
  method: "PUT",
47
- body: {
48
- country,
49
- address,
50
- continuedAddress,
51
- city,
52
- province,
53
- postalCode,
54
- taxId,
55
- },
62
+ body: payload,
56
63
  });
57
64
  }
58
65
 
@@ -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
+ }
@@ -9,27 +9,35 @@ export default function useLocal() {
9
9
 
10
10
  const drawer = useState("drawer", () => true);
11
11
 
12
- const { APP_INVENTORY, APP_ASSET, APP_BOOK_KEEPING } = appConfig;
12
+ const { APP_INVENTORY, APP_ASSET, APP_BOOK_KEEPING, APP_ACCOUNTING } =
13
+ appConfig;
14
+ const { currentOrg } = useOrg();
13
15
 
14
16
  const apps = computed(() => {
15
17
  return [
16
18
  {
17
- title: "Inventory Management",
19
+ title: "Accounting",
20
+ icon: "mdi-file-document-multiple",
21
+ link: APP_ACCOUNTING as string,
22
+ landingPage: `org/${currentOrg.value ?? ""}`,
23
+ },
24
+ {
25
+ title: "Bookkeeping",
26
+ icon: "mdi-file-document-edit-outline",
27
+ link: APP_BOOK_KEEPING as string,
28
+ landingPage: `org/${currentOrg.value ?? ""}`,
29
+ },
30
+ {
31
+ title: "Inventory",
18
32
  icon: "mdi-warehouse",
19
33
  link: APP_INVENTORY as string,
20
- landingPage: "home",
34
+ landingPage: `org/${currentOrg.value ?? ""}`,
21
35
  },
22
36
  {
23
- title: "Asset Management",
37
+ title: "Asset",
24
38
  icon: "mdi-package-variant-closed",
25
39
  link: APP_ASSET as string,
26
- landingPage: "home",
27
- },
28
- {
29
- title: "Bookkeeping Management",
30
- icon: "mdi-file-document-multiple",
31
- link: APP_BOOK_KEEPING as string,
32
- landingPage: "home",
40
+ landingPage: `org/${currentOrg.value ?? ""}`,
33
41
  },
34
42
  ];
35
43
  });
@@ -1,6 +1,38 @@
1
1
  export default function useLocalAuth() {
2
2
  const { cookieConfig } = useRuntimeConfig().public;
3
3
 
4
+ const currentUser = useState<TUser | null>("currentUser", () => null);
5
+
6
+ function authenticate() {
7
+ // Get access token from cookies
8
+ const accessToken = useCookie("accessToken", cookieConfig).value;
9
+
10
+ if (!accessToken) {
11
+ // Redirect to login page if no access token
12
+ navigateTo({ name: "index" });
13
+ }
14
+
15
+ const user = useCookie("user", cookieConfig).value;
16
+
17
+ const { data: getCurrentUserReq, error: getCurrentUserErr } =
18
+ useLazyAsyncData("get-current-user", () =>
19
+ useNuxtApp().$api<TUser>(`/api/users/id/${user}`)
20
+ );
21
+
22
+ watchEffect(() => {
23
+ if (getCurrentUserReq.value) {
24
+ currentUser.value = getCurrentUserReq.value;
25
+ }
26
+ });
27
+
28
+ watchEffect(() => {
29
+ if (getCurrentUserErr.value) {
30
+ // Redirect to login page if user authentication fails
31
+ navigateTo({ name: "index" });
32
+ }
33
+ });
34
+ }
35
+
4
36
  async function login({ email = "", password = "", role = "" }) {
5
37
  return useNuxtApp().$api<TKeyValuePair>("/api/auth/login", {
6
38
  method: "POST",
@@ -42,16 +74,39 @@ export default function useLocalAuth() {
42
74
  }
43
75
  }
44
76
 
45
- const currentUser = useState((): TUser | null => null);
77
+ function getById(id: string) {
78
+ return useNuxtApp().$api<TUser>(`/api/users/id/${id}`);
79
+ }
80
+
81
+ const user = useCookie("user", cookieConfig).value ?? "";
82
+
83
+ if (currentUser.value === null) {
84
+ const { data: userData } = useLazyAsyncData("getCurrentUser", async () =>
85
+ useNuxtApp().$api<TUser>(`/api/users/id/${user}`, {
86
+ method: "GET",
87
+ })
88
+ );
89
+
90
+ watchEffect(() => {
91
+ if (userData.value) {
92
+ currentUser.value = userData.value;
93
+ }
94
+ });
95
+ }
46
96
 
47
97
  async function getCurrentUser() {
48
98
  const user = useCookie("user", cookieConfig).value;
49
99
  if (!user) return null;
50
- const _user = await useNuxtApp().$api<TUser>(`/api/users/id/${user}`, {
51
- method: "GET",
52
- });
53
- currentUser.value = _user;
54
- return _user;
100
+ try {
101
+ const _user = await useNuxtApp().$api<TUser>(`/api/users/id/${user}`, {
102
+ method: "GET",
103
+ });
104
+
105
+ currentUser.value = _user;
106
+ return _user;
107
+ } catch (error) {
108
+ console.log("Error fetching current user:", error);
109
+ }
55
110
  }
56
111
 
57
112
  async function forgotPassword(email: string) {
@@ -105,6 +160,7 @@ export default function useLocalAuth() {
105
160
  const permissions = useState("permissions", (): Array<string> => []);
106
161
 
107
162
  return {
163
+ authenticate,
108
164
  login,
109
165
  logout,
110
166
  clearCookies,
@@ -52,7 +52,7 @@ export default function useOrg() {
52
52
  }
53
53
 
54
54
  const perSeatPrice = 300;
55
- const seats = useState("seats", () => 0);
55
+ const seats = useState("seats", () => 1);
56
56
  const total = computed(() => seats.value * perSeatPrice);
57
57
 
58
58
  function getByName(name = "") {
@@ -78,11 +78,19 @@ export default function usePaymentMethod() {
78
78
  );
79
79
  }
80
80
 
81
+ function getByCustomerId(id = "") {
82
+ return useNuxtApp().$api<Record<string, any>>(
83
+ `/api/payment-methods/customer/${id}`
84
+ );
85
+ }
86
+
81
87
  const eWalletNumber = useState("eWalletNumber", () => "");
82
88
  const cardNumber = useState("cardNumber", () => "");
83
89
  const cardExpiration = useState("cardExpiration", () => "");
84
90
  const cardSecurityCode = useState("cardSecurityCode", () => "");
85
91
  const cardholderName = useState("cardholderName", () => "");
92
+ const cardholderMobileNumber = useState("cardholderMobileNumber", () => "");
93
+ const cardholderEmail = useState("cardholderEmail", () => "");
86
94
  const selectedPaymentMethod = useState("selectedPaymentMethod", () => "");
87
95
 
88
96
  function linkOnly(value: Record<string, any>) {
@@ -100,21 +108,25 @@ export default function usePaymentMethod() {
100
108
  channel: "GCASH",
101
109
  logo: "/gcash-logo.svg",
102
110
  type: "EWALLET",
111
+ text: "GCash",
103
112
  },
104
113
  {
105
114
  channel: "PAYMAYA",
106
115
  logo: "/paymaya-logo.svg",
107
116
  type: "EWALLET",
117
+ text: "PayMaya",
108
118
  },
109
119
  {
110
120
  channel: "GRABPAY",
111
121
  logo: "/grabpay-logo.svg",
112
122
  type: "EWALLET",
123
+ text: "GrabPay",
113
124
  },
114
125
  {
115
126
  channel: "SHOPEEPAY",
116
127
  logo: "/shopeepay-logo.svg",
117
128
  type: "EWALLET",
129
+ text: "ShopeePay",
118
130
  },
119
131
  ];
120
132
 
@@ -123,26 +135,31 @@ export default function usePaymentMethod() {
123
135
  channel: "UBP",
124
136
  logo: "/ubp-logo.svg",
125
137
  type: "DIRECT_DEBIT",
138
+ text: "BA_UBP",
126
139
  },
127
140
  {
128
141
  channel: "BDO",
129
142
  logo: "/bdo-logo.svg",
130
143
  type: "DIRECT_DEBIT",
144
+ text: "BDO",
131
145
  },
132
146
  {
133
147
  channel: "BPI",
134
148
  logo: "/bpi-logo.svg",
135
149
  type: "DIRECT_DEBIT",
150
+ text: "BA_BPI",
136
151
  },
137
152
  {
138
153
  channel: "RCBC",
139
154
  logo: "/rcbc-logo.svg",
140
155
  type: "DIRECT_DEBIT",
156
+ text: "RCBC",
141
157
  },
142
158
  {
143
159
  channel: "Chinabank",
144
160
  logo: "/chinabank-logo.svg",
145
161
  type: "DIRECT_DEBIT",
162
+ text: "Chinabank",
146
163
  },
147
164
  ];
148
165
 
@@ -170,9 +187,9 @@ export default function usePaymentMethod() {
170
187
  paymentMethod.value = null;
171
188
  }
172
189
 
173
- async function initLink(value: TLinkParams) {
190
+ async function initLink(value: TLinkParams, callback?: Function) {
174
191
  const validation = z.object({
175
- subscriptionId: z.string().min(1),
192
+ subscriptionId: z.string().min(1).optional(),
176
193
  paymentMethodType: z.enum(["EWALLET", "DIRECT_DEBIT", "CREDIT_CARD"]),
177
194
  paymentMethodChannel: z.string().min(1),
178
195
  customerId: z.string().min(1),
@@ -221,11 +238,10 @@ export default function usePaymentMethod() {
221
238
  channel_properties: {
222
239
  success_return_url,
223
240
  failure_return_url,
224
- cancel_return_url,
225
241
  },
226
242
  };
227
243
  payload.customer_id = value.customerId;
228
- } else if (payload.type === "CREDIT_CARD") {
244
+ } else if (payload.type === "CARD") {
229
245
  payload.card = {
230
246
  currency: "PHP",
231
247
  channel_properties: {
@@ -269,7 +285,7 @@ export default function usePaymentMethod() {
269
285
 
270
286
  const temp = await getById(_paymentMethod.id);
271
287
 
272
- if (temp.status === "ACTIVE") {
288
+ if (temp.status === "ACTIVE" && value.subscriptionId) {
273
289
  await updatePaymentMethodById(
274
290
  value.subscriptionId,
275
291
  _paymentMethod.id as string
@@ -278,6 +294,10 @@ export default function usePaymentMethod() {
278
294
  paymentMethod.value = await getById(_paymentMethod.id);
279
295
  }
280
296
 
297
+ if (callback) {
298
+ callback();
299
+ }
300
+
281
301
  updatingPaymentMethod.value = false;
282
302
  linkingOverlay.value = false;
283
303
  }
@@ -287,6 +307,16 @@ export default function usePaymentMethod() {
287
307
  }
288
308
  }
289
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
+
290
320
  return {
291
321
  linkEWallet,
292
322
  linkCard,
@@ -297,15 +327,21 @@ export default function usePaymentMethod() {
297
327
  cardExpiration,
298
328
  cardSecurityCode,
299
329
  cardholderName,
330
+ cardholderMobileNumber,
331
+ cardholderEmail,
300
332
  selectedPaymentMethod,
301
333
  reset,
302
334
  linkOnly,
303
335
  getById,
304
336
  supportedPaymentMethods,
337
+ supportedDirectDebit,
338
+ supportedEwallets,
305
339
  initLink,
306
340
  linkingOverlay,
307
341
  updatingPaymentMethod,
308
342
  linkingMessage,
309
343
  paymentMethod,
344
+ getByCustomerId,
345
+ updateStatusById,
310
346
  };
311
347
  }