Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/SpotifyPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function SpotifyPlayer({
// Play from calculated position
play(spotifyUri, startPosition);
}
}, [currentTrack?.id, isReady, isPremium, play, playbackState, playbackMode]);
}, [currentTrack?.id, isReady, isPremium, play, playbackState, playbackMode, currentTrack]);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the entire currentTrack object to the dependency array is redundant and inefficient since currentTrack?.id is already included. The effect should only re-run when the track ID changes, not when other properties of the currentTrack object change. This could cause unnecessary re-renders and re-executions of the effect. Remove currentTrack from the dependency array.

Suggested change
}, [currentTrack?.id, isReady, isPremium, play, playbackState, playbackMode, currentTrack]);
}, [currentTrack?.id, isReady, isPremium, play, playbackState, playbackMode]);

Copilot uses AI. Check for mistakes.

// Track ended - call onTrackEnd
useEffect(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/SpotifyPlaylistSync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import { ExternalLink, Music, Sparkles, Loader2 } from 'lucide-react';
import { Button } from './ui/button';
import { useAuth } from '@/contexts/AuthContext';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
import { Room } from '@/types/wejay';

interface SpotifyPlaylistSyncProps {
Expand All @@ -22,7 +22,7 @@ export function SpotifyPlaylistSync({ playlistUrl, hasTracksInQueue, room }: Spo
if (playlistUrl && !url) {
setUrl(playlistUrl);
}
}, [playlistUrl]);
}, [playlistUrl, url]);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding url to the dependency array is problematic because this effect sets url via setUrl(playlistUrl). While the condition if (playlistUrl && !url) prevents infinite loops, including url in dependencies means the effect will re-run whenever url changes for any reason (e.g., when a playlist is created in handleCreatePlaylist), potentially causing unexpected behavior. The dependency array should only include playlistUrl since that's the external prop being tracked.

Suggested change
}, [playlistUrl, url]);
}, [playlistUrl]);

Copilot uses AI. Check for mistakes.

const handleCreatePlaylist = async () => {
console.log('[SpotifyPlaylistSync] handleCreatePlaylist called');
Expand Down
23 changes: 23 additions & 0 deletions src/components/ui/badge-variants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { cva, type VariantProps } from "class-variance-authority";

export const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
);

export type BadgeVariants = VariantProps<typeof badgeVariants>;
23 changes: 3 additions & 20 deletions src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,12 @@
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { badgeVariants, type BadgeVariants } from "./badge-variants";

import { cn } from "@/lib/utils";

const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);

export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, BadgeVariants {}

function Badge({ className, variant, ...props }: BadgeProps) {
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
}

export { Badge, badgeVariants };
export { Badge };
32 changes: 32 additions & 0 deletions src/components/ui/button-variants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { cva, type VariantProps } from "class-variance-authority";

export const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);

export type ButtonVariants = VariantProps<typeof buttonVariants>;
Comment on lines +1 to +32
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The button-variants.ts file was created but is not being used anywhere. The button.tsx file still defines its own buttonVariants and exports it (which is needed by alert-dialog.tsx, calendar.tsx, and pagination.tsx). Additionally, the variant definitions are out of sync - button.tsx includes gap-2 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 in the base classes (line 8), but button-variants.ts does not (line 4). Either complete the refactoring by updating button.tsx to import from this file, or remove this unused file to avoid confusion and maintenance issues.

Suggested change
import { cva, type VariantProps } from "class-variance-authority";
export const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
export type ButtonVariants = VariantProps<typeof buttonVariants>;

Copilot uses AI. Check for mistakes.
32 changes: 3 additions & 29 deletions src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,12 @@
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { buttonVariants, type ButtonVariants } from "./button-variants";

import { cn } from "@/lib/utils";

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
ButtonVariants {
asChild?: boolean;
}

Expand All @@ -44,4 +18,4 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
);
Button.displayName = "Button";

