Skip to content

Commit f0a229a

Browse files
committed
✅ Address playlist review feedback
1 parent b9a34f5 commit f0a229a

File tree

3 files changed

+46
-29
lines changed

3 files changed

+46
-29
lines changed

app/entities/video/ui/VideoCard.tsx

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,6 @@ export function VideoCard({ video, onQuickView, onTagClick }: VideoCardProps) {
5555
<Clock className="h-3 w-3" />
5656
{formatDuration(video.duration)}
5757
</div>
58-
59-
{hasActions && (
60-
<div className="absolute top-2 right-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100">
61-
<DropdownMenu>
62-
<DropdownMenuTrigger asChild>
63-
<Button
64-
variant="secondary"
65-
size="sm"
66-
className="h-8 w-8 p-0 rounded-full bg-black/60 hover:bg-black/80 text-white border-0"
67-
>
68-
<MoreVertical className="h-4 w-4" />
69-
</Button>
70-
</DropdownMenuTrigger>
71-
<DropdownMenuContent align="end" className="w-48">
72-
{onQuickView && (
73-
<DropdownMenuItem onClick={handleQuickView}>
74-
<Eye className="mr-2 h-4 w-4" />
75-
Quick view
76-
</DropdownMenuItem>
77-
)}
78-
</DropdownMenuContent>
79-
</DropdownMenu>
80-
</div>
81-
)}
8258
</AspectRatio>
8359
</div>
8460

@@ -94,6 +70,31 @@ export function VideoCard({ video, onQuickView, onTagClick }: VideoCardProps) {
9470
</div>
9571
</Link>
9672

73+
{hasActions && (
74+
<div className="absolute top-2 right-2 opacity-0 transition-opacity duration-200 group-hover:opacity-100 group-focus-within:opacity-100 pointer-events-none">
75+
<DropdownMenu>
76+
<DropdownMenuTrigger asChild>
77+
<Button
78+
variant="secondary"
79+
size="sm"
80+
aria-label="Open actions menu"
81+
className="h-8 w-8 p-0 rounded-full bg-black/60 hover:bg-black/80 text-white border-0 pointer-events-auto"
82+
>
83+
<MoreVertical className="h-4 w-4" />
84+
</Button>
85+
</DropdownMenuTrigger>
86+
<DropdownMenuContent align="end" className="w-48">
87+
{onQuickView && (
88+
<DropdownMenuItem onClick={handleQuickView}>
89+
<Eye className="mr-2 h-4 w-4" />
90+
Quick view
91+
</DropdownMenuItem>
92+
)}
93+
</DropdownMenuContent>
94+
</DropdownMenu>
95+
</div>
96+
)}
97+
9798
<div className="flex flex-wrap gap-1 mt-2">
9899
{video.tags.slice(0, 3).map(tag => (
99100
<Badge

app/features/playlist/add-to-playlist/model/useAddToPlaylistDialog.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ export function useAddToPlaylistDialog({ open, video }: UseAddToPlaylistDialogOp
9393
const rawPlaylists = (Array.isArray(data.playlists) ? data.playlists : []) as RawPlaylist[];
9494

9595
const ownedPlaylists = rawPlaylists
96-
.filter(raw => String(raw.ownerId ?? '') === user.id)
96+
.filter((raw) => {
97+
const rawId = String(raw.id ?? '').trim();
98+
return rawId.length > 0 && String(raw.ownerId ?? '') === user.id;
99+
})
97100
.map(raw => toSummary(raw, video.id));
98101

99102
setPlaylists(ownedPlaylists);
@@ -127,6 +130,14 @@ export function useAddToPlaylistDialog({ open, video }: UseAddToPlaylistDialogOp
127130
const handleAdd = useCallback(async (playlistId: string) => {
128131
if (!video) return;
129132

133+
const currentPlaylist = playlists.find(playlist => playlist.id === playlistId);
134+
if (!currentPlaylist) return;
135+
136+
const currentState = actionStates[playlistId];
137+
if (currentState === 'loading' || currentPlaylist.containsVideo) {
138+
return;
139+
}
140+
130141
setActionStates(prev => ({ ...prev, [playlistId]: 'loading' }));
131142

132143
try {
@@ -161,7 +172,7 @@ export function useAddToPlaylistDialog({ open, video }: UseAddToPlaylistDialogOp
161172
setActionStates(prev => ({ ...prev, [playlistId]: 'error' }));
162173
setError(addError instanceof Error ? addError.message : 'Failed to add video to playlist');
163174
}
164-
}, [video]);
175+
}, [video, playlists, actionStates]);
165176

166177
const refresh = useCallback(async () => {
167178
await loadPlaylists();

app/features/playlist/add-to-playlist/ui/AddToPlaylistDialog.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,16 @@ export function AddToPlaylistDialog({ video, open, onOpenChange }: AddToPlaylist
8787
<Button
8888
variant={isAdded ? 'outline' : 'secondary'}
8989
size="sm"
90-
disabled={isAdded && !isErrored}
90+
disabled={isBusy || (isAdded && !isErrored)}
9191
className="w-24 justify-center"
92-
onClick={() => handleAdd(playlist.id)}
92+
onClick={() => {
93+
if (isBusy) return;
94+
void handleAdd(playlist.id);
95+
}}
9396
>
94-
{isBusy ? <Loader2 className="h-4 w-4 animate-spin" /> : buttonLabel}
97+
{isBusy
98+
? <Loader2 className="h-4 w-4 animate-spin" aria-hidden="true" />
99+
: buttonLabel}
95100
</Button>
96101
</div>
97102
);

0 commit comments

Comments
 (0)