discovery-by-llm/frontend/src/components/ResultActions.vue
Justin Visser a3af8f45cc
Some checks are pending
ci / backend (push) Waiting to run
ci / frontend (push) Waiting to run
fix(frontend): harden the streaming ui and extract copy and constants
2026-08-10 15:42:18 +02:00

76 lines
1.8 KiB
Vue

<script setup lang="ts">
import { computed } from 'vue'
import { formatMessage, messages } from '../lib/messages'
import type { PlaylistState } from '../lib/models'
const props = defineProps<{
state: PlaylistState
trackCount: number
canSave: boolean
}>()
defineEmits<{ save: [] }>()
const buttonLabel = computed(() => {
if (props.state.status === 'saving') return messages.resultActionsSaving
if (props.state.status === 'error') return messages.resultActionsTryAgain
return messages.resultActionsSavePlaylist
})
const summary = computed(() => formatMessage('resultActionsSummary', { count: props.trackCount }))
</script>
<template>
<div class="actions">
<button
v-if="canSave"
class="save"
type="button"
:disabled="state.status === 'saving'"
@click="$emit('save')"
>
{{ buttonLabel }}
</button>
<a v-else class="connect" href="/api/auth/login">{{ messages.resultActionsConnectSpotify }}</a>
<span class="summary">{{ summary }}</span>
</div>
</template>
<style scoped>
.actions {
display: flex;
flex-wrap: wrap;
gap: var(--s-5);
align-items: center;
}
.save,
.connect {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: var(--tap-min);
padding: 11px var(--s-6);
color: var(--c-on-accent);
font-size: var(--t-small);
font-weight: 500;
text-decoration: none;
cursor: pointer;
background: var(--c-accent);
border: 1px solid var(--c-accent);
border-radius: var(--r-md);
transition: all var(--dur-fast) ease;
}
.save:hover,
.connect:hover {
color: var(--c-on-accent);
text-decoration: none;
background: var(--c-accent-hover);
border-color: var(--c-accent-hover);
}
.summary {
color: var(--c-text-faint);
font-family: var(--f-mono);
font-size: var(--t-micro);
}
</style>