export { Button, buttonVariants };
export { Button };
4 changes: 2 additions & 2 deletions src/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useTheme } from "next-themes";
import { Toaster as Sonner, toast } from "sonner";
import { Toaster as Sonner } from "sonner";

type ToasterProps = React.ComponentProps<typeof Sonner>;

Expand All @@ -24,4 +24,4 @@ const Toaster = ({ ...props }: ToasterProps) => {
);
};

export { Toaster, toast };
export { Toaster };
25 changes: 25 additions & 0 deletions src/components/ui/toggle-variants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { cva, type VariantProps } from "class-variance-authority";

export const toggleVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
{
variants: {
variant: {
default: "bg-transparent",
outline:
"border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
},
size: {
default: "h-10 px-3",
sm: "h-9 px-2.5",
lg: "h-11 px-5",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);

export type ToggleVariants = VariantProps<typeof toggleVariants>;
27 changes: 3 additions & 24 deletions src/components/ui/toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,16 @@
import * as React from "react";
import * as TogglePrimitive from "@radix-ui/react-toggle";
import { cva, type VariantProps } from "class-variance-authority";
import { toggleVariants, type ToggleVariants } from "./toggle-variants";

import { cn } from "@/lib/utils";

const toggleVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
{
variants: {
variant: {
default: "bg-transparent",
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
},
size: {
default: "h-10 px-3",
sm: "h-9 px-2.5",
lg: "h-11 px-5",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
},
);

const Toggle = React.forwardRef<
React.ElementRef<typeof TogglePrimitive.Root>,
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & VariantProps<typeof toggleVariants>
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> & ToggleVariants
>(({ className, variant, size, ...props }, ref) => (
<TogglePrimitive.Root ref={ref} className={cn(toggleVariants({ variant, size, className }))} {...props} />
));

Toggle.displayName = TogglePrimitive.Root.displayName;

export { Toggle, toggleVariants };
export { Toggle };
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toggleVariants export was removed, but it's still being imported by src/components/ui/toggle-group.tsx on line 6. This will cause a build error. Either re-export toggleVariants here, or update toggle-group.tsx to import from ./toggle-variants instead.

Suggested change
export { Toggle };
export { Toggle };
export { toggleVariants, ToggleVariants };

Copilot uses AI. Check for mistakes.
2 changes: 1 addition & 1 deletion src/hooks/useSocket.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState, useCallback, useRef } from 'react';
import { useAuth } from '@/contexts/AuthContext';
import { Room, Track, SpotifyUser } from '@/types/wejay';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import toast.

Suggested change
import { toast } from '@/lib/toast';

Copilot uses AI. Check for mistakes.
import { io, Socket } from 'socket.io-client';

interface SocketState {
Expand Down
3 changes: 3 additions & 0 deletions src/lib/toast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { toast as sonnerToast } from 'sonner';

export const toast = sonnerToast;
2 changes: 1 addition & 1 deletion src/pages/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AIRecommendations } from "@/components/AIRecommendations";
import { SpotifyPlaylistSync } from "@/components/SpotifyPlaylistSync";
import { arrangeTracks } from "@/lib/dhondt";
import { Track, SearchTrack } from "@/types/wejay";
import { toast } from "sonner";
import { toast } from '@/lib/toast';
import { Heart, Search, Loader2, LogOut } from "lucide-react";
import { useSpotifySearch } from "@/hooks/useSpotifySearch";
import { useSpotifyRecommendations } from "@/hooks/useSpotifyRecommendations";
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useAuth } from '@/contexts/AuthContext';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Loader2, Music, Users, Sparkles } from 'lucide-react';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';

const Login = () => {
const { user, isLoading, login, isAuthenticated, isPremium } = useAuth();
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Rooms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Plus, Users, Copy, Check, Loader2 } from 'lucide-react';
import { Room } from '@/types/wejay';
import { toast } from 'sonner';
import { toast } from '@/lib/toast';

const Rooms = () => {
const { user, isAuthenticated, logout } = useAuth();
Expand Down
Loading