feat: add week 3 audio and timeline enhancements
This commit is contained in:
@@ -6,18 +6,19 @@ import BaseButton from '../components/ui/BaseButton.vue'
|
||||
import LoadingSpinner from '../components/ui/LoadingSpinner.vue'
|
||||
import EmptyState from '../components/ui/EmptyState.vue'
|
||||
import {
|
||||
SparklesIcon,
|
||||
BookOpenIcon,
|
||||
TrophyIcon,
|
||||
FlagIcon,
|
||||
CalendarIcon,
|
||||
SparklesIcon,
|
||||
BookOpenIcon,
|
||||
TrophyIcon,
|
||||
FlagIcon,
|
||||
HeartIcon,
|
||||
CalendarIcon,
|
||||
ChevronLeftIcon,
|
||||
ExclamationCircleIcon
|
||||
} from '@heroicons/vue/24/solid'
|
||||
|
||||
interface TimelineEvent {
|
||||
date: string
|
||||
type: 'story' | 'achievement' | 'milestone'
|
||||
interface TimelineEvent {
|
||||
date: string
|
||||
type: 'story' | 'achievement' | 'milestone' | 'reading_event' | 'memory'
|
||||
title: string
|
||||
description: string | null
|
||||
image_url: string | null
|
||||
@@ -41,19 +42,23 @@ const profileId = route.params.id as string
|
||||
const profileName = ref('') // We might need to fetch profile details separately or store it
|
||||
|
||||
function getIcon(type: string) {
|
||||
switch (type) {
|
||||
case 'milestone': return FlagIcon
|
||||
case 'story': return BookOpenIcon
|
||||
case 'achievement': return TrophyIcon
|
||||
switch (type) {
|
||||
case 'milestone': return FlagIcon
|
||||
case 'story': return BookOpenIcon
|
||||
case 'reading_event': return CalendarIcon
|
||||
case 'memory': return HeartIcon
|
||||
case 'achievement': return TrophyIcon
|
||||
default: return SparklesIcon
|
||||
}
|
||||
}
|
||||
|
||||
function getColor(type: string) {
|
||||
switch (type) {
|
||||
case 'milestone': return 'text-blue-500'
|
||||
case 'story': return 'text-purple-500'
|
||||
case 'achievement': return 'text-yellow-500'
|
||||
switch (type) {
|
||||
case 'milestone': return 'text-blue-500'
|
||||
case 'story': return 'text-purple-500'
|
||||
case 'reading_event': return 'text-emerald-500'
|
||||
case 'memory': return 'text-pink-500'
|
||||
case 'achievement': return 'text-yellow-500'
|
||||
default: return 'text-gray-500'
|
||||
}
|
||||
}
|
||||
@@ -83,7 +88,7 @@ async function fetchTimeline() {
|
||||
}
|
||||
|
||||
function handleEventClick(event: TimelineEvent) {
|
||||
if (event.type === 'story' && event.metadata?.story_id) {
|
||||
if ((event.type === 'story' || event.type === 'reading_event' || event.type === 'memory') && event.metadata?.story_id) {
|
||||
if (event.metadata.mode === 'storybook') {
|
||||
router.push(`/storybook/view/${event.metadata.story_id}`)
|
||||
} else {
|
||||
@@ -175,11 +180,17 @@ onMounted(fetchTimeline)
|
||||
</div>
|
||||
|
||||
<!-- Role Badge -->
|
||||
<div v-if="event.type === 'achievement'" class="mt-4 inline-flex items-center px-3 py-1 rounded-full bg-yellow-50 text-yellow-700 text-xs font-bold border border-yellow-200">
|
||||
<TrophyIcon class="h-3 w-3 mr-1" /> 成就解锁
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="event.type === 'achievement'" class="mt-4 inline-flex items-center px-3 py-1 rounded-full bg-yellow-50 text-yellow-700 text-xs font-bold border border-yellow-200">
|
||||
<TrophyIcon class="h-3 w-3 mr-1" /> 成就解锁
|
||||
</div>
|
||||
<div v-else-if="event.type === 'reading_event'" class="mt-4 inline-flex items-center px-3 py-1 rounded-full bg-emerald-50 text-emerald-700 text-xs font-bold border border-emerald-200">
|
||||
<CalendarIcon class="h-3 w-3 mr-1" /> 阅读记录
|
||||
</div>
|
||||
<div v-else-if="event.type === 'memory'" class="mt-4 inline-flex items-center px-3 py-1 rounded-full bg-pink-50 text-pink-700 text-xs font-bold border border-pink-200">
|
||||
<HeartIcon class="h-3 w-3 mr-1" /> 记忆沉淀
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user