@goweekdays/layer-common 1.3.2 → 1.3.4
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 +12 -0
- package/components/InvitationMain.vue +10 -8
- package/components/MemberInvite.vue +49 -14
- package/components/MemberMain.vue +2 -1
- package/components/RoleForm.vue +23 -25
- package/components/RolePermissionMain.vue +6 -5
- package/composables/useLocalAuth.ts +4 -33
- package/composables/useUser.ts +12 -0
- package/composables/useVerification.ts +2 -1
- package/package.json +1 -1
- package/pages/forgot-password.vue +4 -3
- package/pages/index.vue +92 -1
- package/pages/login.vue +11 -2
- package/pages/reset-password/[otp].vue +110 -0
- package/pages/sign-up/[id].vue +1 -9
- package/pages/verify/invitation/[id].vue +163 -0
- package/pages/verify/member-invite/[id].vue +67 -0
package/CHANGELOG.md
CHANGED
|
@@ -145,14 +145,16 @@ const {
|
|
|
145
145
|
data: getInviteReq,
|
|
146
146
|
refresh: getInvitations,
|
|
147
147
|
status: getInviteReqStatus,
|
|
148
|
-
} = await useLazyAsyncData(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
148
|
+
} = await useLazyAsyncData(
|
|
149
|
+
`get-all-invitations-${props.status}-${page.value}`,
|
|
150
|
+
() =>
|
|
151
|
+
getVerifications({
|
|
152
|
+
page: page.value,
|
|
153
|
+
search: headerSearch.value,
|
|
154
|
+
status: props.status,
|
|
155
|
+
type: "user-invite,member-invite",
|
|
156
|
+
org: props.org,
|
|
157
|
+
})
|
|
156
158
|
);
|
|
157
159
|
|
|
158
160
|
const loading = computed(() => getInviteReqStatus.value === "pending");
|
|
@@ -11,19 +11,22 @@
|
|
|
11
11
|
<v-card-text style="max-height: 100vh; overflow-y: auto">
|
|
12
12
|
<v-form v-model="valid" :disabled="localProps.disabled">
|
|
13
13
|
<v-row no-gutters>
|
|
14
|
-
<v-col cols="12" class="mb-1">
|
|
14
|
+
<v-col v-if="!isAdmin" cols="12" class="mb-1">
|
|
15
15
|
<v-row no-gutters>
|
|
16
16
|
<InputLabel
|
|
17
17
|
class="text-capitalize"
|
|
18
|
-
title="
|
|
18
|
+
title="App"
|
|
19
19
|
:required="isMutable"
|
|
20
20
|
/>
|
|
21
21
|
<v-col cols="12">
|
|
22
|
-
<v-
|
|
23
|
-
v-model="invite.
|
|
24
|
-
:
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
<v-select
|
|
23
|
+
v-model="invite.app"
|
|
24
|
+
:items="apps"
|
|
25
|
+
item-title="name"
|
|
26
|
+
item-value="code"
|
|
27
|
+
:rules="isMutable ? [requiredRule] : []"
|
|
28
|
+
:loading="loadingApps"
|
|
29
|
+
></v-select>
|
|
27
30
|
</v-col>
|
|
28
31
|
</v-row>
|
|
29
32
|
</v-col>
|
|
@@ -49,14 +52,19 @@
|
|
|
49
52
|
</v-row>
|
|
50
53
|
</v-col>
|
|
51
54
|
|
|
52
|
-
<v-col
|
|
55
|
+
<v-col cols="12" class="mb-1">
|
|
53
56
|
<v-row no-gutters>
|
|
54
|
-
<InputLabel
|
|
57
|
+
<InputLabel
|
|
58
|
+
class="text-capitalize"
|
|
59
|
+
title="Email"
|
|
60
|
+
:required="isMutable"
|
|
61
|
+
/>
|
|
55
62
|
<v-col cols="12">
|
|
56
|
-
<v-
|
|
57
|
-
v-model="invite.
|
|
58
|
-
:rules="[requiredRule]"
|
|
59
|
-
|
|
63
|
+
<v-text-field
|
|
64
|
+
v-model="invite.email"
|
|
65
|
+
:rules="isMutable ? [requiredRule, emailRule] : []"
|
|
66
|
+
:readonly="!isMutable"
|
|
67
|
+
></v-text-field>
|
|
60
68
|
</v-col>
|
|
61
69
|
</v-row>
|
|
62
70
|
</v-col>
|
|
@@ -181,6 +189,8 @@ const invite = defineModel<TMemberInvitation>({
|
|
|
181
189
|
default: () => useMember().invitation.value,
|
|
182
190
|
});
|
|
183
191
|
|
|
192
|
+
invite.value.app = localProps.app;
|
|
193
|
+
|
|
184
194
|
const message = defineModel("message", { default: "" });
|
|
185
195
|
|
|
186
196
|
const valid = ref(false);
|
|
@@ -193,7 +203,10 @@ const roles = ref<Array<Record<string, any>>>([]);
|
|
|
193
203
|
|
|
194
204
|
const { data: roleData, status: roleReqStatus } = await useLazyAsyncData(
|
|
195
205
|
`get-all-role-app-${localProps.app}-${localProps.org ?? "org"}`,
|
|
196
|
-
() => getAllRoles({ org: localProps.org, app:
|
|
206
|
+
() => getAllRoles({ org: localProps.org, app: invite.value.app, limit: 50 }),
|
|
207
|
+
{
|
|
208
|
+
watch: [() => invite.value.app],
|
|
209
|
+
}
|
|
197
210
|
);
|
|
198
211
|
|
|
199
212
|
const loadingRoles = computed(() => roleReqStatus.value === "pending");
|
|
@@ -203,4 +216,26 @@ watchEffect(() => {
|
|
|
203
216
|
roles.value = roleData.value.items;
|
|
204
217
|
}
|
|
205
218
|
});
|
|
219
|
+
|
|
220
|
+
const isAdmin = computed(() => localProps.app === "admin");
|
|
221
|
+
|
|
222
|
+
const apps = ref<TApp[]>([]);
|
|
223
|
+
|
|
224
|
+
const { getAll: getAllApps } = useApps();
|
|
225
|
+
|
|
226
|
+
const { data: appsData, status: appsReqStatus } = useLazyAsyncData(
|
|
227
|
+
"get-all-apps-invite-member-form",
|
|
228
|
+
() => getAllApps({ limit: 100 }),
|
|
229
|
+
{
|
|
230
|
+
immediate: !isAdmin.value,
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const loadingApps = computed(() => appsReqStatus.value === "pending");
|
|
235
|
+
|
|
236
|
+
watchEffect(() => {
|
|
237
|
+
if (appsData.value && appsData.value.items) {
|
|
238
|
+
apps.value = appsData.value.items;
|
|
239
|
+
}
|
|
240
|
+
});
|
|
206
241
|
</script>
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
|
|
97
97
|
<v-dialog v-model="dialogAssignRole" width="450" persistent>
|
|
98
98
|
<MemberForm
|
|
99
|
+
:app="type"
|
|
99
100
|
title="Assign Role"
|
|
100
101
|
v-model="member"
|
|
101
102
|
mode="assign-role"
|
|
@@ -291,7 +292,7 @@ async function submitInvite() {
|
|
|
291
292
|
disabledInvite.value = true;
|
|
292
293
|
try {
|
|
293
294
|
await inviteMember({
|
|
294
|
-
app:
|
|
295
|
+
app: invitation.value.app,
|
|
295
296
|
org: props.orgId,
|
|
296
297
|
email: invitation.value.email,
|
|
297
298
|
role: invitation.value.role,
|
package/components/RoleForm.vue
CHANGED
|
@@ -11,6 +11,26 @@
|
|
|
11
11
|
<v-card-text style="max-height: 100vh; overflow-y: auto">
|
|
12
12
|
<v-form v-model="valid">
|
|
13
13
|
<v-row no-gutters>
|
|
14
|
+
<v-col v-if="isOrg" cols="12" class="mb-1">
|
|
15
|
+
<v-row no-gutters>
|
|
16
|
+
<InputLabel
|
|
17
|
+
class="text-capitalize"
|
|
18
|
+
title="App"
|
|
19
|
+
:required="isMutable"
|
|
20
|
+
/>
|
|
21
|
+
<v-col cols="12">
|
|
22
|
+
<v-select
|
|
23
|
+
v-model="role.app"
|
|
24
|
+
:items="apps"
|
|
25
|
+
item-title="name"
|
|
26
|
+
item-value="code"
|
|
27
|
+
:readonly="!isMutable"
|
|
28
|
+
:loading="loadingApps"
|
|
29
|
+
></v-select>
|
|
30
|
+
</v-col>
|
|
31
|
+
</v-row>
|
|
32
|
+
</v-col>
|
|
33
|
+
|
|
14
34
|
<v-col cols="12" class="mb-1">
|
|
15
35
|
<v-row no-gutters>
|
|
16
36
|
<InputLabel
|
|
@@ -65,26 +85,6 @@
|
|
|
65
85
|
</v-col>
|
|
66
86
|
</v-row>
|
|
67
87
|
</v-col>
|
|
68
|
-
|
|
69
|
-
<v-col v-if="!localProps.app && isMutable" cols="12" class="mb-1">
|
|
70
|
-
<v-row no-gutters>
|
|
71
|
-
<InputLabel
|
|
72
|
-
class="text-capitalize"
|
|
73
|
-
title="App"
|
|
74
|
-
:required="isMutable"
|
|
75
|
-
/>
|
|
76
|
-
<v-col cols="12">
|
|
77
|
-
<v-select
|
|
78
|
-
v-model="role.app"
|
|
79
|
-
:items="apps"
|
|
80
|
-
item-title="name"
|
|
81
|
-
item-value="code"
|
|
82
|
-
:readonly="!isMutable"
|
|
83
|
-
:loading="loadingApps"
|
|
84
|
-
></v-select>
|
|
85
|
-
</v-col>
|
|
86
|
-
</v-row>
|
|
87
|
-
</v-col>
|
|
88
88
|
</v-row>
|
|
89
89
|
</v-form>
|
|
90
90
|
|
|
@@ -222,6 +222,8 @@ const apps = ref<TApp[]>([]);
|
|
|
222
222
|
|
|
223
223
|
const { getAll: getAllApps } = useApps();
|
|
224
224
|
|
|
225
|
+
const isOrg = computed(() => localProps.app === "org");
|
|
226
|
+
|
|
225
227
|
const {
|
|
226
228
|
data: appsData,
|
|
227
229
|
status: appsReqStatus,
|
|
@@ -233,14 +235,10 @@ const {
|
|
|
233
235
|
limit: 20,
|
|
234
236
|
}),
|
|
235
237
|
{
|
|
236
|
-
immediate:
|
|
238
|
+
immediate: isOrg.value,
|
|
237
239
|
}
|
|
238
240
|
);
|
|
239
241
|
|
|
240
|
-
if (!localProps.app) {
|
|
241
|
-
refreshApps();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
242
|
const loadingApps = computed(() => appsReqStatus.value === "pending");
|
|
245
243
|
|
|
246
244
|
watchEffect(() => {
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
content="Are you sure you want to delete this role? This action cannot be undone."
|
|
106
106
|
@cancel="setRole({ mode: 'delete' })"
|
|
107
107
|
@confirm="submitDelete()"
|
|
108
|
-
:message="message"
|
|
108
|
+
v-model:message="message"
|
|
109
109
|
/>
|
|
110
110
|
</v-dialog>
|
|
111
111
|
</v-row>
|
|
@@ -136,8 +136,7 @@ const props = defineProps({
|
|
|
136
136
|
title: "permissions",
|
|
137
137
|
value: "permissions",
|
|
138
138
|
},
|
|
139
|
-
{ title: "App", value: "
|
|
140
|
-
{ title: "Action", value: "action-table" },
|
|
139
|
+
{ title: "App", value: "app" },
|
|
141
140
|
],
|
|
142
141
|
},
|
|
143
142
|
canCreateRole: {
|
|
@@ -189,7 +188,7 @@ function setRole({
|
|
|
189
188
|
JSON.parse(
|
|
190
189
|
JSON.stringify({
|
|
191
190
|
...data,
|
|
192
|
-
app: props.app,
|
|
191
|
+
app: mode === "admin" ? props.app : data.app,
|
|
193
192
|
})
|
|
194
193
|
)
|
|
195
194
|
);
|
|
@@ -215,6 +214,8 @@ function setRole({
|
|
|
215
214
|
|
|
216
215
|
const items = ref<Array<Record<string, any>>>([]);
|
|
217
216
|
|
|
217
|
+
const isOrg = computed(() => props.app === "org");
|
|
218
|
+
|
|
218
219
|
const {
|
|
219
220
|
data: getRoleReq,
|
|
220
221
|
refresh: getRoles,
|
|
@@ -225,8 +226,8 @@ const {
|
|
|
225
226
|
_getRoles({
|
|
226
227
|
page: page.value,
|
|
227
228
|
search: headerSearch.value,
|
|
228
|
-
app: props.app,
|
|
229
229
|
org: props.org,
|
|
230
|
+
app: isOrg.value ? "" : props.app,
|
|
230
231
|
}),
|
|
231
232
|
{
|
|
232
233
|
watch: [page, headerSearch],
|
|
@@ -41,38 +41,10 @@ export default function useLocalAuth() {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async function forgotPassword(email: string) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const response = await $fetch("/api/auth/forget-password", {
|
|
50
|
-
method: "POST",
|
|
51
|
-
body: JSON.stringify({ email }),
|
|
52
|
-
headers: { "Content-Type": "application/json" },
|
|
53
|
-
});
|
|
54
|
-
return response;
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error("Error in password reset request:", error);
|
|
57
|
-
throw error;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function resetPassword(
|
|
62
|
-
otp: string,
|
|
63
|
-
newPassword: string,
|
|
64
|
-
passwordConfirmation: string
|
|
65
|
-
) {
|
|
66
|
-
try {
|
|
67
|
-
return await $fetch("/api/auth/reset-password", {
|
|
68
|
-
method: "POST",
|
|
69
|
-
body: JSON.stringify({ otp, newPassword, passwordConfirmation }),
|
|
70
|
-
headers: { "Content-Type": "application/json" },
|
|
71
|
-
});
|
|
72
|
-
} catch (error) {
|
|
73
|
-
console.error("Error resetting password:", error);
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
44
|
+
return $fetch<Record<string, any>>("/api/verifications/forget-password", {
|
|
45
|
+
method: "POST",
|
|
46
|
+
body: JSON.stringify({ email }),
|
|
47
|
+
});
|
|
76
48
|
}
|
|
77
49
|
|
|
78
50
|
function verify(id: string) {
|
|
@@ -94,7 +66,6 @@ export default function useLocalAuth() {
|
|
|
94
66
|
logout,
|
|
95
67
|
getCurrentUser,
|
|
96
68
|
forgotPassword,
|
|
97
|
-
resetPassword,
|
|
98
69
|
verify,
|
|
99
70
|
loggedInUser,
|
|
100
71
|
};
|
package/composables/useUser.ts
CHANGED
|
@@ -87,6 +87,17 @@ export default function useUser() {
|
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
async function resetPassword(value: {
|
|
91
|
+
id: string;
|
|
92
|
+
newPassword: string;
|
|
93
|
+
confirmPassword: string;
|
|
94
|
+
}) {
|
|
95
|
+
return $fetch("/api/users/password", {
|
|
96
|
+
method: "PATCH",
|
|
97
|
+
body: value,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
90
101
|
return {
|
|
91
102
|
inviteUser,
|
|
92
103
|
updateName,
|
|
@@ -98,5 +109,6 @@ export default function useUser() {
|
|
|
98
109
|
getUsers,
|
|
99
110
|
createUserByVerification,
|
|
100
111
|
getById,
|
|
112
|
+
resetPassword,
|
|
101
113
|
};
|
|
102
114
|
}
|
|
@@ -6,10 +6,11 @@ export default function useUser() {
|
|
|
6
6
|
page = 1,
|
|
7
7
|
email = "",
|
|
8
8
|
app = "",
|
|
9
|
+
org = "",
|
|
9
10
|
} = {}) {
|
|
10
11
|
return $fetch<Record<string, any>>("/api/verifications", {
|
|
11
12
|
method: "GET",
|
|
12
|
-
query: { status, search, page, type, email, app },
|
|
13
|
+
query: { status, search, page, type, email, app, org },
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
16
|
|
package/package.json
CHANGED
|
@@ -66,11 +66,12 @@ const { forgotPassword } = useLocalAuth();
|
|
|
66
66
|
const message = ref("");
|
|
67
67
|
|
|
68
68
|
async function submit(email = "") {
|
|
69
|
+
message.value = "";
|
|
69
70
|
try {
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
const result = await forgotPassword(email);
|
|
72
|
+
message.value = result.message;
|
|
72
73
|
} catch (error: any) {
|
|
73
|
-
message.value = error.message;
|
|
74
|
+
message.value = error.response?._data?.message || "An error occurred.";
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
</script>
|
package/pages/index.vue
CHANGED
|
@@ -1,3 +1,94 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<v-row no-gutters class="fill-height" justify="center" align-content="center">
|
|
3
|
+
<v-col cols="12" class="text-center">
|
|
4
|
+
<span class="text-h1 font-weight-bold">{{ APP_NAME }}</span>
|
|
5
|
+
</v-col>
|
|
6
|
+
|
|
7
|
+
<v-col cols="12" class="text-center mt-6" v-if="currentUser">
|
|
8
|
+
<v-row no-gutters justify="center">
|
|
9
|
+
<v-btn
|
|
10
|
+
class="text-lowercase"
|
|
11
|
+
rounded="xl"
|
|
12
|
+
variant="tonal"
|
|
13
|
+
size="large"
|
|
14
|
+
@click="handleSignin()"
|
|
15
|
+
>
|
|
16
|
+
<span class="d-inline-block text-truncate" style="width: 300px">
|
|
17
|
+
Sign-in as {{ currentUser?.email }}
|
|
18
|
+
</span>
|
|
19
|
+
</v-btn>
|
|
20
|
+
</v-row>
|
|
21
|
+
</v-col>
|
|
22
|
+
|
|
23
|
+
<v-col cols="12" class="text-center mt-6" v-else>
|
|
24
|
+
<v-row justify="center">
|
|
25
|
+
<v-col cols="12" lg="2" md="3" sm="3">
|
|
26
|
+
<v-btn
|
|
27
|
+
block
|
|
28
|
+
class="text-lowercase"
|
|
29
|
+
rounded="xl"
|
|
30
|
+
variant="tonal"
|
|
31
|
+
size="large"
|
|
32
|
+
:to="{ name: 'login' }"
|
|
33
|
+
>
|
|
34
|
+
Sign In
|
|
35
|
+
</v-btn>
|
|
36
|
+
</v-col>
|
|
37
|
+
|
|
38
|
+
<v-col cols="12">
|
|
39
|
+
Don't have an account?
|
|
40
|
+
<nuxt-link :href="`${APP_MAIN}/sign-up`">Sign up</nuxt-link>
|
|
41
|
+
</v-col>
|
|
42
|
+
</v-row>
|
|
43
|
+
</v-col>
|
|
44
|
+
</v-row>
|
|
3
45
|
</template>
|
|
46
|
+
|
|
47
|
+
<script setup lang="ts">
|
|
48
|
+
definePageMeta({
|
|
49
|
+
layout: "plain",
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const { APP_NAME, APP_MAIN, APP } = useRuntimeConfig().public;
|
|
53
|
+
|
|
54
|
+
const { getCurrentUser, currentUser, loggedInUser } = useLocalAuth();
|
|
55
|
+
try {
|
|
56
|
+
await getCurrentUser();
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.log(error);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { getByApp } = useMember();
|
|
62
|
+
|
|
63
|
+
const isPartnerApp = computed(() =>
|
|
64
|
+
[
|
|
65
|
+
"org",
|
|
66
|
+
"marketplace",
|
|
67
|
+
"services",
|
|
68
|
+
"stay",
|
|
69
|
+
"ride",
|
|
70
|
+
"eat",
|
|
71
|
+
"experience",
|
|
72
|
+
"job",
|
|
73
|
+
].includes(APP)
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const { data: member } = await useLazyAsyncData(
|
|
77
|
+
"get-member-by-app",
|
|
78
|
+
() => getByApp({ app: APP, user: loggedInUser() }),
|
|
79
|
+
{ immediate: isPartnerApp.value }
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
function handleSignin() {
|
|
83
|
+
if (APP === "main") {
|
|
84
|
+
navigateTo({ name: "feeds" });
|
|
85
|
+
} else if (APP === "admin") {
|
|
86
|
+
navigateTo({ name: "home" });
|
|
87
|
+
} else {
|
|
88
|
+
navigateTo({
|
|
89
|
+
name: "org-dashboard",
|
|
90
|
+
params: { org: member.value?.org ?? "org" },
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
</script>
|
package/pages/login.vue
CHANGED
|
@@ -127,7 +127,7 @@ async function submit({ email = "", password = "" } = {}) {
|
|
|
127
127
|
await login({ email, password });
|
|
128
128
|
|
|
129
129
|
if (APP === "main") {
|
|
130
|
-
await navigateTo({ name: "
|
|
130
|
+
await navigateTo({ name: "feeds" });
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
|
|
@@ -148,7 +148,16 @@ async function submit({ email = "", password = "" } = {}) {
|
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
150
150
|
} catch (error: any) {
|
|
151
|
-
|
|
151
|
+
if (
|
|
152
|
+
error.response &&
|
|
153
|
+
error.response._data &&
|
|
154
|
+
error.response._data.message
|
|
155
|
+
) {
|
|
156
|
+
message.value = error.response._data.message;
|
|
157
|
+
} else {
|
|
158
|
+
message.value = "An unexpected error occurred. Please try again.";
|
|
159
|
+
}
|
|
160
|
+
console.log(error);
|
|
152
161
|
} finally {
|
|
153
162
|
loading.value = false;
|
|
154
163
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters class="fill-height" justify="center" align-content="center">
|
|
3
|
+
<v-col cols="12" lg="3" md="4" sm="6">
|
|
4
|
+
<v-form
|
|
5
|
+
v-model="isValid"
|
|
6
|
+
@submit.prevent="submit(otp, newPassword, confirmPassword)"
|
|
7
|
+
>
|
|
8
|
+
<v-row no-gutters>
|
|
9
|
+
<v-col cols="12">
|
|
10
|
+
<v-row no-gutters justify="center">
|
|
11
|
+
<nuxt-link
|
|
12
|
+
class="text-h2 font-weight-bold text-decoration-none"
|
|
13
|
+
style="color: unset"
|
|
14
|
+
:to="{ name: 'index' }"
|
|
15
|
+
>
|
|
16
|
+
GoWeekdays
|
|
17
|
+
</nuxt-link>
|
|
18
|
+
</v-row>
|
|
19
|
+
</v-col>
|
|
20
|
+
|
|
21
|
+
<v-col cols="12" class="mt-6">
|
|
22
|
+
<v-row no-gutters>
|
|
23
|
+
<v-col cols="12" class="text-h6 font-weight-bold">
|
|
24
|
+
New Password
|
|
25
|
+
</v-col>
|
|
26
|
+
<v-col cols="12">
|
|
27
|
+
<InputPassword
|
|
28
|
+
id="newPassword"
|
|
29
|
+
v-model="newPassword"
|
|
30
|
+
:rules="[requiredRule, passwordRule]"
|
|
31
|
+
/>
|
|
32
|
+
</v-col>
|
|
33
|
+
</v-row>
|
|
34
|
+
</v-col>
|
|
35
|
+
|
|
36
|
+
<v-col cols="12">
|
|
37
|
+
<v-row no-gutters>
|
|
38
|
+
<v-col cols="12" class="text-h6 font-weight-bold">
|
|
39
|
+
Confirm New Password
|
|
40
|
+
</v-col>
|
|
41
|
+
<v-col cols="12">
|
|
42
|
+
<InputPassword
|
|
43
|
+
id="confirmPassword"
|
|
44
|
+
v-model="confirmPassword"
|
|
45
|
+
:rules="[requiredRule, passwordRule]"
|
|
46
|
+
:errorMessages="
|
|
47
|
+
confirmPassword && newPassword !== confirmPassword
|
|
48
|
+
? 'Password mismatch!'
|
|
49
|
+
: ''
|
|
50
|
+
"
|
|
51
|
+
/>
|
|
52
|
+
</v-col>
|
|
53
|
+
</v-row>
|
|
54
|
+
</v-col>
|
|
55
|
+
|
|
56
|
+
<v-col v-if="message" cols="12" class="my-2 font-italic text-center">
|
|
57
|
+
{{ message }}
|
|
58
|
+
</v-col>
|
|
59
|
+
|
|
60
|
+
<v-col cols="12">
|
|
61
|
+
<v-row no-gutters justify="center">
|
|
62
|
+
<v-btn
|
|
63
|
+
type="submit"
|
|
64
|
+
variant="tonal"
|
|
65
|
+
:disabled="!isValid"
|
|
66
|
+
rounded="xl"
|
|
67
|
+
size="large"
|
|
68
|
+
>
|
|
69
|
+
submit
|
|
70
|
+
</v-btn>
|
|
71
|
+
</v-row>
|
|
72
|
+
</v-col>
|
|
73
|
+
|
|
74
|
+
<v-col cols="12" class="mt-6 text-center">
|
|
75
|
+
All good?
|
|
76
|
+
<nuxt-link :to="{ name: 'index' }">Sign in</nuxt-link>
|
|
77
|
+
</v-col>
|
|
78
|
+
</v-row>
|
|
79
|
+
</v-form>
|
|
80
|
+
</v-col>
|
|
81
|
+
</v-row>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<script setup lang="ts">
|
|
85
|
+
definePageMeta({
|
|
86
|
+
layout: "plain",
|
|
87
|
+
});
|
|
88
|
+
const { requiredRule, passwordRule } = useUtils();
|
|
89
|
+
const newPassword = ref("");
|
|
90
|
+
const confirmPassword = ref("");
|
|
91
|
+
const isValid = ref(false);
|
|
92
|
+
const otp = (useRoute().params.otp as string) ?? "";
|
|
93
|
+
|
|
94
|
+
const { resetPassword } = useUser();
|
|
95
|
+
|
|
96
|
+
const message = ref("");
|
|
97
|
+
|
|
98
|
+
async function submit(id = "", newPassword = "", confirmPassword = "") {
|
|
99
|
+
try {
|
|
100
|
+
const result: any = await resetPassword({
|
|
101
|
+
id,
|
|
102
|
+
newPassword,
|
|
103
|
+
confirmPassword,
|
|
104
|
+
});
|
|
105
|
+
message.value = result.message;
|
|
106
|
+
} catch (error: any) {
|
|
107
|
+
message.value = error.response._data.message;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
</script>
|
package/pages/sign-up/[id].vue
CHANGED
|
@@ -139,15 +139,7 @@ const loading = ref(false);
|
|
|
139
139
|
|
|
140
140
|
async function validate() {
|
|
141
141
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (result.type) {
|
|
145
|
-
type.value = result.type;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (result.referralCode) {
|
|
149
|
-
referralCode.value = result.referralCode;
|
|
150
|
-
}
|
|
142
|
+
await verify(id);
|
|
151
143
|
|
|
152
144
|
validInvitation.value = true;
|
|
153
145
|
message.value = "";
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters class="fill-height" justify="center" align-content="center">
|
|
3
|
+
<v-col
|
|
4
|
+
v-if="validating"
|
|
5
|
+
cols="12"
|
|
6
|
+
class="text-subtitle-1 font-weight-medium text-center"
|
|
7
|
+
>
|
|
8
|
+
{{ message }}
|
|
9
|
+
</v-col>
|
|
10
|
+
<v-col v-else cols="12" lg="3" md="4" sm="6">
|
|
11
|
+
<v-row no-gutters>
|
|
12
|
+
<v-col v-if="validInvitation" cols="12">
|
|
13
|
+
<v-form
|
|
14
|
+
v-model="isValid"
|
|
15
|
+
@submit.prevent="submit({ firstName, lastName, password, id })"
|
|
16
|
+
id="form1"
|
|
17
|
+
autocomplete="off"
|
|
18
|
+
>
|
|
19
|
+
<v-row no-gutters>
|
|
20
|
+
<v-col cols="12">
|
|
21
|
+
<v-row no-gutters>
|
|
22
|
+
<InputLabel
|
|
23
|
+
class="text-capitalize"
|
|
24
|
+
title="First Name"
|
|
25
|
+
required
|
|
26
|
+
/>
|
|
27
|
+
<v-col cols="12">
|
|
28
|
+
<v-text-field
|
|
29
|
+
v-model="firstName"
|
|
30
|
+
density="comfortable"
|
|
31
|
+
:rules="[requiredRule]"
|
|
32
|
+
></v-text-field>
|
|
33
|
+
</v-col>
|
|
34
|
+
</v-row>
|
|
35
|
+
</v-col>
|
|
36
|
+
|
|
37
|
+
<v-col cols="12" class="mt-2">
|
|
38
|
+
<v-row no-gutters>
|
|
39
|
+
<InputLabel
|
|
40
|
+
class="text-capitalize"
|
|
41
|
+
title="Last Name"
|
|
42
|
+
required
|
|
43
|
+
/>
|
|
44
|
+
<v-col cols="12">
|
|
45
|
+
<v-text-field
|
|
46
|
+
v-model="lastName"
|
|
47
|
+
density="comfortable"
|
|
48
|
+
:rules="[requiredRule]"
|
|
49
|
+
></v-text-field>
|
|
50
|
+
</v-col>
|
|
51
|
+
</v-row>
|
|
52
|
+
</v-col>
|
|
53
|
+
|
|
54
|
+
<v-col cols="12">
|
|
55
|
+
<v-row no-gutters>
|
|
56
|
+
<InputLabel
|
|
57
|
+
class="text-capitalize"
|
|
58
|
+
title="Password"
|
|
59
|
+
required
|
|
60
|
+
/>
|
|
61
|
+
<v-col cols="12">
|
|
62
|
+
<InputPassword v-model="password" :rules="[requiredRule]" />
|
|
63
|
+
</v-col>
|
|
64
|
+
</v-row>
|
|
65
|
+
</v-col>
|
|
66
|
+
|
|
67
|
+
<v-col
|
|
68
|
+
v-if="errorOnSubmit"
|
|
69
|
+
cols="12"
|
|
70
|
+
class="my-2 text-error text-center"
|
|
71
|
+
>
|
|
72
|
+
{{ message }}
|
|
73
|
+
</v-col>
|
|
74
|
+
|
|
75
|
+
<v-col cols="12">
|
|
76
|
+
<v-btn
|
|
77
|
+
block
|
|
78
|
+
type="submit"
|
|
79
|
+
variant="text"
|
|
80
|
+
:disabled="!isValid"
|
|
81
|
+
rounded="xl"
|
|
82
|
+
size="large"
|
|
83
|
+
>
|
|
84
|
+
submit
|
|
85
|
+
</v-btn>
|
|
86
|
+
</v-col>
|
|
87
|
+
</v-row>
|
|
88
|
+
</v-form>
|
|
89
|
+
</v-col>
|
|
90
|
+
|
|
91
|
+
<v-col
|
|
92
|
+
v-else
|
|
93
|
+
cols="12"
|
|
94
|
+
class="text-subtitle-1 font-weight-medium text-center"
|
|
95
|
+
>
|
|
96
|
+
<span>{{ message }}</span>
|
|
97
|
+
<v-row no-gutters justify="center">
|
|
98
|
+
<nuxt-link :to="{ name: 'index' }">Go to homepage</nuxt-link>
|
|
99
|
+
</v-row>
|
|
100
|
+
</v-col>
|
|
101
|
+
</v-row>
|
|
102
|
+
</v-col>
|
|
103
|
+
</v-row>
|
|
104
|
+
</template>
|
|
105
|
+
|
|
106
|
+
<script setup lang="ts">
|
|
107
|
+
definePageMeta({
|
|
108
|
+
layout: "plain",
|
|
109
|
+
});
|
|
110
|
+
const { verify } = useLocalAuth();
|
|
111
|
+
|
|
112
|
+
const id = (useRoute().params.id as string) ?? "";
|
|
113
|
+
|
|
114
|
+
const validating = ref(true);
|
|
115
|
+
const validInvitation = ref(false);
|
|
116
|
+
|
|
117
|
+
const message = ref("Validating invitation...");
|
|
118
|
+
const invite = ref<Record<string, any> | null>(null);
|
|
119
|
+
|
|
120
|
+
async function validate() {
|
|
121
|
+
try {
|
|
122
|
+
invite.value = await verify(id);
|
|
123
|
+
validInvitation.value = true;
|
|
124
|
+
} catch (error: any) {
|
|
125
|
+
message.value = error.data.message;
|
|
126
|
+
}
|
|
127
|
+
validating.value = false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
await validate();
|
|
131
|
+
|
|
132
|
+
const { requiredRule } = useUtils();
|
|
133
|
+
const firstName = ref("");
|
|
134
|
+
const lastName = ref("");
|
|
135
|
+
const password = ref("");
|
|
136
|
+
const isValid = ref(false);
|
|
137
|
+
|
|
138
|
+
const { createUserByVerification } = useUser();
|
|
139
|
+
|
|
140
|
+
const errorOnSubmit = ref(false);
|
|
141
|
+
|
|
142
|
+
async function submit({
|
|
143
|
+
firstName = "",
|
|
144
|
+
lastName = "",
|
|
145
|
+
password = "",
|
|
146
|
+
id = "",
|
|
147
|
+
} = {}) {
|
|
148
|
+
errorOnSubmit.value = false;
|
|
149
|
+
try {
|
|
150
|
+
await createUserByVerification({
|
|
151
|
+
firstName,
|
|
152
|
+
lastName,
|
|
153
|
+
password,
|
|
154
|
+
id,
|
|
155
|
+
type: invite.value?.type,
|
|
156
|
+
});
|
|
157
|
+
await navigateTo({ name: "index" });
|
|
158
|
+
} catch (error: any) {
|
|
159
|
+
message.value = error.response._data.message;
|
|
160
|
+
errorOnSubmit.value = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
</script>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters class="fill-height" justify="center" align-content="center">
|
|
3
|
+
<v-col cols="12" class="text-subtitle-1 font-weight-medium text-center">
|
|
4
|
+
{{ message }}
|
|
5
|
+
</v-col>
|
|
6
|
+
</v-row>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
definePageMeta({
|
|
11
|
+
layout: "plain",
|
|
12
|
+
});
|
|
13
|
+
const { verify } = useLocalAuth();
|
|
14
|
+
|
|
15
|
+
const id = (useRoute().params.id as string) ?? "";
|
|
16
|
+
|
|
17
|
+
const validating = ref(true);
|
|
18
|
+
const validInvitation = ref(false);
|
|
19
|
+
|
|
20
|
+
const message = ref("Validating invitation...");
|
|
21
|
+
const invite = ref<Record<string, any> | null>(null);
|
|
22
|
+
|
|
23
|
+
async function validate() {
|
|
24
|
+
try {
|
|
25
|
+
invite.value = await verify(id);
|
|
26
|
+
validInvitation.value = true;
|
|
27
|
+
message.value =
|
|
28
|
+
invite.value.message || "Successfully accepted the invitation!";
|
|
29
|
+
} catch (error: any) {
|
|
30
|
+
message.value = error.data.message;
|
|
31
|
+
}
|
|
32
|
+
validating.value = false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
await validate();
|
|
36
|
+
|
|
37
|
+
const { requiredRule } = useUtils();
|
|
38
|
+
const firstName = ref("");
|
|
39
|
+
const lastName = ref("");
|
|
40
|
+
const password = ref("");
|
|
41
|
+
const isValid = ref(false);
|
|
42
|
+
|
|
43
|
+
const { createUserByVerification } = useUser();
|
|
44
|
+
|
|
45
|
+
const errorOnSubmit = ref(false);
|
|
46
|
+
|
|
47
|
+
async function submit({
|
|
48
|
+
firstName = "",
|
|
49
|
+
lastName = "",
|
|
50
|
+
password = "",
|
|
51
|
+
id = "",
|
|
52
|
+
} = {}) {
|
|
53
|
+
errorOnSubmit.value = false;
|
|
54
|
+
try {
|
|
55
|
+
await createUserByVerification({
|
|
56
|
+
firstName,
|
|
57
|
+
lastName,
|
|
58
|
+
password,
|
|
59
|
+
id,
|
|
60
|
+
type: invite.value?.type,
|
|
61
|
+
});
|
|
62
|
+
} catch (error: any) {
|
|
63
|
+
message.value = error.response._data.message;
|
|
64
|
+
errorOnSubmit.value = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</script>
|