@edgedev/create-edge-app 1.1.25 → 1.1.27

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 (111) hide show
  1. package/README.md +55 -20
  2. package/{agent.md → agents.md} +2 -0
  3. package/bin/cli.js +6 -6
  4. package/edge/components/auth/login.vue +384 -0
  5. package/edge/components/auth/register.vue +396 -0
  6. package/edge/components/auth.vue +108 -0
  7. package/edge/components/autoFileUpload.vue +215 -0
  8. package/edge/components/billing.vue +8 -0
  9. package/edge/components/buttonDivider.vue +14 -0
  10. package/edge/components/chip.vue +34 -0
  11. package/edge/components/clipboardButton.vue +42 -0
  12. package/edge/components/cms/block.vue +529 -0
  13. package/edge/components/cms/blockApi.vue +212 -0
  14. package/edge/components/cms/blockEditor.vue +725 -0
  15. package/edge/components/cms/blockInput.vue +66 -0
  16. package/edge/components/cms/blockPicker.vue +486 -0
  17. package/edge/components/cms/blockRender.vue +78 -0
  18. package/edge/components/cms/blockSheetContent.vue +28 -0
  19. package/edge/components/cms/codeEditor.vue +466 -0
  20. package/edge/components/cms/fontUpload.vue +327 -0
  21. package/edge/components/cms/htmlContent.vue +807 -0
  22. package/edge/components/cms/init_blocks/api_with_subarrays.html +17 -0
  23. package/edge/components/cms/init_blocks/array_with_collection.html +7 -0
  24. package/edge/components/cms/init_blocks/array_with_objects.html +7 -0
  25. package/edge/components/cms/init_blocks/carousel.html +103 -0
  26. package/edge/components/cms/init_blocks/contact_us.html +69 -0
  27. package/edge/components/cms/init_blocks/content_with_left_image.html +27 -0
  28. package/edge/components/cms/init_blocks/footer.html +24 -0
  29. package/edge/components/cms/init_blocks/header_divider.html +7 -0
  30. package/edge/components/cms/init_blocks/hero.html +35 -0
  31. package/edge/components/cms/init_blocks/hero_carousel.html +52 -0
  32. package/edge/components/cms/init_blocks/newsletter.html +117 -0
  33. package/edge/components/cms/init_blocks/post_content.html +7 -0
  34. package/edge/components/cms/init_blocks/post_title_header.html +21 -0
  35. package/edge/components/cms/init_blocks/posts_list.html +20 -0
  36. package/edge/components/cms/init_blocks/properties_showcase.html +100 -0
  37. package/edge/components/cms/init_blocks/property_carousel.html +59 -0
  38. package/edge/components/cms/init_blocks/property_detail.html +112 -0
  39. package/edge/components/cms/init_blocks/property_detail_header.html +34 -0
  40. package/edge/components/cms/init_blocks/property_results.html +137 -0
  41. package/edge/components/cms/init_blocks/property_search.html +75 -0
  42. package/edge/components/cms/init_blocks/simple_array.html +7 -0
  43. package/edge/components/cms/mediaCard.vue +116 -0
  44. package/edge/components/cms/mediaManager.vue +386 -0
  45. package/edge/components/cms/menu.vue +1103 -0
  46. package/edge/components/cms/optionsSelect.vue +107 -0
  47. package/edge/components/cms/page.vue +1785 -0
  48. package/edge/components/cms/posts.vue +1083 -0
  49. package/edge/components/cms/site.vue +1475 -0
  50. package/edge/components/cms/themeDefaultMenu.vue +548 -0
  51. package/edge/components/cms/themeEditor.vue +429 -0
  52. package/edge/components/dashboard.vue +776 -0
  53. package/edge/components/editor.vue +671 -0
  54. package/edge/components/fileTree.vue +72 -0
  55. package/edge/components/files.vue +89 -0
  56. package/edge/components/formSubtypes/myOrgs.vue +214 -0
  57. package/edge/components/formSubtypes/users.vue +336 -0
  58. package/edge/components/functionChips.vue +57 -0
  59. package/edge/components/gError.vue +98 -0
  60. package/edge/components/gHelper.vue +67 -0
  61. package/edge/components/gInput.vue +1331 -0
  62. package/edge/components/loggingIn.vue +41 -0
  63. package/edge/components/menu.vue +137 -0
  64. package/edge/components/menuContent.vue +132 -0
  65. package/edge/components/myAccount.vue +317 -0
  66. package/edge/components/myOrganizations.vue +75 -0
  67. package/edge/components/myProfile.vue +122 -0
  68. package/edge/components/orgSwitcher.vue +25 -0
  69. package/edge/components/organizationMembers.vue +522 -0
  70. package/edge/components/organizationSettings.vue +271 -0
  71. package/edge/components/shad/breadcrumbs.vue +35 -0
  72. package/edge/components/shad/button.vue +43 -0
  73. package/edge/components/shad/checkbox.vue +73 -0
  74. package/edge/components/shad/combobox.vue +238 -0
  75. package/edge/components/shad/datepicker.vue +184 -0
  76. package/edge/components/shad/dialog.vue +32 -0
  77. package/edge/components/shad/dropdownMenu.vue +54 -0
  78. package/edge/components/shad/dropdownMenuItem.vue +21 -0
  79. package/edge/components/shad/form.vue +59 -0
  80. package/edge/components/shad/html.vue +877 -0
  81. package/edge/components/shad/input.vue +139 -0
  82. package/edge/components/shad/number.vue +109 -0
  83. package/edge/components/shad/select.vue +151 -0
  84. package/edge/components/shad/selectTags.vue +278 -0
  85. package/edge/components/shad/switch.vue +67 -0
  86. package/edge/components/shad/tags.vue +137 -0
  87. package/edge/components/shad/textarea.vue +102 -0
  88. package/edge/components/shad/typeMoney.vue +167 -0
  89. package/edge/components/sideBar.vue +288 -0
  90. package/edge/components/sideBarContent.vue +268 -0
  91. package/edge/components/sidebarProvider.vue +33 -0
  92. package/edge/components/tooltip.vue +16 -0
  93. package/edge/components/userMenu.vue +148 -0
  94. package/edge/components/v/alert.vue +59 -0
  95. package/edge/components/v/alertTitle.vue +18 -0
  96. package/edge/components/v/card.vue +53 -0
  97. package/edge/components/v/cardActions.vue +18 -0
  98. package/edge/components/v/cardText.vue +18 -0
  99. package/edge/components/v/cardTitle.vue +20 -0
  100. package/edge/components/v/col.vue +56 -0
  101. package/edge/components/v/list.vue +46 -0
  102. package/edge/components/v/listItem.vue +26 -0
  103. package/edge/components/v/listItemTitle.vue +18 -0
  104. package/edge/components/v/row.vue +42 -0
  105. package/edge/components/v/toolbar.vue +24 -0
  106. package/edge/composables/global.ts +519 -0
  107. package/edge-pull.sh +2 -0
  108. package/edge-push.sh +1 -0
  109. package/edge-status.sh +14 -0
  110. package/package.json +1 -1
  111. package/edge-components-install.sh +0 -1
@@ -0,0 +1,41 @@
1
+ <script setup>
2
+ const props = defineProps({
3
+ class: String,
4
+ })
5
+ const state = reactive({
6
+ count: 20,
7
+ })
8
+ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
9
+
10
+ const incrementCount = async () => {
11
+ while (true) {
12
+ if (state.count < 100) {
13
+ state.count += 10
14
+ await sleep(100) // Wait for 100 milliseconds
15
+ }
16
+ else {
17
+ state.count = 0
18
+ await sleep(500) // Wait for 100 milliseconds
19
+ }
20
+ }
21
+ }
22
+
23
+ incrementCount()
24
+ </script>
25
+
26
+ <template>
27
+ <div class="flex h-full w-full align-bottom items-center">
28
+ <Card :class="props.class" class="w-full pt-10 pb-6">
29
+ <CardContent class="text-center">
30
+ <slot>
31
+ Loading...
32
+ </slot>
33
+ <Progress v-model="state.count" class="w-100" />
34
+ </CardContent>
35
+ </Card>
36
+ </div>
37
+ </template>
38
+
39
+ <style lang="scss" scoped>
40
+
41
+ </style>
@@ -0,0 +1,137 @@
1
+ <script setup>
2
+ import { cn } from '@/lib/utils'
3
+
4
+ const props = defineProps({
5
+ type: {
6
+ type: String,
7
+ required: false,
8
+ default: 'Card',
9
+ },
10
+ class: {
11
+ type: String,
12
+ required: false,
13
+ default: '',
14
+ },
15
+ menuItems: {
16
+ type: Array,
17
+ required: false,
18
+ default: () => [],
19
+ },
20
+ navClass: {
21
+ type: String,
22
+ required: false,
23
+ default: '',
24
+ },
25
+ buttonClass: {
26
+ type: String,
27
+ required: false,
28
+ default: '',
29
+ },
30
+ singleOrg: {
31
+ type: Boolean,
32
+ default: false,
33
+ },
34
+ showIcon: {
35
+ type: Boolean,
36
+ required: false,
37
+ default: true,
38
+ },
39
+ selectedBgColor: {
40
+ type: String,
41
+ required: false,
42
+ default: '',
43
+ },
44
+ selectedTextColor: {
45
+ type: String,
46
+ required: false,
47
+ default: '',
48
+ },
49
+ showStart: {
50
+ type: Boolean,
51
+ required: false,
52
+ default: true,
53
+ },
54
+ showEnd: {
55
+ type: Boolean,
56
+ required: false,
57
+ default: true,
58
+ },
59
+ showCenter: {
60
+ type: Boolean,
61
+ required: false,
62
+ default: true,
63
+ },
64
+ })
65
+
66
+ const typeClasses = computed(() => {
67
+ return {
68
+ header: 'top-0',
69
+ footer: 'bottom-0',
70
+ div: '',
71
+ }
72
+ })
73
+ </script>
74
+
75
+ <template>
76
+ <Card
77
+ v-if="props.type === 'Card'"
78
+ :class="cn(typeClasses[props.type], 'z-10 flex items-center gap-1 px-4 flex-shrink-0 overflow-hidden', props.class)"
79
+ >
80
+ <edge-menu-content
81
+ v-bind="props"
82
+ >
83
+ <template v-if="props.showStart" #start>
84
+ <slot name="start" />
85
+ </template>
86
+ <template v-if="props.showCenter" #center>
87
+ <slot name="center" />
88
+ </template>
89
+ <template v-if="props.showEnd" #end>
90
+ <slot name="end" />
91
+ </template>
92
+ </edge-menu-content>
93
+ </Card>
94
+
95
+ <nav
96
+ v-else-if="props.type === 'nav'"
97
+ :class="cn(typeClasses[props.type], 'z-10 flex items-center gap-1 border-b px-4 flex-shrink-0', props.class)"
98
+ >
99
+ <edge-menu-content
100
+ v-bind="props"
101
+ >
102
+ <template v-if="props.showStart" #start>
103
+ <slot name="start" />
104
+ </template>
105
+ <template v-if="props.showCenter" #center>
106
+ <slot name="center" />
107
+ </template>
108
+ <template v-if="props.showEnd" #end>
109
+ <slot name="end" />
110
+ </template>
111
+ </edge-menu-content>
112
+ </nav>
113
+ <footer
114
+ v-else-if="props.type === 'footer'"
115
+ :class="cn(typeClasses[props.type], 'z-10 flex items-center gap-1 border-t px-4 flex-shrink-0', props.class)"
116
+ >
117
+ <edge-menu-content
118
+ v-bind="props"
119
+ >
120
+ <template v-if="props.showStart" #start>
121
+ <slot name="start" />
122
+ </template>
123
+ <template v-if="props.showCenter" #center>
124
+ <slot name="center" />
125
+ </template>
126
+ <template v-if="props.showEnd" #end>
127
+ <slot name="end" />
128
+ </template>
129
+ </edge-menu-content>
130
+ </footer>
131
+ </template>
132
+
133
+ <style lang="scss" scoped>
134
+ .inverted-logo {
135
+ filter: invert(1);
136
+ }
137
+ </style>
@@ -0,0 +1,132 @@
1
+ <script setup>
2
+ import { cn } from '@/lib/utils'
3
+
4
+ const props = defineProps({
5
+ type: {
6
+ type: String,
7
+ required: false,
8
+ default: 'Card',
9
+ },
10
+ singleOrg: {
11
+ type: Boolean,
12
+ default: false,
13
+ },
14
+ class: {
15
+ type: String,
16
+ required: false,
17
+ default: '',
18
+ },
19
+ menuItems: {
20
+ type: Array,
21
+ required: false,
22
+ default: () => [],
23
+ },
24
+ navClass: {
25
+ type: String,
26
+ required: false,
27
+ default: '',
28
+ },
29
+ buttonClass: {
30
+ type: String,
31
+ required: false,
32
+ default: '',
33
+ },
34
+ showIcon: {
35
+ type: Boolean,
36
+ required: false,
37
+ default: true,
38
+ },
39
+ selectedBgColor: {
40
+ type: String,
41
+ required: false,
42
+ default: '',
43
+ },
44
+ selectedTextColor: {
45
+ type: String,
46
+ required: false,
47
+ default: '',
48
+ },
49
+ showStart: {
50
+ type: Boolean,
51
+ required: false,
52
+ default: true,
53
+ },
54
+ showEnd: {
55
+ type: Boolean,
56
+ required: false,
57
+ default: true,
58
+ },
59
+ showCenter: {
60
+ type: Boolean,
61
+ required: false,
62
+ default: true,
63
+ },
64
+ })
65
+
66
+ const route = useRoute()
67
+
68
+ const orgName = computed(() => {
69
+ const org = edgeGlobal.edgeState.organizations.find(
70
+ org => org.docId === edgeGlobal.edgeState.currentOrganization,
71
+ )
72
+ return org?.name
73
+ })
74
+
75
+ const startsWithCurrentRoute = (path) => {
76
+ const currentRoutePath = route.fullPath.endsWith('/')
77
+ ? route.fullPath.substring(0, route.fullPath.length - 1)
78
+ : route.fullPath
79
+ return (
80
+ path === currentRoutePath || currentRoutePath.startsWith(path)
81
+ )
82
+ }
83
+ </script>
84
+
85
+ <template>
86
+ <div v-if="props.showStart" class="flex items-center gap-1">
87
+ <slot name="start">
88
+ <Package class="h-6 w-6 mr-2" />
89
+ <h1 class="text-xl font-bold">
90
+ {{ orgName }}
91
+ </h1>
92
+ </slot>
93
+ </div>
94
+ <div v-if="props.showCenter" class="grow flex items-center gap-1">
95
+ <slot name="center" />
96
+ <div v-if="props.menuItems.length > 0" class="grow">
97
+ <nav
98
+ :class="cn('justify-center ml-4 hidden flex-col gap-3 text-lg font-medium md:flex md:flex-row md:items-center md:gap-2 md:text-sm lg:gap-3', navClass)"
99
+ >
100
+ <edge-shad-button
101
+ v-for="(item, key) in props.menuItems"
102
+ :key="key"
103
+ :to="item.to"
104
+ :class="cn(
105
+ 'transition-colors px-0',
106
+ hoverClass,
107
+ buttonClass,
108
+ {
109
+ [selectedBgColor]: startsWithCurrentRoute(item.to),
110
+ [selectedTextColor]: startsWithCurrentRoute(item.to),
111
+ },
112
+ )"
113
+ variant="text"
114
+ >
115
+ <component
116
+ :is="item.icon"
117
+ v-if="item.icon && props.showIcon"
118
+ class="h-4 w-4 mr-1"
119
+ />
120
+ {{ item.title }}
121
+ </edge-shad-button>
122
+ </nav>
123
+ </div>
124
+ </div>
125
+ <div v-if="props.showEnd" class="flex items-center gap-1">
126
+ <slot name="end">
127
+ <div class="grow text-right">
128
+ <edge-user-menu :single-org="props.singleOrg" button-class="bg-primary" />
129
+ </div>
130
+ </slot>
131
+ </div>
132
+ </template>
@@ -0,0 +1,317 @@
1
+ <script setup>
2
+ import { computed, inject, nextTick, onBeforeMount, reactive, watch } from 'vue'
3
+ import { toTypedSchema } from '@vee-validate/zod'
4
+ import * as z from 'zod'
5
+ const edgeFirebase = inject('edgeFirebase')
6
+ // const edgeGlobal = inject('edgeGlobal')
7
+
8
+ const router = useRouter()
9
+
10
+ const state = reactive({
11
+ loading: false,
12
+ username: '',
13
+ newPassword: '',
14
+ oldPassword: '',
15
+ passwordForm: false,
16
+ userForm: false,
17
+ loaded: true,
18
+ passwordVisible: false,
19
+ passwordShow: false,
20
+ passwordError: { success: true, message: '' },
21
+ userError: { success: true, message: '' },
22
+ showDeleteAccount: false,
23
+ deleteForm: false,
24
+ })
25
+ const updateUser = async () => {
26
+ state.loading = true
27
+ state.userError = await edgeFirebase.updateEmail(state.username)
28
+ if (state.userError.message === 'Firebase: Error (auth/email-already-in-use).') {
29
+ state.userError = { success: false, message: 'Email already in use.' }
30
+ }
31
+ if (state.userError.message === 'Firebase: Error (auth/requires-recent-login).') {
32
+ state.userError = { success: false, message: 'Please log out and log back in to change your email.' }
33
+ }
34
+ state.userError = { success: state.userError.success, message: state.userError.message.replace('Firebase: ', '').replace(' (auth/invalid-email)', '') }
35
+ if (state.userError.success) {
36
+ state.userError = { success: true, message: 'A verification link has been sent to your new email address. Please click the link to complete the email change process.' }
37
+ }
38
+ edgeGlobal.edgeState.changeTracker = {}
39
+ state.loaded = false
40
+ state.loading = false
41
+ await nextTick()
42
+ state.loaded = true
43
+ }
44
+ const updatePassword = async () => {
45
+ state.loading = true
46
+ state.passwordError = await edgeFirebase.setPassword(state.oldPassword, state.newPassword)
47
+ if (state.passwordError.message === 'Firebase: Error (auth/wrong-password).') {
48
+ state.passwordError = { success: false, message: 'Old Password is incorrect.' }
49
+ }
50
+ state.passwordError = { success: state.passwordError.success, message: state.passwordError.message.replace('Firebase: ', '').replace(' (auth/weak-password)', '') }
51
+ if (state.passwordError.success) {
52
+ state.oldPassword = ''
53
+ state.newPassword = ''
54
+ state.passwordError = { success: true, message: 'Password successfully changed' }
55
+ }
56
+ edgeGlobal.edgeState.changeTracker = {}
57
+ state.loading = false
58
+ state.loaded = false
59
+ await nextTick()
60
+ state.loaded = true
61
+ }
62
+ const deleteAccount = async () => {
63
+ state.loading = true
64
+ await edgeFirebase.runFunction('edgeFirebase-deleteSelf', { uid: edgeFirebase.user.uid })
65
+ await edgeFirebase.logOut()
66
+ state.loading = false
67
+ router.push('/app/login')
68
+ }
69
+
70
+ const currentOrgName = computed(() => {
71
+ if (edgeGlobal.objHas(edgeFirebase.data, edgeGlobal.edgeState.organizationDocPath) === false) {
72
+ return ''
73
+ }
74
+ return edgeFirebase.data[edgeGlobal.edgeState.organizationDocPath].name
75
+ })
76
+ onBeforeMount(() => {
77
+ if (edgeFirebase.user.firebaseUser.providerData.length === 0) {
78
+ state.username = edgeFirebase.user.uid
79
+ }
80
+ else {
81
+ state.username = edgeFirebase.user.firebaseUser.providerData[0].email
82
+ }
83
+ })
84
+ watch(currentOrgName, async () => {
85
+ state.org = currentOrgName.value
86
+ edgeGlobal.edgeState.changeTracker = {}
87
+ state.loaded = false
88
+ await nextTick()
89
+ state.loaded = true
90
+ })
91
+
92
+ const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
93
+
94
+ const passwordSchema = toTypedSchema(z.object({
95
+ oldPassword: z.string({
96
+ required_error: 'Password is required',
97
+ }).superRefine((value, ctx) => {
98
+ if (value.length < 8 || value.length > 50 || !passwordPattern.test(value)) {
99
+ ctx.addIssue({
100
+ code: z.ZodIssueCode.custom,
101
+ message: 'Password must have at least 8 characters, including uppercase and lowercase letters, numbers, and a special character',
102
+ })
103
+ }
104
+ }),
105
+ newPassword: z.string({
106
+ required_error: 'Password is required',
107
+ }).superRefine((value, ctx) => {
108
+ if (value.length < 8 || value.length > 50 || !passwordPattern.test(value)) {
109
+ ctx.addIssue({
110
+ code: z.ZodIssueCode.custom,
111
+ message: 'Password must have at least 8 characters, including uppercase and lowercase letters, numbers, and a special character',
112
+ })
113
+ }
114
+ }),
115
+ }))
116
+
117
+ const usernameSchema = toTypedSchema(z.object({
118
+ username: z.string({
119
+ required_error: 'Username is required',
120
+ }).email({
121
+ message: 'Invalid email address',
122
+ }),
123
+ }))
124
+
125
+ const deleteSchema = toTypedSchema(z.object({
126
+ delete_account: z.boolean({
127
+ required_error: 'You must confirm that you understand the consequences of deleting your account',
128
+ }),
129
+ }))
130
+
131
+ const route = useRoute()
132
+ </script>
133
+
134
+ <template>
135
+ <Card class="w-full flex-1 bg-muted/50 mx-auto w-full border-none shadow-none pt-2">
136
+ <slot name="header">
137
+ <edge-menu class="bg-secondary text-foreground rounded-none sticky top-0 py-6">
138
+ <template #start>
139
+ <slot name="header-start">
140
+ <component :is="edgeGlobal.iconFromMenu(route)" class="mr-2" />
141
+ <span class="capitalize">My Account</span>
142
+ </slot>
143
+ </template>
144
+ <template #center>
145
+ <slot name="header-center">
146
+ <div class="w-full px-6" />
147
+ </slot>
148
+ </template>
149
+ <template #end>
150
+ <slot name="header-end">
151
+ <div />
152
+ </slot>
153
+ </template>
154
+ </edge-menu>
155
+ </slot>
156
+ <CardContent v-if="state.loaded" class="p-3 w-full overflow-y-auto scroll-area">
157
+ <Card v-if="state.loaded" class="bg-transparent border-0">
158
+ <CardContent>
159
+ <template v-if="edgeFirebase.user.firebaseUser.providerData.length === 0">
160
+ <edge-v-alert>
161
+ Logged in as:
162
+ <edge-v-alert-title>{{ state.username }}</edge-v-alert-title>
163
+ <strong>Custom Provider</strong>
164
+ <Separator class="my-4 dark:bg-slate-600" />
165
+ Notice: You're signed in with a custom provider. Nothing to update here.
166
+ </edge-v-alert>
167
+ </template>
168
+ <template v-else-if="edgeFirebase.user.firebaseUser.providerData[0].providerId === 'password'">
169
+ <div class="mb-2 font-bold">
170
+ Update Email
171
+ </div>
172
+ <edge-shad-form
173
+ v-model="state.userForm"
174
+ :schema="usernameSchema"
175
+ @submit="updateUser"
176
+ >
177
+ <edge-g-input
178
+ v-model="state.username"
179
+ name="username"
180
+ field-type="text"
181
+ label="Username"
182
+ parent-tracker-id="my-account"
183
+ hint="Update your email address, which also serves as your username."
184
+ persistent-hint
185
+ />
186
+ <edge-v-alert
187
+ v-if="state.userError.message !== ''"
188
+ :type="state.userError.success ? 'success' : 'error'"
189
+ dismissible
190
+ class="mt-0 mb-3 text-caption" density="compact" variant="tonal"
191
+ >
192
+ {{ state.userError.message }}
193
+ </edge-v-alert>
194
+
195
+ <edge-shad-button
196
+ type="submit"
197
+ :disabled="state.loading"
198
+ class="text-white bg-slate-800 hover:bg-slate-400"
199
+ >
200
+ <Loader2 v-if="state.loading" class="w-4 h-4 mr-2 animate-spin" />
201
+ Update Email
202
+ </edge-shad-button>
203
+ </edge-shad-form>
204
+ <Separator class="my-4 dark:bg-slate-600" />
205
+ <edge-shad-form
206
+ v-model="state.passwordForm"
207
+ :schema="passwordSchema"
208
+ @submit="updatePassword"
209
+ >
210
+ <div class="mb-2 font-bold">
211
+ Change Password
212
+ </div>
213
+ <edge-shad-input
214
+ v-model="state.oldPassword"
215
+ type="password"
216
+ label="Old Password"
217
+ placeholder="Enter your old password"
218
+ name="oldPassword"
219
+ />
220
+ <edge-shad-input
221
+ v-model="state.newPassword"
222
+ type="password"
223
+ label="New Password"
224
+ placeholder="Enter your new password"
225
+ name="newPassword"
226
+ />
227
+ <edge-v-alert
228
+ v-if="state.passwordError.message !== ''"
229
+ :type="state.passwordError.success ? 'success' : 'error'"
230
+ dismissible
231
+ class="mt-0 mb-3 text-caption" density="compact" variant="tonal"
232
+ >
233
+ {{ state.passwordError.message }}
234
+ </edge-v-alert>
235
+ <edge-shad-button
236
+ type="submit"
237
+ :disabled="state.loading"
238
+ class="text-white bg-slate-800 hover:bg-slate-400"
239
+ >
240
+ <Loader2 v-if="state.loading" class="w-4 h-4 mr-2 animate-spin" />
241
+ Update Password
242
+ </edge-shad-button>
243
+ </edge-shad-form>
244
+ </template>
245
+ <template v-else>
246
+ <edge-v-alert>
247
+ Logged in as:
248
+ <edge-v-alert-title>{{ edgeFirebase.user.firebaseUser.providerData[0].email }}</edge-v-alert-title>
249
+ <strong>Provider: {{ edgeFirebase.user.firebaseUser.providerData[0].providerId }}</strong>
250
+ <Separator class="my-4 dark:bg-slate-600" />
251
+ Notice: You're signed in with a third-party provider. To update your login information, please visit your provider's account settings. Changes cannot be made directly within this app.
252
+ </edge-v-alert>
253
+ </template>
254
+ <van-divider class="my-2">
255
+ <h4 class="font-bold">
256
+ Delete Account
257
+ </h4>
258
+ </van-divider>
259
+ <Separator class="my-4 dark:bg-slate-600" />
260
+ <edge-shad-form
261
+ v-model="state.deleteForm"
262
+ :schema="deleteSchema"
263
+ @submit="deleteAccount"
264
+ >
265
+ <edge-shad-button
266
+ v-if="!state.showDeleteAccount"
267
+ :disabled="state.loading"
268
+ variant="destructive"
269
+ class="w-full"
270
+ @click.stop.prevent="state.showDeleteAccount = true"
271
+ >
272
+ <Loader2 v-if="state.loading" class="w-4 h-4 mr-2 animate-spin" />
273
+ Delete Account
274
+ </edge-shad-button>
275
+ <edge-v-alert v-else closable variant="tonal" border="start" type="error" prominent @click:close="state.showDeleteAccount = false">
276
+ <div class="text-xl font-bold">
277
+ Are you sure?
278
+ </div>
279
+ <h3 class="my-2">
280
+ <strong>Warning:</strong> Deleting your account will permanently remove all of your data from this app. This action cannot be undone.
281
+ </h3>
282
+ <edge-g-input
283
+ name="delete_account"
284
+ field-type="boolean"
285
+ label="I understand the consequences of deleting my account."
286
+ :disable-tracking="true"
287
+ />
288
+ <div class="flex gap-2 items-center">
289
+ <edge-shad-button
290
+ :disabled="state.loading"
291
+ variant="destructive"
292
+ class="text-white bg-slate-800 hover:bg-slate-400 mt-3"
293
+ @click.stop.prevent="state.showDeleteAccount = false"
294
+ >
295
+ Cancel
296
+ </edge-shad-button>
297
+ <edge-shad-button
298
+ type="submit"
299
+ :disabled="state.loading"
300
+ variant="destructive"
301
+ class="text-white mt-3 uppercase text-lg"
302
+ >
303
+ <Loader2 v-if="state.loading" class="w-4 h-4 mr-2 animate-spin" />
304
+ Delete Account
305
+ </edge-shad-button>
306
+ </div>
307
+ </edge-v-alert>
308
+ </edge-shad-form>
309
+ </CardContent>
310
+ </Card>
311
+ </CardContent>
312
+ </Card>
313
+ </template>
314
+
315
+ <style lang="scss" scoped>
316
+
317
+ </style>
@@ -0,0 +1,75 @@
1
+ <script setup>
2
+ import { computed, defineProps, inject, nextTick, reactive, watch } from 'vue'
3
+
4
+ const props = defineProps({
5
+ registrationCode: {
6
+ type: String,
7
+ default: '',
8
+ },
9
+ title: {
10
+ type: String,
11
+ default: 'My Organizations',
12
+ },
13
+ })
14
+
15
+ const edgeFirebase = inject('edgeFirebase')
16
+ // const edgeGlobal = inject('edgeGlobal')
17
+
18
+ const state = reactive({
19
+ loaded: true,
20
+ })
21
+
22
+ const roles = computed(() => {
23
+ return edgeFirebase.user.roles
24
+ })
25
+
26
+ watch(roles, async () => {
27
+ await edgeGlobal.getOrganizations(edgeFirebase)
28
+ state.loaded = false
29
+ await nextTick()
30
+ state.loaded = true
31
+ })
32
+
33
+ const route = useRoute()
34
+ </script>
35
+
36
+ <template>
37
+ <Card class="w-full flex-1 bg-muted/50 mx-auto w-full border-none shadow-none pt-2">
38
+ <slot name="header">
39
+ <edge-menu class="bg-secondary text-foreground rounded-none sticky top-0 py-6">
40
+ <template #start>
41
+ <slot name="header-start">
42
+ <component :is="edgeGlobal.iconFromMenu(route)" class="mr-2" />
43
+ <span class="capitalize">My Organizations</span>
44
+ </slot>
45
+ </template>
46
+ <template #center>
47
+ <slot name="header-center">
48
+ <div class="w-full px-6" />
49
+ </slot>
50
+ </template>
51
+ <template #end>
52
+ <slot name="header-end">
53
+ <div />
54
+ </slot>
55
+ </template>
56
+ </edge-menu>
57
+ </slot>
58
+ <CardContent v-if="state.loaded" class="p-3 w-full overflow-y-auto scroll-area">
59
+ <edge-g-input
60
+ v-if="state.loaded"
61
+ v-model="edgeGlobal.edgeState.organizations"
62
+ name="organizations"
63
+ :disable-tracking="true"
64
+ field-type="objectList"
65
+ sub-field-type="my-orgs"
66
+ parent-tracker-id="myOrgs"
67
+ :pass-through-props="props.registrationCode"
68
+ />
69
+ </CardContent>
70
+ </Card>
71
+ </template>
72
+
73
+ <style lang="scss" scoped>
74
+
75
+ </style>