Adds expandable event card
Improves the Scheduled Event Card component by adding an expandable view. This change introduces a collapsed view that shows the event time and title, and an expanded view which displays all event details. This allows users to quickly scan the scheduled events and expand those they are interested in.
This commit is contained in:
parent
661b700092
commit
4bf1da7331
1 changed files with 109 additions and 48 deletions
|
|
@ -33,6 +33,9 @@ const emit = defineEmits<Emits>()
|
||||||
// Confirmation dialog state
|
// Confirmation dialog state
|
||||||
const showConfirmDialog = ref(false)
|
const showConfirmDialog = ref(false)
|
||||||
|
|
||||||
|
// Collapsed state (collapsed by default)
|
||||||
|
const isExpanded = ref(false)
|
||||||
|
|
||||||
// Event address for tracking completion
|
// Event address for tracking completion
|
||||||
const eventAddress = computed(() => `31922:${props.event.pubkey}:${props.event.dTag}`)
|
const eventAddress = computed(() => `31922:${props.event.pubkey}:${props.event.dTag}`)
|
||||||
|
|
||||||
|
|
@ -113,69 +116,127 @@ function confirmMarkComplete() {
|
||||||
function cancelMarkComplete() {
|
function cancelMarkComplete() {
|
||||||
showConfirmDialog.value = false
|
showConfirmDialog.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle expanded/collapsed state
|
||||||
|
function toggleExpanded() {
|
||||||
|
isExpanded.value = !isExpanded.value
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="border-b md:border md:rounded-lg bg-card p-4 md:p-6 transition-all"
|
<div class="border-b md:border md:rounded-lg bg-card transition-all"
|
||||||
:class="{ 'opacity-60': isCompletable && isCompleted }">
|
:class="{ 'opacity-60': isCompletable && isCompleted }">
|
||||||
<!-- Event Details -->
|
|
||||||
<div class="flex-1 min-w-0">
|
<!-- Collapsed View (Default) -->
|
||||||
<!-- Title and badges -->
|
<div v-if="!isExpanded"
|
||||||
<div class="flex items-start gap-2 mb-2 flex-wrap">
|
class="flex items-center gap-3 p-3 md:p-4">
|
||||||
<h3 class="font-semibold text-base md:text-lg flex-1"
|
<!-- Time -->
|
||||||
:class="{ 'line-through': isCompletable && isCompleted }">
|
<div @click="toggleExpanded" class="flex items-center gap-1.5 text-sm text-muted-foreground shrink-0 cursor-pointer">
|
||||||
{{ event.title }}
|
<Clock class="h-3.5 w-3.5" />
|
||||||
</h3>
|
<span class="font-medium">{{ formattedTimeRange || formattedDate }}</span>
|
||||||
<Badge v-if="isAdminEvent" variant="secondary" class="shrink-0">
|
</div>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<h3 @click="toggleExpanded"
|
||||||
|
class="font-semibold text-sm md:text-base flex-1 truncate cursor-pointer hover:text-foreground/80 transition-colors"
|
||||||
|
:class="{ 'line-through': isCompletable && isCompleted }">
|
||||||
|
{{ event.title }}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<!-- Badges and Actions -->
|
||||||
|
<div class="flex items-center gap-2 shrink-0">
|
||||||
|
<!-- Mark Complete Button (for uncompleted tasks) -->
|
||||||
|
<Button
|
||||||
|
v-if="isCompletable && !isCompleted"
|
||||||
|
@click.stop="handleMarkComplete"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
class="h-7 w-7 p-0"
|
||||||
|
>
|
||||||
|
<CheckCircle class="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Completed Badge -->
|
||||||
|
<Badge v-if="isCompletable && isCompleted" variant="secondary" class="text-xs">
|
||||||
|
✓
|
||||||
|
</Badge>
|
||||||
|
|
||||||
|
<!-- Admin Badge -->
|
||||||
|
<Badge v-if="isAdminEvent" variant="secondary" class="text-xs">
|
||||||
Admin
|
Admin
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Date/Time -->
|
<!-- Expanded View -->
|
||||||
<div class="flex items-center gap-4 text-sm text-muted-foreground mb-2 flex-wrap">
|
<div v-else class="p-4 md:p-6">
|
||||||
<div class="flex items-center gap-1.5">
|
<!-- Event Details -->
|
||||||
<Calendar class="h-4 w-4" />
|
<div class="flex-1 min-w-0">
|
||||||
<span>{{ formattedDate }}</span>
|
<!-- Title and badges with close button -->
|
||||||
|
<div class="flex items-start gap-2 mb-2 flex-wrap">
|
||||||
|
<h3 class="font-semibold text-base md:text-lg flex-1"
|
||||||
|
:class="{ 'line-through': isCompletable && isCompleted }">
|
||||||
|
{{ event.title }}
|
||||||
|
</h3>
|
||||||
|
<Badge v-if="isAdminEvent" variant="secondary" class="shrink-0">
|
||||||
|
Admin
|
||||||
|
</Badge>
|
||||||
|
<Button
|
||||||
|
@click="toggleExpanded"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
class="h-6 w-6 p-0 shrink-0"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="formattedTimeRange" class="flex items-center gap-1.5">
|
|
||||||
<Clock class="h-4 w-4" />
|
<!-- Date/Time -->
|
||||||
<span>{{ formattedTimeRange }}</span>
|
<div class="flex items-center gap-4 text-sm text-muted-foreground mb-2 flex-wrap">
|
||||||
|
<div class="flex items-center gap-1.5">
|
||||||
|
<Calendar class="h-4 w-4" />
|
||||||
|
<span>{{ formattedDate }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="formattedTimeRange" class="flex items-center gap-1.5">
|
||||||
|
<Clock class="h-4 w-4" />
|
||||||
|
<span>{{ formattedTimeRange }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Location -->
|
<!-- Location -->
|
||||||
<div v-if="event.location" class="flex items-center gap-1.5 text-sm text-muted-foreground mb-3">
|
<div v-if="event.location" class="flex items-center gap-1.5 text-sm text-muted-foreground mb-3">
|
||||||
<MapPin class="h-4 w-4" />
|
<MapPin class="h-4 w-4" />
|
||||||
<span>{{ event.location }}</span>
|
<span>{{ event.location }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Description/Content -->
|
<!-- Description/Content -->
|
||||||
<div v-if="event.description || event.content" class="text-sm mb-3">
|
<div v-if="event.description || event.content" class="text-sm mb-3">
|
||||||
<p class="whitespace-pre-wrap break-words">{{ event.description || event.content }}</p>
|
<p class="whitespace-pre-wrap break-words">{{ event.description || event.content }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Completion info (only for completable events) -->
|
<!-- Completion info (only for completable events) -->
|
||||||
<div v-if="isCompletable && isCompleted && getCompletion(eventAddress)" class="text-xs text-muted-foreground mb-3">
|
<div v-if="isCompletable && isCompleted && getCompletion(eventAddress)" class="text-xs text-muted-foreground mb-3">
|
||||||
✓ Completed by {{ getDisplayName(getCompletion(eventAddress)!.pubkey) }}
|
✓ Completed by {{ getDisplayName(getCompletion(eventAddress)!.pubkey) }}
|
||||||
<span v-if="getCompletion(eventAddress)!.notes"> - {{ getCompletion(eventAddress)!.notes }}</span>
|
<span v-if="getCompletion(eventAddress)!.notes"> - {{ getCompletion(eventAddress)!.notes }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Author (if not admin) -->
|
<!-- Author (if not admin) -->
|
||||||
<div v-if="!isAdminEvent" class="text-xs text-muted-foreground mb-3">
|
<div v-if="!isAdminEvent" class="text-xs text-muted-foreground mb-3">
|
||||||
Posted by {{ getDisplayName(event.pubkey) }}
|
Posted by {{ getDisplayName(event.pubkey) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mark Complete Button (only for completable task events) -->
|
<!-- Mark Complete Button (only for completable task events) -->
|
||||||
<div v-if="isCompletable && !isCompleted" class="mt-3">
|
<div v-if="isCompletable && !isCompleted" class="mt-3">
|
||||||
<Button
|
<Button
|
||||||
@click="handleMarkComplete"
|
@click.stop="handleMarkComplete"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
class="gap-2"
|
class="gap-2"
|
||||||
>
|
>
|
||||||
<CheckCircle class="h-4 w-4" />
|
<CheckCircle class="h-4 w-4" />
|
||||||
Mark Complete
|
Mark Complete
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue