@sowell/quasar-app-extension-auth 1.6.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/boot/router-guards.ts +2 -0
- package/src/components/pages/AuthReporter.vue +47 -16
- package/src/components/pages/FirstLogin.vue +604 -0
- package/src/components/pages/ResetPassword.vue +122 -15
- package/src/components/pages/SetPassword.vue +35 -0
- package/src/composables/auth.ts +11 -1
- package/src/composables/resetPassword.ts +49 -6
- package/src/composables/useMagicLink.ts +208 -0
- package/src/composables/useValidateMagicLink.ts +183 -0
- package/src/injects/prompts.ts +5 -0
- package/src/prompts.js +35 -0
- package/src/routes/index.ts +27 -1
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<q-layout
|
|
3
|
+
class="column justify-start items-center q-pb-lg bg-white first-login-page"
|
|
4
|
+
style="max-width: 100vw; overflow-x: hidden">
|
|
5
|
+
<div class="background-logo-container">
|
|
6
|
+
<img
|
|
7
|
+
src="../../assets/Background-logo.svg"
|
|
8
|
+
class="background-logo"
|
|
9
|
+
alt="Background logo" />
|
|
10
|
+
</div>
|
|
11
|
+
<div class="row justify-between items-center full-width q-px-lg q-pt-lg top-bar">
|
|
12
|
+
<div
|
|
13
|
+
class="row items-center back-link"
|
|
14
|
+
data-testid="back-btn"
|
|
15
|
+
@click="goBackToLogin">
|
|
16
|
+
<q-icon name="arrow_back" size="16px" />
|
|
17
|
+
<span class="q-ml-xs">{{ $t("auth.back") }}</span>
|
|
18
|
+
</div>
|
|
19
|
+
<img src="../../assets/sowell-min.svg" style="width: auto; height: 33px" />
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="full-width first-login-card q-mt-lg">
|
|
23
|
+
<template v-if="restricted">
|
|
24
|
+
<div class="column items-center header-section">
|
|
25
|
+
<div class="restricted-badge">
|
|
26
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="82" height="82" viewBox="0 0 82 82" fill="none" class="restricted-blob">
|
|
27
|
+
<path d="M20.467 13.2638C20.467 13.2638 32.783 22.7041 51.5063 5.05236C68.1346 -10.6241 81.7117 14.1097 81.8067 25.9544C81.9298 41.298 65.1784 53.5748 73.3078 63.6526C81.4372 73.7304 57.1861 90.3722 44.116 75.9698C27.8572 58.0538 23.4525 72.6106 14.185 72.6106C7.53374 72.6106 -6.12216 55.9168 3.09953 43.4971C10.8594 33.0461 6.6273 29.5776 4.57785 25.9544C1.62159 20.7288 8.64242 6.54534 20.467 13.2638Z" fill="#FFEFCF"/>
|
|
28
|
+
</svg>
|
|
29
|
+
<div class="restricted-circle">
|
|
30
|
+
<q-icon name="lock" size="24px" color="white" />
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="title text-center q-mt-md">{{ $t("auth.restrictedTitle") }}</div>
|
|
34
|
+
<div class="subtitle text-center q-mt-sm">
|
|
35
|
+
{{ restrictedMessage || $t("auth.restrictedDescription") }}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<q-btn
|
|
39
|
+
data-testid="restricted-back-btn"
|
|
40
|
+
color="primary"
|
|
41
|
+
unelevated
|
|
42
|
+
no-caps
|
|
43
|
+
text-color="white"
|
|
44
|
+
class="full-width q-mt-lg submit-button"
|
|
45
|
+
@click="goBackToLogin">
|
|
46
|
+
{{ $t("auth.backToLoginFull") }}
|
|
47
|
+
</q-btn>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<template v-else-if="step === 'email'">
|
|
51
|
+
<template v-if="isActivateContext">
|
|
52
|
+
<div class="eyebrow-title">{{ $t("auth.firstConnectionTitle") }}</div>
|
|
53
|
+
<div class="description q-mt-sm">{{ $t("auth.firstConnectionDescription") }}</div>
|
|
54
|
+
</template>
|
|
55
|
+
<template v-else>
|
|
56
|
+
<div class="column items-center header-section">
|
|
57
|
+
<div class="icon-badge">
|
|
58
|
+
<q-icon name="verified_user" size="28px" color="primary" />
|
|
59
|
+
</div>
|
|
60
|
+
<div class="forgot-password-title text-center q-mt-md">
|
|
61
|
+
{{ $t("auth.forgotPasswordTitle") }}
|
|
62
|
+
</div>
|
|
63
|
+
<div class="subtitle text-center q-mt-sm">
|
|
64
|
+
{{ $t("auth.forgotPasswordDescription") }}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
68
|
+
<q-form
|
|
69
|
+
class="column q-mt-lg"
|
|
70
|
+
data-testid="first-login-email-form"
|
|
71
|
+
@submit="requestChannels">
|
|
72
|
+
<div class="input-container">
|
|
73
|
+
<div class="input-label">{{ $t("auth.email") }}</div>
|
|
74
|
+
<q-input
|
|
75
|
+
v-model.trim="email"
|
|
76
|
+
data-testid="first-login-email-input"
|
|
77
|
+
data-cy="first-login-email"
|
|
78
|
+
type="email"
|
|
79
|
+
borderless
|
|
80
|
+
:error="!!emailError"
|
|
81
|
+
:error-message="emailError"
|
|
82
|
+
:placeholder="$t('auth.emailPlaceholder')"
|
|
83
|
+
class="q-mt-sm"
|
|
84
|
+
:input-style="{ fontSize: '13px', fontWeight: '500' }">
|
|
85
|
+
<template #prepend>
|
|
86
|
+
<q-icon name="mail_outline" color="#7E868E" />
|
|
87
|
+
</template>
|
|
88
|
+
</q-input>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div v-if="apiErrorMessage" class="server-error q-mt-md" data-testid="server-error">
|
|
92
|
+
{{ apiErrorMessage }}
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<q-btn
|
|
96
|
+
data-testid="first-login-continue-btn"
|
|
97
|
+
data-cy="first-login-continue"
|
|
98
|
+
color="primary"
|
|
99
|
+
unelevated
|
|
100
|
+
no-caps
|
|
101
|
+
text-color="white"
|
|
102
|
+
:loading="isLoading"
|
|
103
|
+
type="submit"
|
|
104
|
+
class="full-width q-mt-lg submit-button">
|
|
105
|
+
{{ $t("auth.continueButton") }}
|
|
106
|
+
</q-btn>
|
|
107
|
+
</q-form>
|
|
108
|
+
</template>
|
|
109
|
+
|
|
110
|
+
<template v-else-if="step === 'channel'">
|
|
111
|
+
<div class="column items-center header-section">
|
|
112
|
+
<div class="icon-badge">
|
|
113
|
+
<q-icon name="lock_outline" size="28px" color="primary" />
|
|
114
|
+
</div>
|
|
115
|
+
<div class="title text-center q-mt-md">{{ $t("auth.channelTitle") }}</div>
|
|
116
|
+
<div class="subtitle text-center q-mt-sm">{{ $t("auth.channelSubtitle") }}</div>
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
<div class="channel-options q-mt-lg">
|
|
120
|
+
<div
|
|
121
|
+
class="channel-option"
|
|
122
|
+
:class="{ 'channel-option--selected': selectedChannel === 'email' }"
|
|
123
|
+
data-testid="channel-email-option"
|
|
124
|
+
data-cy="channel-email"
|
|
125
|
+
@click="selectChannel('email')">
|
|
126
|
+
<div class="channel-icon-box">
|
|
127
|
+
<svg width="20" height="16" viewBox="0 0 20 16" fill="none"><path d="M2 16C1.45 16 0.979167 15.8042 0.5875 15.4125C0.195833 15.0208 0 14.55 0 14V2C0 1.45 0.195833 0.979167 0.5875 0.5875C0.979167 0.195833 1.45 0 2 0H18C18.55 0 19.0208 0.195833 19.4125 0.5875C19.8042 0.979167 20 1.45 20 2V14C20 14.55 19.8042 15.0208 19.4125 15.4125C19.0208 15.8042 18.55 16 18 16H2V16M10 9L2 4V14V14V14H18V14V14V4L10 9V9M10 7L18 2H2L10 7V7M2 4V2V2V4V14V14V14V14V14V14V4V4" fill="#40C4FF"/></svg>
|
|
128
|
+
</div>
|
|
129
|
+
<div class="channel-text">
|
|
130
|
+
<div class="channel-label">{{ $t("auth.channelEmailLabel") }}</div>
|
|
131
|
+
<div class="channel-description">{{ maskedEmail }}</div>
|
|
132
|
+
</div>
|
|
133
|
+
<div
|
|
134
|
+
class="channel-radio"
|
|
135
|
+
:class="{ 'channel-radio--selected': selectedChannel === 'email' }">
|
|
136
|
+
<div v-if="selectedChannel === 'email'" class="channel-radio-dot" />
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div
|
|
141
|
+
v-if="channels.includes('sms')"
|
|
142
|
+
class="channel-option q-mt-sm"
|
|
143
|
+
:class="{ 'channel-option--selected': selectedChannel === 'sms' }"
|
|
144
|
+
data-testid="channel-sms-option"
|
|
145
|
+
data-cy="channel-sms"
|
|
146
|
+
@click="selectChannel('sms')">
|
|
147
|
+
<div class="channel-icon-box">
|
|
148
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M6 9C6.28333 9 6.52083 8.90417 6.7125 8.7125C6.90417 8.52083 7 8.28333 7 8C7 7.71667 6.90417 7.47917 6.7125 7.2875C6.52083 7.09583 6.28333 7 6 7C5.71667 7 5.47917 7.09583 5.2875 7.2875C5.09583 7.47917 5 7.71667 5 8C5 8.28333 5.09583 8.52083 5.2875 8.7125C5.47917 8.90417 5.71667 9 6 9V9M10 9C10.2833 9 10.5208 8.90417 10.7125 8.7125C10.9042 8.52083 11 8.28333 11 8C11 7.71667 10.9042 7.47917 10.7125 7.2875C10.5208 7.09583 10.2833 7 10 7C9.71667 7 9.47917 7.09583 9.2875 7.2875C9.09583 7.47917 9 7.71667 9 8C9 8.28333 9.09583 8.52083 9.2875 8.7125C9.47917 8.90417 9.71667 9 10 9V9M14 9C14.2833 9 14.5208 8.90417 14.7125 8.7125C14.9042 8.52083 15 8.28333 15 8C15 7.71667 14.9042 7.47917 14.7125 7.2875C14.5208 7.09583 14.2833 7 14 7C13.7167 7 13.4792 7.09583 13.2875 7.2875C13.0958 7.47917 13 7.71667 13 8C13 8.28333 13.0958 8.52083 13.2875 8.7125C13.4792 8.90417 13.7167 9 14 9V9M0 20V2C0 1.45 0.195833 0.979167 0.5875 0.5875C0.979167 0.195833 1.45 0 2 0H18C18.55 0 19.0208 0.195833 19.4125 0.5875C19.8042 0.979167 20 1.45 20 2V14C20 14.55 19.8042 15.0208 19.4125 15.4125C19.0208 15.8042 18.55 16 18 16H4L0 20V20M3.15 14H18V14V14V2V2V2H2V2V2V15.125L3.15 14V14M2 14V14V2V2V2V2V2V2V14V14V14V14V14" fill="#00668A"/></svg>
|
|
149
|
+
</div>
|
|
150
|
+
<div class="channel-text">
|
|
151
|
+
<div class="channel-label">{{ $t("auth.channelSmsLabel") }}</div>
|
|
152
|
+
<div class="channel-description">{{ $t("auth.channelSmsDescription") }}</div>
|
|
153
|
+
</div>
|
|
154
|
+
<div
|
|
155
|
+
class="channel-radio"
|
|
156
|
+
:class="{ 'channel-radio--selected': selectedChannel === 'sms' }">
|
|
157
|
+
<div v-if="selectedChannel === 'sms'" class="channel-radio-dot" />
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<div v-if="apiErrorMessage" class="server-error q-mt-md" data-testid="server-error">
|
|
163
|
+
{{ apiErrorMessage }}
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<q-btn
|
|
167
|
+
data-testid="send-magic-link-btn"
|
|
168
|
+
data-cy="send-magic-link"
|
|
169
|
+
color="primary"
|
|
170
|
+
unelevated
|
|
171
|
+
no-caps
|
|
172
|
+
text-color="white"
|
|
173
|
+
:loading="isLoading"
|
|
174
|
+
class="full-width q-mt-lg submit-button"
|
|
175
|
+
@click="sendMagicLink()">
|
|
176
|
+
{{ $t("auth.sendMagicLink") }}
|
|
177
|
+
</q-btn>
|
|
178
|
+
|
|
179
|
+
<div class="expiry-banner">
|
|
180
|
+
<div class="banner-icon-badge">
|
|
181
|
+
<q-icon :name="icons.ionWarningOutline" size="12px" color="white" />
|
|
182
|
+
</div>
|
|
183
|
+
<span class="q-ml-sm">{{ $t("auth.channelExpiryWarning") }}</span>
|
|
184
|
+
</div>
|
|
185
|
+
</template>
|
|
186
|
+
|
|
187
|
+
<template v-else>
|
|
188
|
+
<div class="column items-center header-section">
|
|
189
|
+
<div class="success-badge">
|
|
190
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="82" height="82" viewBox="0 0 82 82" fill="none">
|
|
191
|
+
<path d="M20.467 13.2638C20.467 13.2638 32.783 22.7041 51.5063 5.05236C68.1346 -10.6241 81.7117 14.1097 81.8067 25.9544C81.9298 41.298 65.1784 53.5748 73.3078 63.6526C81.4372 73.7304 57.1861 90.3722 44.116 75.9698C27.8572 58.0538 23.4525 72.6106 14.185 72.6106C7.53374 72.6106 -6.12216 55.9168 3.09953 43.4971C10.8594 33.0461 6.6273 29.5776 4.57785 25.9544C1.62159 20.7288 8.64242 6.54534 20.467 13.2638Z" fill="#E7F8FF"/>
|
|
192
|
+
<path d="M41.0002 63.6615C53.4542 63.6615 63.5502 53.4896 63.5502 40.9419C63.5502 28.3942 53.4542 18.2223 41.0002 18.2223C28.5462 18.2223 18.4502 28.3942 18.4502 40.9419C18.4502 53.4896 28.5462 63.6615 41.0002 63.6615Z" fill="#40C4FF"/>
|
|
193
|
+
<path d="M37.9271 52.7776C37.5379 52.7781 37.1541 52.6868 36.8062 52.511C36.4584 52.3353 36.1562 52.08 35.9238 51.7655L29.7663 43.4957C29.5555 43.2317 29.3996 42.9277 29.3076 42.6018C29.2157 42.276 29.1896 41.9348 29.231 41.5986C29.2724 41.2624 29.3803 40.938 29.5485 40.6446C29.7166 40.3512 29.9415 40.0948 30.2099 39.8906C30.4782 39.6865 30.7845 39.5387 31.1106 39.456C31.4367 39.3734 31.776 39.3575 32.1082 39.4095C32.4405 39.4614 32.7591 39.58 33.045 39.7583C33.3309 39.9366 33.5784 40.1709 33.7728 40.4473L37.8266 45.8712L48.162 30.2426C48.5412 29.7088 49.1114 29.3443 49.7523 29.2261C50.3932 29.108 51.0545 29.2454 51.5968 29.6093C52.139 29.9733 52.5196 30.5353 52.6583 31.1767C52.7969 31.818 52.6828 32.4886 52.3399 33.0468L40.0131 51.6464C39.7907 51.9823 39.4917 52.2598 39.1411 52.4556C38.7906 52.6513 38.3986 52.7597 37.998 52.7717L37.9271 52.7776Z" fill="white"/>
|
|
194
|
+
</svg>
|
|
195
|
+
</div>
|
|
196
|
+
<div class="title text-center q-mt-md">{{ $t("auth.magicLinkSentTitle") }}</div>
|
|
197
|
+
<div class="subtitle text-center q-mt-sm">
|
|
198
|
+
{{ $t("auth.magicLinkSentDescription") }}
|
|
199
|
+
</div>
|
|
200
|
+
<div class="subtitle-secondary text-center q-mt-md">
|
|
201
|
+
{{ $t("auth.magicLinkCheckInboxMessage") }}
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
<q-btn
|
|
206
|
+
data-testid="open-mailbox-btn"
|
|
207
|
+
data-cy="open-mailbox"
|
|
208
|
+
color="primary"
|
|
209
|
+
unelevated
|
|
210
|
+
no-caps
|
|
211
|
+
text-color="white"
|
|
212
|
+
class="full-width q-mt-lg submit-button"
|
|
213
|
+
@click="openMailbox">
|
|
214
|
+
<q-icon name="mail_outline" size="18px" class="q-mr-sm" />
|
|
215
|
+
{{ $t("auth.openMailbox") }}
|
|
216
|
+
</q-btn>
|
|
217
|
+
|
|
218
|
+
<q-btn
|
|
219
|
+
data-testid="resend-magic-link-btn"
|
|
220
|
+
data-cy="resend-magic-link"
|
|
221
|
+
outline
|
|
222
|
+
no-caps
|
|
223
|
+
class="full-width q-mt-sm resend-button"
|
|
224
|
+
:disable="resendCountdown > 0 || isLoading"
|
|
225
|
+
:loading="isLoading"
|
|
226
|
+
@click="resend">
|
|
227
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" class="q-mr-sm"><path d="M6.75 13.5C5.025 13.5 3.52187 12.9281 2.24062 11.7844C0.959375 10.6406 0.225 9.2125 0.0375 7.5H1.575C1.75 8.8 2.32812 9.875 3.30938 10.725C4.29063 11.575 5.4375 12 6.75 12C8.2125 12 9.45312 11.4906 10.4719 10.4719C11.4906 9.45312 12 8.2125 12 6.75C12 5.2875 11.4906 4.04688 10.4719 3.02813C9.45312 2.00938 8.2125 1.5 6.75 1.5C5.8875 1.5 5.08125 1.7 4.33125 2.1C3.58125 2.5 2.95 3.05 2.4375 3.75H4.5V5.25H0V0.75H1.5V2.5125C2.1375 1.7125 2.91562 1.09375 3.83437 0.65625C4.75312 0.21875 5.725 0 6.75 0C7.6875 0 8.56562 0.178125 9.38437 0.534375C10.2031 0.890625 10.9156 1.37188 11.5219 1.97812C12.1281 2.58437 12.6094 3.29688 12.9656 4.11562C13.3219 4.93437 13.5 5.8125 13.5 6.75C13.5 7.6875 13.3219 8.56562 12.9656 9.38437C12.6094 10.2031 12.1281 10.9156 11.5219 11.5219C10.9156 12.1281 10.2031 12.6094 9.38437 12.9656C8.56562 13.3219 7.6875 13.5 6.75 13.5ZM8.85 9.9L6 7.05V3H7.5V6.45L9.9 8.85L8.85 9.9Z" fill="#40C4FF"/></svg>
|
|
228
|
+
{{
|
|
229
|
+
resendCountdown > 0
|
|
230
|
+
? $t("auth.resendMagicLinkCountdown", { seconds: resendCountdown })
|
|
231
|
+
: $t("auth.resendMagicLink")
|
|
232
|
+
}}
|
|
233
|
+
</q-btn>
|
|
234
|
+
|
|
235
|
+
<div class="warning-banner">
|
|
236
|
+
<div class="banner-icon-badge">
|
|
237
|
+
<q-icon :name="icons.ionInformationCircleOutline" size="12px" color="white" />
|
|
238
|
+
</div>
|
|
239
|
+
<span class="q-ml-sm">{{ $t("auth.magicLinkWarning") }}</span>
|
|
240
|
+
</div>
|
|
241
|
+
</template>
|
|
242
|
+
</div>
|
|
243
|
+
</q-layout>
|
|
244
|
+
</template>
|
|
245
|
+
|
|
246
|
+
<script lang="ts">
|
|
247
|
+
import { defineComponent } from "vue"
|
|
248
|
+
import {
|
|
249
|
+
ionWarningOutline,
|
|
250
|
+
ionInformationCircleOutline
|
|
251
|
+
} from "@quasar/extras/ionicons-v5"
|
|
252
|
+
import { useMagicLink } from "composables/useMagicLink"
|
|
253
|
+
|
|
254
|
+
export default defineComponent({
|
|
255
|
+
name: "FirstLogin",
|
|
256
|
+
setup() {
|
|
257
|
+
const {
|
|
258
|
+
email,
|
|
259
|
+
emailError,
|
|
260
|
+
apiErrorMessage,
|
|
261
|
+
channels,
|
|
262
|
+
selectedChannel,
|
|
263
|
+
step,
|
|
264
|
+
isLoading,
|
|
265
|
+
resendCountdown,
|
|
266
|
+
restricted,
|
|
267
|
+
restrictedMessage,
|
|
268
|
+
isActivateContext,
|
|
269
|
+
maskedEmail,
|
|
270
|
+
requestChannels,
|
|
271
|
+
sendMagicLink,
|
|
272
|
+
resend,
|
|
273
|
+
selectChannel,
|
|
274
|
+
goBackToLogin,
|
|
275
|
+
openMailbox
|
|
276
|
+
} = useMagicLink()
|
|
277
|
+
|
|
278
|
+
const icons = {
|
|
279
|
+
ionWarningOutline,
|
|
280
|
+
ionInformationCircleOutline
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
email,
|
|
285
|
+
emailError,
|
|
286
|
+
apiErrorMessage,
|
|
287
|
+
channels,
|
|
288
|
+
selectedChannel,
|
|
289
|
+
step,
|
|
290
|
+
isLoading,
|
|
291
|
+
resendCountdown,
|
|
292
|
+
restricted,
|
|
293
|
+
restrictedMessage,
|
|
294
|
+
isActivateContext,
|
|
295
|
+
maskedEmail,
|
|
296
|
+
icons,
|
|
297
|
+
requestChannels,
|
|
298
|
+
sendMagicLink,
|
|
299
|
+
resend,
|
|
300
|
+
selectChannel,
|
|
301
|
+
goBackToLogin,
|
|
302
|
+
openMailbox
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
</script>
|
|
307
|
+
|
|
308
|
+
<style scoped>
|
|
309
|
+
.first-login-page {
|
|
310
|
+
min-height: 100vh;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.background-logo-container {
|
|
314
|
+
position: fixed;
|
|
315
|
+
top: -53px;
|
|
316
|
+
left: 0;
|
|
317
|
+
width: 100%;
|
|
318
|
+
height: 100vh;
|
|
319
|
+
display: flex;
|
|
320
|
+
justify-content: center;
|
|
321
|
+
align-items: center;
|
|
322
|
+
opacity: 0.25;
|
|
323
|
+
overflow: hidden;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.background-logo {
|
|
327
|
+
width: 100%;
|
|
328
|
+
height: 100%;
|
|
329
|
+
object-fit: cover;
|
|
330
|
+
max-width: 100%;
|
|
331
|
+
max-height: 100vh;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.top-bar {
|
|
335
|
+
z-index: 1;
|
|
336
|
+
max-width: 430px;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.back-link {
|
|
340
|
+
cursor: pointer;
|
|
341
|
+
color: #00668a;
|
|
342
|
+
font-size: 14px;
|
|
343
|
+
font-weight: 600;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.first-login-card {
|
|
347
|
+
z-index: 1;
|
|
348
|
+
max-width: 398px;
|
|
349
|
+
padding: 32px 24px;
|
|
350
|
+
margin-top: 24px;
|
|
351
|
+
flex: 1;
|
|
352
|
+
display: flex;
|
|
353
|
+
flex-direction: column;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.eyebrow-title {
|
|
357
|
+
font-size: 24px;
|
|
358
|
+
font-weight: 700;
|
|
359
|
+
color: #41c4ff;
|
|
360
|
+
text-transform: uppercase;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.description {
|
|
364
|
+
font-size: 16px;
|
|
365
|
+
font-weight: 400;
|
|
366
|
+
color: #152f3b;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.forgot-password-title {
|
|
370
|
+
font-size: 24px;
|
|
371
|
+
font-weight: 600;
|
|
372
|
+
color: #20627f;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.header-section {
|
|
376
|
+
width: 100%;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.icon-badge {
|
|
380
|
+
width: 64px;
|
|
381
|
+
height: 64px;
|
|
382
|
+
border-radius: 9999px;
|
|
383
|
+
background: rgba(56, 189, 248, 0.1);
|
|
384
|
+
border: 1px solid rgba(56, 189, 248, 0.3);
|
|
385
|
+
display: flex;
|
|
386
|
+
align-items: center;
|
|
387
|
+
justify-content: center;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.success-badge {
|
|
391
|
+
width: 82px;
|
|
392
|
+
height: 82px;
|
|
393
|
+
display: flex;
|
|
394
|
+
align-items: center;
|
|
395
|
+
justify-content: center;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.restricted-badge {
|
|
399
|
+
position: relative;
|
|
400
|
+
width: 82px;
|
|
401
|
+
height: 82px;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.restricted-blob {
|
|
405
|
+
position: absolute;
|
|
406
|
+
top: 0;
|
|
407
|
+
left: 0;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.restricted-circle {
|
|
411
|
+
position: absolute;
|
|
412
|
+
top: 50%;
|
|
413
|
+
left: 50%;
|
|
414
|
+
transform: translate(-50%, -50%);
|
|
415
|
+
width: 45px;
|
|
416
|
+
height: 45px;
|
|
417
|
+
border-radius: 9999px;
|
|
418
|
+
background: #ffce6e;
|
|
419
|
+
display: flex;
|
|
420
|
+
align-items: center;
|
|
421
|
+
justify-content: center;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.title {
|
|
425
|
+
font-size: 24px;
|
|
426
|
+
font-weight: 600;
|
|
427
|
+
color: #20627f;
|
|
428
|
+
line-height: 1.4;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.subtitle {
|
|
432
|
+
font-size: 14px;
|
|
433
|
+
font-weight: 400;
|
|
434
|
+
color: #3e484f;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.subtitle-secondary {
|
|
438
|
+
font-size: 14px;
|
|
439
|
+
font-weight: 400;
|
|
440
|
+
color: rgba(62, 72, 79, 0.8);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.input-label {
|
|
444
|
+
font-size: 14px;
|
|
445
|
+
font-weight: 700;
|
|
446
|
+
color: #112240;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.first-login-page :deep(.q-field__control-container) {
|
|
450
|
+
padding: 4px;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.first-login-page :deep(div.q-field__control) {
|
|
454
|
+
border: 1px solid #bdc8d1;
|
|
455
|
+
border-radius: 8px;
|
|
456
|
+
height: 55px;
|
|
457
|
+
padding: 0 12px;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.first-login-page :deep(.q-field--error .q-field__control) {
|
|
461
|
+
border-color: #ff8b87;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.first-login-page :deep(.q-field--error .q-field__bottom) {
|
|
465
|
+
color: #ef476f;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.first-login-page :deep(.q-field__bottom) {
|
|
469
|
+
padding: 4px 0px;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.server-error {
|
|
473
|
+
font-size: 13px;
|
|
474
|
+
font-weight: 500;
|
|
475
|
+
color: #ef476f;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.submit-button {
|
|
479
|
+
border-radius: 15px;
|
|
480
|
+
height: 54px;
|
|
481
|
+
font-size: 14px;
|
|
482
|
+
font-weight: 500;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.resend-button {
|
|
486
|
+
border-radius: 15px;
|
|
487
|
+
height: 56px;
|
|
488
|
+
font-size: 14px;
|
|
489
|
+
font-weight: 600;
|
|
490
|
+
color: #414651;
|
|
491
|
+
border-color: #d5d7da;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.channel-options {
|
|
495
|
+
width: 100%;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.channel-option {
|
|
499
|
+
display: flex;
|
|
500
|
+
align-items: center;
|
|
501
|
+
padding: 17px;
|
|
502
|
+
border-radius: 8px;
|
|
503
|
+
border: 1px solid #bdc8d1;
|
|
504
|
+
cursor: pointer;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.channel-option--selected {
|
|
508
|
+
border-color: #40c4ff;
|
|
509
|
+
background: #f3fcff;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.channel-icon-box {
|
|
513
|
+
width: 48px;
|
|
514
|
+
height: 48px;
|
|
515
|
+
min-width: 48px;
|
|
516
|
+
border-radius: 8px;
|
|
517
|
+
background: #cff0ff;
|
|
518
|
+
display: flex;
|
|
519
|
+
align-items: center;
|
|
520
|
+
justify-content: center;
|
|
521
|
+
margin-right: 12px;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.channel-text {
|
|
525
|
+
flex: 1;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.channel-label {
|
|
529
|
+
font-size: 14px;
|
|
530
|
+
font-weight: 600;
|
|
531
|
+
color: #0f172a;
|
|
532
|
+
letter-spacing: 0.7px;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
.channel-description {
|
|
536
|
+
font-size: 14px;
|
|
537
|
+
color: #64748b;
|
|
538
|
+
margin-top: 2px;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.channel-radio {
|
|
542
|
+
width: 20px;
|
|
543
|
+
height: 20px;
|
|
544
|
+
min-width: 20px;
|
|
545
|
+
border-radius: 9999px;
|
|
546
|
+
border: 1px solid #bdc8d1;
|
|
547
|
+
display: flex;
|
|
548
|
+
align-items: center;
|
|
549
|
+
justify-content: center;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
.channel-radio--selected {
|
|
553
|
+
background: #40c4ff;
|
|
554
|
+
border-color: #40c4ff;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.channel-radio-dot {
|
|
558
|
+
width: 10px;
|
|
559
|
+
height: 10px;
|
|
560
|
+
border-radius: 9999px;
|
|
561
|
+
background: white;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.expiry-banner {
|
|
565
|
+
display: flex;
|
|
566
|
+
align-items: center;
|
|
567
|
+
background: rgba(255, 189, 61, 0.15);
|
|
568
|
+
border: 1px solid rgba(255, 206, 110, 0.5);
|
|
569
|
+
border-radius: 8px;
|
|
570
|
+
padding: 12px 16px;
|
|
571
|
+
font-size: 13px;
|
|
572
|
+
color: #607680;
|
|
573
|
+
margin-top: auto;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
.banner-icon-badge {
|
|
577
|
+
width: 26px;
|
|
578
|
+
height: 26px;
|
|
579
|
+
min-width: 26px;
|
|
580
|
+
border-radius: 9999px;
|
|
581
|
+
background: #f09e00;
|
|
582
|
+
display: flex;
|
|
583
|
+
align-items: center;
|
|
584
|
+
justify-content: center;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.warning-banner {
|
|
588
|
+
display: flex;
|
|
589
|
+
align-items: flex-start;
|
|
590
|
+
background: rgba(255, 189, 61, 0.15);
|
|
591
|
+
border-left: 4px solid #ffce6e;
|
|
592
|
+
border-radius: 0 8px 8px 0;
|
|
593
|
+
padding: 16px 20px 16px 16px;
|
|
594
|
+
font-size: 14px;
|
|
595
|
+
color: #607680;
|
|
596
|
+
margin-top: auto;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
@media (max-width: 389px) {
|
|
600
|
+
.first-login-card {
|
|
601
|
+
padding: 24px 16px;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
</style>
|