@wishbone-media/spark 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.js +818 -845
- package/formkit.theme.mjs +3415 -3415
- package/package.json +31 -1
- package/src/assets/css/spark-table.css +1 -1
- package/src/assets/css/spark-tooltip.css +9 -3
- package/src/components/SparkAddressInput.vue +20 -3
- package/src/components/SparkAppSelector.vue +7 -7
- package/src/components/SparkBrandSelector.vue +2 -2
- package/src/components/SparkButton.vue +4 -4
- package/src/components/SparkButtonGroup.vue +2 -2
- package/src/components/SparkCard.vue +5 -3
- package/src/components/SparkEntityBadge.vue +3 -9
- package/src/components/SparkFileDragUpload.vue +13 -9
- package/src/components/SparkImageUpload.vue +4 -1
- package/src/components/SparkModalContainer.vue +23 -19
- package/src/components/SparkModalDialog.vue +36 -17
- package/src/components/SparkNotificationOutlet.vue +1 -1
- package/src/components/SparkOverlay.vue +20 -24
- package/src/components/SparkSubNav.vue +7 -14
- package/src/components/SparkTable.vue +72 -73
- package/src/components/SparkTablePaginationPaging.vue +2 -2
- package/src/components/SparkTableToolbar.vue +1 -1
- package/src/components/SparkToastContainer.vue +25 -41
- package/src/components/SparkTooltip.vue +14 -22
- package/src/components/plugins/SparkTableFilterButtons.vue +5 -1
- package/src/components/plugins/SparkTableFilterSelect.vue +1 -4
- package/src/components/plugins/SparkTableReset.vue +21 -19
- package/src/components/plugins/SparkTableSearch.vue +3 -2
- package/src/composables/index.js +1 -1
- package/src/composables/sparkModalService.js +64 -64
- package/src/composables/sparkNotificationService.js +10 -8
- package/src/composables/sparkOverlayService.js +36 -36
- package/src/composables/useCrudResource.js +1 -7
- package/src/composables/useFormSubmission.js +1 -3
- package/src/composables/useSparkOverlay.js +1 -1
- package/src/composables/useSparkTableRouteSync.js +4 -6
- package/src/composables/useSubNavigation.js +18 -15
- package/src/containers/SparkDefaultContainer.vue +8 -8
- package/src/containers/SparkPublicContainer.vue +1 -2
- package/src/directives/sparkTooltip.js +4 -11
- package/src/index.js +1 -1
- package/src/plugins/app-bootstrap.js +1 -1
- package/src/plugins/axios.js +1 -1
- package/src/plugins/fontawesome.js +3 -3
- package/src/plugins/index.js +17 -3
- package/src/plugins/router.js +8 -12
- package/src/stores/auth.js +1 -1
- package/src/stores/brand-filter.js +40 -40
- package/src/stores/index.js +1 -1
- package/src/stores/navigation.js +1 -1
- package/src/utils/formatTemporal.js +4 -4
- package/src/utils/sparkTable/renderers/badge.js +1 -1
- package/src/utils/sparkTable/renderers/boolean.js +3 -3
- package/src/utils/sparkTable/renderers/currency.js +1 -1
- package/src/utils/sparkTable/renderers/date.js +14 -6
- package/src/utils/sparkTable/renderers/datetime.js +1 -1
- package/src/utils/sparkTable/renderers/image.js +1 -1
- package/src/utils/sparkTable/renderers/link.js +1 -1
- package/src/views/SparkError403View.vue +3 -7
- package/src/views/SparkError404View.vue +3 -9
- package/src/views/SparkErrorGeneralView.vue +1 -3
- package/src/views/SparkForgotPasswordView.vue +7 -4
- package/src/views/SparkLoginView.vue +8 -7
- package/src/views/SparkLogoutView.vue +2 -1
- package/src/views/SparkResetPasswordView.vue +4 -6
package/src/plugins/router.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { useSparkAuthStore } from '../stores/auth.js'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
hasAnyDirtyForm,
|
|
4
|
+
getDirtyFormMessage,
|
|
5
|
+
clearAllDirtyForms,
|
|
6
|
+
} from '../composables/useFormDirtyGuard.js'
|
|
3
7
|
import { sparkModalService } from '../composables/sparkModalService.js'
|
|
4
8
|
import {
|
|
5
9
|
SparkLoginView,
|
|
@@ -8,7 +12,6 @@ import {
|
|
|
8
12
|
SparkResetPasswordView,
|
|
9
13
|
SparkError403View,
|
|
10
14
|
SparkError404View,
|
|
11
|
-
SparkErrorGeneralView,
|
|
12
15
|
} from '../views/index.js'
|
|
13
16
|
|
|
14
17
|
export function createAuthRoutes(options = {}) {
|
|
@@ -108,7 +111,7 @@ function processNavigation(to, next, authStore, defaultAuthenticatedRoute) {
|
|
|
108
111
|
|
|
109
112
|
next({
|
|
110
113
|
path: authStore.state.routes.auth,
|
|
111
|
-
query: { redirect }
|
|
114
|
+
query: { redirect },
|
|
112
115
|
})
|
|
113
116
|
return
|
|
114
117
|
}
|
|
@@ -143,11 +146,7 @@ function processNavigation(to, next, authStore, defaultAuthenticatedRoute) {
|
|
|
143
146
|
* @returns {Object} Route configuration for 403 error page
|
|
144
147
|
*/
|
|
145
148
|
export function create403Route(options = {}) {
|
|
146
|
-
const {
|
|
147
|
-
forbiddenPath = '/error/403',
|
|
148
|
-
logo = '',
|
|
149
|
-
homeRoute = '/dashboard',
|
|
150
|
-
} = options
|
|
149
|
+
const { forbiddenPath = '/error/403', logo = '', homeRoute = '/dashboard' } = options
|
|
151
150
|
|
|
152
151
|
return {
|
|
153
152
|
path: forbiddenPath,
|
|
@@ -167,10 +166,7 @@ export function create403Route(options = {}) {
|
|
|
167
166
|
* @returns {Object} Route configuration for 404 catch-all
|
|
168
167
|
*/
|
|
169
168
|
export function create404Route(options = {}) {
|
|
170
|
-
const {
|
|
171
|
-
logo = '',
|
|
172
|
-
homeRoute = '/dashboard',
|
|
173
|
-
} = options
|
|
169
|
+
const { logo = '', homeRoute = '/dashboard' } = options
|
|
174
170
|
|
|
175
171
|
return {
|
|
176
172
|
path: '/:pathMatch(.*)*',
|
package/src/stores/auth.js
CHANGED
|
@@ -145,7 +145,7 @@ export const useSparkAuthStore = defineStore('auth', () => {
|
|
|
145
145
|
if (!state.overrideToken) {
|
|
146
146
|
state.token = token
|
|
147
147
|
}
|
|
148
|
-
} catch
|
|
148
|
+
} catch {
|
|
149
149
|
// Only clear cookie if not using override token
|
|
150
150
|
if (!state.overrideToken) {
|
|
151
151
|
clearTokenCookie()
|
|
@@ -8,55 +8,55 @@ export const useSparkBrandFilterStore = defineStore(
|
|
|
8
8
|
brands: [],
|
|
9
9
|
})
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Validate brand structure
|
|
19
|
-
const validBrands = config.brands.filter((brand) => {
|
|
20
|
-
const isValid = brand.name && brand.logo
|
|
21
|
-
if (!isValid) {
|
|
22
|
-
console.warn('useSparkBrandFilterStore: Invalid brand object', brand)
|
|
11
|
+
const initialize = (config = {}) => {
|
|
12
|
+
if (!config.brands || !Array.isArray(config.brands)) {
|
|
13
|
+
console.warn('useSparkBrandFilterStore: No brands provided to initialize()')
|
|
14
|
+
state.brands = []
|
|
15
|
+
return
|
|
23
16
|
}
|
|
24
|
-
return isValid
|
|
25
|
-
})
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
brand.current = brand === currentBrands[0]
|
|
18
|
+
// Validate brand structure
|
|
19
|
+
const validBrands = config.brands.filter((brand) => {
|
|
20
|
+
const isValid = brand.name && brand.logo
|
|
21
|
+
if (!isValid) {
|
|
22
|
+
console.warn('useSparkBrandFilterStore: Invalid brand object', brand)
|
|
23
|
+
}
|
|
24
|
+
return isValid
|
|
35
25
|
})
|
|
26
|
+
|
|
27
|
+
// Ensure exactly one brand is marked as current
|
|
28
|
+
const currentBrands = validBrands.filter((b) => b.current)
|
|
29
|
+
if (currentBrands.length === 0 && validBrands.length > 0) {
|
|
30
|
+
validBrands[0].current = true
|
|
31
|
+
} else if (currentBrands.length > 1) {
|
|
32
|
+
// Only the first current brand stays current
|
|
33
|
+
validBrands.forEach((brand) => {
|
|
34
|
+
brand.current = brand === currentBrands[0]
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
state.brands = validBrands.map((brand) => ({
|
|
39
|
+
id: brand.id,
|
|
40
|
+
name: brand.name,
|
|
41
|
+
logo: brand.logo,
|
|
42
|
+
current: brand.current || false,
|
|
43
|
+
}))
|
|
36
44
|
}
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
name: brand.name,
|
|
41
|
-
logo: brand.logo,
|
|
42
|
-
current: brand.current || false,
|
|
43
|
-
}))
|
|
44
|
-
}
|
|
46
|
+
const currentBrand = computed(() => state.brands.find((item) => item.current) || null)
|
|
47
|
+
const allBrands = computed(() => state.brands)
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
const toggleBrand = (brand) => {
|
|
50
|
+
if (!brand || !state.brands.includes(brand)) {
|
|
51
|
+
console.warn('useSparkBrandFilterStore: Invalid brand provided to toggleBrand()')
|
|
52
|
+
return
|
|
53
|
+
}
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return
|
|
55
|
+
state.brands.forEach((item) => {
|
|
56
|
+
item.current = item === brand
|
|
57
|
+
})
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
state.brands.forEach((item) => {
|
|
56
|
-
item.current = item === brand
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
60
|
return {
|
|
61
61
|
state,
|
|
62
62
|
initialize,
|
package/src/stores/index.js
CHANGED
package/src/stores/navigation.js
CHANGED
|
@@ -95,7 +95,7 @@ const getFormatter = (locale, options) => {
|
|
|
95
95
|
const getFormattedPart = (date, locale, options, type) => {
|
|
96
96
|
const formatter = getFormatter(locale, options)
|
|
97
97
|
const parts = formatter.formatToParts(date)
|
|
98
|
-
const part = parts.find(p => p.type === type)
|
|
98
|
+
const part = parts.find((p) => p.type === type)
|
|
99
99
|
return part ? part.value : ''
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -117,7 +117,7 @@ const temporalToDate = (temporal) => {
|
|
|
117
117
|
temporal.hour || 0,
|
|
118
118
|
temporal.minute || 0,
|
|
119
119
|
temporal.second || 0,
|
|
120
|
-
temporal.millisecond || 0
|
|
120
|
+
temporal.millisecond || 0,
|
|
121
121
|
)
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -223,8 +223,8 @@ const createTokens = (temporal, locale) => {
|
|
|
223
223
|
['SSS', () => pad(comp.millisecond, 3)],
|
|
224
224
|
|
|
225
225
|
// AM/PM
|
|
226
|
-
['A', () => comp.isPM ? 'PM' : 'AM'],
|
|
227
|
-
['a', () => comp.isPM ? 'pm' : 'am'],
|
|
226
|
+
['A', () => (comp.isPM ? 'PM' : 'AM')],
|
|
227
|
+
['a', () => (comp.isPM ? 'pm' : 'am')],
|
|
228
228
|
|
|
229
229
|
// Timezone offset
|
|
230
230
|
['ZZ', () => getTimezoneOffset(temporal, false)],
|
|
@@ -29,7 +29,7 @@ const colorClasses = {
|
|
|
29
29
|
indigo: 'bg-indigo-100 text-indigo-800',
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
export const badgeRenderer = (
|
|
32
|
+
export const badgeRenderer = (_sparkTable) => {
|
|
33
33
|
return (instance, td, row, col, prop, value, cellProperties) => {
|
|
34
34
|
// Clear cell
|
|
35
35
|
td.innerHTML = ''
|
|
@@ -54,7 +54,7 @@ const isTruthy = (value) => {
|
|
|
54
54
|
return false
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export const booleanRenderer = (
|
|
57
|
+
export const booleanRenderer = (_sparkTable) => {
|
|
58
58
|
return (instance, td, row, col, prop, value, cellProperties) => {
|
|
59
59
|
// Clear cell
|
|
60
60
|
td.innerHTML = ''
|
|
@@ -63,8 +63,8 @@ export const booleanRenderer = (sparkTable) => {
|
|
|
63
63
|
const config = cellProperties.rendererConfig || {}
|
|
64
64
|
|
|
65
65
|
const truthy = isTruthy(value)
|
|
66
|
-
const iconName = truthy ?
|
|
67
|
-
const colorName = truthy ?
|
|
66
|
+
const iconName = truthy ? config.trueIcon || 'check' : config.falseIcon || 'xmark'
|
|
67
|
+
const colorName = truthy ? config.trueColor || 'green' : config.falseColor || 'red'
|
|
68
68
|
const size = config.size || 32
|
|
69
69
|
const iconPrefix = config.iconPrefix || 'far'
|
|
70
70
|
|
|
@@ -43,7 +43,7 @@ const formatCurrency = (value, decimals = 2) => {
|
|
|
43
43
|
return isNegative ? `-$${formatted}` : `$${formatted}`
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export const currencyRenderer = (
|
|
46
|
+
export const currencyRenderer = (_sparkTable) => {
|
|
47
47
|
return (instance, td, row, col, prop, value, cellProperties) => {
|
|
48
48
|
td.innerHTML = ''
|
|
49
49
|
td.classList.add('spark-table-cell-currency')
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* }
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
export const dateRenderer = (
|
|
17
|
+
export const dateRenderer = (_sparkTable) => {
|
|
18
18
|
return (instance, td, row, col, prop, value, cellProperties) => {
|
|
19
19
|
// Clear cell
|
|
20
20
|
td.innerHTML = ''
|
|
@@ -28,7 +28,7 @@ export const dateRenderer = (sparkTable) => {
|
|
|
28
28
|
const format = config.format || 'short'
|
|
29
29
|
const locale = config.locale || 'en-US'
|
|
30
30
|
|
|
31
|
-
let formattedDate
|
|
31
|
+
let formattedDate
|
|
32
32
|
|
|
33
33
|
try {
|
|
34
34
|
const date = new Date(value)
|
|
@@ -89,14 +89,22 @@ function getRelativeTime(date) {
|
|
|
89
89
|
if (seconds < 60) {
|
|
90
90
|
return isPast ? 'just now' : 'in a moment'
|
|
91
91
|
} else if (minutes < 60) {
|
|
92
|
-
return isPast
|
|
92
|
+
return isPast
|
|
93
|
+
? `${minutes} minute${minutes > 1 ? 's' : ''} ago`
|
|
94
|
+
: `in ${minutes} minute${minutes > 1 ? 's' : ''}`
|
|
93
95
|
} else if (hours < 24) {
|
|
94
|
-
return isPast
|
|
96
|
+
return isPast
|
|
97
|
+
? `${hours} hour${hours > 1 ? 's' : ''} ago`
|
|
98
|
+
: `in ${hours} hour${hours > 1 ? 's' : ''}`
|
|
95
99
|
} else if (days < 30) {
|
|
96
100
|
return isPast ? `${days} day${days > 1 ? 's' : ''} ago` : `in ${days} day${days > 1 ? 's' : ''}`
|
|
97
101
|
} else if (months < 12) {
|
|
98
|
-
return isPast
|
|
102
|
+
return isPast
|
|
103
|
+
? `${months} month${months > 1 ? 's' : ''} ago`
|
|
104
|
+
: `in ${months} month${months > 1 ? 's' : ''}`
|
|
99
105
|
} else {
|
|
100
|
-
return isPast
|
|
106
|
+
return isPast
|
|
107
|
+
? `${years} year${years > 1 ? 's' : ''} ago`
|
|
108
|
+
: `in ${years} year${years > 1 ? 's' : ''}`
|
|
101
109
|
}
|
|
102
110
|
}
|
|
@@ -61,7 +61,7 @@ import { formatTemporal, parseDatetime } from '@/utils/formatTemporal.js'
|
|
|
61
61
|
* - 'DD/MM/YY [at] h:mma' → "03/12/25 at 11:36am"
|
|
62
62
|
*/
|
|
63
63
|
|
|
64
|
-
export const datetimeRenderer = (
|
|
64
|
+
export const datetimeRenderer = (_sparkTable) => {
|
|
65
65
|
return (instance, td, row, col, prop, value, cellProperties) => {
|
|
66
66
|
// Clear cell
|
|
67
67
|
td.innerHTML = ''
|
|
@@ -29,19 +29,15 @@
|
|
|
29
29
|
<div class="max-w-lg grid gap-y-6 text-center -mt-8">
|
|
30
30
|
<div>
|
|
31
31
|
<div class="text-primary-600 text-7xl font-bold mb-4">403</div>
|
|
32
|
-
<h1 class="text-3xl text-gray-900 font-semibold tracking-tight mb-3">
|
|
33
|
-
Access Forbidden
|
|
34
|
-
</h1>
|
|
32
|
+
<h1 class="text-3xl text-gray-900 font-semibold tracking-tight mb-3">Access Forbidden</h1>
|
|
35
33
|
<p class="text-gray-600">
|
|
36
|
-
You don't have permission to access this resource.<br
|
|
34
|
+
You don't have permission to access this resource.<br />
|
|
37
35
|
If you believe this is an error, please contact your administrator.
|
|
38
36
|
</p>
|
|
39
37
|
</div>
|
|
40
38
|
|
|
41
39
|
<div class="flex gap-4 justify-center">
|
|
42
|
-
<
|
|
43
|
-
Go to Home
|
|
44
|
-
</spark-button>
|
|
40
|
+
<SparkButton size="lg" @click="goHome"> Go to Home </SparkButton>
|
|
45
41
|
</div>
|
|
46
42
|
</div>
|
|
47
43
|
</div>
|
|
@@ -29,18 +29,12 @@
|
|
|
29
29
|
<div class="max-w-lg grid gap-y-6 text-center -mt-8">
|
|
30
30
|
<div>
|
|
31
31
|
<div class="text-primary-600 text-7xl font-bold mb-4">404</div>
|
|
32
|
-
<h1 class="text-3xl text-gray-900 font-semibold tracking-tight mb-3">
|
|
33
|
-
|
|
34
|
-
</h1>
|
|
35
|
-
<p class="text-gray-600">
|
|
36
|
-
The page you're looking for doesn't exist or has been moved.
|
|
37
|
-
</p>
|
|
32
|
+
<h1 class="text-3xl text-gray-900 font-semibold tracking-tight mb-3">Page Not Found</h1>
|
|
33
|
+
<p class="text-gray-600">The page you're looking for doesn't exist or has been moved.</p>
|
|
38
34
|
</div>
|
|
39
35
|
|
|
40
36
|
<div class="flex gap-4 justify-center">
|
|
41
|
-
<
|
|
42
|
-
Go to Home
|
|
43
|
-
</spark-button>
|
|
37
|
+
<SparkButton size="lg" @click="goHome"> Go to Home </SparkButton>
|
|
44
38
|
</div>
|
|
45
39
|
</div>
|
|
46
40
|
</div>
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
</p>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
|
-
<FormKit type="form"
|
|
38
|
+
<FormKit type="form" :actions="false" @submit="handleSubmit">
|
|
39
39
|
<FormKit
|
|
40
40
|
label="Email"
|
|
41
41
|
name="email"
|
|
@@ -53,12 +53,15 @@
|
|
|
53
53
|
{{ successMessage }}
|
|
54
54
|
</div>
|
|
55
55
|
|
|
56
|
-
<
|
|
56
|
+
<SparkButton type="submit" size="xl" :disabled="isLoading" button-class="w-full mb-2">
|
|
57
57
|
<span v-if="!isLoading">Send reset link</span>
|
|
58
58
|
<span v-else>Sending...</span>
|
|
59
|
-
</
|
|
59
|
+
</SparkButton>
|
|
60
60
|
|
|
61
|
-
<router-link
|
|
61
|
+
<router-link
|
|
62
|
+
:to="props.loginRoute"
|
|
63
|
+
class="text-sm text-center text-primary-600 font-semibold block"
|
|
64
|
+
>
|
|
62
65
|
Back to login
|
|
63
66
|
</router-link>
|
|
64
67
|
</FormKit>
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
<h1 class="text-4xl text-gray-900 semibold tracking-tight mb-3">Log in</h1>
|
|
32
32
|
|
|
33
33
|
<p class="text-gray-600">
|
|
34
|
-
Welcome back{{ appStore.state.app ? ` to ${appStore.state.app}` : '' }}! Please enter
|
|
35
|
-
|
|
34
|
+
Welcome back{{ appStore.state.app ? ` to ${appStore.state.app}` : '' }}! Please enter your
|
|
35
|
+
details.
|
|
36
36
|
</p>
|
|
37
37
|
</div>
|
|
38
38
|
|
|
39
|
-
<FormKit type="form"
|
|
39
|
+
<FormKit type="form" :actions="false" @submit="handleLogin">
|
|
40
40
|
<FormKit
|
|
41
41
|
label="Email"
|
|
42
42
|
name="email"
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
/>
|
|
59
59
|
|
|
60
60
|
<div class="grid grid-flow-col justify-between mt-1 mb-4">
|
|
61
|
-
<span
|
|
61
|
+
<span />
|
|
62
62
|
|
|
63
63
|
<router-link
|
|
64
64
|
:to="props.forgotPasswordRoute"
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
{{ errorMessage }}
|
|
73
73
|
</div>
|
|
74
74
|
|
|
75
|
-
<
|
|
75
|
+
<SparkButton type="submit" size="xl" :disabled="isLoading" button-class="w-full mb-2">
|
|
76
76
|
<span v-if="!isLoading">Sign in</span>
|
|
77
77
|
<span v-else>Signing in...</span>
|
|
78
|
-
</
|
|
78
|
+
</SparkButton>
|
|
79
79
|
</FormKit>
|
|
80
80
|
</div>
|
|
81
81
|
</div>
|
|
@@ -130,7 +130,8 @@ const handleLogin = async (credentials) => {
|
|
|
130
130
|
await router.push(props.defaultRedirect)
|
|
131
131
|
}
|
|
132
132
|
} catch (error) {
|
|
133
|
-
errorMessage.value =
|
|
133
|
+
errorMessage.value =
|
|
134
|
+
error.response?.data?.message || error.message || 'Login failed. Please try again.'
|
|
134
135
|
} finally {
|
|
135
136
|
isLoading.value = false
|
|
136
137
|
}
|
|
@@ -30,12 +30,10 @@
|
|
|
30
30
|
<div class="mb-7">
|
|
31
31
|
<h1 class="text-4xl text-gray-900 semibold tracking-tight mb-3">Set new password</h1>
|
|
32
32
|
|
|
33
|
-
<p class="text-gray-600">
|
|
34
|
-
Enter your new password below.
|
|
35
|
-
</p>
|
|
33
|
+
<p class="text-gray-600">Enter your new password below.</p>
|
|
36
34
|
</div>
|
|
37
35
|
|
|
38
|
-
<FormKit type="form"
|
|
36
|
+
<FormKit type="form" :actions="false" @submit="handleSubmit">
|
|
39
37
|
<FormKit
|
|
40
38
|
label="New Password"
|
|
41
39
|
name="password"
|
|
@@ -58,10 +56,10 @@
|
|
|
58
56
|
{{ errorMessage }}
|
|
59
57
|
</div>
|
|
60
58
|
|
|
61
|
-
<
|
|
59
|
+
<SparkButton type="submit" size="xl" :disabled="isLoading" button-class="w-full mb-2">
|
|
62
60
|
<span v-if="!isLoading">Reset password</span>
|
|
63
61
|
<span v-else>Resetting...</span>
|
|
64
|
-
</
|
|
62
|
+
</SparkButton>
|
|
65
63
|
</FormKit>
|
|
66
64
|
</div>
|
|
67
65
|
</div>
|