102 lines
3.3 KiB
Vue
Executable File
102 lines
3.3 KiB
Vue
Executable File
<script setup lang="ts">
|
|
import { format, isToday } from 'date-fns'
|
|
import type { Activity } from '~/types'
|
|
|
|
const props = defineProps<{
|
|
activities: Activity[]
|
|
}>()
|
|
|
|
const activitiesRefs = ref<Record<number, Element | null>>({})
|
|
|
|
const selectedActivity = defineModel<Activity | null>()
|
|
|
|
watch(selectedActivity, () => {
|
|
if (!selectedActivity.value) {
|
|
return
|
|
}
|
|
const ref = activitiesRefs.value[selectedActivity.value._id]
|
|
if (ref) {
|
|
ref.scrollIntoView({ block: 'nearest' })
|
|
}
|
|
})
|
|
|
|
const activityLinks = [
|
|
{
|
|
label: 'Youtube',
|
|
},
|
|
{
|
|
label: 'Audio',
|
|
},
|
|
{
|
|
label: 'Libro',
|
|
},
|
|
{
|
|
label: 'Sencillo',
|
|
}
|
|
]
|
|
|
|
defineShortcuts({
|
|
arrowdown: () => {
|
|
const index = props.activities.findIndex((activity: Activity) => activity._id === selectedActivity.value?._id)
|
|
|
|
if (index === -1) {
|
|
selectedActivity.value = props.activities[0]
|
|
} else if (index < props.activities.length - 1) {
|
|
selectedActivity.value = props.activities[index + 1]
|
|
}
|
|
},
|
|
arrowup: () => {
|
|
const index = props.activities.findIndex((activity: Activity) => activity._id === selectedActivity.value?._id)
|
|
|
|
if (index === -1) {
|
|
selectedActivity.value = props.activities[props.activities.length - 1]
|
|
} else if (index > 0) {
|
|
selectedActivity.value = props.activities[index - 1]
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="overflow-y-auto divide-y divide-default">
|
|
<div
|
|
v-for="(activity, index) in activities"
|
|
:key="index"
|
|
:ref="(el) => { activitiesRefs[activity._id] = el as Element | null }"
|
|
>
|
|
<div
|
|
class="p-4 sm:px-6 text-sm cursor-pointer border-l-2 transition-colors"
|
|
:class="[
|
|
activity.unread ? 'text-highlighted' : 'text-toned',
|
|
selectedActivity && selectedActivity._id === activity._id
|
|
? 'border-primary bg-primary/10'
|
|
: 'border-bg hover:border-primary hover:bg-primary/5'
|
|
]"
|
|
@click="selectedActivity = activity"
|
|
>
|
|
<div class="flex items-center justify-between" :class="[activity.unread && 'font-semibold']">
|
|
<div class="flex items-center gap-3 text-md font-semibold mb-2">
|
|
{{ activity.title }}
|
|
|
|
<UChip v-if="activity.unread" />
|
|
</div>
|
|
|
|
<!-- <span>{{ isToday(new Date(activity.date || '')) ? format(new Date(activity.date || ''), 'HH:mm') : format(new Date(activity.date || ''), 'dd MMM') }}</span> -->
|
|
</div>
|
|
<p class="flex justify-between text-xs" :class="[activity.unread && 'font-semibold']">
|
|
{{ formatDate(new Date(activity.date).getTime()/1000) }}<USeparator orientation="vertical" class="h-4" /> {{ formatLocation(activity) }}
|
|
</p>
|
|
<p class="text-dimmed line-clamp-1" v-html="activity.body">
|
|
|
|
</p>
|
|
<ul class="flex space-x-4 text-xs my-2 text-gray-400">
|
|
<li class="flex align-center"><UIcon name="i-lucide-youtube" class="size-4 mr-1" />Youtube</li>
|
|
<li class="flex align-center"><UIcon name="i-lucide-file-audio" class="size-4 mr-1" />Audio</li>
|
|
<li class="flex align-center"><UIcon name="i-lucide-book-open-text" class="size-4 mr-1" />Libro</li>
|
|
<li class="flex align-center"><UIcon name="i-lucide-notebook-text" class="size-4 mr-1" />Sencillo</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|