- Created comprehensive audit document: MUTATION_BUTTONS_AUDIT.md - Identified 28 mutation buttons across 9 categories - 5 buttons already have loading states (18%) - 23 buttons missing loading states (82%) - Categorized by priority: High (8), Medium (11), Low (4) - Documented existing patterns and recommendations - Task 8.3.1.2 complete
317 lines
12 KiB
Markdown
317 lines
12 KiB
Markdown
# Mutation Buttons Audit
|
|
|
|
**Date**: 2025-01-27
|
|
**Task**: Action 8.3.1.2 - Audit all mutation buttons
|
|
**Status**: Complete
|
|
|
|
## Summary
|
|
|
|
This document lists all mutation buttons in the frontend codebase that use React Query mutations (`mutate` or `mutateAsync`). Each entry includes:
|
|
- Component location
|
|
- Mutation type
|
|
- Button element
|
|
- Current loading state status
|
|
- Priority for adding loading states
|
|
|
|
## Categories
|
|
|
|
### 1. Playlist Mutations
|
|
|
|
#### 1.1 Create Playlist
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistForm.tsx`
|
|
- **Mutation**: `createMutation.mutateAsync()`
|
|
- **Button**: Form submit button (line ~140)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Form submission button, should show loading during creation
|
|
|
|
#### 1.2 Update Playlist
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistForm.tsx`
|
|
- **Mutation**: `updateMutation.mutateAsync()`
|
|
- **Button**: Form submit button (line ~140)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Form submission button, should show loading during update
|
|
|
|
#### 1.3 Delete Playlist
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistActions.tsx`
|
|
- **Mutation**: `deleteMutation.mutateAsync()`
|
|
- **Button**: Delete button (line ~92)
|
|
- **Loading State**: ✅ Present (uses `isPending` on line 112)
|
|
- **Priority**: N/A (already implemented)
|
|
- **Notes**: Already has loading state with `Loader2` spinner
|
|
|
|
#### 1.4 Edit Playlist
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistActions.tsx`
|
|
- **Mutation**: `updateMutation.mutateAsync()`
|
|
- **Button**: Edit button (line ~109)
|
|
- **Loading State**: ✅ Present (uses `isPending` on line 112, 116)
|
|
- **Priority**: N/A (already implemented)
|
|
- **Notes**: Already has loading state with `Loader2` spinner
|
|
|
|
### 2. Track Mutations
|
|
|
|
#### 2.1 Add Track to Playlist
|
|
- **File**: `apps/web/src/features/library/pages/LibraryPage.tsx`
|
|
- **Mutation**: `addTrackToPlaylistMutation.mutateAsync()`
|
|
- **Button**: DropdownMenuItem in playlist submenu (line ~708-724)
|
|
- **Loading State**: ✅ Present (Action 8.3.1.1)
|
|
- **Priority**: N/A (already implemented)
|
|
- **Notes**: Recently added loading state with `Loader2` spinner
|
|
|
|
#### 2.2 Add Track to Playlist (Modal)
|
|
- **File**: `apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx`
|
|
- **Mutation**: `addTrackMutation.mutateAsync()`
|
|
- **Button**: "Add Tracks" button (line ~132)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Modal button for adding multiple tracks, should show loading during batch operation
|
|
|
|
#### 2.3 Like Track
|
|
- **File**: `apps/web/src/features/tracks/components/LikeButton.tsx`
|
|
- **Mutation**: `likeMutation.mutate()` / `unlikeMutation.mutate()`
|
|
- **Button**: LikeButton component (line ~156)
|
|
- **Loading State**: ✅ Present (uses `isPending` on line 152-153, 169-175)
|
|
- **Priority**: N/A (already implemented)
|
|
- **Notes**: Already has loading state with `Loader2` spinner
|
|
|
|
#### 2.4 Reorder Playlist Tracks
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistTrackList.tsx`
|
|
- **Mutation**: `reorderMutation.mutateAsync()`
|
|
- **Button**: Drag-and-drop reorder (line ~193)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Drag-and-drop operation, could show loading indicator during reorder
|
|
|
|
### 3. Comment Mutations
|
|
|
|
#### 3.1 Create Comment
|
|
- **File**: `apps/web/src/features/tracks/components/CommentSection.tsx`
|
|
- **Mutation**: `createCommentMutation.mutate()`
|
|
- **Button**: Form submit button (line ~121)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Comment form submission, should show loading
|
|
|
|
#### 3.2 Create Reply
|
|
- **File**: `apps/web/src/features/tracks/components/CommentThread.tsx`
|
|
- **Mutation**: `createReplyMutation.mutate()`
|
|
- **Button**: Reply form submit button (line ~322)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Reply form submission, should show loading
|
|
|
|
#### 3.3 Update Comment
|
|
- **File**: `apps/web/src/features/tracks/components/CommentThread.tsx`
|
|
- **Mutation**: `updateCommentMutation.mutate()`
|
|
- **Button**: Edit form submit button (line ~328)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Edit form submission, should show loading
|
|
|
|
#### 3.4 Delete Comment
|
|
- **File**: `apps/web/src/features/tracks/components/CommentThread.tsx`
|
|
- **Mutation**: `deleteCommentMutation.mutate()`
|
|
- **Button**: Delete button (line ~332)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Delete action, should show loading
|
|
|
|
### 4. Playlist Collaboration Mutations
|
|
|
|
#### 4.1 Add Collaborator
|
|
- **File**: `apps/web/src/features/playlists/components/AddCollaboratorModal.tsx`
|
|
- **Mutation**: `addCollaboratorMutation.mutateAsync()`
|
|
- **Button**: "Add Collaborator" button (line ~60, 87)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Modal form submission, should show loading
|
|
|
|
#### 4.2 Remove Collaborator
|
|
- **File**: `apps/web/src/features/playlists/components/CollaboratorList.tsx`
|
|
- **Mutation**: `removeMutation.mutateAsync()`
|
|
- **Button**: Remove button (line ~46)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Remove action with confirmation, should show loading
|
|
|
|
#### 4.3 Update Collaborator Permission
|
|
- **File**: `apps/web/src/features/playlists/components/CollaboratorList.tsx`
|
|
- **Mutation**: `updatePermissionMutation.mutateAsync()`
|
|
- **Button**: Permission dropdown/button (line ~63)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Permission change action, should show loading
|
|
|
|
### 5. Playlist Follow Mutations
|
|
|
|
#### 5.1 Follow/Unfollow Playlist
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistFollowButton.tsx`
|
|
- **Mutation**: `followMutation.mutate()` / `unfollowMutation.mutate()`
|
|
- **Button**: FollowButton component (line ~173)
|
|
- **Loading State**: ✅ Present (uses `isPending` on line 168-169, 180-184)
|
|
- **Priority**: N/A (already implemented)
|
|
- **Notes**: Already has loading state with `Loader2` spinner
|
|
|
|
### 6. Share Link Mutations
|
|
|
|
#### 6.1 Create Share Link
|
|
- **File**: `apps/web/src/features/playlists/components/SharePlaylistModal.tsx`
|
|
- **Mutation**: `createShareLinkMutation.mutateAsync()`
|
|
- **Button**: Auto-triggered on modal open (line ~42)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Auto-triggered, should show loading indicator in modal
|
|
|
|
#### 6.2 Create Share Link (Batch)
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistBatchActions.tsx`
|
|
- **Mutation**: `createShareLinkMutation.mutateAsync()`
|
|
- **Button**: "Share" button in batch actions (line ~141)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Batch operation, should show loading
|
|
|
|
#### 6.3 Create Share Link (Generic)
|
|
- **File**: `apps/web/src/components/share/ShareLinkManager.tsx`
|
|
- **Mutation**: `createShareMutation.mutateAsync()`
|
|
- **Button**: "Create Share Link" button (line ~172)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Generic share link creation, should show loading
|
|
|
|
#### 6.4 Revoke Share Link
|
|
- **File**: `apps/web/src/components/share/ShareLinkManager.tsx`
|
|
- **Mutation**: `revokeShareMutation.mutate()`
|
|
- **Button**: Revoke button (line ~199)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Revoke action, should show loading
|
|
|
|
### 7. Notification Mutations
|
|
|
|
#### 7.1 Mark Notification as Read
|
|
- **File**: `apps/web/src/components/notifications/NotificationMenu.tsx`
|
|
- **Mutation**: `markAsReadMutation.mutate()`
|
|
- **Button**: Notification item click / mark as read button (line ~163)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: LOW
|
|
- **Notes**: Auto-triggered on click, could show subtle loading indicator
|
|
|
|
#### 7.2 Mark All Notifications as Read
|
|
- **File**: `apps/web/src/components/notifications/NotificationMenu.tsx`
|
|
- **Mutation**: `markAllAsReadMutation.mutate()`
|
|
- **Button**: "Mark All as Read" button (line ~167)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Batch operation, should show loading
|
|
|
|
#### 7.3 Mark Notification as Read (Page)
|
|
- **File**: `apps/web/src/features/notifications/pages/NotificationsPage.tsx`
|
|
- **Mutation**: `markAsReadMutation.mutate()`
|
|
- **Button**: Notification item click / mark as read button (line ~179)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: LOW
|
|
- **Notes**: Auto-triggered on click, could show subtle loading indicator
|
|
|
|
#### 7.4 Mark All Notifications as Read (Page)
|
|
- **File**: `apps/web/src/features/notifications/pages/NotificationsPage.tsx`
|
|
- **Mutation**: `markAllAsReadMutation.mutate()`
|
|
- **Button**: "Mark All as Read" button (line ~184)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Batch operation, should show loading
|
|
|
|
### 8. Chat Mutations
|
|
|
|
#### 8.1 Leave Room
|
|
- **File**: `apps/web/src/features/chat/components/ChatSidebar.tsx`
|
|
- **Mutation**: `leaveRoomMutation.mutate()`
|
|
- **Button**: Leave button (line ~174)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Leave action with confirmation, should show loading
|
|
|
|
#### 8.2 Delete Room
|
|
- **File**: `apps/web/src/features/chat/components/ChatSidebar.tsx`
|
|
- **Mutation**: `deleteRoomMutation.mutate()`
|
|
- **Button**: Delete button (line ~180)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: MEDIUM
|
|
- **Notes**: Delete action with confirmation, should show loading
|
|
|
|
### 9. Batch Operations
|
|
|
|
#### 9.1 Delete Multiple Playlists
|
|
- **File**: `apps/web/src/features/playlists/components/PlaylistBatchActions.tsx`
|
|
- **Mutation**: `deleteMutation.mutateAsync()` (loop)
|
|
- **Button**: "Delete Selected" button (line ~107)
|
|
- **Loading State**: ❌ Missing
|
|
- **Priority**: HIGH
|
|
- **Notes**: Batch delete operation, should show loading with progress
|
|
|
|
## Statistics
|
|
|
|
- **Total Mutation Buttons**: 28
|
|
- **With Loading States**: 5 (18%)
|
|
- **Missing Loading States**: 23 (82%)
|
|
- **High Priority**: 8
|
|
- **Medium Priority**: 11
|
|
- **Low Priority**: 4
|
|
|
|
## Priority Breakdown
|
|
|
|
### High Priority (8 buttons)
|
|
1. Create Playlist (PlaylistForm)
|
|
2. Update Playlist (PlaylistForm)
|
|
3. Add Track to Playlist (Modal)
|
|
4. Create Comment
|
|
5. Create Reply
|
|
6. Update Comment
|
|
7. Add Collaborator
|
|
8. Delete Multiple Playlists (Batch)
|
|
|
|
### Medium Priority (11 buttons)
|
|
1. Reorder Playlist Tracks
|
|
2. Delete Comment
|
|
3. Remove Collaborator
|
|
4. Update Collaborator Permission
|
|
5. Create Share Link (SharePlaylistModal)
|
|
6. Create Share Link (Batch)
|
|
7. Create Share Link (Generic)
|
|
8. Revoke Share Link
|
|
9. Mark All Notifications as Read (Menu)
|
|
10. Mark All Notifications as Read (Page)
|
|
11. Leave Room / Delete Room
|
|
|
|
### Low Priority (4 buttons)
|
|
1. Mark Notification as Read (Menu)
|
|
2. Mark Notification as Read (Page)
|
|
|
|
## Patterns Identified
|
|
|
|
### Already Implemented (Good Examples)
|
|
1. **LikeButton** (`LikeButton.tsx`): Uses `isPending`, shows `Loader2` spinner, disables button
|
|
2. **PlaylistFollowButton** (`PlaylistFollowButton.tsx`): Uses `isPending`, shows `Loader2` spinner, disables button
|
|
3. **PlaylistActions** (`PlaylistActions.tsx`): Uses `isPending`, shows `Loader2` spinner, disables button
|
|
4. **LibraryPage addToPlaylist** (`LibraryPage.tsx`): Uses `isPending`, shows `Loader2` spinner, disables menu items
|
|
|
|
### Missing Patterns
|
|
1. Form submission buttons (PlaylistForm, CommentSection, CommentThread)
|
|
2. Modal action buttons (AddCollaboratorModal, AddTrackToPlaylistModal)
|
|
3. Batch operation buttons (PlaylistBatchActions)
|
|
4. Auto-triggered mutations (SharePlaylistModal, NotificationMenu)
|
|
|
|
## Recommendations
|
|
|
|
1. **Follow existing pattern**: Use `mutation.isPending` to check loading state
|
|
2. **Use Loader2 spinner**: Import from `lucide-react`, show during loading
|
|
3. **Disable buttons**: Set `disabled={mutation.isPending}` on buttons
|
|
4. **Show loading text**: Replace or append loading text during mutation
|
|
5. **Batch operations**: Show progress indicator for batch operations
|
|
6. **Auto-triggered**: Show subtle loading indicator in UI (e.g., modal spinner)
|
|
|
|
## Next Steps
|
|
|
|
1. Action 8.3.1.3: Add loading states to all high-priority mutation buttons
|
|
2. Action 8.3.1.4: Create Spinner component (if needed, though Loader2 is already used)
|
|
3. Action 8.3.1.5: Use Spinner in loading states (standardize on Loader2 or create Spinner component)
|