@live-change/user-frontend 0.0.3

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/e2e/codecept.conf.js +60 -0
  3. package/e2e/connectEmailCode.test.js +61 -0
  4. package/e2e/connectEmailLink.test.js +60 -0
  5. package/e2e/delete.test.js +44 -0
  6. package/e2e/disconnectEmail.test.js +42 -0
  7. package/e2e/resetPasswordWithEmailCode.test.js +62 -0
  8. package/e2e/resetPasswordWithEmailLink.test.js +62 -0
  9. package/e2e/setPassword.test.js +70 -0
  10. package/e2e/signInEmailCode.test.js +52 -0
  11. package/e2e/signInEmailLink.test.js +52 -0
  12. package/e2e/signInEmailPassword.test.js +47 -0
  13. package/e2e/signOut.test.js +41 -0
  14. package/e2e/signUpEmailCode.test.js +41 -0
  15. package/e2e/signUpEmailLink.test.js +41 -0
  16. package/e2e/steps.d.ts +12 -0
  17. package/e2e/steps_file.js +89 -0
  18. package/front/index.html +11 -0
  19. package/front/public/favicon.ico +0 -0
  20. package/front/public/images/empty-photo.svg +38 -0
  21. package/front/public/images/empty-user-photo.svg +33 -0
  22. package/front/public/images/logo.svg +34 -0
  23. package/front/public/images/logo128.png +0 -0
  24. package/front/src/App.vue +31 -0
  25. package/front/src/Index.vue +14 -0
  26. package/front/src/NavBar.vue +103 -0
  27. package/front/src/SettingsTabs.vue +48 -0
  28. package/front/src/connected/Connect.vue +58 -0
  29. package/front/src/connected/ConnectFinished.vue +16 -0
  30. package/front/src/connected/Connected.vue +84 -0
  31. package/front/src/connected/routes.js +16 -0
  32. package/front/src/delete/Delete.vue +53 -0
  33. package/front/src/delete/DeleteFeedbackSent.vue +16 -0
  34. package/front/src/delete/DeleteFinished.vue +32 -0
  35. package/front/src/delete/routes.js +16 -0
  36. package/front/src/entry-client.js +6 -0
  37. package/front/src/entry-server.js +6 -0
  38. package/front/src/identification/IdentificationSettings.vue +116 -0
  39. package/front/src/identification/ObjectIdentification.vue +36 -0
  40. package/front/src/identification/UserIdentification.vue +101 -0
  41. package/front/src/identification/routes.js +12 -0
  42. package/front/src/message-auth/ConnectEmail.vue +105 -0
  43. package/front/src/message-auth/MessageLink.vue +95 -0
  44. package/front/src/message-auth/MessageSent.vue +103 -0
  45. package/front/src/message-auth/ResetPasswordEmail.vue +105 -0
  46. package/front/src/message-auth/SignInEmail.vue +105 -0
  47. package/front/src/message-auth/SignUpEmail.vue +105 -0
  48. package/front/src/message-auth/routes.js +25 -0
  49. package/front/src/notifications/NotificationButtons.vue +70 -0
  50. package/front/src/notifications/NotificationListPage.vue +22 -0
  51. package/front/src/notifications/NotificationsIcon.vue +75 -0
  52. package/front/src/notifications/NotificationsList.vue +144 -0
  53. package/front/src/notifications/NotificationsSettings.vue +117 -0
  54. package/front/src/notifications/SimpleNotification.vue +34 -0
  55. package/front/src/notifications/TestNotification.vue +25 -0
  56. package/front/src/notifications/UnknownNotification.vue +25 -0
  57. package/front/src/notifications/notificationTypes.js +11 -0
  58. package/front/src/notifications/routes.js +37 -0
  59. package/front/src/password/ChangePassword.vue +106 -0
  60. package/front/src/password/ChangePasswordFinished.vue +16 -0
  61. package/front/src/password/ResetPassword.vue +56 -0
  62. package/front/src/password/ResetPasswordFinished.vue +16 -0
  63. package/front/src/password/ResetPasswordForm.vue +118 -0
  64. package/front/src/password/routes.js +41 -0
  65. package/front/src/router.js +90 -0
  66. package/front/src/settings/Settings.vue +33 -0
  67. package/front/src/settings/SettingsIndex.vue +22 -0
  68. package/front/src/settings/SettingsMenu.vue +81 -0
  69. package/front/src/settings/SettingsMenuItem.vue +35 -0
  70. package/front/src/sign/SignIn.vue +93 -0
  71. package/front/src/sign/SignInFinished.vue +27 -0
  72. package/front/src/sign/SignOut.vue +37 -0
  73. package/front/src/sign/SignOutFinished.vue +16 -0
  74. package/front/src/sign/SignUp.vue +51 -0
  75. package/front/src/sign/SignUpFinished.vue +16 -0
  76. package/front/src/sign/routes.js +24 -0
  77. package/front/vite.config.js +11 -0
  78. package/index.js +11 -0
  79. package/package.json +87 -0
  80. package/server/init.js +53 -0
  81. package/server/security.config.js +53 -0
  82. package/server/services.config.js +74 -0
@@ -0,0 +1,118 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card border-round shadow-2 p-4" v-if="isUnknown">
4
+ <div class="text-900 font-medium mb-3 text-xl">Unknown link</div>
5
+ <p class="mt-0 mb-2 p-0 line-height-3">We can't find your secret link. Check if you copied the address correctly.</p>
6
+ </div>
7
+
8
+ <div class="surface-card border-round shadow-2 p-4" v-if="isUsed">
9
+ <div class="text-900 font-medium mb-3 text-xl">Link used</div>
10
+ <p class="mt-0 mb-2 p-0 line-height-3">This link was already used.</p>
11
+ </div>
12
+
13
+ <div class="surface-card border-round shadow-2 p-4" v-if="isExpired && !isUsed">
14
+ <div class="text-900 font-medium mb-3 text-xl">Link expired</div>
15
+ <p class="mt-0 mb-4 p-0 line-height-3">Your password reset authentication already expired.</p>
16
+ </div>
17
+
18
+ <div class="surface-card p-4 shadow-2 border-round" v-if="isReady">
19
+ <div class="text-center mb-5">
20
+ <div class="text-900 text-3xl font-medium mb-3">Reset password</div>
21
+ </div>
22
+
23
+ <command-form service="passwordAuthentication" action="finishResetPassword" v-slot="{ data }"
24
+ :parameters="{ key: resetKey }" ref="form"
25
+ @done="handleDone" keepOnDone>
26
+
27
+ <template v-if="isMounted">
28
+ <div class="p-field mb-3">
29
+ <label for="newPassword" class="block text-900 font-medium mb-2">New password</label>
30
+ <Password id="newPassword" class="w-full" inputClass="w-full" toggleMask
31
+ :class="{ 'p-invalid': data.passwordHashError }"
32
+ v-model="data.passwordHash">
33
+ <template #footer>
34
+ <Divider />
35
+ <p class="p-mt-2">Suggestions</p>
36
+ <ul class="p-pl-2 p-ml-2 p-mt-0" style="line-height: 1.5">
37
+ <li>At least one lowercase</li>
38
+ <li>At least one uppercase</li>
39
+ <li>At least one numeric</li>
40
+ <li>Minimum 8 characters</li>
41
+ </ul>
42
+ </template>
43
+ </Password>
44
+ <small id="newPassword-help" class="p-error">{{ data.passwordHashError }}</small>
45
+ </div>
46
+
47
+ <div class="p-field mb-3">
48
+ <label for="reenterPassword" class="block text-900 font-medium mb-2">Re-enter password</label>
49
+ <Password id="reenterPassword" class="w-full" inputClass="w-full"
50
+ v-model="secondPassword"
51
+ :feedback="false" toggleMask />
52
+ </div>
53
+
54
+ </template>
55
+
56
+ <Button type="submit" label="Reset password" icon="pi pi-key" class="w-full"></Button>
57
+
58
+ </command-form>
59
+ </div>
60
+ </div>
61
+ </template>
62
+
63
+ <script setup>
64
+ import InputText from "primevue/inputtext"
65
+ import Checkbox from "primevue/checkbox"
66
+ import Button from "primevue/button"
67
+ import Divider from "primevue/divider"
68
+ import Password from "primevue/password"
69
+
70
+ const { resetKey } = defineProps({
71
+ resetKey: {
72
+ type: String,
73
+ required: true
74
+ }
75
+ })
76
+
77
+ import { useNow } from '@vueuse/core'
78
+ const now = useNow({ interval: 1000 })
79
+
80
+ import { ref, onMounted, computed } from 'vue'
81
+ const secondPassword = ref('')
82
+ const form = ref()
83
+ onMounted(() => {
84
+ form.value.addValidator('passwordHash', () => {
85
+ const value = form.value.getFieldValue('passwordHash')
86
+ console.log("PASSWORDS MATCH?", secondPassword.value, value)
87
+ if(value != secondPassword.value) return "passwordsNotMatch"
88
+ })
89
+ })
90
+
91
+ import { useRouter } from 'vue-router'
92
+ const router = useRouter()
93
+
94
+ const isMounted = ref(false)
95
+ onMounted(() => isMounted.value = true)
96
+
97
+ import { live, path } from '@live-change/vue3-ssr'
98
+ const [ authentication ] = await Promise.all([
99
+ live( path().passwordAuthentication.resetPasswordAuthentication({ key: resetKey }) )
100
+ ])
101
+
102
+ const isUnknown = computed(() => authentication.value === null)
103
+ const isExpired = computed(() =>
104
+ authentication.value ? (now.value.toISOString() > authentication.value.expire) : false )
105
+ const isUsed = computed(() => authentication.value && authentication.value.state == 'used')
106
+ const isReady = computed(() => !(isUnknown.value || isExpired.value || isUsed.value))
107
+
108
+ function handleDone({ parameters, result }) {
109
+ console.log("DONE RESULT", result)
110
+ router.push({
111
+ name: 'user:resetPasswordFinished'
112
+ })
113
+ }
114
+ </script>
115
+
116
+ <style>
117
+
118
+ </style>
@@ -0,0 +1,41 @@
1
+ export function passwordResetRoutes(config = {}) {
2
+ const { prefix = '/', route = (r) => r } = config
3
+
4
+ return [
5
+
6
+ route({ name: 'user:resetPassword', path: prefix + 'reset-password',
7
+ component: () => import("./ResetPassword.vue") }),
8
+ route({ name: 'user:resetPasswordForm', path: prefix + 'set-new-password/:resetKey',
9
+ component: () => import("./ResetPasswordForm.vue"), props: true }),
10
+ route({ name: 'user:resetPasswordFinished', path: prefix + 'reset-password-finished',
11
+ component: () => import("./ResetPasswordFinished.vue") }),
12
+
13
+ ]
14
+ }
15
+
16
+
17
+ export function passwordChangeRoutes(config = {}) {
18
+ const { prefix = '/', route = (r) => r } = config
19
+
20
+ return [
21
+
22
+ route({ name: 'user:changePassword', path: prefix + 'change-password',
23
+ component: () => import("./ChangePassword.vue") }),
24
+ route({ name: 'user:changePasswordFinished', path: prefix + 'change-password-finished',
25
+ component: () => import("./ChangePasswordFinished.vue") })
26
+
27
+ ]
28
+ }
29
+
30
+ export function routes(config = {}) {
31
+ const { prefix = '/', route = (r) => r } = config
32
+
33
+ return [
34
+
35
+ ...passwordResetRoutes(config),
36
+ ...passwordChangeRoutes(config)
37
+
38
+ ]
39
+ }
40
+
41
+ export default routes
@@ -0,0 +1,90 @@
1
+ import {
2
+ createMemoryHistory,
3
+ createRouter as _createRouter,
4
+ createWebHistory
5
+ } from 'vue-router'
6
+
7
+ import messageAuthRoutes from "./message-auth/routes.js"
8
+ import signRoutes from "./sign/routes.js"
9
+ import connectedRoutes from "./connected/routes.js"
10
+ import identificationRoutes from "./identification/routes.js"
11
+ import deleteRoutes from "./delete/routes.js"
12
+ import { passwordResetRoutes, passwordChangeRoutes } from "./password/routes.js"
13
+ import { notificationsSettingsRoutes, notificationsRoutes } from "./notifications/routes.js"
14
+
15
+ import { dbAdminRoutes } from "@live-change/db-admin"
16
+
17
+ export function userRoutes(config = {}) {
18
+ const { prefix = '/', route = (r) => r } = config
19
+ return [
20
+
21
+ ...messageAuthRoutes(config),
22
+ ...signRoutes(config),
23
+ ...passwordResetRoutes(config),
24
+ ...notificationsRoutes(config),
25
+
26
+ route({
27
+ path: prefix + 'settings', meta: { pageType: 'wide' },
28
+ component: () => import("./settings/Settings.vue"),
29
+ children: [
30
+ {
31
+ name: 'user:settings', path: '', meta: { viewType: 'wide', signedIn: true },
32
+ component: () => import("./settings/SettingsIndex.vue")
33
+ },
34
+ ...deleteRoutes({ ...config, prefix: '' }),
35
+ ...passwordChangeRoutes({ ...config, prefix: '' }),
36
+ ...connectedRoutes({ ...config, prefix: '' }),
37
+ ...identificationRoutes({ ...config, prefix: '' }),
38
+ ...notificationsSettingsRoutes({ ...config, prefix: '' })
39
+ ]
40
+ })
41
+
42
+ ]
43
+ }
44
+
45
+ export async function sitemap(route, api) {
46
+ route({ name: 'SignIn' })
47
+ route({ name: 'SignUp' })
48
+ }
49
+
50
+ import { client as useClient } from '@live-change/vue3-ssr'
51
+
52
+ export function installUserRedirects(router, app, config) {
53
+ const client = useClient(app._context)
54
+ router.beforeEach(async (to, from) => {
55
+ if(to?.matched.find(m => m?.meta.signedIn)) {
56
+ if(!client.value.user) {
57
+ console.log("REDIRECT TO LOGIN BECAUSE PAGE REQUIRES LOGIN!")
58
+ router.redirectAfterSignIn = to.fullPath
59
+ return { name: 'user:signIn' }
60
+ }
61
+ }
62
+ if(to?.matched.find(m => m?.meta.signedOut)) {
63
+ if(client.value.user) {
64
+ console.log("REDIRECT TO USER INDEX BECAUSE PAGE REQUIRES LOGOUT!")
65
+ return { name: 'user:settings' }
66
+ }
67
+ }
68
+ if(to && to.name == 'user:signIn' && from?.matched.find(m => m?.meta.saveForSignIn)) {
69
+ console.log("SAVE FOR LOGIN", from.fullPath)
70
+ localStorage.redirectAfterLogin = from.fullPath
71
+ }
72
+ })
73
+ }
74
+
75
+ export function createRouter(app, config) {
76
+ //console.log("APP CTX", app._context)
77
+ const router = _createRouter({
78
+ // use appropriate history implementation for server/client
79
+ // import.meta.env.SSR is injected by Vite.
80
+ history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
81
+ routes: [
82
+ { path: '/', component: () => import('./Index.vue') },
83
+ ...userRoutes(config),
84
+ ...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) })
85
+ ]
86
+ })
87
+ installUserRedirects(router, app, config)
88
+ return router
89
+ }
90
+
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <div class="flex relative lg:static surface-ground" style="height: calc(100vh - 88px)">
3
+ <div id="settings-menu" class="surface-section hidden flex-shrink-0 absolute left-0 h-full
4
+ top-0 z-1 border-right-1 surface-border select-none md:static md:block" style="width:280px">
5
+ <SettingsMenu />
6
+ </div>
7
+
8
+ <div class="flex flex-column relative flex-auto">
9
+ <div v-if="viewType == 'simple'" class="p-5 flex flex-column flex-auto align-items-center">
10
+ <router-view></router-view>
11
+ </div>
12
+ <template v-if="viewType == 'wide'">
13
+ <router-view></router-view>
14
+ </template>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup>
20
+ import SettingsMenu from "./SettingsMenu.vue"
21
+
22
+ import { computed } from 'vue'
23
+
24
+ import { useRoute } from 'vue-router'
25
+ const route = useRoute()
26
+
27
+ const viewType = computed(() => route.meta.viewType ?? 'simple' )
28
+
29
+ </script>
30
+
31
+ <style scoped>
32
+
33
+ </style>
@@ -0,0 +1,22 @@
1
+ <template>
2
+
3
+ <SettingsMenu class="h-full block md:hidden surface-section" />
4
+
5
+ <div class="flex-column flex-auto align-items-center p-5 hidden md:flex">
6
+ <Connected class="mb-5" />
7
+ <ChangePassword />
8
+ </div>
9
+
10
+ </template>
11
+
12
+ <script setup>
13
+ import SettingsMenu from "./SettingsMenu.vue"
14
+
15
+ import ChangePassword from "../password/ChangePassword.vue"
16
+ import Connected from "../connected/Connected.vue"
17
+
18
+ </script>
19
+
20
+ <style scoped>
21
+
22
+ </style>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <div class="flex flex-column h-full">
3
+ <div class="overflow-y-auto">
4
+ <ul class="list-none p-2 m-0">
5
+ <li>
6
+ <div class="p-3 text-500 font-medium">SETTINGS</div>
7
+ </li>
8
+
9
+ <SettingsMenuItem name="user:identification" icon="id-card" label="Identification" class="hidden md:block" />
10
+
11
+ <SettingsMenuItem name="user:settings" icon="id-card" label="General Settings" class="hidden md:block" />
12
+
13
+ <SettingsMenuItem name="user:notificationsSettings" icon="exclamation-circle" label="Notifications" />
14
+
15
+ </ul>
16
+
17
+ <ul class="list-none p-2 m-0 border-top-1 surface-border">
18
+ <li>
19
+ <div class="p-3 text-500 font-medium">AUTHORIZATION</div>
20
+ </li>
21
+
22
+ <SettingsMenuItem name="user:connected" icon="users" label="Connected Accounts" />
23
+
24
+ <SettingsMenuItem name="user:changePassword" icon="key" label="ChangePassword" />
25
+
26
+ </ul>
27
+
28
+ <ul class="list-none p-2 m-0 border-top-1 surface-border">
29
+
30
+ <SettingsMenuItem name="user:delete" icon="trash" label="Delete Account" />
31
+
32
+ </ul>
33
+ </div>
34
+
35
+ <!-- <div class="p-2 mt-auto border-top-1 surface-border">
36
+ <ul class="list-none p-2 m-0 hidden origin-bottom animation-duration-150">
37
+ <li>
38
+ <a v-ripple class="flex align-items-center cursor-pointer p-3 text-700 hover:surface-100
39
+ border-round transition-colors transition-duration-150 p-ripple">
40
+ <i class="pi pi-user mr-2"></i>
41
+ <span class="font-medium">Profile</span>
42
+ </a>
43
+ </li>
44
+ <li>
45
+ <a v-ripple class="flex align-items-center cursor-pointer p-3 text-700 hover:surface-100
46
+ border-round transition-colors transition-duration-150 p-ripple">
47
+ <i class="pi pi-cog mr-2"></i>
48
+ <span class="font-medium">Settings</span>
49
+ </a>
50
+ </li>
51
+ <li>
52
+ <a v-ripple class="flex align-items-center cursor-pointer p-3 text-700 hover:surface-100
53
+ border-round transition-colors transition-duration-150 p-ripple">
54
+ <i class="pi pi-sign-out mr-2"></i>
55
+ <span class="font-medium">Sign Out</span>
56
+ </a>
57
+ </li>
58
+ </ul>
59
+ <a v-ripple class="p-3 flex align-items-center cursor-pointer text-700 hover:surface-100
60
+ border-round transition-colors transition-duration-150 p-ripple"
61
+ v-styleclass="{ selector: '@prev', enterClass: 'hidden', enterActiveClass: 'scalein',
62
+ leaveToClass: 'hidden', leaveActiveClass: 'fadeout' }">
63
+ <img src="/images/empty-user-photo.svg" class="mr-2 border-circle" style="width: 28px; height: 28px"/>
64
+ <span class="font-medium">Amy Elsner</span>
65
+ <i class="pi pi-chevron-up ml-auto"></i>
66
+ </a>
67
+ </div>-->
68
+ </div>
69
+ </template>
70
+
71
+ <script setup>
72
+ import SettingsMenuItem from "./SettingsMenuItem.vue"
73
+
74
+ import { useRoute } from 'vue-router'
75
+ const route = useRoute()
76
+
77
+ </script>
78
+
79
+ <style scoped>
80
+
81
+ </style>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <li class="block">
3
+ <router-link :to="{ name }"
4
+ :class="route.name == name ? 'text-blue-500' : 'text-700'"
5
+ v-ripple
6
+ class="flex align-items-center cursor-pointer p-3 hover:surface-100
7
+ border-round transition-colors transition-duration-150 p-ripple no-underline">
8
+ <i class="pi mr-2" :class="'pi-'+icon"></i>
9
+ <span class="font-medium">{{ label }}</span>
10
+ </router-link>
11
+ </li>
12
+ </template>
13
+
14
+ <script setup>
15
+
16
+ import { useRoute } from 'vue-router'
17
+ const route = useRoute()
18
+
19
+
20
+ const { name, label, icon } = defineProps({
21
+ name: {
22
+ type: String,
23
+ required: true
24
+ },
25
+ label: {
26
+ type: String,
27
+ required: true
28
+ },
29
+ icon: {
30
+ type: String,
31
+ required: true
32
+ }
33
+ })
34
+
35
+ </script>
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card p-4 shadow-2 border-round">
4
+ <div class="text-center mb-5">
5
+ <div class="text-900 text-3xl font-medium mb-3">Welcome Back</div>
6
+ <span class="text-600 font-medium line-height-3">Don't have an account?</span>
7
+ <router-link :to="{ name: 'user:signUp' }"
8
+ class="font-medium no-underline ml-2 text-blue-500 cursor-pointer">
9
+ Create today!</router-link>
10
+ </div>
11
+
12
+ <command-form service="passwordAuthentication" action="signInEmail" v-slot="{ data }"
13
+ @done="handleDone" keepOnDone v-if="isMounted">
14
+
15
+ <div class="p-field mb-3">
16
+ <label for="email" class="block text-900 font-medium mb-2">
17
+ Email address
18
+ </label>
19
+ <InputText id="email" type="text" class="w-full"
20
+ aria-describedby="email-help" :class="{ 'p-invalid': data.emailError }"
21
+ v-model="data.email" />
22
+ <small id="email-help" class="p-error">{{ data.emailError }}</small>
23
+ </div>
24
+
25
+ <div class="p-field mb-3">
26
+ <label for="password" class="block text-900 font-medium mb-2">Password (optional)</label>
27
+ <Password id="password" class="w-full" inputClass="w-full" toggleMask
28
+ aria-describedby="password-help" :class="{ 'p-invalid': data.passwordHashError }"
29
+ v-model="data.passwordHash" />
30
+ <small id="password-help" class="p-error">{{ data.passwordHashError }}</small>
31
+ </div>
32
+
33
+ <div class="flex align-items-center justify-content-between mb-6">
34
+ <div class="flex align-items-center">
35
+ <Checkbox id="rememberme" :binary="true" class="mr-2"></Checkbox>
36
+ <label for="rememberme">Remember me</label>
37
+ </div>
38
+ <router-link :to="{ name: 'user:resetPassword' }"
39
+ class="font-medium no-underline ml-2 text-blue-500 text-right cursor-pointer">
40
+ Forgot password?
41
+ </router-link>
42
+ </div>
43
+
44
+ <Button label="Sign In" icon="pi pi-user" class="w-full" type="submit"></Button>
45
+
46
+ <Divider align="center" class="my-4">
47
+ <span class="text-600 font-normal text-sm">OR</span>
48
+ </Divider>
49
+
50
+ <Button label="Sign In with GitHub" icon="pi pi-github" class="w-full p-button-secondary mb-2"></Button>
51
+ <Button label="Sign In with Google" icon="pi pi-google" class="w-full p-button-secondary mb-1"></Button>
52
+
53
+ </command-form>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <script setup>
59
+ import InputText from "primevue/inputtext"
60
+ import Checkbox from "primevue/checkbox"
61
+ import Button from "primevue/button"
62
+ import Divider from "primevue/divider"
63
+ import Password from "primevue/password"
64
+
65
+ import { onMounted, ref } from 'vue'
66
+ const isMounted = ref(false)
67
+ onMounted(() => isMounted.value = true)
68
+
69
+ import { useRouter } from 'vue-router'
70
+ const router = useRouter()
71
+
72
+ function handleDone({ parameters, result }) {
73
+ console.log("DONE RESULT", result)
74
+ if(result.type == 'sent') {
75
+ const { authentication } = result
76
+ router.push({
77
+ name: 'user:sent',
78
+ params: {
79
+ authentication
80
+ }
81
+ })
82
+ } else {
83
+ router.push({
84
+ name: 'user:signInFinished',
85
+ })
86
+ }
87
+ }
88
+
89
+ </script>
90
+
91
+ <style>
92
+
93
+ </style>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card border-round shadow-2 p-4">
4
+ <div class="text-900 font-medium mb-3 text-xl mb-4">Signed In</div>
5
+ <p class="mt-0 p-0 line-height-3">Congratulations! You have successfully logged in to your account.</p>
6
+ <div v-if="afterSignIn" class="flex flex-row align-items-center">
7
+ <Button label="Next" />
8
+ </div>
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup>
14
+ import Button from 'primevue/button'
15
+
16
+ import { onMounted, ref } from 'vue'
17
+ const isMounted = ref(false)
18
+ onMounted(() => isMounted.value = true)
19
+
20
+ import { computed } from 'vue'
21
+
22
+ const afterSignIn = computed( () => isMounted.value && localStorage.redirectAfterSignIn )
23
+ </script>
24
+
25
+ <style>
26
+
27
+ </style>
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card border-round shadow-2 p-4">
4
+ <div class="text-900 font-medium mb-3 text-xl mb-4">Sign Out</div>
5
+ <p class="mt-0 p-0 line-height-3">Signing out</p>
6
+ <ProgressSpinner v-if="isMounted" class="m-3" />
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup>
12
+ import ProgressSpinner from "primevue/progressspinner"
13
+
14
+ import { onMounted, ref } from 'vue'
15
+ const isMounted = ref(false)
16
+ onMounted(() => isMounted.value = true)
17
+
18
+ import { actions } from '@live-change/vue3-ssr'
19
+ import { inject } from 'vue'
20
+ import { useRouter } from 'vue-router'
21
+ const router = useRouter()
22
+
23
+ const workingZone = inject('workingZone')
24
+
25
+ const { signOut } = actions().user
26
+
27
+ if(typeof window != 'undefined') {
28
+ workingZone.addPromise('signOut', (async () => {
29
+ await signOut({})
30
+ router.push({name: 'user:signOutFinished'})
31
+ })())
32
+ }
33
+ </script>
34
+
35
+ <style>
36
+
37
+ </style>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card border-round shadow-2 p-4">
4
+ <div class="text-900 font-medium mb-3 text-xl mb-4">Signed Out</div>
5
+ <p class="mt-0 p-0 line-height-3">You have successfully signed out of your account.</p>
6
+ </div>
7
+ </div>
8
+ </template>
9
+
10
+ <script setup>
11
+
12
+ </script>
13
+
14
+ <style>
15
+
16
+ </style>
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card p-4 shadow-2 border-round">
4
+ <div class="text-center mb-5">
5
+ <div class="text-900 text-3xl font-medium mb-3">Sign Up</div>
6
+ </div>
7
+
8
+ <command-form service="messageAuthentication" action="signUpEmail" v-slot="{ data, submit }"
9
+ @done="handleSent" keepOnDone>
10
+
11
+ <div class="p-field mb-3">
12
+ <label for="email" class="block text-900 font-medium mb-2">
13
+ Email address
14
+ </label>
15
+ <InputText id="email" type="text" class="w-full"
16
+ aria-describedby="email-help" :class="{ 'p-invalid': data.emailError}"
17
+ v-model="data.email" />
18
+ <small v-if="data.emailError" id="email-help" class="p-error">{{ data.emailError }}</small>
19
+ </div>
20
+
21
+ <Button label="Sign Up with email" icon="pi pi-user" class="w-full" type="submit"></Button>
22
+
23
+ </command-form>
24
+ </div>
25
+ </div>
26
+ </template>
27
+
28
+ <script setup>
29
+ import InputText from "primevue/inputtext"
30
+ import Checkbox from "primevue/checkbox"
31
+ import Button from "primevue/button"
32
+ import Divider from "primevue/divider"
33
+
34
+ import { useRouter } from 'vue-router'
35
+ const router = useRouter()
36
+
37
+ function handleSent({ parameters, result }) {
38
+ const { authentication } = result
39
+ router.push({
40
+ name: 'user:sent',
41
+ params: {
42
+ authentication
43
+ }
44
+ })
45
+ }
46
+
47
+ </script>
48
+
49
+ <style>
50
+
51
+ </style>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div class="w-full lg:w-6 md:w-9" v-shared-element:form="{ duration: '300ms', includeChildren: true }">
3
+ <div class="surface-card border-round shadow-2 p-4">
4
+ <div class="text-900 font-medium mb-3 text-xl mb-4">Signed Up</div>
5
+ <p class="mt-0 p-0 line-height-3">Congratulations! You have successfully created your account.</p>
6
+ </div>
7
+ </div>
8
+ </template>
9
+
10
+ <script setup>
11
+
12
+ </script>
13
+
14
+ <style>
15
+
16
+ </style>