Implement task status workflow: claimed, in-progress, completed
Added granular task state management to scheduled events/tasks with three states plus unclaimed. Tasks now support a full workflow from claiming to completion with visual feedback at each stage. **New Task States:** - **Unclaimed** (no RSVP event) - Task available for anyone to claim - **Claimed** - User has reserved the task but hasn't started - **In Progress** - User is actively working on the task - **Completed** - Task is done - **Blocked** - Task is stuck (supported but not yet used in UI) - **Cancelled** - Task won't be completed (supported but not yet used in UI) **Service Layer (ScheduledEventService.ts):** - Updated `EventCompletion` interface: replaced `completed: boolean` with `taskStatus: TaskStatus` - Added `TaskStatus` type: `'claimed' | 'in-progress' | 'completed' | 'blocked' | 'cancelled'` - New methods: `claimTask()`, `startTask()`, `getTaskStatus()` - Refactored `completeEvent()` and renamed `uncompleteEvent()` to `unclaimTask()` - Internal `updateTaskStatus()` method handles all state changes - Uses `task-status` tag instead of `completed` tag in Nostr events - `unclaimTask()` publishes deletion event (kind 5) to remove RSVP - Backward compatibility: reads old `completed` tag and converts to new taskStatus **Composable (useScheduledEvents.ts):** - Exported new methods: `claimTask`, `startTask`, `unclaimTask`, `getTaskStatus` - Updated `completeEvent` signature to accept occurrence parameter - Marked `toggleComplete` as deprecated (still works for compatibility) **UI (ScheduledEventCard.vue):** - Context-aware action buttons based on current task status: - Unclaimed: "Claim Task" button - Claimed: "Start Task" + "Unclaim" buttons - In Progress: "Mark Complete" + "Unclaim" buttons - Completed: "Unclaim" button only - Status badges with icons and color coding: - 👋 Claimed (blue) - 🔄 In Progress (orange) - ✓ Completed (green) - Shows who claimed/is working on/completed each task - Unified confirmation dialog for all actions - Quick action buttons in collapsed view - Full button set in expanded view **Feed Integration (NostrFeed.vue):** - Added handlers: `onClaimTask`, `onStartTask`, `onCompleteTask`, `onUnclaimTask` - Passes `getTaskStatus` prop to ScheduledEventCard - Wired up all new event emitters **Nostr Protocol:** - Uses NIP-52 Calendar Event RSVP (kind 31925) - Custom `task-status` tag for granular state tracking - Deletion events (kind 5) for unclaiming tasks - Fully decentralized - all state stored on Nostr relays 🐢 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2e6f215157
commit
d497cfa4d9
4 changed files with 452 additions and 100 deletions
|
|
@ -99,7 +99,16 @@ const { getDisplayName, fetchProfiles } = useProfiles()
|
|||
const { getEventReactions, subscribeToReactions, toggleLike } = useReactions()
|
||||
|
||||
// Use scheduled events service
|
||||
const { getEventsForSpecificDate, getCompletion, toggleComplete, allCompletions } = useScheduledEvents()
|
||||
const {
|
||||
getEventsForSpecificDate,
|
||||
getCompletion,
|
||||
getTaskStatus,
|
||||
claimTask,
|
||||
startTask,
|
||||
completeEvent,
|
||||
unclaimTask,
|
||||
allCompletions
|
||||
} = useScheduledEvents()
|
||||
|
||||
// Selected date for viewing scheduled tasks (defaults to today)
|
||||
const selectedDate = ref(new Date().toISOString().split('T')[0])
|
||||
|
|
@ -255,14 +264,40 @@ async function onToggleLike(note: FeedPost) {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle scheduled event completion toggle
|
||||
async function onToggleComplete(event: ScheduledEvent, occurrence?: string) {
|
||||
console.log('🎯 NostrFeed: onToggleComplete called for event:', event.title, 'occurrence:', occurrence)
|
||||
// Task action handlers
|
||||
async function onClaimTask(event: ScheduledEvent, occurrence?: string) {
|
||||
console.log('👋 NostrFeed: Claiming task:', event.title)
|
||||
try {
|
||||
await toggleComplete(event, occurrence)
|
||||
console.log('✅ NostrFeed: toggleComplete succeeded')
|
||||
await claimTask(event, '', occurrence)
|
||||
} catch (error) {
|
||||
console.error('❌ NostrFeed: Failed to toggle event completion:', error)
|
||||
console.error('❌ Failed to claim task:', error)
|
||||
}
|
||||
}
|
||||
|
||||
async function onStartTask(event: ScheduledEvent, occurrence?: string) {
|
||||
console.log('▶️ NostrFeed: Starting task:', event.title)
|
||||
try {
|
||||
await startTask(event, '', occurrence)
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to start task:', error)
|
||||
}
|
||||
}
|
||||
|
||||
async function onCompleteTask(event: ScheduledEvent, occurrence?: string) {
|
||||
console.log('✅ NostrFeed: Completing task:', event.title)
|
||||
try {
|
||||
await completeEvent(event, occurrence, '')
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to complete task:', error)
|
||||
}
|
||||
}
|
||||
|
||||
async function onUnclaimTask(event: ScheduledEvent, occurrence?: string) {
|
||||
console.log('🔙 NostrFeed: Unclaiming task:', event.title)
|
||||
try {
|
||||
await unclaimTask(event, occurrence)
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to unclaim task:', error)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -514,8 +549,12 @@ function cancelDelete() {
|
|||
:event="event"
|
||||
:get-display-name="getDisplayName"
|
||||
:get-completion="getCompletion"
|
||||
:get-task-status="getTaskStatus"
|
||||
:admin-pubkeys="adminPubkeys"
|
||||
@toggle-complete="onToggleComplete"
|
||||
@claim-task="onClaimTask"
|
||||
@start-task="onStartTask"
|
||||
@complete-task="onCompleteTask"
|
||||
@unclaim-task="onUnclaimTask"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="text-center py-3 text-muted-foreground text-sm px-4">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue