127 lines
3.9 KiB
TypeScript
127 lines
3.9 KiB
TypeScript
import { createRouter, createRootRoute, createRoute, lazyRouteComponent } from "@tanstack/react-router";
|
|
import Root from "./routes/root";
|
|
import apiClient from "./lib/api-client";
|
|
import type { SearchResult, SearchApiResponse } from "./types/spotify";
|
|
import { isValidSearchResult } from "./types/spotify";
|
|
|
|
// Lazy load route components for code splitting
|
|
const Album = lazyRouteComponent(() => import("./routes/album").then(m => ({ default: m.Album })));
|
|
const Artist = lazyRouteComponent(() => import("./routes/artist").then(m => ({ default: m.Artist })));
|
|
const Track = lazyRouteComponent(() => import("./routes/track").then(m => ({ default: m.Track })));
|
|
const Home = lazyRouteComponent(() => import("./routes/home").then(m => ({ default: m.Home })));
|
|
const Config = lazyRouteComponent(() => import("./routes/config").then(m => ({ default: m.Config })));
|
|
const Playlist = lazyRouteComponent(() => import("./routes/playlist").then(m => ({ default: m.Playlist })));
|
|
const History = lazyRouteComponent(() => import("./routes/history").then(m => ({ default: m.History })));
|
|
const Watchlist = lazyRouteComponent(() => import("./routes/watchlist").then(m => ({ default: m.Watchlist })));
|
|
|
|
const rootRoute = createRootRoute({
|
|
component: Root,
|
|
});
|
|
|
|
export const indexRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/",
|
|
component: Home,
|
|
validateSearch: (
|
|
search: Record<string, unknown>,
|
|
): { q?: string; type?: "track" | "album" | "artist" | "playlist" } => {
|
|
return {
|
|
q: search.q as string | undefined,
|
|
type: search.type as "track" | "album" | "artist" | "playlist" | undefined,
|
|
};
|
|
},
|
|
loaderDeps: ({ search: { q, type } }) => ({ q, type: type || "track" }),
|
|
loader: async ({ deps: { q, type } }) => {
|
|
if (!q || q.length < 3) return { items: [] };
|
|
|
|
const spotifyUrlRegex = /https:\/\/open\.spotify\.com\/(?:[a-zA-Z0-9-]+\/)*(playlist|album|artist|track)\/([a-zA-Z0-9]+)/;
|
|
const match = q.match(spotifyUrlRegex);
|
|
|
|
if (match) {
|
|
const [, urlType, id] = match;
|
|
const response = await apiClient.get<SearchResult>(`/${urlType}/info?id=${id}`);
|
|
return { items: [{ ...response.data, model: urlType as "track" | "album" | "artist" | "playlist" }] };
|
|
}
|
|
|
|
const response = await apiClient.get<SearchApiResponse>(`/search?q=${q}&search_type=${type}&limit=50`);
|
|
|
|
// Filter out null values and add the model property
|
|
const validResults = response.data.items
|
|
.filter(isValidSearchResult)
|
|
.map((item) => ({
|
|
...item,
|
|
model: type,
|
|
}));
|
|
|
|
return { items: validResults };
|
|
},
|
|
gcTime: 5 * 60 * 1000, // 5 minutes
|
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
});
|
|
|
|
const albumRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/album/$albumId",
|
|
component: Album,
|
|
});
|
|
|
|
const artistRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/artist/$artistId",
|
|
component: Artist,
|
|
});
|
|
|
|
const trackRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/track/$trackId",
|
|
component: Track,
|
|
});
|
|
|
|
const configRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/config",
|
|
component: Config,
|
|
validateSearch: (search: Record<string, unknown>): { tab?: string } => {
|
|
return {
|
|
tab: typeof search.tab === "string" ? search.tab : undefined,
|
|
};
|
|
},
|
|
});
|
|
|
|
const playlistRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/playlist/$playlistId",
|
|
component: Playlist,
|
|
});
|
|
|
|
const historyRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/history",
|
|
component: History,
|
|
});
|
|
|
|
const watchlistRoute = createRoute({
|
|
getParentRoute: () => rootRoute,
|
|
path: "/watchlist",
|
|
component: Watchlist,
|
|
});
|
|
|
|
const routeTree = rootRoute.addChildren([
|
|
indexRoute,
|
|
albumRoute,
|
|
artistRoute,
|
|
trackRoute,
|
|
configRoute,
|
|
playlistRoute,
|
|
historyRoute,
|
|
watchlistRoute,
|
|
]);
|
|
|
|
export const router = createRouter({ routeTree });
|
|
|
|
declare module "@tanstack/react-router" {
|
|
interface Register {
|
|
router: typeof router;
|
|
}
|
|
}
|