import { useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "@tanstack/react-router"; import { toast } from "sonner"; import { LOCATIONS } from "@/client/features/keywords/locations"; import { AlertTriangle, Archive, Globe, Plus, ChevronRight, } from "lucide-react"; import { getRankTrackingConfigSummaries, updateRankTrackingConfig, } from "@/serverFunctions/rank-tracking"; import { devicesLabel as getDevicesLabel, scheduleLabel as getScheduleLabel, } from "@/shared/rank-tracking"; import { Modal } from "@/client/components/Modal"; type ConfigSummary = Awaited< ReturnType >[number]; export function RankTrackingDomainList({ projectId, onAddDomain, }: { projectId: string; onAddDomain: () => void; }) { const navigate = useNavigate(); const queryClient = useQueryClient(); const [archiveTarget, setArchiveTarget] = useState( null, ); const { data: summaries } = useQuery({ queryKey: ["rankTrackingConfigSummaries", projectId], queryFn: () => getRankTrackingConfigSummaries({ data: { projectId } }), }); const archiveMutation = useMutation({ mutationFn: (configId: string) => updateRankTrackingConfig({ data: { projectId, configId, isActive: false }, }), onSuccess: () => { setArchiveTarget(null); void queryClient.invalidateQueries({ queryKey: ["rankTrackingConfigSummaries", projectId], }); void queryClient.invalidateQueries({ queryKey: ["rankTrackingConfigs", projectId], }); toast.success("Domain archived"); }, }); return (

Tracked Domains

{(summaries ?? []).length === 0 ? (

No tracked domains yet

Add a domain to start monitoring keyword rankings over time.

) : ( (summaries ?? []).map((summary) => ( void navigate({ to: "/p/$projectId/rank-tracking/$configId", params: { projectId, configId: summary.id }, }) } onArchive={() => setArchiveTarget(summary)} /> )) )}
{archiveTarget && (

Archive {archiveTarget.domain}?

Scheduled checks will stop and this domain will be hidden from the list. Ranking history is preserved.

)}
); } function DomainRow({ summary, onClick, onArchive, }: { summary: ConfigSummary; onClick: () => void; onArchive: () => void; }) { const dl = getDevicesLabel(summary.devices); const sl = getScheduleLabel(summary.scheduleInterval); return (
{ if (e.key === "Enter" || e.key === " ") { e.preventDefault(); onClick(); } }} >

{summary.domain}

{LOCATIONS[summary.locationCode] ?? "US"} · {dl} · {sl} {summary.lastRunCompletedAt && ( <> {" "} · Last:{" "} {new Date(summary.lastRunCompletedAt).toLocaleDateString()} )}

{summary.lastSkipReason === "insufficient_credits" && (

Scheduled check skipped — insufficient credits

)}
{summary.keywordCount > 0 && (

Keywords

{summary.keywordCount}

)}
); }