mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 01:35:39 -04:00
Replace tmdb-* URL routing with resolveTitle/resolvePerson server actions
- Add `resolveTitle` and `resolvePerson` server actions that import
from TMDB and return the internal DB id
- Remove `tmdb-{id}-{type}` URL pattern and server-side redirect logic
from TitleDetailPage and PersonDetailPage
- Rename `importTitle` → `getOrFetchTitleByTmdbId`; add `getOrFetchTitle`
combining fetch + children lookup
- Update HeroBanner, TitleCard, and CommandPalette to call resolve
actions client-side before pushing to router
- Batch availability offer inserts into a single transaction
This commit is contained in:
@@ -36,6 +36,8 @@ import { Kbd } from "@/components/ui/kbd";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { useDebounce } from "@/hooks/use-debounce";
|
||||
import { useSearch } from "@/hooks/use-search";
|
||||
import { resolvePerson } from "@/lib/actions/people";
|
||||
import { resolveTitle } from "@/lib/actions/titles";
|
||||
import {
|
||||
commandPaletteOpenAtom,
|
||||
helpOpenAtom,
|
||||
@@ -118,9 +120,13 @@ export function CommandPalette() {
|
||||
setCommandPaletteOpen(false);
|
||||
progress.start();
|
||||
if (result.type === "person") {
|
||||
router.push(`/people/tmdb-${result.tmdbId}`);
|
||||
void resolvePerson(result.tmdbId).then((id) => {
|
||||
if (id) router.push(`/people/${id}`);
|
||||
});
|
||||
} else {
|
||||
router.push(`/titles/tmdb-${result.tmdbId}-${result.type}`);
|
||||
void resolveTitle(result.tmdbId, result.type).then((id) => {
|
||||
if (id) router.push(`/titles/${id}`);
|
||||
});
|
||||
}
|
||||
},
|
||||
[router, setCommandPaletteOpen, progress],
|
||||
|
||||
+47
-23
@@ -14,13 +14,16 @@ import {
|
||||
import { type MotionStyle, type MotionValue, motion } from "motion/react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState, useTransition } from "react";
|
||||
import { useProgress } from "@/components/navigation-progress";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { useTiltEffect } from "@/hooks/use-tilt-effect";
|
||||
import { resolveTitle } from "@/lib/actions/titles";
|
||||
import { quickAddToWatchlist } from "@/lib/actions/watchlist";
|
||||
|
||||
type TitleStatus = "watchlist" | "in_progress" | "completed";
|
||||
@@ -280,8 +283,30 @@ export function TitleCard({
|
||||
userStatus,
|
||||
episodeProgress,
|
||||
}: TitleCardProps) {
|
||||
const href = id ? `/titles/${id}` : `/titles/tmdb-${tmdbId}-${type}`;
|
||||
const tilt = useTiltEffect();
|
||||
const router = useRouter();
|
||||
const progress = useProgress();
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
const cardContent = (
|
||||
<motion.div ref={tilt.ref} style={tilt.containerStyle} {...tilt.handlers}>
|
||||
<CardInner
|
||||
title={title}
|
||||
type={type}
|
||||
posterPath={posterPath}
|
||||
releaseDate={releaseDate}
|
||||
voteAverage={voteAverage}
|
||||
userStatus={userStatus}
|
||||
episodeProgress={episodeProgress}
|
||||
tiltStyles={{
|
||||
imageStyle: tilt.imageStyle,
|
||||
glareBackground: tilt.glareBackground,
|
||||
glareOpacity: tilt.glareOpacity,
|
||||
}}
|
||||
/>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="group relative">
|
||||
<QuickAddButton
|
||||
@@ -289,28 +314,27 @@ export function TitleCard({
|
||||
type={type as "movie" | "tv"}
|
||||
userStatus={userStatus}
|
||||
/>
|
||||
<Link href={href}>
|
||||
<motion.div
|
||||
ref={tilt.ref}
|
||||
style={tilt.containerStyle}
|
||||
{...tilt.handlers}
|
||||
{id ? (
|
||||
<Link href={`/titles/${id}`}>{cardContent}</Link>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
disabled={isPending}
|
||||
className={`w-full text-left ${isPending ? "pointer-events-none opacity-70" : "cursor-pointer"}`}
|
||||
onClick={() => {
|
||||
progress.start();
|
||||
startTransition(async () => {
|
||||
const resolvedId = await resolveTitle(
|
||||
tmdbId,
|
||||
type as "movie" | "tv",
|
||||
);
|
||||
if (resolvedId) router.push(`/titles/${resolvedId}`);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<CardInner
|
||||
title={title}
|
||||
type={type}
|
||||
posterPath={posterPath}
|
||||
releaseDate={releaseDate}
|
||||
voteAverage={voteAverage}
|
||||
userStatus={userStatus}
|
||||
episodeProgress={episodeProgress}
|
||||
tiltStyles={{
|
||||
imageStyle: tilt.imageStyle,
|
||||
glareBackground: tilt.glareBackground,
|
||||
glareOpacity: tilt.glareOpacity,
|
||||
}}
|
||||
/>
|
||||
</motion.div>
|
||||
</Link>
|
||||
{cardContent}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user