import { useCallback, useEffect, useMemo, useRef } from "react"; import { useAppendedPages } from "./pages"; import type { CloudJobsMoverPayload, CloudJobsPosting, CloudJobsSummaryPayload } from "../../../api-client/types"; import { Badge, Button, DataTableStackView, DataTableView, EmptyState, PaneStatusBody, SectionHeading, StaticChartSurface, Tabs, usePaneFooter, usePaneNoticeFooter, useTableLoadMore, type DataTableCell, type PaneFooterSegment, } from "../../../components"; import { resolveChartPalette } from "../../../components/chart/core/palette"; import { useAsyncResource } from "../../../react/async-resource"; import { useShortcut } from "../../../react/input"; import { blendHex, colors } from "../../../theme/colors"; import { Box, Text, TextAttributes, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui"; import { formatCompact, formatNumber } from "../../../utils/format"; import { isPlainKey } from "../../../utils/keyboard"; import { SignInWall } from "../cloud/auth-actions"; import { useCloudPlanAction, useCloudUpgradeAction } from "../shared/cloud-upgrade"; import { usePlanAccess } from "../shared/plan-access"; import { usePluginPaneState, usePluginTickerActions } from "../../runtime"; import { fetchJobs, fetchJobsMovers, fetchJobsPostings, type JobsCompanyState } from "./client"; import { DEFAULT_MOVER_SORT, DEFAULT_POSTING_SORT, buildAgeBars, buildMoverColumns, buildMoverRows, buildPostingColumns, buildPostingRows, buildShareBars, changeTone, formatChange, formatCollectedAgo, formatSalaryRange, formatShare, historyChartPoints, moversHaveWeekHistory, nextMoverSort, nextPostingSort, sortMoverRows, sortPostingRows, type MoverColumn, type MoverRow, type MoverSort, type PostingColumn, type PostingRow, type PostingSort, } from "./model"; import { ShareBars } from "./share-bars"; import { usePaneTickerIdentity } from "../../../state/hooks/pane-ticker"; export const JOBS_PANE_ID = "jobs"; const PENDING_POLL_MS = 20_000; const POSTINGS_PAGE = 100; const MOVERS_PAGE = 200; type DetailTab = "roles" | "locations" | "seniority" | "salary"; function toneColor(tone: "positive" | "negative" | "neutral"): string { return tone === "positive" ? colors.positive : tone === "negative" ? colors.negative : colors.textDim; } /** One headline figure: a big number with a small label under it. */ function Stat({ label, value, detail, color, width }: { label: string; value: string; detail?: string; color?: string; width: number }) { return ( {value} {detail ? {` ${detail}`} : null} {label} ); } function ProWall({ action }: { action: string }) { const openUpgrade = useCloudUpgradeAction(); const openPlan = useCloudPlanAction(); return (