@goweekdays/layer-common 1.4.6 → 1.5.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @goweekdays/layer-common
2
2
 
3
+ ## 1.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 4390428: Add default props for VCombobox in Vuetify plugin
8
+ - 0304ef9: Refactor API calls to use $api from Nuxt plugin
9
+
10
+ ## 1.5.0
11
+
12
+ ### Minor Changes
13
+
14
+ - fab8c5c: Add promo code support and input components
15
+
3
16
  ## 1.4.6
4
17
 
5
18
  ### Patch Changes
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <v-text-field
3
+ type="text"
4
+ inputmode="numeric"
5
+ :model-value="display"
6
+ @update:model-value="onInput"
7
+ @blur="format"
8
+ @keydown="onKeydown"
9
+ v-bind="$attrs"
10
+ >
11
+ <!-- forward all slots -->
12
+ <template v-for="(_, name) in $slots" #[name]="slotProps">
13
+ <slot :name="name" v-bind="slotProps" />
14
+ </template>
15
+ </v-text-field>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ /**
20
+ * numeric v-model
21
+ */
22
+
23
+ const localProps = defineProps({
24
+ step: {
25
+ type: Number,
26
+ default: 1,
27
+ },
28
+ });
29
+ const model = defineModel<number>({ default: 0 });
30
+
31
+ const display = ref<string>("");
32
+
33
+ const parse = (v: string) => Number(v.replace(/[^0-9]/g, "") || 0);
34
+
35
+ const format = () => {
36
+ display.value = model.value.toLocaleString("en-US");
37
+ };
38
+
39
+ function onInput(val: string) {
40
+ if (!/^[0-9,]*$/.test(val)) return;
41
+ model.value = parse(val);
42
+ display.value = val;
43
+ }
44
+
45
+ function onKeydown(e: KeyboardEvent) {
46
+ if (e.key === "ArrowUp") {
47
+ e.preventDefault();
48
+ model.value += localProps.step;
49
+ format();
50
+ }
51
+
52
+ if (e.key === "ArrowDown") {
53
+ e.preventDefault();
54
+ model.value = Math.max(0, model.value - localProps.step);
55
+ format();
56
+ }
57
+ }
58
+
59
+ watch(() => model.value, format, { immediate: true });
60
+ </script>
@@ -0,0 +1,112 @@
1
+ <template>
2
+ <v-text-field
3
+ type="text"
4
+ inputmode="numeric"
5
+ :model-value="display"
6
+ @update:model-value="onInput"
7
+ @update:focused="doAutoCorrect"
8
+ @keydown="onKeydown"
9
+ v-bind="$attrs"
10
+ >
11
+ <!-- forward all slots -->
12
+ <template v-for="(_, name) in $slots" #[name]="slotProps">
13
+ <slot :name="name" v-bind="slotProps" />
14
+ </template>
15
+ </v-text-field>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ /**
20
+ * Numeric input that displays ∞ when value is 0
21
+ */
22
+
23
+ const localProps = defineProps({
24
+ step: {
25
+ type: Number,
26
+ default: 1,
27
+ },
28
+ minValue: {
29
+ type: Number,
30
+ default: 0,
31
+ },
32
+ autoCorrect: {
33
+ type: Boolean,
34
+ default: false,
35
+ },
36
+ });
37
+
38
+ const model = defineModel<number>({ default: 0 });
39
+
40
+ const display = ref<string>("");
41
+
42
+ const INFINITY_SYMBOL = "∞";
43
+
44
+ const parse = (v: string) => {
45
+ if (v === INFINITY_SYMBOL || v === "") return 0;
46
+ return Number(v.replace(/[^0-9]/g, "") || 0);
47
+ };
48
+
49
+ const format = () => {
50
+ display.value =
51
+ model.value === 0 ? INFINITY_SYMBOL : model.value.toLocaleString("en-US");
52
+ };
53
+
54
+ function doAutoCorrect() {
55
+ if (!localProps.autoCorrect) return;
56
+
57
+ // Auto-correct if value is invalid (> 0 but <= minValue)
58
+ if (model.value > 0 && model.value <= localProps.minValue) {
59
+ model.value = localProps.minValue + 1;
60
+ format();
61
+ }
62
+ }
63
+
64
+ function onInput(val: string) {
65
+ // Allow infinity symbol, empty, or numeric input
66
+ if (val === INFINITY_SYMBOL || val === "") {
67
+ model.value = 0;
68
+ display.value = val;
69
+ return;
70
+ }
71
+
72
+ // If current display is infinity and user types a number, replace entirely
73
+ if (display.value === INFINITY_SYMBOL) {
74
+ const numericOnly = val.replace(/[^0-9]/g, "");
75
+ if (numericOnly) {
76
+ model.value = Number(numericOnly);
77
+ display.value = numericOnly;
78
+ return;
79
+ }
80
+ }
81
+
82
+ if (!/^[0-9,]*$/.test(val)) return;
83
+ model.value = parse(val);
84
+ display.value = val;
85
+ }
86
+
87
+ function onKeydown(e: KeyboardEvent) {
88
+ if (e.key === "Enter") {
89
+ doAutoCorrect();
90
+ }
91
+
92
+ if (e.key === "ArrowUp") {
93
+ e.preventDefault();
94
+ // If value is 0 (infinity), start from minValue + 1
95
+ if (model.value === 0) {
96
+ model.value = localProps.minValue + 1;
97
+ } else {
98
+ model.value += localProps.step;
99
+ }
100
+ format();
101
+ }
102
+
103
+ if (e.key === "ArrowDown") {
104
+ e.preventDefault();
105
+ // Don't go below 0
106
+ model.value = Math.max(0, model.value - localProps.step);
107
+ format();
108
+ }
109
+ }
110
+
111
+ watch(() => model.value, format, { immediate: true });
112
+ </script>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <v-text-field
3
+ type="text"
4
+ :model-value="display"
5
+ @update:model-value="onInput"
6
+ @blur="format"
7
+ @keydown="onKeydown"
8
+ v-bind="$attrs"
9
+ >
10
+ <!-- forward all slots -->
11
+ <template v-for="(_, name) in $slots" #[name]="slotProps">
12
+ <slot :name="name" v-bind="slotProps" />
13
+ </template>
14
+ </v-text-field>
15
+ </template>
16
+
17
+ <script setup lang="ts">
18
+ /**
19
+ * Input that converts spaces to hyphens and forces lowercase, useful for slugs, codes, or identifiers
20
+ */
21
+
22
+ const model = defineModel<string>({ default: "" });
23
+
24
+ const display = ref<string>("");
25
+
26
+ const transform = (v: string) => {
27
+ return v.replace(/\s+/g, "-").toLowerCase();
28
+ };
29
+
30
+ const format = () => {
31
+ display.value = transform(model.value);
32
+ model.value = display.value;
33
+ };
34
+
35
+ function onInput(val: string) {
36
+ const transformed = transform(val);
37
+ model.value = transformed;
38
+ display.value = transformed;
39
+ }
40
+
41
+ function onKeydown(e: KeyboardEvent) {
42
+ if (e.key === " ") {
43
+ e.preventDefault();
44
+ model.value = transform(display.value + "-");
45
+ display.value = model.value;
46
+ }
47
+ }
48
+
49
+ watch(() => model.value, format, { immediate: true });
50
+ </script>
@@ -66,7 +66,6 @@
66
66
  <v-dialog v-model="dialogView" width="450" persistent>
