84 lines
2.1 KiB
Vue
84 lines
2.1 KiB
Vue
<!-- StoriesRail.vue -->
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue';
|
|
import StoryRing from './StoryRing.vue';
|
|
import StoryViewer from './StoryViewer.vue';
|
|
import type { StoryLink } from '@/types/dredge.types';
|
|
|
|
const stories = ref<StoryLink[]>([]);
|
|
const loading = ref(true);
|
|
const error = ref<string | null>(null);
|
|
const openUsername = ref<string | null>(null);
|
|
|
|
async function fetchStories() {
|
|
loading.value = true;
|
|
error.value = null;
|
|
try {
|
|
const response = await fetch('/api/stories');
|
|
if (!response.ok) throw new Error('Failed to load stories');
|
|
stories.value = await response.json();
|
|
} catch (e) {
|
|
error.value = 'Could not load stories.';
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
function openStory(username: string) {
|
|
openUsername.value = username;
|
|
}
|
|
|
|
async function closeStory() {
|
|
openUsername.value = null;
|
|
await fetchStories();
|
|
}
|
|
|
|
onMounted(fetchStories);
|
|
</script>
|
|
|
|
<template>
|
|
<section class="rail" aria-label="Surface catches">
|
|
<p v-if="loading" class="rail__status">Loading stories…</p>
|
|
<p v-else-if="error" class="rail__status" role="alert">{{ error }}</p>
|
|
<p v-else-if="stories.length === 0" class="rail__status">
|
|
No active stories.
|
|
</p>
|
|
|
|
<template v-else>
|
|
<StoryRing
|
|
v-for="s in stories"
|
|
:key="s.username"
|
|
:username="s.username"
|
|
:profile-pic-url="s.profile_pic_url"
|
|
:is-unread="s.is_unread"
|
|
:muted="s.muted"
|
|
@select="openStory(s.username)"
|
|
/>
|
|
</template>
|
|
</section>
|
|
|
|
<StoryViewer
|
|
v-if="openUsername"
|
|
:username="openUsername"
|
|
@close="closeStory"
|
|
/>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.rail {
|
|
display: flex;
|
|
gap: 1.1rem;
|
|
overflow-x: auto;
|
|
padding-bottom: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
border-bottom: 1px solid var(--line);
|
|
min-width: 0; /* add */
|
|
width: 100%; /* add */
|
|
}
|
|
.rail__status {
|
|
font-size: 0.8rem;
|
|
color: var(--haze);
|
|
padding: 0.5rem 0;
|
|
}
|
|
</style>
|