@@ -9,6 +9,7 @@ import { PinInput, PinInputGroup, PinInputSlot } from '@/components/ui/pin-input
99import { useClipboard } from ' @/composables/useClipboard' ;
1010import AppLayout from ' @/layouts/AppLayout.vue' ;
1111import SettingsLayout from ' @/layouts/settings/Layout.vue' ;
12+ import { BreadcrumbItem } from ' @/types' ;
1213import { Form , Head } from ' @inertiajs/vue3' ;
1314import { Check , Copy , Eye , EyeOff , Loader2 , LockKeyhole , RefreshCw , ScanLine , ShieldBan , ShieldCheck } from ' lucide-vue-next' ;
1415import { computed , nextTick , reactive , ref } from ' vue' ;
@@ -23,25 +24,33 @@ const props = withDefaults(defineProps<Props>(), {
2324 twoFactorEnabled: false ,
2425});
2526
26- const breadcrumbs = [
27+ const breadcrumbs: BreadcrumbItem [] = [
2728 {
2829 title: ' Two-Factor Authentication' ,
2930 href: ' /settings/two-factor' ,
3031 },
3132];
3233
33- const { copied , copyToClipboard } = useClipboard ();
34+ const { recentlyCopied , copyToClipboard } = useClipboard ();
3435
35- const setupData = reactive ({
36- qrCodeSvg: null as string | null ,
37- manualSetupKey: null as string | null ,
36+ const setupData: {
37+ qrCodeSvg: string | null ;
38+ manualSetupKey: string | null ;
39+ reset(): void ;
40+ } = reactive ({
41+ qrCodeSvg: null ,
42+ manualSetupKey: null ,
3843 reset() {
3944 this .qrCodeSvg = null ;
4045 this .manualSetupKey = null ;
4146 },
4247});
4348
44- const modalState = reactive ({
49+ const modalState: {
50+ isOpen: boolean ;
51+ isInVerificationStep: boolean ;
52+ reset(): void ;
53+ } = reactive ({
4554 isOpen: false ,
4655 isInVerificationStep: false ,
4756 reset() {
@@ -99,7 +108,7 @@ const enableTwoFactorAuthenticationSuccess = async () => {
99108 const [qrResponse, keyResponse, codesResponse] = await Promise .all ([
100109 fetch (route (' two-factor.qr-code' ), { headers: { Accept: ' application/json' } }),
101110 fetch (route (' two-factor.secret-key' ), { headers: { Accept: ' application/json' } }),
102- fetch ( route ( ' two-factor.recovery-codes ' ), { headers: { Accept: ' application/json ' } } ),
111+ fetchRecoveryCodes ( ),
103112 ]);
104113
105114 const { svg } = await qrResponse .json ();
@@ -121,8 +130,12 @@ const disableTwoFactorAuthenticationSuccess = () => {
121130 code .value = [];
122131};
123132
124- const recoveryCodes = reactive ({
125- list: [] as string [],
133+ const recoveryCodes: {
134+ list: string [];
135+ isVisible: boolean ;
136+ reset(): void ;
137+ } = reactive ({
138+ list: [],
126139 isVisible: false ,
127140 reset() {
128141 this .list = [];
@@ -293,11 +306,6 @@ const verificationCode = computed(() => code.value.join(''));
293306 </div >
294307 <div v-else class =" relative z-10 overflow-hidden border p-5" >
295308 <div v-html =" setupData.qrCodeSvg" class =" flex aspect-square size-full items-center justify-center" />
296- <div v-if =" setupData.qrCodeSvg" class =" animate-scanning-line absolute inset-0 h-full w-full" >
297- <div
298- class =" absolute inset-x-0 h-0.5 bg-blue-500 opacity-60 transition-all duration-300 ease-in-out"
299- />
300- </div >
301309 </div >
302310 </div >
303311 </div >
@@ -329,7 +337,7 @@ const verificationCode = computed(() => code.value.join(''));
329337 @click =" copyToClipboard(setupData.manualSetupKey || '')"
330338 class =" relative block h-auto border-l border-border px-3 hover:bg-muted"
331339 >
332- <Check v-if =" copied " class =" w-4 text-green-500" />
340+ <Check v-if =" recentlyCopied " class =" w-4 text-green-500" />
333341 <Copy v-else class =" w-4" />
334342 </button >
335343 </template >
@@ -391,21 +399,3 @@ const verificationCode = computed(() => code.value.join(''));
391399 </SettingsLayout >
392400 </AppLayout >
393401</template >
394-
395- <style scoped>
396- @keyframes scan {
397- 0% {
398- top : 0 ;
399- }
400- 50% {
401- top : 100% ;
402- }
403- 100% {
404- top : 0 ;
405- }
406- }
407-
408- .animate-scanning-line div {
409- animation : scan 3s ease-in-out infinite ;
410- }
411- </style >
0 commit comments