Files
laravel-nuxt-ui-inertia-tem…/resources/js/components/auth/RecoveryCodesPanel.vue

79 lines
1.7 KiB
Vue

<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps<{
codes: string[]
}>()
const copied = ref(false)
function recoveryCodesText() {
return [
'Two-factor authentication recovery codes',
'',
...props.codes,
'',
'Each code can only be used once. Store these codes securely.',
].join('\n')
}
async function copyAll() {
await navigator.clipboard.writeText(props.codes.join('\n'))
copied.value = true
window.setTimeout(() => {
copied.value = false
}, 2000)
}
function download() {
const blob = new Blob([recoveryCodesText()], {
type: 'text/plain;charset=utf-8',
})
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'two-factor-recovery-codes.txt'
link.click()
URL.revokeObjectURL(url)
}
</script>
<template>
<div class="space-y-3">
<div class="flex flex-wrap gap-2">
<UButton
type="button"
variant="outline"
size="sm"
:color="copied ? 'success' : 'neutral'"
:icon="copied ? 'i-lucide-check' : 'i-lucide-copy'"
:aria-label="copied ? 'Recovery codes copied' : 'Copy all recovery codes'"
@click="copyAll"
>
{{ copied ? 'Copied' : 'Copy all' }}
</UButton>
<UButton
type="button"
color="neutral"
variant="outline"
size="sm"
icon="i-lucide-download"
aria-label="Download recovery codes"
@click="download"
>
Download
</UButton>
</div>
<div class="grid gap-2 sm:grid-cols-2">
<code
v-for="code in codes"
:key="code"
class="rounded bg-elevated px-3 py-2 text-center text-sm"
>{{ code }}</code>
</div>
</div>
</template>