Download event times showed raw UTC wall-clock (iso.slice). Added formatDateTime()/formatLocalDate() (local tz, robust to naive vs tz-aware ISO) and applied them to the download row + detail modal datetimes and the credential/artist date displays. formatPostDate stays UTC (date-only, locale-stable, unit-tested). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
70 lines
2.1 KiB
Vue
70 lines
2.1 KiB
Vue
<template>
|
||
<section class="fc-cred-row">
|
||
<header class="fc-cred-row__head">
|
||
<span class="fc-cred-row__name">{{ platform.name }}</span>
|
||
<v-chip size="x-small" variant="tonal">{{ platform.auth_type }}</v-chip>
|
||
</header>
|
||
<div class="fc-cred-row__body">
|
||
<template v-if="credential">
|
||
<span class="fc-cred-row__status">
|
||
✓ Stored · captured {{ fmtDate(credential.captured_at) }}
|
||
<template v-if="credential.expires_at">
|
||
· expires {{ fmtDate(credential.expires_at) }}
|
||
</template>
|
||
</span>
|
||
<v-spacer />
|
||
<v-btn size="small" variant="outlined" @click="$emit('replace', platform)">
|
||
Replace
|
||
</v-btn>
|
||
<v-btn size="small" variant="text" color="error" @click="$emit('remove', platform)">
|
||
×
|
||
</v-btn>
|
||
</template>
|
||
<template v-else>
|
||
<span class="fc-cred-row__status fc-cred-row__status--empty">○ No credential</span>
|
||
<v-spacer />
|
||
<v-btn size="small" variant="flat" color="accent" @click="$emit('replace', platform)">
|
||
{{ platform.auth_type === 'cookies' ? 'Paste cookies.txt' : 'Paste token' }}
|
||
</v-btn>
|
||
</template>
|
||
</div>
|
||
</section>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { formatLocalDate } from '../../utils/date.js'
|
||
|
||
defineProps({
|
||
platform: { type: Object, required: true },
|
||
credential: { type: Object, default: null },
|
||
})
|
||
defineEmits(['replace', 'remove'])
|
||
|
||
function fmtDate(iso) {
|
||
return iso ? formatLocalDate(iso) : '—'
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.fc-cred-row {
|
||
border: 1px solid rgb(var(--v-theme-on-surface-variant) / 0.18);
|
||
border-radius: 6px;
|
||
padding: 0.75rem 1rem;
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
.fc-cred-row__head {
|
||
display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem;
|
||
}
|
||
.fc-cred-row__name { font-weight: 600; }
|
||
.fc-cred-row__body {
|
||
display: flex; align-items: center; gap: 0.5rem;
|
||
}
|
||
.fc-cred-row__status {
|
||
font-size: 0.9rem;
|
||
color: rgb(var(--v-theme-on-surface));
|
||
}
|
||
.fc-cred-row__status--empty {
|
||
color: rgb(var(--v-theme-on-surface-variant));
|
||
}
|
||
</style>
|