diff --git a/apps/native/src/app/title/[id].tsx b/apps/native/src/app/title/[id].tsx index 0fd13ef..a652810 100644 --- a/apps/native/src/app/title/[id].tsx +++ b/apps/native/src/app/title/[id].tsx @@ -104,17 +104,6 @@ export default function TitleDetailScreen() { }), ); - const watchAll = useMutation( - orpc.titles.watchAll.mutationOptions({ - onSuccess: () => { - toast.success("Marked all episodes as watched"); - queryClient.invalidateQueries({ queryKey: orpc.titles.key() }); - queryClient.invalidateQueries({ queryKey: orpc.dashboard.key() }); - }, - onError: () => toast.error("Failed to mark all episodes as watched"), - }), - ); - const quickAddMutation = useMutation( orpc.titles.quickAdd.mutationOptions({ onSuccess: () => { @@ -193,10 +182,10 @@ export default function TitleDetailScreen() { {/* Actions skeleton */} - - - - + + + + {/* Overview skeleton */} @@ -415,57 +404,52 @@ export default function TitleDetailScreen() { entering={FadeInDown.duration(300).delay(200)} className="mt-4 px-4" > - { - if (status === null) { - updateStatus.mutate({ id, status: null }); - } else if (status === "watchlist") { - quickAddMutation.mutate({ - tmdbId: title.tmdbId, - type: title.type, - }); - } else if (status === "completed" && title.type === "movie") { - watchMovie.mutate({ id }); - } else if (status === "completed" && title.type === "tv") { - watchAll.mutate({ id }); - } else { - updateStatus.mutate({ id, status }); + + { + if (status === "watchlist") { + quickAddMutation.mutate({ + tmdbId: title.tmdbId, + type: title.type, + }); + } else { + updateStatus.mutate({ id, status: null }); + } + }} + isPending={ + updateStatus.isPending || + quickAddMutation.isPending || + watchMovie.isPending } - }} - isPending={ - updateStatus.isPending || - quickAddMutation.isPending || - watchMovie.isPending || - watchAll.isPending - } - /> - - - updateRating.mutate({ id, stars })} - accentColor={titleAccent} /> {title.type === "movie" && ( watchMovie.mutate({ id })} disabled={watchMovie.isPending} - className="flex-row items-center gap-1.5 rounded-full bg-title-accent px-4 py-2" + className="flex-row items-center gap-1.5 rounded-lg bg-title-accent px-4 py-2" > {watchMovie.isPending ? ( ) : ( <> - + Mark Watched )} )} + + + + updateRating.mutate({ id, stars })} + accentColor={titleAccent} + /> diff --git a/apps/native/src/components/titles/status-action-button.tsx b/apps/native/src/components/titles/status-action-button.tsx index 5660039..6b20f03 100644 --- a/apps/native/src/components/titles/status-action-button.tsx +++ b/apps/native/src/components/titles/status-action-button.tsx @@ -1,15 +1,33 @@ import { - IconBookmark, - IconCircleCheck, - IconPlayerPlay, + IconCheck, + IconPlayerPlayFilled, + IconPlus, } from "@tabler/icons-react-native"; -import { Pressable, View } from "react-native"; +import { Pressable } from "react-native"; import { useCSSVariable } from "uniwind"; import { Text } from "@/components/ui/text"; import * as Haptics from "@/utils/haptics"; type TitleStatus = "watchlist" | "in_progress" | "completed"; +const watchingStyle = { + label: "Watching", + Icon: IconPlayerPlayFilled, + bgClass: "bg-title-accent/10 border-title-accent/20", + textClass: "text-title-accent", +}; + +const statusConfig = { + watchlist: watchingStyle, + in_progress: watchingStyle, + completed: { + label: "Completed", + Icon: IconCheck, + bgClass: "bg-status-completed/10 border-status-completed/20", + textClass: "text-status-completed", + }, +} as const; + export function StatusActionButton({ currentStatus, onStatusChange, @@ -19,46 +37,49 @@ export function StatusActionButton({ onStatusChange: (status: TitleStatus | null) => void; isPending: boolean; }) { - const statuses: Array<{ - status: TitleStatus; - label: string; - Icon: typeof IconBookmark; - }> = [ - { status: "watchlist", label: "Watchlist", Icon: IconBookmark }, - { status: "in_progress", label: "Watching", Icon: IconPlayerPlay }, - { status: "completed", label: "Completed", Icon: IconCircleCheck }, - ]; + const [titleAccent, completedColor] = useCSSVariable([ + "--color-title-accent", + "--color-status-completed", + ]) as [string, string]; - const primaryColor = useCSSVariable("--color-title-accent") as string; - const mutedFgColor = useCSSVariable("--color-muted-foreground") as string; + const config = currentStatus + ? statusConfig[currentStatus as keyof typeof statusConfig] + : null; + + if (!config) { + return ( + { + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); + onStatusChange("watchlist"); + }} + disabled={isPending} + className="flex-row items-center gap-1.5 rounded-lg border border-title-accent/20 bg-title-accent/10 px-4 py-2" + > + + + Watchlist + + + ); + } + + const iconColor = + currentStatus === "completed" ? completedColor : titleAccent; return ( - - {statuses.map(({ status, label, Icon }) => { - const isActive = currentStatus === status; - return ( - { - Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); - onStatusChange(isActive ? null : status); - }} - disabled={isPending} - className={`flex-row items-center gap-1.5 rounded-full border px-3 py-2 ${ - isActive - ? "border-title-accent bg-title-accent/10" - : "border-border bg-card" - }`} - > - - - {label} - - - ); - })} - + { + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); + onStatusChange(null); + }} + disabled={isPending} + className={`flex-row items-center gap-1.5 rounded-lg border px-4 py-2 ${config.bgClass}`} + > + + + {config.label} + + ); }