67
67
  <MemberInvite
68
68
  title="Invite Details"
69
- :app="props.app"
70
69
  v-model="invitation"
71
70
  @close="setInvite({ dialog: false })"
72
71
  @cancel:invite="handleOpenCancelInvite()"
@@ -141,6 +140,8 @@ const pageRange = ref("-- - -- of --");
141
140
  const items = ref<Array<Record<string, any>>>([]);
142
141
  const { headerSearch } = useLocal();
143
142
 
143
+ const isOrg = computed(() => props.app === "org");
144
+
144
145
  const {
145
146
  data: getInviteReq,
146
147
  refresh: getInvitations,
@@ -154,6 +155,7 @@ const {
154
155
  status: props.status,
155
156
  type: "user-invite,member-invite",
156
157
  org: props.org,
158
+ app: isOrg.value ? "" : props.app,
157
159
  })
158
160
  );
159
161
 
@@ -179,9 +181,7 @@ function setInvite({
179
181
  } = {}) {
180
182
  Object.assign(invitation.value, JSON.parse(JSON.stringify(data)));
181
183
 
182
- if (dialog) {
183
- dialogView.value = dialog;
184
- }
184
+ dialogView.value = dialog;
185
185
  }
186
186
 
187
187
  function tableRowClickHandler(_: any, data: any) {
@@ -26,6 +26,7 @@
26
26
  item-value="code"
27
27
  :rules="isMutable ? [requiredRule] : []"
28
28
  :loading="loadingApps"
29
+ :readonly="!isMutable"
29
30
  ></v-select>
30
31
  </v-col>
31
32
  </v-row>
@@ -189,7 +190,9 @@ const invite = defineModel<TMemberInvitation>({
189
190
  default: () => useMember().invitation.value,
190
191
  });
191
192
 
192
- invite.value.app = localProps.app;
193
+ if (localProps.mode === "add") {
194
+ invite.value.app = localProps.app;
195
+ }
193
196
 
194
197
  const message = defineModel("message", { default: "" });
195
198
 
@@ -13,7 +13,7 @@ export default function useAddress() {
13
13
  postalCode = "",
14
14
  taxId = "",
15
15
  } = {}) {
16
- return $fetch("/api/addresses", {
16
+ return useNuxtApp().$api("/api/addresses", {
17
17
  method: "POST",
18
18
  body: {
19
19
  type,
@@ -57,18 +57,18 @@ export default function useAddress() {
57
57
  payload.org = orgId;
58
58
  }
59
59
 
60
- return $fetch(`/api/addresses/details/${id}`, {
60
+ return useNuxtApp().$api(`/api/addresses/details/${id}`, {
61
61
  method: "PUT",
62
62
  body: payload,
63
63
  });
64
64
  }
65
65
 
66
66
  function getByUserId(user = "") {
67
- return $fetch<TAddress>(`/api/addresses/user/${user}`);
67
+ return useNuxtApp().$api<TAddress>(`/api/addresses/user/${user}`);
68
68
  }
69
69
 
70
70
  function getByOrgId(id = "") {
71
- return $fetch<TAddress>(`/api/addresses/org/${id}`);
71
+ return useNuxtApp().$api<TAddress>(`/api/addresses/org/${id}`);
72
72
  }
73
73
 
74
74
  const _address = useState("address", (): TAddress => {
@@ -13,7 +13,7 @@ export default function useApps() {
13
13
  const resource = "/api/apps";
14
14
 
15
15
  function add(value: TApp) {
16
- return $fetch(resource, {
16
+ return useNuxtApp().$api(resource, {
17
17
  method: "POST",
18
18
  body: value,
19
19
  });
@@ -26,7 +26,7 @@ export default function useApps() {
26
26
  status = "active",
27
27
  type = "standard",
28
28
  } = {}) {
29
- return $fetch<Record<string, any>>(resource, {
29
+ return useNuxtApp().$api<Record<string, any>>(resource, {
30
30
  method: "GET",
31
31
  query: { page, limit, search, status, type },
32
32
  });
@@ -36,14 +36,14 @@ export default function useApps() {
36
36
  id: string,
37
37
  value: { name: string; description: string }
38
38
  ) {
39
- return $fetch(`${resource}/id/${id}`, {
39
+ return useNuxtApp().$api(`${resource}/id/${id}`, {
40
40
  method: "PATCH",
41
41
  body: value,
42
42
  });
43
43
  }
44
44
 
45
45
  function deleteById(id: string) {
46
- return $fetch(`${resource}/id/${id}`, {
46
+ return useNuxtApp().$api(`${resource}/id/${id}`, {
47
47
  method: "DELETE",
48
48
  });
49
49
  }
@@ -7,7 +7,7 @@ export default function useChartOfAccount() {
7
7
  children?: number;
8
8
  }
9
9
  ) {
10
- return $fetch<Record<string, any>>("/api/chart-of-accounts", {
10
+ return useNuxtApp().$api<Record<string, any>>("/api/chart-of-accounts", {
11
11
  method: "GET",
12
12
  query: { page, status, orgId, children },
13
13
  });
@@ -23,30 +23,35 @@ export default function useChartOfAccount() {
23
23
  };
24
24
 
25
25
  function add(value: TAddPayload) {
26
- return $fetch<TAddPayload>("/api/chart-of-accounts", {
26
+ return useNuxtApp().$api<TAddPayload>("/api/chart-of-accounts", {
27
27
  method: "POST",
28
28
  body: value,
29
29
  });
30
30
  }
31
31
 
32
32
  function getById(id: string) {
33
- return $fetch<Record<string, any>>(`/api/chart-of-accounts/id/${id}`);
33
+ return useNuxtApp().$api<Record<string, any>>(
34
+ `/api/chart-of-accounts/id/${id}`
35
+ );
34
36
  }
35
37
 
36
38
  function updateById(
37
39
  id: string,
38
40
  value: Pick<TAddPayload, "name" | "code" | "normalBalance" | "parent">
39
41
  ) {
40
- return $fetch<TAddPayload>(`/api/chart-of-accounts/id/${id}`, {
42
+ return useNuxtApp().$api<TAddPayload>(`/api/chart-of-accounts/id/${id}`, {
41
43
  method: "PUT",
42
44
  body: value,
43
45
  });
44
46
  }
45
47
 
46
48
  function deleteById(id: string) {
47
- return $fetch<Record<string, any>>(`/api/chart-of-accounts/id/${id}`, {
48
- method: "DELETE",
49
- });
49
+ return useNuxtApp().$api<Record<string, any>>(
50
+ `/api/chart-of-accounts/id/${id}`,
51
+ {
52
+ method: "DELETE",
53
+ }
54
+ );
50
55
  }
51
56
 
52
57
  return {
@@ -7,16 +7,19 @@ export default function useFile() {
7
7
  const formData = new FormData();
8
8
  formData.append("file", file);
9
9
 
10
- return $fetch<Record<string, any>>("/api/files", {
10
+ return useNuxtApp().$api<Record<string, any>>("/api/files", {
11
11
  method: "POST",
12
12
  body: formData,
13
13
  });
14
14
  }
15
15
 
16
16
  function deleteFile(attachmentId: string) {
17
- return $fetch<Record<string, any>>(`/api/files/${attachmentId}`, {
18
- method: "DELETE",
19
- });
17
+ return useNuxtApp().$api<Record<string, any>>(
18
+ `/api/files/${attachmentId}`,
19
+ {
20
+ method: "DELETE",
21
+ }
22
+ );
20
23
  }
21
24
 
22
25
  return {
@@ -4,23 +4,29 @@ export default function useInvoice() {
4
4
  throw new Error("Subscription ID is required");
5
5
  }
6
6
 
7
- return $fetch<Record<string, any>>(`/api/invoices/subscription/${id}`, {
8
- method: "GET",
9
- params: {
10
- search,
11
- page,
12
- },
13
- });
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
+ );
14
17
  }
15
18
 
16
19
  function getByNumber(number: string) {
17
- return $fetch<Record<string, any>>(`/api/invoices/number/${number}`, {
18
- method: "GET",
19
- });
20
+ return useNuxtApp().$api<Record<string, any>>(
21
+ `/api/invoices/number/${number}`,
22
+ {
23
+ method: "GET",
24
+ }
25
+ );
20
26
  }
21
27
 
22
28
  function getByDueDateStatus(date: string, status: string) {
23
- return $fetch<Record<string, any>>(
29
+ return useNuxtApp().$api<Record<string, any>>(
24
30
  `/api/invoices/due-date/${date}/status/${status}`,
25
31
  {
26
32
  method: "GET",
@@ -0,0 +1,67 @@
1
+ export function useJobPost() {
2
+ const jobPost = ref<TJobPost>({
3
+ title: "",
4
+ org: "",
5
+ setup: "",
6
+ location: "",
7
+ type: "",
8
+ description: "",
9
+ });
10
+
11
+ function getAll({ page = 1, limit = 50, search = "" } = {}) {
12
+ return useNuxtApp().$api<Record<string, any>>(`/api/job/posts`, {
13
+ method: "GET",
14
+ query: {
15
+ page,
16
+ limit,
17
+ search,
18
+ },
19
+ });
20
+ }
21
+
22
+ function getJobPostsByOrg(
23
+ id: any,
24
+ { page = 1, search = "", status = "draft", limit = 10, org = "" } = {}
25
+ ) {
26
+ return useNuxtApp().$api<Record<string, any>>(`/api/job/posts/${id}`, {
27
+ method: "GET",
28
+ query: {
29
+ page,
30
+ search,
31
+ limit,
32
+ status,
33
+ org,
34
+ },
35
+ });
36
+ }
37
+
38
+ function getJobPostsById(id: any) {
39
+ return useNuxtApp().$api<Record<string, any>>(`/api/job/posts/id/${id}`, {
40
+ method: "GET",
41
+ });
42
+ }
43
+
44
+ function deleteJobPostById(id: any) {
45
+ return useNuxtApp().$api<Record<string, any>>(`/api/job/posts/id/${id}`, {
46
+ method: "DELETE",
47
+ });
48
+ }
49
+
50
+ function updateJobPostStatusById(id: any, status: any) {
51
+ return useNuxtApp().$api<Record<string, any>>(
52
+ `/api/job/posts/id/${id}/status/${status}`,
53
+ {
54
+ method: "PATCH",
55
+ }
56
+ );
57
+ }
58
+
59
+ return {
60
+ jobPost,
61
+ getAll,
62
+ getJobPostsByOrg,
63
+ getJobPostsById,
64
+ deleteJobPostById,
65
+ updateJobPostStatusById,
66
+ };
67
+ }
@@ -1,6 +1,6 @@
1
1
  export default function useLedgerBilling() {
2
2
  function getAll({ org = "", search = "", page = 1, status = "" } = {}) {
3
- return $fetch<Record<string, any>>("/api/ledger/billings", {
3
+ return useNuxtApp().$api<Record<string, any>>("/api/ledger/billings", {
4
4
  method: "GET",
5
5
  query: {
6
6
  org,
@@ -12,13 +12,16 @@ export default function useLedgerBilling() {
12
12
  }
13
13
 
14
14
  function getById(id = "") {
15
- return $fetch<Record<string, any>>(`/api/ledger/billings/id/${id}`, {
16
- method: "GET",
17
- });
15
+ return useNuxtApp().$api<Record<string, any>>(
16
+ `/api/ledger/billings/id/${id}`,
17
+ {
18
+ method: "GET",
19
+ }
20
+ );
18
21
  }
19
22
 
20
23
  function getSummary(org = "", status = "") {
21
- return $fetch<Record<string, any>>(
24
+ return useNuxtApp().$api<Record<string, any>>(
22
25
  `/api/ledger/billings/summary/org/${org}/status/${status}`,
23
26
  {
24
27
  method: "GET",
@@ -13,7 +13,7 @@ export default function useLocalAuth() {
13
13
  };
14
14
 
15
15
  async function login({ email = "", password = "", role = "" }) {
16
- return $fetch<Record<string, any>>("/api/auth/login", {
16
+ return useNuxtApp().$api<Record<string, any>>("/api/auth/login", {
17
17
  method: "POST",
18
18
  body: JSON.stringify({ email, password, role }),
19
19
  });
@@ -29,7 +29,7 @@ export default function useLocalAuth() {
29
29
  const user = useCookie("user", cookieConfig).value;
30
30
  if (!user) return null;
31
31
  try {
32
- const _user = await $fetch<TUser>(`/api/users/id/${user}`, {
32
+ const _user = await useNuxtApp().$api<TUser>(`/api/users/id/${user}`, {
33
33
  method: "GET",
34
34
  });
35
35
 
@@ -41,14 +41,17 @@ export default function useLocalAuth() {
41
41
  }
42
42
 
43
43
  async function forgotPassword(email: string) {
44
- return $fetch<Record<string, any>>("/api/verifications/forget-password", {
45
- method: "POST",
46
- body: JSON.stringify({ email }),
47
- });
44
+ return useNuxtApp().$api<Record<string, any>>(
45
+ "/api/verifications/forget-password",
46
+ {
47
+ method: "POST",
48
+ body: JSON.stringify({ email }),
49
+ }
50
+ );
48
51
  }
49
52
 
50
53
  function verify(id: string) {
51
- return $fetch<Record<string, any>>(`/api/auth/verify/${id}`, {
54
+ return useNuxtApp().$api<Record<string, any>>(`/api/auth/verify/${id}`, {
52
55
  method: "GET",
53
56
  });
54
57
  }