import type React from "react";
import type { Layout } from "react-resizable-panels";
import type { BuilderLayout } from "./-store/sidebar";
import { useSuspenseQuery } from "@tanstack/react-query";
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
import Cookies from "js-cookie";
import { useEffect, useRef } from "react";
import { usePanelRef } from "react-resizable-panels";
import { ResizableGroup, ResizablePanel, ResizableSeparator } from "@reactive-resume/ui/components/resizable";
import {
useBuilderResumeUpdateSubscription,
useInitializeResumeStore,
useMergeResumeMetadata,
useResumeCleanup,
useResumeStore,
} from "@/features/resume/builder/draft";
import { useIsMobile } from "@/hooks/use-mobile";
import { orpc } from "@/libs/orpc/client";
import { createNoindexFollowMeta } from "@/libs/seo";
import { BuilderHeader } from "./-components/header";
import { BuilderSidebarLeft } from "./-sidebar/left";
import { BuilderSidebarRight } from "./-sidebar/right";
import {
BUILDER_LAYOUT_COOKIE_NAME,
DEFAULT_BUILDER_LAYOUT,
mapPanelLayoutToBuilderLayout,
parseBuilderLayoutCookie,
useBuilderSidebar,
useBuilderSidebarStore,
} from "./-store/sidebar";
export const Route = createFileRoute("/builder/$resumeId")({
component: RouteComponent,
beforeLoad: async ({ context }) => {
if (!context.session) throw redirect({ to: "/auth/login", replace: true });
return { session: context.session };
},
loader: async ({ params, context }) => {
const [layout, resume] = await Promise.all([
getBuilderLayout(),
context.queryClient.ensureQueryData(orpc.resume.getById.queryOptions({ input: { id: params.resumeId } })),
]);
return { layout, name: resume.name };
},
head: ({ loaderData }) => ({
meta: loaderData
? [{ title: `${loaderData.name} - Reactive Resume` }, createNoindexFollowMeta()]
: [createNoindexFollowMeta()],
}),
});
function RouteComponent() {
const { layout: initialLayout } = Route.useLoaderData();
const { resumeId } = Route.useParams();
const { data: resume } = useSuspenseQuery(orpc.resume.getById.queryOptions({ input: { id: resumeId } }));
const initializeResumeStore = useInitializeResumeStore();
const mergeResumeMetadata = useMergeResumeMetadata();
const isReady = useResumeStore((state) => state.isReady);
const initializedResumeId = useResumeStore((state) => state.resumeId);
const isInitialized = isReady && initializedResumeId === resumeId;
useResumeCleanup();
useBuilderResumeUpdateSubscription();
useEffect(() => {
if (isInitialized) return;
initializeResumeStore(resume);
}, [initializeResumeStore, isInitialized, resume]);
useEffect(() => {
mergeResumeMetadata(resume);
}, [
mergeResumeMetadata,
resume.id,
resume.name,
resume.slug,
resume.tags,
resume.isLocked,
resume.isPublic,
resume.hasPassword,
resume.updatedAt,
resume,
]);
if (!isInitialized) return null;
return