@timurtekb/tekjobs 0.24.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +93 -46
- package/app/dist/assets/{index-QteuouKv.js → index--cO0sfK7.js} +2 -2
- package/app/dist/index.html +1 -1
- package/cli.mjs +1 -1
- package/package.json +9 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Every release, newest first. Written by semantic-release from the commit messages.
|
|
4
4
|
|
|
5
|
+
## 0.25.0 (2026-09-24)
|
|
6
|
+
|
|
7
|
+
* feat(site): who it is for, counted numbers, an AI-clients page, and honest privacy copy ([e809942](https://github.com/Timurtek/tekjobs/commit/e809942))
|
|
8
|
+
* chore(deps): typescript 7 in the app and the site ([164fcf9](https://github.com/Timurtek/tekjobs/commit/164fcf9))
|
|
9
|
+
* chore(npm): write the bin path the way npm normalises it ([b695e4f](https://github.com/Timurtek/tekjobs/commit/b695e4f))
|
|
10
|
+
|
|
11
|
+
## <small>0.24.2 (2026-09-24)</small>
|
|
12
|
+
|
|
13
|
+
* fix(docs): the readme said nothing is published to npm ([7475812](https://github.com/Timurtek/tekjobs/commit/7475812))
|
|
14
|
+
* fix(release): make semantic-release use the npm plugin that knows trusted publishing ([6ee8f48](https://github.com/Timurtek/tekjobs/commit/6ee8f48))
|
|
15
|
+
|
|
5
16
|
## <small>0.24.1 (2026-09-24)</small>
|
|
6
17
|
|
|
7
18
|
* fix(cli): publish as @timurtekb/tekjobs ([b573310](https://github.com/Timurtek/tekjobs/commit/b573310))
|
package/README.md
CHANGED
|
@@ -1,59 +1,67 @@
|
|
|
1
1
|
# TekJobs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@timurtekb/tekjobs)
|
|
4
|
+
[](https://github.com/Timurtek/tekjobs/releases)
|
|
5
|
+
[](https://github.com/Timurtek/tekjobs/actions/workflows/release.yml)
|
|
6
|
+
[](package.json)
|
|
7
|
+
[](LICENSE)
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
A local career memory for you and your AI. TekJobs scans hundreds of public company job boards every morning, scores each posting against criteria you control, and saves the results as readable markdown files on your machine. Connect it to Claude Code, Codex, Cursor or Claude Desktop over MCP and your agent can weigh roles, prepare truthful application material and track the search, without ever making the final submission.
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
[Website](https://tekjobs.timurtek.com) · [Getting started](https://tekjobs.timurtek.com/docs/getting-started) · [Connect your AI client](https://tekjobs.timurtek.com/docs/ai-clients) · [npm](https://www.npmjs.com/package/@timurtekb/tekjobs) · [Releases](https://github.com/Timurtek/tekjobs/releases)
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
- **A folder for your profile.** Plain markdown. Obsidian is the nicest way to read it, and not required.
|
|
11
|
-
- **A coding CLI that can run MCP tools, signed in on this machine.** Claude Code by default. The interview and everything an agent does over MCP work with any MCP client (Codex, Cursor, Claude Desktop). The app's "Write cover letter" and "Tailor resume" buttons run a CLI with the prompt as an argument and read its output; the default is `claude -p --output-format text`, and another command goes under `"llm"` in `~/.tekjobs/config.json` or on the Settings page. No API key, nothing metered.
|
|
12
|
-
- **"Check mail" needs Claude Code specifically**, with its Gmail connector enabled. The run allows exactly three Gmail read tools by name and denies every write and shell tool, which is what makes it safe to run unattended; another CLI would need a Gmail MCP with matching tool names. Everything else works without it.
|
|
13
|
-
- Optional: free Adzuna and USAJOBS keys for those two feeds, and `"contact"` in `~/.tekjobs/config.json` so the user agent on scan requests names a way to reach you.
|
|
13
|
+
## Why it exists
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Most job-search products keep what they learn about your search inside their platform. TekJobs keeps it with you. Your resume, preferences, decisions, job notes, application history and drafts form a record on your own disk that gets more useful the longer you search, and you can change models, editors and AI clients without rebuilding it from zero.
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Who it is for
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
- **A daily scan** over Greenhouse, Lever, Ashby, Workday, Rippling, SmartRecruiters, Workable, BambooHR, Breezy, Personio, Teamtailor and Eightfold boards, the Atlassian, GitHub, Spotify and Amazon career APIs, the Google and Apple career pages (keyword-searched; they have no API), and eleven aggregator feeds including Wellfound's and Built In's remote listing pages. All public, all key-free. Two optional feeds need a free key: Adzuna, which reaches listings that never make it to a company board, and USAJOBS, which is every federal posting in the United States. Job alert emails saved into `Inbox/` are read too, which is how LinkedIn and Indeed listings get in without anything contacting those sites. Around 25,000 postings a run, deduplicated, scored, and cut to the ones that fit you.
|
|
21
|
-
- **An app** (Zengin UI): a Today queue, filterable jobs table with a detail sheet, drag-and-drop pipeline, a Sources page with each board's health and a retry for the failed ones, criteria editor, scan history with a run button, and the agent setup page.
|
|
22
|
-
- **An MCP server** with 42 tools, so Claude Code, Claude Desktop, ChatGPT or Cursor can run the whole search: onboard you, find matches, move them through the pipeline, pull your profile and a posting together to tailor an application, save the draft into the note, add boards, start scans.
|
|
19
|
+
It fits if you apply across more than one kind of role and want criteria you can read and change; if you want to know why a job was recommended, point by point; if you already use Claude Code, Codex, Cursor or another MCP client and want it working from your notes; if you keep career notes in Markdown or Obsidian, or would like to; and if you want help with applications without anything being submitted for you.
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
It does not fit if you want a hosted service with nothing to install (TekJobs is a command and a folder), if you want one-click applications sent on your behalf (it stops before send, on purpose), or if you do not want any AI provider to see your resume (the scan and the notes never leave your machine, but the interview and the drafting send what you choose to the model you connect).
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
## What it does
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
- **A profile folder** (default `~/.tekjobs/profile`): your profile, your resume as text, the scoring criteria, the board watchlist, one note per matched job, your application history, and scan logs. Plain markdown, readable in Obsidian or anything else.
|
|
26
|
+
- **A daily scan** over Greenhouse, Lever, Ashby, Workday, Rippling, SmartRecruiters, Workable, BambooHR, Breezy, Personio, Teamtailor and Eightfold boards, the Atlassian, GitHub, Spotify and Amazon career APIs, the Google and Apple career pages (keyword-searched; they have no API), and eleven aggregator feeds including Wellfound's and Built In's remote listing pages. All public, all key-free. Two optional feeds need a free key: Adzuna, which reaches listings that never make it to a company board, and USAJOBS, which is every federal posting in the United States. Job alert emails saved into `Inbox/` are read too, which is how LinkedIn and Indeed listings get in without anything contacting those sites. Tens of thousands of postings a run, deduplicated, scored with every point written down as a reason, and cut to the ones that fit you.
|
|
27
|
+
- **An app** (Zengin UI): a Today queue, a filterable jobs table with a detail sheet, a drag-and-drop pipeline from reviewing to offer, a Sources page with each board's health and a retry for the failed ones, a criteria editor with a live preview of what a change would do, scan history with a run button, the profile pages, and the agent setup page.
|
|
28
|
+
- **Application material** written from your resume of record and checked against it: a tailored resume, a cover letter in your voice, and a copy panel for the answers forms keep asking for. Nothing is ever submitted; you review and click.
|
|
29
|
+
- **An MCP server** with 42 tools, so Claude Code, Codex, Cursor or Claude Desktop can run the whole search: onboard you, find matches, move them through the pipeline, pull your profile and a posting together to tailor an application, save the draft into the note, add boards, start scans, read the mailbox.
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
## Quick start
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
1. Create your search. The folder can be anywhere; inside an Obsidian vault is the nicest place.
|
|
35
34
|
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
npm run init -- --resume ~/Downloads/resume.pdf # creates the profile folder and imports the resume
|
|
40
|
-
```
|
|
35
|
+
```
|
|
36
|
+
npx @timurtekb/tekjobs init ~/Obsidian/JobSearch --resume ~/Downloads/resume.pdf
|
|
37
|
+
```
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
2. Install the command, so the morning task has a home that lasts (npx's cache does not).
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
```
|
|
42
|
+
npm install -g @timurtekb/tekjobs
|
|
43
|
+
```
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
3. Connect your AI client. Claude Code is one line; [Codex, Cursor and Claude Desktop](https://tekjobs.timurtek.com/docs/ai-clients) each take the same command, `tekjobs mcp`.
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
```
|
|
48
|
+
claude mcp add tekjobs -- tekjobs mcp
|
|
49
|
+
```
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
npm run dev # UI on http://localhost:5173
|
|
54
|
-
```
|
|
51
|
+
Then say:
|
|
52
|
+
|
|
53
|
+
> Use the tekjobs MCP server. Call onboarding_status, then onboarding_materials, and follow its script: interview me, write my profile, set the criteria, run a dry scan, and show me the top matches.
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
The interview reads your resume, asks the few things a resume cannot say (target titles, seniority, work mode, pay floor, hard exclusions, links), writes `Profile/Profile.md` and the criteria, and runs the first scan. LinkedIn: give it your LinkedIn data export, not a URL; it will not scrape profile pages.
|
|
56
|
+
|
|
57
|
+
4. Run the app, and schedule the mornings.
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
tekjobs serve # the app on http://127.0.0.1:8787
|
|
61
|
+
tekjobs schedule # the scan and the read-only mail pass, daily at 07:30 (--time to change it)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
About twenty-five minutes end to end on a fresh machine, most of it the interview. To change the code, or to run the app from source, clone instead: `git clone https://github.com/Timurtek/tekjobs && cd tekjobs && npm install`, then `npm run init -- --resume <file>`; the app is `cd app && npm install && npm run dev` with `npm run server` beside it. The clone's `app/.mcp.json` connects the server for Claude Code on its own.
|
|
57
65
|
|
|
58
66
|
## Try it without your own data
|
|
59
67
|
|
|
@@ -66,6 +74,37 @@ cd app && npm run dev
|
|
|
66
74
|
|
|
67
75
|
Point the API at it and the app shows a search in progress instead of an empty folder. Nothing in it is a real person, company or posting.
|
|
68
76
|
|
|
77
|
+
## What local-first means
|
|
78
|
+
|
|
79
|
+
TekJobs keeps your profile, criteria, job notes, decisions and application history in files on your machine. It has no account and keeps no hosted copy of those records. There is no telemetry.
|
|
80
|
+
|
|
81
|
+
Two kinds of request do leave: the scan's reads of public job boards, and whatever context you choose to send to the AI provider you connect, which processes it under that provider's terms. Optional sources (Adzuna, USAJOBS) call their APIs with your key. Your files remain the durable record whichever model you use.
|
|
82
|
+
|
|
83
|
+
## Requirements
|
|
84
|
+
|
|
85
|
+
- **Node 20 or newer.** The scan has one dependency (PDF reading); the app ships built.
|
|
86
|
+
- **A folder for your profile.** Plain markdown. Obsidian is the nicest way to read it, and not required.
|
|
87
|
+
- **An AI client that speaks MCP, signed in on this machine.** Claude Code by default; Codex, Cursor and Claude Desktop work the same way. The interview and everything an agent does over MCP run there. The app's "Write cover letter" and "Tailor resume" buttons run a CLI with the prompt as an argument and read its output; the default is `claude -p --output-format text`, and another command goes under `"llm"` in `~/.tekjobs/config.json` or on the Settings page. No API key, nothing metered.
|
|
88
|
+
- **"Check mail" needs Claude Code specifically**, with its Gmail connector enabled. The run allows exactly three Gmail read tools by name and denies every write and shell tool, which is what makes it safe to run unattended; another CLI would need a Gmail MCP with matching tool names. Everything else works without it.
|
|
89
|
+
- Optional: free Adzuna and USAJOBS keys for those two feeds, and `"contact"` in `~/.tekjobs/config.json` so the user agent on scan requests names a way to reach you.
|
|
90
|
+
|
|
91
|
+
Nothing personal lives in this repository. Your profile folder (profile, resume, criteria, watchlist, job notes, logs, mail state) and `~/.tekjobs/config.json` are outside it; the repository is the code and the starter notes a new profile folder begins with.
|
|
92
|
+
|
|
93
|
+
## Known limitations
|
|
94
|
+
|
|
95
|
+
- **LinkedIn and Indeed are not scanned.** Their listings arrive through job-alert emails saved into `Inbox/`, or through a link you paste. Indeed blocks signed-out reads, so paste the company's own link instead.
|
|
96
|
+
- **Check mail is Claude Code only**, because it depends on that client's Gmail connector and on denying its tools by name.
|
|
97
|
+
- **Boards go quiet.** Company boards move platforms, rename slugs and rate-limit. The Sources page shows each board's health and retries the failed ones, and the registry is a table anyone can fix.
|
|
98
|
+
- **The app has no login.** It serves on 127.0.0.1 and is meant for one person on one machine. Do not expose the port to a network.
|
|
99
|
+
- **Pay parsing reads posted ranges.** A posting that hides its pay scores lower rather than being guessed at, which is the point, and also means some good roles rank below a candid one.
|
|
100
|
+
- **One person has run it in anger so far.** The onboarding has been rehearsed on the fictional sample resume and on a clean clone; the first report from another machine is welcome as an issue.
|
|
101
|
+
|
|
102
|
+
## Roadmap
|
|
103
|
+
|
|
104
|
+
- **Now**: the npm package, employer postings that enter the same scan, board health on the Sources page, a live preview when criteria change, the profile summary.
|
|
105
|
+
- **Next**: a short recorded demo of install, interview and the first Today; a LinkedIn data-export import into People; criteria presets per role that ship with the repository.
|
|
106
|
+
- **Later**: a command palette in the app, a desktop shell, and mail for clients other than Claude Code once they carry a Gmail connector with read-only tools.
|
|
107
|
+
|
|
69
108
|
## Cover letters
|
|
70
109
|
|
|
71
110
|
Each job has a Cover letter tab. "Write cover letter" runs a local LLM CLI you are already signed in to (Claude Code by default; set another under `"llm"` in `~/.tekjobs/config.json`), so there is no API key and nothing metered. It writes from the live posting and your resume, and your resume is the only source of facts. How it sounds comes from `Profile/Voice.md` in your profile folder: your voice rules, the shape of a letter you would send, the patterns you never use, and samples of your own prose. Edit that note to change every letter after it; there is a generic fallback for a profile without one. The prompt makes the model draft and then edit against the same checklist (portability test, repeated shapes, self-adjectives, quote count). The result is saved under `## Cover letter` in the job note and checked: a figure that is not on your resume, your profile or the posting is flagged, along with dashes, placeholders, stock phrases, a letter that never names the company, and the tells of a generated letter: a "decade" opener, "You ask for X" stanzas, tag lines, "not X but Y" contrasts, colon reveals, applicant boilerplate, adjectives about yourself. An agent connected over MCP can do the same with `cover_letter_materials` and `save_cover_letter`. If the CLI is signed out or out of date the tab says so and what to run.
|
|
@@ -107,16 +146,20 @@ The **Profile** page edits the notes applications are written from: `Profile/Pro
|
|
|
107
146
|
## Commands
|
|
108
147
|
|
|
109
148
|
```
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
149
|
+
tekjobs init [dir] [--resume <file>] create (or adopt) a profile folder and remember it
|
|
150
|
+
tekjobs resume <file> import or replace the resume (PDF, DOCX, Markdown, text)
|
|
151
|
+
tekjobs status what the onboarding still needs
|
|
152
|
+
tekjobs scan [--dry] [--min N] [--floor N] [--only <slug>] [--criteria <preset name | file>] [--retry-failed]
|
|
153
|
+
tekjobs add <url> [<url>...] [--dry] add postings you found yourself
|
|
154
|
+
tekjobs mail [--days N] the read-only mail pass
|
|
155
|
+
tekjobs rescore [--full] [--dry] what existing notes score under the current criteria
|
|
156
|
+
tekjobs schedule [--time HH:MM] [--print] the morning task, for Windows, macOS or Linux
|
|
157
|
+
tekjobs serve the app + API on http://127.0.0.1:8787
|
|
158
|
+
tekjobs mcp the MCP server on stdio
|
|
159
|
+
tekjobs --version
|
|
117
160
|
```
|
|
118
161
|
|
|
119
|
-
The profile folder is resolved from `TEKJOBS_PROFILE`, then `~/.tekjobs/config.json`, then `~/.tekjobs/profile`.
|
|
162
|
+
From a clone the same commands are `node cli.mjs <command>`. The profile folder is resolved from `TEKJOBS_PROFILE`, then `~/.tekjobs/config.json`, then `~/.tekjobs/profile`.
|
|
120
163
|
|
|
121
164
|
## Layout
|
|
122
165
|
|
|
@@ -129,17 +172,21 @@ scraper/resume.mjs PDF / DOCX / Markdown text extraction
|
|
|
129
172
|
scraper/sources.mjs Greenhouse, Lever, Ashby, Workday, RemoteOK, HN
|
|
130
173
|
scraper/sources-extra.mjs the other platforms, career APIs, aggregators
|
|
131
174
|
scraper/score.mjs scoring and pay-range parsing
|
|
175
|
+
scraper/health.mjs per-board health for the Sources page
|
|
132
176
|
scraper/vault.mjs job notes, dedupe state, closed detection, log, dashboard
|
|
133
177
|
scraper/starter/ the notes a new profile folder starts with (including the board registry)
|
|
134
178
|
app/ Zengin UI front end, API server, MCP server
|
|
135
179
|
site/ tekjobs.timurtek.com: the landing page and docs (Next.js on Zengin UI, deployed from this folder on Vercel)
|
|
136
|
-
|
|
180
|
+
samples/vault/ the fictional profile folder
|
|
181
|
+
tools/ board discovery scripts, the sample-vault builder, the counts the README and the site print
|
|
137
182
|
```
|
|
138
183
|
|
|
139
184
|
## Releases
|
|
140
185
|
|
|
141
|
-
The package on npm is [`@timurtekb/tekjobs`](https://www.npmjs.com/package/@timurtekb/tekjobs) (the bare name was too close to an existing package for npm's liking); every release that changes the scan, the CLI or the app is published there by the release workflow, and `npx @timurtekb/tekjobs` runs the latest. Versions come from the commit messages, by [semantic-release](https://semantic-release.gitbook.io/) on every push to `main` (`.github/workflows/release.yml`): tests, the app's type check and `zengin check` run first; then `feat:` commits make a minor release and `fix:` and `perf:` a patch. The project is at 0.x on purpose, so a `BREAKING CHANGE:` footer or a `!` after the type also bumps the minor (the `releaseRules` line in
|
|
186
|
+
The package on npm is [`@timurtekb/tekjobs`](https://www.npmjs.com/package/@timurtekb/tekjobs) (the bare name was too close to an existing package for npm's liking); every release that changes the scan, the CLI or the app is published there by the release workflow, and `npx @timurtekb/tekjobs` runs the latest. Versions come from the commit messages, by [semantic-release](https://semantic-release.gitbook.io/) on every push to `main` (`.github/workflows/release.yml`): tests, the app's type check and `zengin check` run first; then `feat:` commits make a minor release and `fix:` and `perf:` a patch. The project is at 0.x on purpose, so a `BREAKING CHANGE:` footer or a `!` after the type also bumps the minor (the `releaseRules` line in `release.config.cjs`); delete that line when 1.0 is earned and breaking changes become majors. The release bumps `package.json`, writes `CHANGELOG.md`, tags `vX.Y.Z`, publishes the notes on GitHub and publishes the package to npm through [Trusted Publishing](https://docs.npmjs.com/trusted-publishers), so no npm token exists anywhere; the repository variable `NPM_PUBLISH` switches that last step on. Commit messages are checked locally by commitlint through a husky hook (`npm install` at the root sets it up), in the [Conventional Commits](https://www.conventionalcommits.org/) shape: `type(scope): summary`, scope optional, and a prose body is welcome. The app's sidebar footer shows the running version.
|
|
142
187
|
|
|
143
188
|
## Contributing
|
|
144
189
|
|
|
145
190
|
The two things that compound are data files: the board registry (`scraper/starter/companies-table.md`, platform + slug per company) and, soon, criteria presets per role. Pull requests to either are the most useful contribution. [CONTRIBUTING.md](CONTRIBUTING.md) has the mechanics (three installs, the design-system check, the commit format); [SECURITY.md](SECURITY.md) says where to report a vulnerability, and what counts as one.
|
|
191
|
+
|
|
192
|
+
Built by [Timurtek](https://www.timurtek.com) for his own search first. MIT licensed.
|
|
@@ -57,7 +57,7 @@ Defaulting to \`null\`.`}md(Ad,`getInvalidValueError`);var jd=xd,Md=Cd;(0,b.forw
|
|
|
57
57
|
`)});continue}let a=/^(#{1,6})\s+(.*)$/.exec(e);if(a){n.push({kind:`heading`,level:a[1].length,children:ug(a[2])}),r++;continue}if(/^(-{3,}|\*{3,}|_{3,})\s*$/.test(e)){n.push({kind:`rule`}),r++;continue}if(sg(e)&&r+1<t.length&&cg(t[r+1])){let i=og(e).map(ug);r+=2;let a=[];for(;r<t.length&&sg(t[r]);)a.push(og(t[r++]).map(ug));n.push({kind:`table`,header:i,rows:a});continue}if(/^>\s?/.test(e)){let e=[];for(;r<t.length&&/^>\s?/.test(t[r]);)e.push(t[r++].replace(/^>\s?/,``));n.push({kind:`quote`,children:ug(e.join(` `))});continue}let o=/^\s*([-*+]|\d+[.)])\s+/.exec(e);if(o){let e=/\d/.test(o[1]),i=[];for(;r<t.length;){let e=/^\s*([-*+]|\d+[.)])\s+(.*)$/.exec(t[r]);if(!e)break;let n=e[2];for(r++;r<t.length&&/^\s{2,}\S/.test(t[r])&&!/^\s*([-*+]|\d+[.)])\s+/.test(t[r]);)n+=` `+t[r++].trim();i.push(ug(n))}n.push({kind:`list`,ordered:e,items:i});continue}let s=[];for(;r<t.length&&t[r].trim()!==``&&!/^```/.test(t[r])&&!/^(#{1,6})\s/.test(t[r])&&!/^\s*([-*+]|\d+[.)])\s+/.test(t[r])&&!/^>\s?/.test(t[r])&&!(sg(t[r])&&r+1<t.length&&cg(t[r+1]));)s.push(t[r++].trim());n.push({kind:`paragraph`,children:ug(s.join(` `))})}return n}function ug(e){let t=[],n=e,r=e=>{let n=t[t.length-1];e.kind===`text`&&n?.kind===`text`?n.text+=e.text:t.push(e)};for(;n.length;){let e=/^`([^`]+)`/.exec(n);if(e){r({kind:`code`,text:e[1]}),n=n.slice(e[0].length);continue}let t=/^\[([^\]]+)\]\((https?:\/\/[^\s)]+|\/[^\s)]*|#[^\s)]*)\)/.exec(n);if(t){r({kind:`link`,href:t[2],children:ug(t[1])}),n=n.slice(t[0].length);continue}let i=/^(\*\*|__)(.+?)\1/.exec(n);if(i){r({kind:`strong`,children:ug(i[2])}),n=n.slice(i[0].length);continue}let a=/^(\*|_)([^*_]+?)\1/.exec(n);if(a){r({kind:`em`,children:ug(a[2])}),n=n.slice(a[0].length);continue}let o=n.slice(1).search(/[`*_[]/),s=o===-1?n.length:o+1;r({kind:`text`,text:n.slice(0,s)}),n=n.slice(s)}return t}var dg=(0,b.forwardRef)(function({text:e,streaming:t=!1,className:n,...r},i){let a=lg(e);return(0,x.jsxs)(`div`,{ref:i,className:R(`z-markdown`,n),"data-streaming":t||void 0,...r,children:[a.map((e,n)=>(0,x.jsx)(fg,{block:e,last:n===a.length-1,streaming:t},n)),t&&a.length===0&&(0,x.jsx)(`span`,{className:`z-markdown__cursor`,"aria-hidden":`true`})]})});function fg({block:e,last:t,streaming:n}){let r=t&&n?(0,x.jsx)(`span`,{className:`z-markdown__cursor`,"aria-hidden":`true`}):null;switch(e.kind){case`paragraph`:return(0,x.jsxs)(`p`,{children:[(0,x.jsx)(pg,{nodes:e.children}),r]});case`heading`:{let t=`h${e.level}`;return(0,x.jsxs)(t,{children:[(0,x.jsx)(pg,{nodes:e.children}),r]})}case`list`:{let t=e.ordered?`ol`:`ul`;return(0,x.jsx)(t,{children:e.items.map((t,n)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(pg,{nodes:t}),n===e.items.length-1?r:null]},n))})}case`code`:return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(ag,{code:e.code,language:e.language||void 0}),r]});case`quote`:return(0,x.jsxs)(`blockquote`,{children:[(0,x.jsx)(pg,{nodes:e.children}),r]});case`table`:return(0,x.jsxs)(Y,{density:`sm`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsx)(Y.Row,{children:e.header.map((e,t)=>(0,x.jsx)(Y.HeadCell,{children:(0,x.jsx)(pg,{nodes:e})},t))})}),(0,x.jsx)(Y.Body,{children:e.rows.map((e,t)=>(0,x.jsx)(Y.Row,{children:e.map((e,t)=>(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(pg,{nodes:e})},t))},t))})]});case`rule`:return(0,x.jsx)(`hr`,{})}}function pg({nodes:e}){return e.map((e,t)=>{switch(e.kind){case`text`:return e.text;case`code`:return(0,x.jsx)(`code`,{children:e.text},t);case`strong`:return(0,x.jsx)(`strong`,{children:(0,x.jsx)(pg,{nodes:e.children})},t);case`em`:return(0,x.jsx)(`em`,{children:(0,x.jsx)(pg,{nodes:e.children})},t);case`link`:return(0,x.jsx)(`a`,{href:e.href,target:e.href.startsWith(`http`)?`_blank`:void 0,rel:e.href.startsWith(`http`)?`noreferrer`:void 0,children:(0,x.jsx)(pg,{nodes:e.children})},t)}})}var mg=Object.defineProperty,hg=(e,t)=>mg(e,`name`,{value:t,configurable:!0}),gg=`Tabs`,[_g,vg]=T(gg,[rc]),yg=rc(),[bg,xg]=_g(gg),Sg=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,value:r,onValueChange:i,defaultValue:a,orientation:o=`horizontal`,dir:s,activationMode:c=`automatic`,...l}=e,u=G(s),[d,f]=kt({prop:r,onChange:i,defaultProp:a??``,caller:gg});return(0,x.jsx)(bg,{scope:n,baseId:bt(),value:d,onValueChange:f,orientation:o,dir:u,activationMode:c,children:(0,x.jsx)(L.div,{dir:u,"data-orientation":o,...l,ref:t})})},`Tabs`)),Cg=`TabsList`,wg=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,loop:r=!0,...i}=e,a=xg(Cg,n),o=yg(n);return(0,x.jsx)(hc,{asChild:!0,...o,orientation:a.orientation,dir:a.dir,loop:r,children:(0,x.jsx)(L.div,{role:`tablist`,"aria-orientation":a.orientation,...i,ref:t})})},`TabsList`)),Tg=`TabsTrigger`,Eg=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,value:r,disabled:i=!1,...a}=e,o=xg(Tg,n),s=yg(n),c=kg(o.baseId,r),l=Ag(o.baseId,r),u=r===o.value;return(0,x.jsx)(gc,{asChild:!0,...s,focusable:!i,active:u,children:(0,x.jsx)(L.button,{type:`button`,role:`tab`,"aria-selected":u,"aria-controls":l,"data-state":u?`active`:`inactive`,"data-disabled":i?``:void 0,disabled:i,id:c,...a,ref:t,onMouseDown:U(e.onMouseDown,e=>{!i&&e.button===0&&e.ctrlKey===!1?o.onValueChange(r):e.preventDefault()}),onKeyDown:U(e.onKeyDown,e=>{i||e.target!==e.currentTarget||[` `,`Enter`].includes(e.key)&&o.onValueChange(r)}),onFocus:U(e.onFocus,()=>{let e=o.activationMode!==`manual`;!u&&!i&&e&&o.onValueChange(r)})})})},`TabsTrigger`)),Dg=`TabsContent`,Og=b.forwardRef(hg(function(e,t){let{__scopeTabs:n,value:r,forceMount:i,children:a,...o}=e,s=xg(Dg,n),c=kg(s.baseId,r),l=Ag(s.baseId,r),u=r===s.value,d=b.useRef(u);return b.useEffect(()=>{let e=requestAnimationFrame(()=>d.current=!1);return()=>cancelAnimationFrame(e)},[]),(0,x.jsx)(bn,{present:i||u,children:({present:n})=>(0,x.jsx)(L.div,{"data-state":u?`active`:`inactive`,"data-orientation":s.orientation,role:`tabpanel`,"aria-labelledby":c,hidden:!n,id:l,tabIndex:0,...o,ref:t,style:{...e.style,animationDuration:d.current?`0s`:void 0},children:n&&a})})},`TabsContent`));function kg(e,t){return`${e}-trigger-${t}`}hg(kg,`makeTriggerId`);function Ag(e,t){return`${e}-content-${t}`}hg(Ag,`makeContentId`);var jg=Sg,Mg=wg,Ng=Eg,Pg=Og,Fg=(0,b.forwardRef)(function({variant:e=`line`,size:t=`md`,className:n,...r},i){return(0,x.jsx)(jg,{ref:i,className:R(`z-tabs`,n),"data-variant":e,"data-size":t,...r})}),Ig=(0,b.forwardRef)(function({className:e,...t},n){return(0,x.jsx)(Mg,{ref:n,className:R(`z-tabs__list`,e),...t})}),Lg=(0,b.forwardRef)(function({className:e,...t},n){return(0,x.jsx)(Ng,{ref:n,className:R(`z-tabs__trigger z-focusable`,e),...t})}),Rg=(0,b.forwardRef)(function({className:e,...t},n){return(0,x.jsx)(Pg,{ref:n,className:R(`z-tabs__content z-focusable`,e),...t})}),Z=Object.assign(Fg,{List:Ig,Trigger:Lg,Content:Rg}),zg=(0,b.forwardRef)(function({variant:e=`text`,width:t,height:n,lines:r=1,className:i,style:a,...o},s){return e===`text`&&r>1?(0,x.jsx)(`span`,{ref:s,className:R(`z-skeleton-lines`,i),"aria-hidden":`true`,style:a,...o,children:Array.from({length:r},(e,n)=>(0,x.jsx)(`span`,{className:`z-skeleton`,"data-variant":`text`,style:{width:n===r-1?`60%`:t}},n))}):(0,x.jsx)(`span`,{ref:s,className:R(`z-skeleton`,i),"data-variant":e,"aria-hidden":`true`,style:{width:t,height:n,...a},...o})}),Bg=(0,b.forwardRef)(function({label:e=`Thinking`,showLabel:t=!1,size:n=`md`,className:r,...i},a){return(0,x.jsxs)(`span`,{ref:a,className:R(`z-loader`,r),"data-size":n,role:`status`,"aria-label":e,...i,children:[(0,x.jsxs)(`span`,{className:`z-loader__dots`,"aria-hidden":`true`,children:[(0,x.jsx)(`span`,{}),(0,x.jsx)(`span`,{}),(0,x.jsx)(`span`,{})]}),t&&(0,x.jsx)(`span`,{className:`z-loader__label`,children:e})]})}),Vg=(0,b.forwardRef)(function({title:e,description:t,icon:n,action:r,size:i=`md`,tone:a=`neutral`,className:o,...s},c){return(0,x.jsxs)(`div`,{ref:c,className:R(`z-empty`,o),"data-size":i,"data-tone":a,...s,children:[n&&(0,x.jsx)(`span`,{className:`z-empty__icon`,"aria-hidden":`true`,children:n}),(0,x.jsx)(`p`,{className:`z-empty__title`,children:e}),t&&(0,x.jsx)(`p`,{className:`z-empty__description`,children:t}),r&&(0,x.jsx)(`div`,{className:`z-empty__action`,children:r})]})});function Hg({columns:e,cards:t,cardId:n,cardColumn:r,renderCard:i,cardLabel:a,onMove:o,density:s=`md`,label:c,className:l}){let[u,d]=(0,b.useState)(null),[f,p]=(0,b.useState)(null),[m,h]=(0,b.useState)(``),g=(0,b.useId)(),_=(0,b.useRef)(new Map),v=(0,b.useCallback)(e=>t.filter(t=>r(t)===e),[t,r]),y=(0,b.useCallback)((e,t,r,i)=>{(t!==r||v(t).findIndex(t=>n(t)===e)!==i)&&o?.({cardId:e,from:t,to:r,index:i})},[v,n,o]);(0,b.useEffect)(()=>{u&&_.current.get(u.id)?.focus()},[u,t]);let S=(e,t)=>{u&&(y(u.id,u.column,e,t),d(null),p(null))},C=(t,i,o,s)=>{if(t.target!==t.currentTarget)return;let c=n(i),l=t.key;if(l===` `||l===`Enter`){if(t.preventDefault(),!u)d({id:c,column:r(i),index:s}),h(`${a(i)} lifted. Use the arrow keys to move it, Enter to drop, Escape to cancel.`);else{let t=f??{column:u.column,index:u.index},n=e.find(e=>e.id===t.column);y(u.id,u.column,t.column,t.index),h(`${a(i)} moved to ${typeof n?.title==`string`?n.title:t.column}, position ${t.index+1}.`),d(null),p(null)}return}if(l===`Escape`&&u){t.preventDefault(),h(`${a(i)} put back.`),d(null),p(null);return}if(!u)return;let m=f??{column:u.column,index:u.index},g=e.findIndex(e=>e.id===m.column);if(l===`ArrowLeft`||l===`ArrowRight`){t.preventDefault();let r=e[g+(l===`ArrowRight`?1:-1)];if(!r)return;let i=v(r.id).filter(e=>n(e)!==u.id).length,a=Math.min(m.index,i);p({column:r.id,index:a}),h(`Over ${typeof r.title==`string`?r.title:r.id}, position ${a+1}.`);return}if(l===`ArrowUp`||l===`ArrowDown`){t.preventDefault();let e=v(m.column).filter(e=>n(e)!==u.id).length,r=Math.max(0,Math.min(e,m.index+(l===`ArrowDown`?1:-1)));p({column:m.column,index:r}),h(`Position ${r+1}.`)}};return(0,x.jsxs)(`div`,{className:R(`z-kanban`,l),"data-density":s,role:`group`,"aria-label":c,children:[(0,x.jsx)(`p`,{className:`z-sr-only`,role:`status`,"aria-live":`polite`,children:m}),e.map((e,t)=>{let r=v(e.id),o=f?.column===e.id,s=e.limit!==void 0&&r.length>e.limit;return(0,x.jsxs)(`section`,{className:`z-kanban__column`,"data-over":o||void 0,"aria-labelledby":`${g}-${e.id}`,onDragOver:t=>{u&&(t.preventDefault(),p({column:e.id,index:r.filter(e=>n(e)!==u.id).length}))},onDrop:t=>{t.preventDefault(),S(e.id,f?.column===e.id?f.index:r.length)},children:[(0,x.jsxs)(`header`,{className:`z-kanban__head`,children:[(0,x.jsx)(`h3`,{className:`z-kanban__title`,id:`${g}-${e.id}`,children:e.title}),(0,x.jsx)(z,{size:`sm`,tone:s?`warning`:`neutral`,variant:`outline`,children:e.limit===void 0?r.length:`${r.length}/${e.limit}`})]}),(0,x.jsxs)(`ul`,{className:`z-kanban__list`,children:[r.map((r,s)=>{let c=n(r),l=u?.id===c;return(0,x.jsx)(`li`,{className:`z-kanban__slot`,"data-drop":o&&f?.index===s?``:void 0,children:(0,x.jsx)(`article`,{ref:e=>{e?_.current.set(c,e):_.current.delete(c)},className:`z-kanban__card z-focusable`,tabIndex:0,draggable:!0,"data-lifted":l||void 0,"aria-roledescription":`Draggable card`,"aria-label":a(r),"aria-grabbed":l||void 0,onKeyDown:e=>C(e,r,t,s),onDragStart:()=>d({id:c,column:e.id,index:s}),onDragEnd:()=>{d(null),p(null)},children:i(r)})},c)}),r.length===0&&(0,x.jsx)(`li`,{className:`z-kanban__slot`,"data-drop":o?``:void 0,children:e.empty??(0,x.jsx)(Vg,{size:`sm`,title:`Nothing here`})})]})]},e.id)})]})}function Ug(e,t){return`${e}-option-${t}`}function Wg(e){let{options:t,label:n,description:r,error:i,placeholder:a,size:o=`md`,disabled:s,emptyMessage:c=`No matches`,className:l,id:u}=e,d=e.multiple===!0,f=(0,b.useId)(),p=u??f,m=`${p}-list`,[h,g]=(0,b.useState)(!1),[_,v]=(0,b.useState)(``),[y,S]=(0,b.useState)(0),C=(0,b.useRef)(null),w=(0,b.useRef)(null),T=(0,b.useRef)(null),E=(0,b.useMemo)(()=>{if(d)return e.value??[];let t=e.value;return t?[t]:[]},[d,e]),D=(0,b.useMemo)(()=>new Map(t.map(e=>[e.value,e])),[t]),O=(0,b.useMemo)(()=>{let e=_.trim().toLowerCase();return e?t.filter(t=>t.label.toLowerCase().includes(e)||(t.hint??``).toLowerCase().includes(e)):t},[t,_,d]);(0,b.useEffect)(()=>S(0),[_,h]),(0,b.useEffect)(()=>{if(!h)return;let e=e=>{T.current?.contains(e.target)||g(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[h]),(0,b.useEffect)(()=>{h&&w.current?.querySelector(`[data-active="true"]`)?.scrollIntoView({block:`nearest`})},[y,h]);let k=t=>{if(!t.disabled){if(d){let n=E.includes(t.value)?E.filter(e=>e!==t.value):[...E,t.value];e.onValueChange?.(n),v(``),C.current?.focus();return}e.onValueChange?.(t.value),v(``),g(!1)}},A=t=>{d&&(e.onValueChange?.(E.filter(e=>e!==t)),C.current?.focus())},j=e=>{let t=e.key;if(t===`ArrowDown`||t===`ArrowUp`){if(e.preventDefault(),!h){g(!0);return}let n=t===`ArrowDown`?1:-1;for(let e=1;e<=O.length;e++){let t=(y+n*e+O.length*e)%O.length;if(!O[t]?.disabled){S(t);return}}return}if(t===`Enter`&&h){let t=O[y];t&&(e.preventDefault(),k(t));return}if(t===`Escape`){h&&(e.preventDefault(),g(!1));return}t===`Backspace`&&d&&_===``&&E.length&&A(E[E.length-1])},ee=(0,b.useMemo)(()=>{let e=[];for(let t of O){let n=e[e.length-1];n&&n.name===t.group?n.options.push(t):e.push({name:t.group,options:[t]})}return e},[O]),M=-1,N=[r?`${p}-description`:null,i?`${p}-error`:null].filter(Boolean).join(` `)||void 0;return(0,x.jsxs)(`div`,{ref:T,className:R(`z-combobox`,l),"data-size":o,"data-invalid":i?``:void 0,"data-disabled":s||void 0,children:[(0,x.jsx)(`label`,{className:`z-combobox__label`,htmlFor:p,children:n}),(0,x.jsxs)(`div`,{className:`z-combobox__control`,children:[d&&E.map(e=>(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,variant:`soft`,className:`z-combobox__chip`,children:[D.get(e)?.label??e,(0,x.jsx)(`button`,{type:`button`,className:`z-combobox__remove z-focusable`,"aria-label":`Remove ${D.get(e)?.label??e}`,onClick:()=>A(e),disabled:s,children:(0,x.jsx)(H.Close,{size:12})})]},e)),(0,x.jsx)(`input`,{ref:C,id:p,className:`z-combobox__input z-focusable`,role:`combobox`,type:`text`,autoComplete:`off`,"aria-expanded":h,"aria-controls":m,"aria-autocomplete":`list`,"aria-activedescendant":h&&O[y]?Ug(p,y):void 0,"aria-describedby":N,"aria-invalid":i?!0:void 0,disabled:s,placeholder:d||!E.length?a:D.get(E[0])?.label,value:_,onChange:e=>{v(e.target.value),g(!0)},onFocus:()=>g(!0),onKeyDown:j}),(0,x.jsx)(`span`,{className:`z-combobox__chevron`,"aria-hidden":`true`,children:(0,x.jsx)(H.ChevronDown,{size:16})})]}),h&&(0,x.jsxs)(`ul`,{ref:w,className:`z-combobox__list`,id:m,role:`listbox`,"aria-label":typeof n==`string`?n:void 0,"aria-multiselectable":d||void 0,children:[ee.map((e,t)=>(0,x.jsxs)(`li`,{className:`z-combobox__group`,role:`presentation`,children:[e.name&&(0,x.jsx)(`p`,{className:`z-combobox__group-name`,children:e.name}),(0,x.jsx)(`ul`,{role:`presentation`,children:e.options.map(e=>{M+=1;let t=M,n=E.includes(e.value);return(0,x.jsxs)(`li`,{id:Ug(p,t),"data-value":e.value,className:`z-combobox__option`,role:`option`,"aria-selected":n,"aria-disabled":e.disabled||void 0,"data-active":t===y,"data-selected":n||void 0,onPointerDown:t=>{t.preventDefault(),k(e)},onPointerEnter:()=>S(t),children:[(0,x.jsx)(`span`,{className:`z-combobox__option-label`,children:e.label}),e.hint&&(0,x.jsx)(`span`,{className:`z-combobox__option-hint`,children:e.hint}),n&&(0,x.jsx)(`span`,{className:`z-combobox__tick`,"aria-hidden":`true`,children:(0,x.jsx)(H.Check,{size:14})})]},e.value)})})]},e.name??`g${t}`)),O.length===0&&(0,x.jsx)(`li`,{className:`z-combobox__empty`,role:`presentation`,children:c})]}),r&&!i&&(0,x.jsx)(`p`,{className:`z-combobox__description`,id:`${p}-description`,children:r}),i&&(0,x.jsx)(`p`,{className:`z-combobox__error`,id:`${p}-error`,children:i})]})}var Gg=[`new`,`reviewing`,`applying`,`ready`,`applied`,`interviewing`,`offer`,`rejected`,`passed`],Kg=[`wrong role shape`,`weak evidence match`,`compensation`,`location or authorisation`,`too managerial`,`too visual`,`too engineering`,`stale or duplicate`,`company`],qg=[`recruiter`,`hiring-manager`,`interviewer`,`referral`,`other`];async function Q(e,t){let n=await fetch(e,{headers:{"content-type":`application/json`},...t}),r=await n.json().catch(()=>({}));if(!n.ok)throw Error(r.error||`${n.status} ${n.statusText}`);return r}var $={summary:()=>Q(`/api/summary`),jobs:e=>{let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!==void 0&&r!==``&&r!==null&&t.set(n,String(r));return Q(`/api/jobs?${t}`)},facets:e=>{let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!==void 0&&r!==``&&r!==null&&t.set(n,String(r));return Q(`/api/jobs/facets?${t}`)},job:e=>Q(`/api/jobs/${encodeURIComponent(e)}`),attachPosting:(e,t,n=!1)=>Q(`/api/jobs/${encodeURIComponent(e)}/attach`,{method:`POST`,body:JSON.stringify({url:t,linkOnly:n})}),settings:()=>Q(`/api/settings`),saveSettings:e=>Q(`/api/settings`,{method:`PUT`,body:JSON.stringify(e)}),resumes:()=>Q(`/api/resumes`),useResume:e=>Q(`/api/resumes/use`,{method:`POST`,body:JSON.stringify({name:e})}),openResume:e=>Q(`/api/resumes/open`,{method:`POST`,body:JSON.stringify({name:e})}),revealJob:e=>Q(`/api/jobs/${encodeURIComponent(e)}/reveal`,{method:`POST`}),importLinks:e=>Q(`/api/jobs/import`,{method:`POST`,body:JSON.stringify({urls:e})}),today:(e=7)=>Q(`/api/today?cap=${e}`),setStatus:(e,t,n)=>Q(`/api/jobs/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({status:t,reason:n})}),addNote:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({note:t})}),packet:e=>Q(`/api/jobs/${encodeURIComponent(e)}/packet`),coverLetter:e=>Q(`/api/jobs/${encodeURIComponent(e)}/cover-letter`),writeCoverLetter:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/cover-letter`,{method:`POST`,body:JSON.stringify(t)}),tailoredResume:e=>Q(`/api/jobs/${encodeURIComponent(e)}/resume`),writeTailoredResume:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/resume`,{method:`POST`,body:JSON.stringify(t)}),saveTailoredResume:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/resume`,{method:`PUT`,body:JSON.stringify({text:t})}),resumePrintUrl:e=>`/api/jobs/${encodeURIComponent(e)}/resume.html`,saveCoverLetter:(e,t)=>Q(`/api/jobs/${encodeURIComponent(e)}/cover-letter`,{method:`PUT`,body:JSON.stringify({text:t})}),saveApplication:(e,t,n)=>Q(`/api/jobs/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({application:{field:t,value:n}})}),runs:()=>Q(`/api/runs`),scan:()=>Q(`/api/scan`),startScan:(e=!1,t,n=!1)=>Q(`/api/scan`,{method:`POST`,body:JSON.stringify({dry:e,criteria:t||``,retryFailed:n})}),criteria:()=>Q(`/api/criteria`),saveCriteria:e=>Q(`/api/criteria`,{method:`PUT`,body:JSON.stringify({raw:e})}),outcomes:()=>Q(`/api/outcomes`),views:()=>Q(`/api/views`),defaultViews:()=>Q(`/api/views/defaults`),saveViews:e=>Q(`/api/views`,{method:`PUT`,body:JSON.stringify({views:e})}),mail:()=>Q(`/api/mail`),mailCheck:e=>Q(`/api/mail/check`,{method:`POST`,body:JSON.stringify({sinceDays:e})}),mailConfirm:(e,t)=>Q(`/api/mail/${encodeURIComponent(e)}/confirm`,{method:`POST`,body:JSON.stringify({noteId:t})}),mailConfirmSafe:()=>Q(`/api/mail/confirm-safe`,{method:`POST`}),mailDismiss:e=>Q(`/api/mail/${encodeURIComponent(e)}/dismiss`,{method:`POST`}),previewCriteria:e=>Q(`/api/criteria/preview`,{method:`POST`,body:JSON.stringify({raw:e})}),rescoreNotes:(e=!1)=>Q(`/api/rescore`,{method:`POST`,body:JSON.stringify({dry:e})}),criteriaPresets:()=>Q(`/api/criteria/presets`),criteriaPreset:e=>Q(`/api/criteria/presets/${encodeURIComponent(e)}`),saveCriteriaPreset:(e,t)=>Q(`/api/criteria/presets/${encodeURIComponent(e)}`,{method:`PUT`,body:JSON.stringify({raw:t})}),deleteCriteriaPreset:e=>Q(`/api/criteria/presets/${encodeURIComponent(e)}`,{method:`DELETE`}),activateCriteriaPreset:e=>Q(`/api/criteria/presets/${encodeURIComponent(e)}/activate`,{method:`POST`}),profileNotes:()=>Q(`/api/profile`),profileSummary:()=>Q(`/api/profile/summary`),saveProfileNote:(e,t)=>Q(`/api/profile`,{method:`PUT`,body:JSON.stringify({note:e,markdown:t})}),snippets:()=>Q(`/api/snippets`),saveSnippets:e=>Q(`/api/snippets`,{method:`PUT`,body:JSON.stringify({items:e})}),people:()=>Q(`/api/people`),person:e=>Q(`/api/people/${encodeURIComponent(e)}`),addPerson:e=>Q(`/api/people`,{method:`POST`,body:JSON.stringify(e)}),attachPerson:(e,t,n,r)=>Q(`/api/people/${encodeURIComponent(e)}/attach`,{method:`POST`,body:JSON.stringify({jobId:t,role:n,context:r})}),logContact:(e,t,n)=>Q(`/api/people/${encodeURIComponent(e)}/log`,{method:`POST`,body:JSON.stringify({text:t,date:n})}),jobPeople:e=>Q(`/api/jobs/${encodeURIComponent(e)}/people`),companies:()=>Q(`/api/companies`),addCompany:e=>Q(`/api/companies`,{method:`POST`,body:JSON.stringify(e)}),feeds:()=>Q(`/api/feeds`),onboarding:()=>Q(`/api/onboarding`),initProfile:()=>Q(`/api/onboarding/init`,{method:`POST`,body:`{}`}),importResume:e=>Q(`/api/onboarding/resume`,{method:`POST`,body:JSON.stringify({path:e})})},Jg=e=>`$${Math.round(e/1e3)}k`,Yg=e=>e.replace(/\s*[•·].*$/,``).replace(/\s+/g,` `).trim(),Xg=e=>{if(!e)return``;let t=Math.floor((Date.now()-new Date(e).getTime())/864e5);return Number.isFinite(t)?t<=0?`today`:`${t}d ago`:``},Zg={floor:`Floor`,stretch:`Stretch`,below:`Below`,unknown:`Not stated`},Qg={floor:`success`,stretch:`warning`,below:`neutral`,unknown:`neutral`},$g={new:`neutral`,reviewing:`primary`,applying:`primary`,ready:`warning`,applied:`primary`,interviewing:`warning`,offer:`success`,rejected:`danger`,passed:`neutral`};function e_(e){let[t,n]=(0,b.useState)(()=>typeof window<`u`&&window.matchMedia(e).matches);return(0,b.useEffect)(()=>{let t=window.matchMedia(e),r=()=>n(t.matches);return r(),t.addEventListener(`change`,r),()=>t.removeEventListener(`change`,r)},[e]),t}var t_={name:`TekJobs`,logo:`/favicon.svg`};function n_({href:e=`/`}){return(0,x.jsxs)(`a`,{className:`brand-mark`,href:e,"aria-label":t_.name,children:[t_.logo&&(0,x.jsx)(`img`,{className:`brand-mark__logo`,src:t_.logo,alt:``}),(0,x.jsxs)(`span`,{"aria-hidden":`true`,children:[`Tek`,(0,x.jsx)(`span`,{className:`brand-mark__accent`,children:`Jobs`})]})]})}function r_(){let[e,t]=(0,b.useState)(!1),[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)(``),[o,s]=(0,b.useState)(null),[c,l]=(0,b.useState)(!1),u=(0,b.useRef)(null),d=()=>$.snippets().then(r).catch(e=>X({title:`Could not load the copy panel`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{e&&!n&&d()},[e]),(0,b.useEffect)(()=>{e?setTimeout(()=>u.current?.focus(),30):a(``)},[e]);let f=(0,b.useMemo)(()=>{let e=i.trim().toLowerCase(),t=(n?.items??[]).filter(t=>t.value&&(!e||`${t.group} ${t.label} ${t.value}`.toLowerCase().includes(e))),r=new Map;for(let e of t){let t=e.group||`Other`;r.has(t)||r.set(t,[]),r.get(t).push(e)}return[...r.entries()]},[n,i]),p=async e=>{try{await navigator.clipboard.writeText(e.value),s(e.label),setTimeout(()=>s(t=>t===e.label?null:t),1600)}catch(e){X({title:`Could not copy`,description:e.message,tone:`danger`})}},m=f[0]?.[1][0];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(fd,{open:e,onOpenChange:t,size:`lg`,children:[(0,x.jsx)(Bh,{content:`Copy panel`,children:(0,x.jsx)(fd.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,"aria-label":`Copy panel`,leadingIcon:(0,x.jsx)(H.Copy,{})})})}),(0,x.jsx)(fd.Content,{align:`end`,showArrow:!1,children:(0,x.jsxs)(`div`,{className:`copy`,children:[(0,x.jsx)(`form`,{className:`copy__search`,onSubmit:e=>{e.preventDefault(),m&&p(m)},children:(0,x.jsx)(Zp,{ref:u,size:`sm`,"aria-label":`Find a snippet`,placeholder:`Find, then Enter copies the first`,leadingIcon:(0,x.jsx)(H.Search,{}),value:i,onChange:e=>a(e.target.value)})}),n?f.length===0?(0,x.jsx)(`p`,{className:`muted copy__empty`,children:n.items.length===0?`Nothing here yet. Customize adds lines.`:i?`Nothing matches.`:`Every snippet is empty. Customize fills them in.`}):(0,x.jsx)(`div`,{className:`copy__groups`,children:f.map(([e,t])=>(0,x.jsxs)(`div`,{className:`copy__group`,children:[(0,x.jsx)(`div`,{className:`microlabel`,children:e}),t.map(t=>(0,x.jsx)(B,{asChild:!0,variant:`ghost`,tone:`neutral`,size:`sm`,align:`start`,className:`copy__row`,children:(0,x.jsxs)(`button`,{type:`button`,onClick:()=>p(t),title:t.value,children:[(0,x.jsx)(`span`,{className:`copy__label`,children:t.label}),(0,x.jsxs)(`span`,{className:`copy__value num`,children:[o===t.label?`Copied`:t.value.split(`
|
|
58
58
|
`)[0],t.value.includes(`
|
|
59
59
|
`)&&o!==t.label?` …`:``]})]})},`${e}:${t.label}`))]},e))}):(0,x.jsx)(zg,{lines:4}),(0,x.jsxs)(`div`,{className:`copy__foot`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Edit,{}),onClick:()=>{t(!1),l(!0)},children:`Customize`}),n&&!n.exists&&(0,x.jsx)(`span`,{className:`muted`,children:`Read from your profile until you save once.`})]})]})})]}),c&&n&&(0,x.jsx)(i_,{initial:n.items,path:n.path,onClose:()=>l(!1),onSaved:e=>{r(e),l(!1)}})]})}function i_({initial:e,path:t,onClose:n,onSaved:r}){let[i,a]=(0,b.useState)(e.length?e:[{group:``,label:``,value:``}]),[o,s]=(0,b.useState)(!1),c=(e,t)=>a(n=>n.map((n,r)=>r===e?{...n,...t}:n)),l=(e,t)=>a(n=>{let r=e+t;if(r<0||r>=n.length)return n;let i=[...n];return[i[e],i[r]]=[i[r],i[e]],i}),u=e=>a(t=>t.filter((t,n)=>n!==e));return(0,x.jsx)(Sp,{open:!0,onOpenChange:e=>!e&&n(),side:`right`,size:`md`,children:(0,x.jsx)(Sp.Content,{children:(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(Sp.Title,{children:`Customize the copy panel`}),(0,x.jsxs)(Sp.Description,{children:[`Label is the button, group is its heading, value is what lands on the clipboard. Lines with no label are dropped. Saved to `,(0,x.jsx)(`code`,{className:`mono`,children:t.split(/[\\/]/).slice(-2).join(`/`)}),`, so Obsidian works too.`]}),(0,x.jsx)(`div`,{className:`copy__rows`,children:i.map((e,t)=>(0,x.jsxs)(`div`,{className:`copy__edit`,children:[(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(Zp,{size:`sm`,label:`Label`,value:e.label,onChange:e=>c(t,{label:e.target.value})}),(0,x.jsx)(Zp,{size:`sm`,label:`Group`,value:e.group,onChange:e=>c(t,{group:e.target.value})})]}),(0,x.jsx)(Xp,{label:`Value`,rows:e.value.includes(`
|
|
60
|
-
`)?4:1,value:e.value,onChange:e=>c(t,{value:e.target.value})}),(0,x.jsxs)(`div`,{className:`copy__edit-actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move up`,leadingIcon:(0,x.jsx)(H.ArrowUp,{}),disabled:t===0,onClick:()=>l(t,-1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move down`,leadingIcon:(0,x.jsx)(H.ArrowDown,{}),disabled:t===i.length-1,onClick:()=>l(t,1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`danger`,"aria-label":`Remove`,leadingIcon:(0,x.jsx)(H.Trash,{}),onClick:()=>u(t)})]})]},t))}),(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Plus,{}),onClick:()=>a(e=>[...e,{group:e[e.length-1]?.group??``,label:``,value:``}]),children:`Add a line`}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:n,children:`Cancel`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,loading:o,onClick:async()=>{s(!0);try{let e=await $.saveSnippets(i);X({title:`Copy panel saved`,description:`Profile/Snippets.md`,tone:`success`}),r(e)}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}s(!1)},children:`Save`})]})]})})})}var a_=[{page:`onboarding`,label:`Get started`,icon:H.Sparkles},{page:`today`,label:`Today`,icon:H.Star},{page:`overview`,label:`Overview`,icon:H.Home},{page:`jobs`,label:`Jobs`,icon:H.Inbox},{page:`pipeline`,label:`Pipeline`,icon:H.Layers},{page:`mail`,label:`Mail`,icon:H.Mail},{page:`people`,label:`People`,icon:H.Users},{page:`companies`,label:`Sources`,icon:H.Globe},{page:`criteria`,label:`Criteria`,icon:H.Filter},{page:`profile`,label:`Profile`,icon:H.User},{page:`runs`,label:`Runs`,icon:H.Refresh},{page:`agent`,label:`Agent access`,icon:H.Terminal},{page:`settings`,label:`Settings`,icon:H.Settings}],o_={onboarding:`Get started`,today:`Today`,overview:`Overview`,jobs:`Jobs`,pipeline:`Pipeline`,mail:`Mail`,people:`People`,companies:`Sources`,criteria:`Criteria`,profile:`Profile`,runs:`Runs`,agent:`Agent access`,settings:`Settings`},s_=[{title:`Work`,pages:[`today`,`jobs`,`pipeline`,`mail`,`people`]},{title:`Insights`,pages:[`overview`]},{title:`Setup`,pages:[`profile`,`criteria`,`companies`]},{title:`System`,pages:[`runs`,`agent`,`settings`,`onboarding`]}];function c_({page:e,onNavigate:t,onSearch:n,theme:r,onToggleTheme:i,onboarded:a=!0,counts:o={},lastScan:s=``,children:c}){let[l,u]=(0,b.useState)(!1),d=e_(`(max-width: 40rem)`),[f,p]=(0,b.useState)(``),[m,h]=(0,b.useState)(()=>{try{return localStorage.getItem(`tekjobs.sidebar`)===`collapsed`}catch{return!1}}),g=()=>h(e=>{try{localStorage.setItem(`tekjobs.sidebar`,e?`open`:`collapsed`)}catch{}return!e}),_=e=>{t(e),u(!1)};return(0,x.jsxs)(`div`,{className:`shell${m?` shell--collapsed`:``}${d?` shell--strip`:``}`,children:[(0,x.jsx)(`aside`,{className:`sidebar`,"aria-label":`Primary`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:m||d,onToggleCollapsed:d?void 0:g,tipSide:d?`bottom`:`right`})}),(0,x.jsxs)(`div`,{className:`main`,children:[(0,x.jsxs)(`header`,{className:`topbar`,children:[(0,x.jsxs)(Sp,{open:l,onOpenChange:u,side:`left`,size:`sm`,children:[(0,x.jsx)(Sp.Trigger,{asChild:!0,children:(0,x.jsx)(B,{className:`topbar__menu`,variant:`ghost`,size:`sm`,"aria-label":`Open navigation`,leadingIcon:(0,x.jsx)(H.Menu,{})})}),(0,x.jsxs)(Sp.Content,{children:[(0,x.jsx)(Sp.Title,{children:`Navigation`}),(0,x.jsx)(`div`,{className:`sidebar sidebar--sheet`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:!1})})]})]}),(0,x.jsx)(`h1`,{className:`topbar__title`,children:o_[e]}),(0,x.jsx)(`form`,{className:`topbar__search`,onSubmit:e=>{e.preventDefault(),n(f.trim())},children:(0,x.jsx)(Zp,{size:`sm`,placeholder:`Search company or role`,"aria-label":`Search jobs`,leadingIcon:(0,x.jsx)(H.Search,{}),trailingIcon:(0,x.jsx)(`span`,{className:`num`,children:`⌘K`}),value:f,onChange:e=>p(e.target.value)})}),(0,x.jsxs)(`div`,{className:`topbar__actions`,children:[(0,x.jsx)(r_,{}),(0,x.jsx)(Bh,{content:r===`light`?`Switch to dark`:`Switch to light`,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,onClick:i,"aria-label":`Toggle theme`,leadingIcon:r===`light`?(0,x.jsx)(H.Moon,{}):(0,x.jsx)(H.Sun,{})})})]})]}),c]})]})}function l_({page:e,onNavigate:t,onboarded:n,counts:r,lastScan:i,collapsed:a,onToggleCollapsed:o,tipSide:s=`right`}){let c=new Map(a_.map(e=>[e.page,e])),l=n?s_:[{title:`Start`,pages:[`onboarding`]},...s_.map(e=>({...e,pages:e.pages.filter(e=>e!==`onboarding`)}))];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`brand`,children:[(0,x.jsx)(n_,{}),o&&(0,x.jsx)(Bh,{content:a?`Expand the sidebar`:`Collapse the sidebar`,children:(0,x.jsx)(B,{className:`sidebar__collapse`,variant:`ghost`,size:`sm`,tone:`neutral`,"aria-label":a?`Expand the sidebar`:`Collapse the sidebar`,leadingIcon:a?(0,x.jsx)(H.ChevronRight,{}):(0,x.jsx)(H.ChevronLeft,{}),onClick:o})})]}),(0,x.jsx)(`nav`,{className:`nav`,"aria-label":`Pages`,children:l.map(n=>(0,x.jsxs)(`div`,{className:`nav__group`,children:[!a&&(0,x.jsx)(`div`,{className:`nav__group-title`,children:n.title}),n.pages.map(e=>c.get(e)).filter(e=>!!e).map(n=>{let i=(0,x.jsx)(B,{className:`nav__item`,align:`start`,variant:e===n.page?`soft`:`ghost`,tone:e===n.page?`primary`:`neutral`,size:`sm`,leadingIcon:(0,x.jsx)(n.icon,{}),trailingIcon:!a&&r[n.page]!=null?(0,x.jsx)(`span`,{className:`nav__count`,children:r[n.page]}):void 0,"aria-current":e===n.page?`page`:void 0,"aria-label":a?n.label:void 0,onClick:()=>t(n.page),children:a?null:n.label},n.page);return a?(0,x.jsx)(Bh,{content:r[n.page]==null?n.label:`${n.label} · ${r[n.page]}`,side:s,children:i},n.page):i})]},n.title))}),!a&&(0,x.jsx)(`div`,{className:`sidebar__foot`,children:(0,x.jsxs)(`div`,{children:[`Notes are the record.`,i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`br`,{}),(0,x.jsx)(`span`,{className:`num`,children:i})]}),(0,x.jsx)(`br`,{}),(0,x.jsxs)(`span`,{className:`num`,children:[`v`,`0.24.
|
|
60
|
+
`)?4:1,value:e.value,onChange:e=>c(t,{value:e.target.value})}),(0,x.jsxs)(`div`,{className:`copy__edit-actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move up`,leadingIcon:(0,x.jsx)(H.ArrowUp,{}),disabled:t===0,onClick:()=>l(t,-1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Move down`,leadingIcon:(0,x.jsx)(H.ArrowDown,{}),disabled:t===i.length-1,onClick:()=>l(t,1)}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`danger`,"aria-label":`Remove`,leadingIcon:(0,x.jsx)(H.Trash,{}),onClick:()=>u(t)})]})]},t))}),(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Plus,{}),onClick:()=>a(e=>[...e,{group:e[e.length-1]?.group??``,label:``,value:``}]),children:`Add a line`}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:n,children:`Cancel`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,loading:o,onClick:async()=>{s(!0);try{let e=await $.saveSnippets(i);X({title:`Copy panel saved`,description:`Profile/Snippets.md`,tone:`success`}),r(e)}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}s(!1)},children:`Save`})]})]})})})}var a_=[{page:`onboarding`,label:`Get started`,icon:H.Sparkles},{page:`today`,label:`Today`,icon:H.Star},{page:`overview`,label:`Overview`,icon:H.Home},{page:`jobs`,label:`Jobs`,icon:H.Inbox},{page:`pipeline`,label:`Pipeline`,icon:H.Layers},{page:`mail`,label:`Mail`,icon:H.Mail},{page:`people`,label:`People`,icon:H.Users},{page:`companies`,label:`Sources`,icon:H.Globe},{page:`criteria`,label:`Criteria`,icon:H.Filter},{page:`profile`,label:`Profile`,icon:H.User},{page:`runs`,label:`Runs`,icon:H.Refresh},{page:`agent`,label:`Agent access`,icon:H.Terminal},{page:`settings`,label:`Settings`,icon:H.Settings}],o_={onboarding:`Get started`,today:`Today`,overview:`Overview`,jobs:`Jobs`,pipeline:`Pipeline`,mail:`Mail`,people:`People`,companies:`Sources`,criteria:`Criteria`,profile:`Profile`,runs:`Runs`,agent:`Agent access`,settings:`Settings`},s_=[{title:`Work`,pages:[`today`,`jobs`,`pipeline`,`mail`,`people`]},{title:`Insights`,pages:[`overview`]},{title:`Setup`,pages:[`profile`,`criteria`,`companies`]},{title:`System`,pages:[`runs`,`agent`,`settings`,`onboarding`]}];function c_({page:e,onNavigate:t,onSearch:n,theme:r,onToggleTheme:i,onboarded:a=!0,counts:o={},lastScan:s=``,children:c}){let[l,u]=(0,b.useState)(!1),d=e_(`(max-width: 40rem)`),[f,p]=(0,b.useState)(``),[m,h]=(0,b.useState)(()=>{try{return localStorage.getItem(`tekjobs.sidebar`)===`collapsed`}catch{return!1}}),g=()=>h(e=>{try{localStorage.setItem(`tekjobs.sidebar`,e?`open`:`collapsed`)}catch{}return!e}),_=e=>{t(e),u(!1)};return(0,x.jsxs)(`div`,{className:`shell${m?` shell--collapsed`:``}${d?` shell--strip`:``}`,children:[(0,x.jsx)(`aside`,{className:`sidebar`,"aria-label":`Primary`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:m||d,onToggleCollapsed:d?void 0:g,tipSide:d?`bottom`:`right`})}),(0,x.jsxs)(`div`,{className:`main`,children:[(0,x.jsxs)(`header`,{className:`topbar`,children:[(0,x.jsxs)(Sp,{open:l,onOpenChange:u,side:`left`,size:`sm`,children:[(0,x.jsx)(Sp.Trigger,{asChild:!0,children:(0,x.jsx)(B,{className:`topbar__menu`,variant:`ghost`,size:`sm`,"aria-label":`Open navigation`,leadingIcon:(0,x.jsx)(H.Menu,{})})}),(0,x.jsxs)(Sp.Content,{children:[(0,x.jsx)(Sp.Title,{children:`Navigation`}),(0,x.jsx)(`div`,{className:`sidebar sidebar--sheet`,children:(0,x.jsx)(l_,{page:e,onNavigate:_,onboarded:a,counts:o,lastScan:s,collapsed:!1})})]})]}),(0,x.jsx)(`h1`,{className:`topbar__title`,children:o_[e]}),(0,x.jsx)(`form`,{className:`topbar__search`,onSubmit:e=>{e.preventDefault(),n(f.trim())},children:(0,x.jsx)(Zp,{size:`sm`,placeholder:`Search company or role`,"aria-label":`Search jobs`,leadingIcon:(0,x.jsx)(H.Search,{}),trailingIcon:(0,x.jsx)(`span`,{className:`num`,children:`⌘K`}),value:f,onChange:e=>p(e.target.value)})}),(0,x.jsxs)(`div`,{className:`topbar__actions`,children:[(0,x.jsx)(r_,{}),(0,x.jsx)(Bh,{content:r===`light`?`Switch to dark`:`Switch to light`,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,onClick:i,"aria-label":`Toggle theme`,leadingIcon:r===`light`?(0,x.jsx)(H.Moon,{}):(0,x.jsx)(H.Sun,{})})})]})]}),c]})]})}function l_({page:e,onNavigate:t,onboarded:n,counts:r,lastScan:i,collapsed:a,onToggleCollapsed:o,tipSide:s=`right`}){let c=new Map(a_.map(e=>[e.page,e])),l=n?s_:[{title:`Start`,pages:[`onboarding`]},...s_.map(e=>({...e,pages:e.pages.filter(e=>e!==`onboarding`)}))];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`brand`,children:[(0,x.jsx)(n_,{}),o&&(0,x.jsx)(Bh,{content:a?`Expand the sidebar`:`Collapse the sidebar`,children:(0,x.jsx)(B,{className:`sidebar__collapse`,variant:`ghost`,size:`sm`,tone:`neutral`,"aria-label":a?`Expand the sidebar`:`Collapse the sidebar`,leadingIcon:a?(0,x.jsx)(H.ChevronRight,{}):(0,x.jsx)(H.ChevronLeft,{}),onClick:o})})]}),(0,x.jsx)(`nav`,{className:`nav`,"aria-label":`Pages`,children:l.map(n=>(0,x.jsxs)(`div`,{className:`nav__group`,children:[!a&&(0,x.jsx)(`div`,{className:`nav__group-title`,children:n.title}),n.pages.map(e=>c.get(e)).filter(e=>!!e).map(n=>{let i=(0,x.jsx)(B,{className:`nav__item`,align:`start`,variant:e===n.page?`soft`:`ghost`,tone:e===n.page?`primary`:`neutral`,size:`sm`,leadingIcon:(0,x.jsx)(n.icon,{}),trailingIcon:!a&&r[n.page]!=null?(0,x.jsx)(`span`,{className:`nav__count`,children:r[n.page]}):void 0,"aria-current":e===n.page?`page`:void 0,"aria-label":a?n.label:void 0,onClick:()=>t(n.page),children:a?null:n.label},n.page);return a?(0,x.jsx)(Bh,{content:r[n.page]==null?n.label:`${n.label} · ${r[n.page]}`,side:s,children:i},n.page):i})]},n.title))}),!a&&(0,x.jsx)(`div`,{className:`sidebar__foot`,children:(0,x.jsxs)(`div`,{children:[`Notes are the record.`,i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`br`,{}),(0,x.jsx)(`span`,{className:`num`,children:i})]}),(0,x.jsx)(`br`,{}),(0,x.jsxs)(`span`,{className:`num`,children:[`v`,`0.24.2`]}),(0,x.jsx)(`br`,{}),(0,x.jsx)(`a`,{className:`sidebar__legal`,href:`https://tekjobs.timurtek.com/legal/terms`,target:`_blank`,rel:`noreferrer`,children:`Terms`}),` · `,(0,x.jsx)(`a`,{className:`sidebar__legal`,href:`https://tekjobs.timurtek.com/legal/privacy`,target:`_blank`,rel:`noreferrer`,children:`Privacy`})]})})]})}var u_=`{
|
|
61
61
|
"mcpServers": {
|
|
62
62
|
"tekjobs": {
|
|
63
63
|
"command": "node",
|
|
@@ -73,5 +73,5 @@ Defaulting to \`null\`.`}md(Ad,`getInvalidValueError`);var jd=xd,Md=Cd;(0,b.forw
|
|
|
73
73
|
`),[s,c]=(0,b.useState)(()=>o(n)),[l,u]=(0,b.useState)(``);return(0,b.useEffect)(()=>{c(o(n)),u(``)},[n]),(0,x.jsx)(Xp,{label:e,description:t,font:`mono`,rows:i,resize:`vertical`,value:s,onChange:e=>c(e.target.value),onBlur:()=>{let e=s.split(`
|
|
74
74
|
`).map(e=>e.trim()).filter(Boolean);if(!r){u(``),a(e);return}let t={};for(let n of e){let e=n.match(/^(.*?)\s*:\s*(-?\d+(?:\.\d+)?)\s*$/);if(!e||!e[1]){u(`"${n}" is not "term: weight".`);return}t[e[1].trim().toLowerCase()]=Number(e[2])}u(``),a(t)},error:l||void 0})}function O_(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(``),[i,a]=(0,b.useState)(x_),[o,s]=(0,b.useState)([]),[c,l]=(0,b.useState)(!1),[u,d]=(0,b.useState)(``),[f,p]=(0,b.useState)(``),[m,h]=(0,b.useState)(null),[g,_]=(0,b.useState)(!1),[v,y]=(0,b.useState)(null),[S,C]=(0,b.useState)(!1),[w,T]=(0,b.useState)(null),E=(0,b.useRef)(null),[D,O]=(0,b.useState)(null),[k,A]=(0,b.useState)(!1),j=(0,b.useMemo)(()=>e?JSON.stringify(e,null,2):``,[e]),ee=e!==null&&j!==n,M=i!==x_;(0,b.useEffect)(()=>{if(E.current&&window.clearTimeout(E.current),!ee||M){T(null);return}return E.current=window.setTimeout(()=>{$.previewCriteria(j).then(T).catch(()=>T(null))},700),()=>{E.current&&window.clearTimeout(E.current)}},[j,ee,M]),(0,b.useEffect)(()=>{if(!ee)return;let e=e=>{e.preventDefault()};return window.addEventListener(`beforeunload`,e),()=>window.removeEventListener(`beforeunload`,e)},[ee]);let N=()=>$.criteriaPresets().then(s).catch(()=>s([])),te=async e=>{try{let n=e===x_?await $.criteria():await $.criteriaPreset(e);if(!n.parsed)throw Error(`That note's JSON does not parse. Fix it in Obsidian first.`);t(n.parsed),r(JSON.stringify(n.parsed,null,2)),d(JSON.stringify(n.parsed,null,2)),p(``),a(e)}catch(e){X({title:`Could not load criteria`,description:e.message,tone:`danger`})}};(0,b.useEffect)(()=>{te(x_),N()},[]),(0,b.useEffect)(()=>{d(j),p(``)},[j]);let P=e=>t(e),F=async()=>{if(e){l(!0);try{if(M){let e=await $.saveCriteriaPreset(i,j);r(JSON.stringify(e.parsed,null,2)),X({title:`Preset "${i}" saved`,description:`Run a scan with it from here or from Runs; make it active to have the daily scan use it.`,tone:`success`})}else{let e=!!w?.weightsChange,t=w?w.notesAtCurrent:0,n=await $.saveCriteria(j);r(JSON.stringify(n.parsed,null,2)),X({title:`Criteria saved`,description:`Targets/Search Criteria.md updated. The next scan uses it.`,tone:`success`}),O(e&&t>0?{notes:t}:null)}N()}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}l(!1)}},ne=async()=>{if(e&&m?.trim()){l(!0);try{let e=await $.saveCriteriaPreset(m.trim(),j);h(null),await N(),a(e.name),r(JSON.stringify(e.parsed,null,2)),X({title:`Preset "${e.name}" created`,description:e.file,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}l(!1)}},re=async()=>{l(!0);try{await $.activateCriteriaPreset(i),await N(),X({title:`"${i}" is now the active criteria`,description:`Search Criteria.md holds a copy. The daily scan uses it from the next run.`,tone:`success`})}catch(e){X({title:`Could not activate`,description:e.message,tone:`danger`})}l(!1)},ie=async()=>{l(!0);try{await $.deleteCriteriaPreset(i),_(!1),await N(),await te(x_),X({title:`Preset deleted`,tone:`success`})}catch(e){X({title:`Could not delete`,description:e.message,tone:`danger`})}l(!1)},ae=async e=>{try{await $.startScan(e,M?i:void 0),X({title:e?`Dry run started`:`Scan started`,description:`Scoring with ${M?`"${i}"`:`the active criteria`}. Watch it on Runs.`,tone:`success`})}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},oe=async()=>{A(!0);try{let e=await $.rescoreNotes(!1);O(null),X({title:`${e.changed} note${e.changed===1?``:`s`} rescored`,description:`${e.alreadyCurrent} were already at these weights. Each moved note carries the new score, band and reasons, and a status-log line saying so.`,tone:`success`})}catch(e){X({title:`Rescore failed`,description:e.message,tone:`danger`})}A(!1)},se=async()=>{if(w){y(w);return}C(!0);try{y(await $.previewCriteria(j))}catch(e){X({title:`Could not preview`,description:e.message,tone:`danger`})}C(!1)},ce=()=>{try{let e=JSON.parse(u);t(e),p(``)}catch(e){p(e.message)}};if(!e)return(0,x.jsx)(zg,{variant:`rect`,height:`24rem`});let le=e.salary??{},ue={...Object.fromEntries(S_.map(e=>[e,!1])),...e.openSources??{}},de=o.find(e=>e.name===i);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[`What the scan looks for and how it scores. Fields write into the JSON in `,M?(0,x.jsxs)(`code`,{children:[`Targets/Criteria/`,i,`.md`]}):(0,x.jsx)(`code`,{children:`Targets/Search Criteria.md`}),`; keys this form does not show are kept as they are.`]})}),(0,x.jsxs)(`div`,{className:`chips`,children:[(0,x.jsxs)(z,{tone:`neutral`,size:`sm`,children:[`bar `,String(e.minScore??`?`)]}),le.minAnnual&&(0,x.jsxs)(z,{tone:`success`,size:`sm`,children:[`floor `,Jg(le.minAnnual)]}),le.stretchAnnual&&(0,x.jsxs)(z,{tone:`warning`,size:`sm`,children:[`stretch `,Jg(le.stretchAnnual)]}),ee&&(0,x.jsx)(z,{tone:`warning`,size:`sm`,children:`unsaved`})]})]}),(0,x.jsxs)(V,{padding:`md`,children:[(0,x.jsxs)(`div`,{className:`toolbar`,children:[(0,x.jsxs)(J,{className:`toolbar__filter toolbar__filter--wide`,size:`sm`,label:`Editing`,value:i,onValueChange:e=>{(!ee||window.confirm(`Discard unsaved changes?`))&&te(e)},children:[(0,x.jsx)(J.Item,{value:x_,children:`Active criteria (daily scan)`}),o.map(e=>(0,x.jsxs)(J.Item,{value:e.name,children:[e.name,e.active?` · same as active`:``]},e.name))]}),(0,x.jsx)(`div`,{className:`toolbar__spacer`}),(0,x.jsxs)(`div`,{className:`toolbar__switch pager__buttons`,children:[M&&(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`danger`,disabled:c,onClick:()=>_(!0),children:`Delete preset`}),M&&(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:c||ee||de?.active,onClick:re,children:de?.active?`Is the active set`:`Make active`}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:c||S,loading:S,onClick:se,children:`Preview impact`}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:c,onClick:()=>h(M?`${i} copy`:``),children:`Save as preset…`}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:c||ee,onClick:()=>ae(!0),children:`Dry run with this`}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:c||ee,onClick:()=>ae(!1),children:`Scan with this`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:!ee||c,loading:c,onClick:F,children:M?`Save preset`:`Save to the vault`})]})]}),M&&de&&(0,x.jsxs)(`p`,{className:`muted`,children:[`Preset · `,de.titles,` title terms · updated `,de.updated,` · `,de.file]}),w&&(0,x.jsxs)(`div`,{className:`impact`,role:`status`,"aria-live":`polite`,children:[(0,x.jsx)(`span`,{className:`microlabel`,children:`If saved`}),(0,x.jsxs)(z,{size:`sm`,tone:w.aboveAfter>=w.aboveBefore?`success`:`warning`,children:[`above the bar `,w.aboveBefore,` → `,w.aboveAfter]}),(0,x.jsxs)(z,{size:`sm`,tone:w.changed?`primary`:`neutral`,children:[w.changed,` of `,w.openNotes,` change score`]}),(0,x.jsxs)(z,{size:`sm`,tone:w.rise.length?`success`:`neutral`,children:[w.rise.length,` rise`]}),(0,x.jsxs)(z,{size:`sm`,tone:w.fall.length?`warning`:`neutral`,children:[w.fall.length,` fall`]}),(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,children:[`top 20: `,w.enterTop20.length,` in, `,w.leaveTop20.length,` out`]}),w.weightsChange&&(0,x.jsx)(z,{size:`sm`,tone:`neutral`,variant:`outline`,children:(0,x.jsxs)(`span`,{className:`num`,children:[w.fingerprintBefore,` → `,w.fingerprintAfter]})}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,onClick:()=>y(w),children:`Details`})]}),D&&!ee&&(0,x.jsxs)(`div`,{className:`impact impact--after`,children:[(0,x.jsx)(`span`,{className:`microlabel`,children:`Saved`}),(0,x.jsxs)(`span`,{children:[D.notes,` open note`,D.notes===1?` was`:`s were`,` scored under the previous weights. The next scan scores new postings with the new ones; the existing notes keep their scores until you rescore them.`]}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsxs)(B,{size:`sm`,variant:`soft`,tone:`primary`,loading:k,disabled:k,onClick:oe,children:[`Rescore `,D.notes,` notes`]}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,disabled:k,onClick:()=>O(null),children:`Later`})]})]}),(0,x.jsxs)(Z,{defaultValue:`fields`,variant:`line`,size:`sm`,children:[(0,x.jsxs)(Z.List,{"aria-label":`Criteria editors`,children:[(0,x.jsx)(Z.Trigger,{value:`fields`,children:`Fields`}),(0,x.jsx)(Z.Trigger,{value:`titles`,children:`Titles and terms`}),(0,x.jsx)(Z.Trigger,{value:`location`,children:`Location and pay`}),(0,x.jsx)(Z.Trigger,{value:`sources`,children:`Sources`}),(0,x.jsx)(Z.Trigger,{value:`json`,children:`JSON (advanced)`})]}),(0,x.jsx)(Z.Content,{value:`fields`,children:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`minScore`],label:`Bar (minScore)`,hint:`A posting needs this many points to become a note.`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`noTitleMatchPenalty`],label:`No title match penalty`,hint:`Taken when the title matches nothing in the title terms.`,onChange:P})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`descCap`],label:`Description points cap`,hint:`Description terms add up to this many points, no more.`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`maxDescriptionChars`],label:`Description characters kept in a note`,onChange:P,step:500})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`titleExtraPer`],label:`Points per extra title match`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`titleExtraCap`],label:`Extra title matches cap`,onChange:P})]}),(0,x.jsx)(`h3`,{children:`Seniority`}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(D_,{label:`Boost (word: points)`,hint:`Words in the title that add. Example: staff: 10`,value:w_(e,[`seniority`,`boost`]),weighted:!0,rows:6,onCommit:t=>P(T_(e,[`seniority`,`boost`],t))}),(0,x.jsx)(D_,{label:`Penalty (word: points)`,hint:`Words in the title that subtract. Example: junior: -40`,value:w_(e,[`seniority`,`penalty`]),weighted:!0,rows:6,onCommit:t=>P(T_(e,[`seniority`,`penalty`],t))})]}),(0,x.jsx)(`h3`,{children:`Recency`}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`recency`,`days2`],label:`Posted within 2 days`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`recency`,`days7`],label:`Within 7 days`,onChange:P})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`recency`,`days30`],label:`Within 30 days`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`recency`,`days90`],label:`Within 90 days`,onChange:P})]}),(0,x.jsx)(`div`,{className:`form__row`,children:(0,x.jsx)(E_,{doc:e,path:[`recency`,`older`],label:`Older than 90 days`,onChange:P})})]})})}),(0,x.jsx)(Z.Content,{value:`titles`,children:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(D_,{label:`Title terms (term: weight)`,hint:`The best single match in the title counts fully; each extra match adds the per-extra points. One per line.`,value:e.titleTerms,weighted:!0,rows:18,onCommit:t=>P(T_(e,[`titleTerms`],t))}),(0,x.jsx)(D_,{label:`Title exclusions (one per line)`,hint:`Any hit in the title drops the posting entirely.`,value:e.titleExclude,weighted:!1,rows:18,onCommit:t=>P(T_(e,[`titleExclude`],t))})]}),(0,x.jsx)(D_,{label:`Description terms (term: weight)`,hint:`Each term found in the description adds its weight, up to the description cap.`,value:e.descTerms,weighted:!0,rows:14,onCommit:t=>P(T_(e,[`descTerms`],t))})]})})}),(0,x.jsx)(Z.Content,{value:`location`,children:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsx)(`h3`,{children:`Location`}),(0,x.jsx)(Hp,{label:`Remote only`,description:`Anything not remote takes the penalty below, which drops it under the bar.`,checked:!!w_(e,[`location`,`requireRemote`]),onCheckedChange:t=>P(T_(e,[`location`,`requireRemote`],t===!0))}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`location`,`notRemotePenalty`],label:`Not remote penalty`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`location`,`remoteBoost`],label:`Remote boost`,onChange:P})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`location`,`nonUsPenalty`],label:`Non-US penalty`,hint:`Applied when the location names a place in the list below and nothing US.`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`location`,`bayAreaBoost`],label:`Metro boost`,hint:`For the metro terms below. Set to 0 to switch it off.`,onChange:P})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(D_,{label:`Metro terms (one per line)`,hint:`Places that earn the metro boost. The interview seeds these from your location; empty the list for no boost.`,value:w_(e,[`location`,`bayAreaTerms`]),weighted:!1,rows:8,onCommit:t=>P(T_(e,[`location`,`bayAreaTerms`],t))}),(0,x.jsx)(D_,{label:`US terms (one per line)`,hint:`Words that mark a posting as US.`,value:w_(e,[`location`,`usTerms`]),weighted:!1,rows:8,onCommit:t=>P(T_(e,[`location`,`usTerms`],t))})]}),(0,x.jsx)(D_,{label:`Non-US terms (one per line)`,hint:`Places that trigger the non-US penalty. Whole words.`,value:w_(e,[`location`,`nonUsTerms`]),weighted:!1,rows:10,onCommit:t=>P(T_(e,[`location`,`nonUsTerms`],t))}),(0,x.jsx)(`h3`,{children:`Pay`}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`salary`,`minAnnual`],label:`Floor (annual)`,hint:`A stated range that tops out at or above this earns the bonus.`,onChange:P,step:5e3}),(0,x.jsx)(E_,{doc:e,path:[`salary`,`stretchAnnual`],label:`Stretch (annual)`,hint:`Between stretch and floor is the stretch band: kept visible, small penalty.`,onChange:P,step:5e3})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`salary`,`meetsBonus`],label:`Meets floor bonus`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`salary`,`stretchPenalty`],label:`Stretch band penalty`,onChange:P})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(E_,{doc:e,path:[`salary`,`belowPenalty`],label:`Below stretch penalty`,onChange:P}),(0,x.jsx)(E_,{doc:e,path:[`salary`,`abovePer10k`],label:`Points per $10k above floor`,hint:`Capped at ${String(w_(e,[`salary`,`aboveCap`])??`?`)} (aboveCap).`,onChange:P})]})]})})}),(0,x.jsx)(Z.Content,{value:`sources`,children:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`Aggregator feeds with no company slug. Company boards live on the Companies page. Adzuna and USAJOBS also need a free key in the environment.`}),(0,x.jsx)(`div`,{className:`form__row`,children:Object.keys(ue).map(t=>(0,x.jsx)(Hp,{label:C_[t]??t,checked:!!ue[t],onCheckedChange:n=>P(T_(e,[`openSources`,t],n===!0))},t))})]})})}),(0,x.jsx)(Z.Content,{value:`json`,children:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsx)(Xp,{label:`Criteria JSON`,description:`The whole document. Apply to push it into the fields; Save to write it to the vault.`,font:`mono`,rows:28,resize:`vertical`,value:u,onChange:e=>d(e.target.value),error:f||void 0}),(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:u===j,onClick:()=>{d(j),p(``)},children:`Revert`}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:u===j,onClick:ce,children:`Apply to fields`})]})]})})})]}),(0,x.jsx)(W,{open:v!==null,onOpenChange:e=>!e&&y(null),size:`lg`,children:(0,x.jsxs)(W.Content,{children:[(0,x.jsx)(W.Title,{children:`What this set would do to the notes you have`}),(0,x.jsxs)(W.Description,{children:[`Against the active criteria. Covers `,v?.covers,`. Nothing is written by a preview.`,v?.weightsChange?` The weights change (${v.fingerprintBefore} → ${v.fingerprintAfter}); ${v.notesAtCurrent} open notes were scored under the current ones and can be rescored after saving.`:` The weights do not change; only the bar or the sources do.`]}),v&&(0,x.jsxs)(`div`,{className:`preview`,children:[(0,x.jsxs)(`div`,{className:`chips`,children:[(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,children:[v.openNotes,` open notes`]}),(0,x.jsxs)(z,{size:`sm`,tone:v.changed?`primary`:`neutral`,children:[v.changed,` change score`]}),(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,children:[`bar `,v.barBefore,` → `,v.barAfter]}),(0,x.jsxs)(z,{size:`sm`,tone:v.aboveAfter>=v.aboveBefore?`success`:`warning`,children:[`above the bar `,v.aboveBefore,` → `,v.aboveAfter]})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(b_,{title:`Rise above the bar`,rows:v.rise,empty:`Nothing crosses upward.`}),(0,x.jsx)(b_,{title:`Fall below the bar`,rows:v.fall,empty:`Nothing drops out.`})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(b_,{title:`Enter the top 20`,rows:v.enterTop20,empty:`The top 20 keeps its members.`}),(0,x.jsx)(b_,{title:`Leave the top 20`,rows:v.leaveTop20,empty:`The top 20 keeps its members.`})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(b_,{title:`Biggest gains`,rows:v.up,empty:`No note gains points.`}),(0,x.jsx)(b_,{title:`Biggest losses`,rows:v.down,empty:`No note loses points.`})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(y_,{title:`By role family`,rows:v.byKind,barBefore:v.barBefore,barAfter:v.barAfter}),(0,x.jsx)(y_,{title:`By source`,rows:v.bySource,barBefore:v.barBefore,barAfter:v.barAfter})]})]}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,children:`Close`})}),ee&&(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:c,onClick:()=>{y(null),F()},children:M?`Save preset`:`Save to the vault`})]})]})}),(0,x.jsx)(W,{open:m!==null,onOpenChange:e=>!e&&h(null),size:`sm`,children:(0,x.jsxs)(W.Content,{children:[(0,x.jsx)(W.Title,{children:`Save as a preset`}),(0,x.jsx)(W.Description,{children:`A named copy under Targets/Criteria/. The daily scan keeps using the active set until you make this one active.`}),(0,x.jsx)(Zp,{label:`Name`,placeholder:`Wider net, 180k floor`,value:m??``,onChange:e=>h(e.target.value)}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,children:`Cancel`})}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:!m?.trim()||c,loading:c,onClick:ne,children:`Save preset`})]})]})}),(0,x.jsx)(W,{open:g,onOpenChange:_,size:`sm`,children:(0,x.jsxs)(W.Content,{children:[(0,x.jsxs)(W.Title,{children:[`Delete "`,i,`"?`]}),(0,x.jsx)(W.Description,{children:`Removes the note under Targets/Criteria/. The active criteria and every job note stay as they are.`}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,children:`Keep it`})}),(0,x.jsx)(B,{size:`sm`,tone:`danger`,disabled:c,loading:c,onClick:ie,children:`Delete`})]})]})})]})}function k_({job:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),[a,o]=(0,b.useState)({emphasis:`auto`,length:`standard`,extra:``}),[s,c]=(0,b.useState)(!1),l=(0,b.useRef)(!1),u=(e,t)=>{n(e),t&&i(e.saved?.text??``)};(0,b.useEffect)(()=>{n(null),$.coverLetter(e.id).then(e=>u(e,!0)).catch(e=>X({title:`Could not read the letter`,description:e.message,tone:`danger`}))},[e.id]),(0,b.useEffect)(()=>{if(!t?.running){l.current&&t&&(l.current=!1,u(t,!t.error),t.error||X({title:`Cover letter drafted`,description:`Saved into the note. Read it before you use it.`,tone:`success`}));return}l.current=!0;let r=setInterval(()=>$.coverLetter(e.id).then(e=>n(e)).catch(()=>{}),2500);return()=>clearInterval(r)},[t?.running,e.id]);let d=async()=>{if(!t?.saved||window.confirm(`Write a new letter? It replaces the one saved in this note.`))try{u(await $.writeCoverLetter(e.id,a),!1)}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},f=async()=>{c(!0);try{u(await $.saveCoverLetter(e.id,r),!0),X({title:`Letter saved`,description:`Written into the note and checked against your resume.`,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}c(!1)},p=async()=>{try{await navigator.clipboard.writeText(r),X({title:`Copied`,tone:`success`})}catch{X({title:`Could not copy`,description:`Select the text and copy it by hand.`,tone:`danger`})}};if(!t)return(0,x.jsx)(`div`,{className:`detail`,children:(0,x.jsx)(zg,{lines:6})});let m=t.saved,h=!!m&&r!==m.text;return(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsxs)(`div`,{className:`letter__options`,children:[(0,x.jsxs)(J,{size:`sm`,label:`Emphasis`,value:a.emphasis,onValueChange:e=>o({...a,emphasis:e}),disabled:t.running,children:[(0,x.jsx)(J.Item,{value:`auto`,children:`Let the posting decide`}),(0,x.jsx)(J.Item,{value:`design-systems`,children:`Design systems first`}),(0,x.jsx)(J.Item,{value:`ai-product`,children:`AI product surfaces first`})]}),(0,x.jsxs)(J,{size:`sm`,label:`Length`,value:a.length,onValueChange:e=>o({...a,length:e}),disabled:t.running,children:[(0,x.jsx)(J.Item,{value:`short`,children:`Short, about 150 words`}),(0,x.jsx)(J.Item,{value:`standard`,children:`Standard, about 220 words`})]})]}),(0,x.jsx)(Zp,{size:`sm`,label:`Anything it should include`,description:`Optional. A person you spoke to, a product of theirs you use, a point to make.`,value:a.extra,onChange:e=>o({...a,extra:e.target.value}),disabled:t.running}),(0,x.jsxs)(`div`,{className:`form__actions form__actions--start`,children:[(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:d,disabled:t.running,leadingIcon:t.running?(0,x.jsx)(Bg,{size:`sm`}):(0,x.jsx)(H.Sparkles,{}),children:t.running?`Writing`:m?`Write a new one`:`Write cover letter`}),m&&(0,x.jsx)(B,{variant:`soft`,size:`sm`,onClick:p,leadingIcon:(0,x.jsx)(H.Copy,{}),children:`Copy`}),h&&(0,x.jsx)(B,{variant:`soft`,tone:`primary`,size:`sm`,onClick:f,loading:s,children:`Save edits`})]}),t.running&&(0,x.jsx)(Bg,{showLabel:!0,label:`${t.runner} is writing from your resume and this posting`,size:`sm`}),t.error&&!t.running&&(0,x.jsx)(Vg,{tone:`danger`,size:`sm`,icon:(0,x.jsx)(H.Warning,{}),title:t.errorKind===`auth`?`${t.runner} is signed out`:t.errorKind===`missing`?`${t.runner} is not installed`:t.errorKind===`outdated`?`${t.runner} is out of date`:`The letter was not written`,description:`${t.error} You can also ask any agent connected to the TekJobs MCP server to write it: "write the cover letter for ${e.company}".`}),!m&&!t.running&&!t.error&&(0,x.jsx)(Vg,{size:`sm`,icon:(0,x.jsx)(H.File,{}),title:`No letter yet`,description:`It is written from your resume and ${e.company}'s posting, and only your resume supplies the facts.`}),m&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Xp,{label:`Cover letter`,rows:16,resize:`vertical`,value:r,onChange:e=>i(e.target.value),description:`Edit freely. Saving checks it against your resume again.`}),(0,x.jsxs)(`div`,{className:`letter__meta`,children:[(0,x.jsxs)(z,{tone:`neutral`,size:`sm`,children:[m.words,` words`]}),m.warnings.length===0?(0,x.jsx)(z,{tone:`success`,size:`sm`,children:`Nothing flagged`}):(0,x.jsxs)(z,{tone:`warning`,size:`sm`,children:[m.warnings.length,` to check`]}),h&&(0,x.jsx)(z,{tone:`primary`,variant:`outline`,size:`sm`,children:`Unsaved edits`})]}),m.warnings.length>0&&(0,x.jsx)(`ul`,{className:`letter__warnings`,children:m.warnings.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(z,{tone:e.kind===`claim`||e.kind===`placeholder`?`danger`:`warning`,size:`sm`,children:e.kind}),(0,x.jsx)(`span`,{children:e.text})]},e.text))})]}),(0,x.jsx)(`p`,{className:`muted`,children:`The letter is saved under "Cover letter" in the job note. Nothing is sent from here; you paste it where the application asks for it.`})]})}var A_={recruiter:`recruiter`,"hiring-manager":`hiring manager`,interviewer:`interviewer`,referral:`referral`,other:`contact`},j_={recruiter:`primary`,"hiring-manager":`warning`,interviewer:`neutral`,referral:`success`,other:`neutral`},M_=e=>qg.includes(e)?e:`other`;function N_(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(``),[i,a]=(0,b.useState)(`all`),[o,s]=(0,b.useState)(null),c=()=>$.people().then(t).catch(e=>X({title:`Could not load people`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{c()},[]);let l=(0,b.useMemo)(()=>{let t=n.trim().toLowerCase();return(e??[]).filter(e=>(i===`all`||e.role===i)&&(!t||`${e.name} ${e.company} ${e.email}`.toLowerCase().includes(t)))},[e,n,i]);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`toolbar`,children:[(0,x.jsx)(Zp,{className:`toolbar__search`,size:`sm`,label:`Search`,placeholder:`Name, company or email`,value:n,onChange:e=>r(e.target.value)}),(0,x.jsxs)(J,{className:`toolbar__filter`,size:`sm`,label:`Role`,value:i,onValueChange:a,children:[(0,x.jsx)(J.Item,{value:`all`,children:`Everyone`}),qg.map(e=>(0,x.jsx)(J.Item,{value:e,children:A_[e]},e))]}),(0,x.jsx)(`span`,{className:`toolbar__spacer`}),(0,x.jsx)(P_,{onAdded:e=>{c(),s(e.id)}})]}),(0,x.jsx)(V,{padding:`none`,children:e===null?(0,x.jsx)(`div`,{className:`loading`,children:(0,x.jsx)(zg,{lines:6})}):e.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`No people yet`,description:`Confirming an email that a person wrote adds them here, with the thread. Or add someone: a recruiter who reached out, a referral, the hiring manager you met.`}):(0,x.jsxs)(Y,{"aria-label":`People`,density:`md`,stickyHeader:!0,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Name`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Email`}),(0,x.jsx)(Y.HeadCell,{children:`Last contact`}),(0,x.jsx)(Y.HeadCell,{children:`Threads`})]})}),(0,x.jsx)(Y.Body,{children:l.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,selected:o===e.id,onClick:()=>s(e.id),children:[(0,x.jsx)(Y.Cell,{children:e.name}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:j_[M_(e.role)],variant:`soft`,children:A_[M_(e.role)]})}),(0,x.jsx)(Y.Cell,{children:e.company||(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:e.email||`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num`,children:e.lastContact?`${e.lastContact} · ${Xg(e.lastContact)}`:`—`})}),(0,x.jsxs)(Y.Cell,{children:[(0,x.jsx)(`span`,{className:`num`,children:e.threads.length}),e.live>0&&(0,x.jsxs)(`span`,{className:`muted`,children:[` · `,e.live,` live`]})]})]},e.id))})]})}),(0,x.jsxs)(`p`,{className:`muted`,children:[l.length,` of `,e?.length??0,` people. Notes live in `,(0,x.jsx)(`code`,{className:`mono`,children:`People/`}),`; a job note lists its people under `,(0,x.jsx)(`code`,{className:`mono`,children:`## People`}),`.`]}),(0,x.jsx)(F_,{id:o,onClose:()=>s(null),onChanged:c})]})}function P_({onAdded:e,job:t}){let[n,r]=(0,b.useState)(!1),i={name:``,role:`recruiter`,company:t?.company??``,email:``,links:``,about:``},[a,o]=(0,b.useState)(i),[s,c]=(0,b.useState)(!1);return(0,x.jsxs)(W,{open:n,onOpenChange:r,size:`sm`,children:[(0,x.jsx)(W.Trigger,{asChild:!0,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,leadingIcon:(0,x.jsx)(H.Plus,{}),children:`Add a person`})}),(0,x.jsx)(W.Content,{children:(0,x.jsxs)(`form`,{className:`form`,onSubmit:async n=>{n.preventDefault(),c(!0);try{let n=await $.addPerson({...a,jobId:t?.id});r(!1),o(i),X({title:`${n.name} ${n.created===new Date().toISOString().slice(0,10)?`added`:`recognised`}`,description:t?`On ${t.company} - ${t.title}.`:`People/${n.id}.md`,tone:`success`}),e(n)}catch(e){X({title:`Not added`,description:e.message,tone:`danger`})}c(!1)},children:[(0,x.jsx)(W.Title,{children:t?`Someone on ${t.company}`:`Add a person`}),(0,x.jsx)(W.Description,{children:`A note under People/. Someone already there, by email or by name at the same company, is recognised rather than duplicated.`}),(0,x.jsx)(Zp,{label:`Name`,required:!0,value:a.name,onChange:e=>o({...a,name:e.target.value})}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(J,{label:`Role`,value:a.role,onValueChange:e=>o({...a,role:e}),children:qg.map(e=>(0,x.jsx)(J.Item,{value:e,children:A_[e]},e))}),(0,x.jsx)(Zp,{label:`Company`,value:a.company,onChange:e=>o({...a,company:e.target.value})})]}),(0,x.jsx)(Zp,{label:`Email`,type:`email`,value:a.email,onChange:e=>o({...a,email:e.target.value})}),(0,x.jsx)(Zp,{label:`Links`,description:`LinkedIn or anything else, as text.`,value:a.links,onChange:e=>o({...a,links:e.target.value})}),(0,x.jsx)(Zp,{label:`About`,description:`How you know them, in a line.`,value:a.about,onChange:e=>o({...a,about:e.target.value})}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,children:`Cancel`})}),(0,x.jsx)(B,{type:`submit`,tone:`primary`,loading:s,children:`Add`})]})]})})]})}function F_({id:e,onClose:t,onChanged:n}){let[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)(``),[s,c]=(0,b.useState)(!1);return(0,b.useEffect)(()=>{i(null),e&&$.person(e).then(i).catch(e=>X({title:`Could not open the note`,description:e.message,tone:`danger`}))},[e]),(0,x.jsx)(Sp,{open:e!==null,onOpenChange:e=>!e&&t(),side:`right`,size:`md`,children:(0,x.jsx)(Sp.Content,{children:r?(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsxs)(`div`,{className:`sheet-head`,children:[(0,x.jsxs)(`div`,{className:`sheet-head__main`,children:[(0,x.jsxs)(`p`,{className:`sheet-head__meta`,children:[r.company||`no company`,r.created?` · since ${r.created}`:``]}),(0,x.jsx)(Sp.Title,{children:r.name}),(0,x.jsxs)(`div`,{className:`chips`,children:[(0,x.jsx)(z,{size:`sm`,tone:j_[M_(r.role)],variant:`soft`,children:A_[M_(r.role)]}),r.email&&(0,x.jsx)(z,{size:`sm`,tone:`neutral`,variant:`outline`,children:(0,x.jsx)(`span`,{className:`num`,children:r.email})}),r.lastContact&&(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,variant:`outline`,children:[`last contact `,(0,x.jsx)(`span`,{className:`num`,children:r.lastContact})]})]})]}),(0,x.jsx)(`div`,{className:`sheet-head__side`,children:(0,x.jsxs)(`div`,{className:`sheet-head__links`,children:[r.email&&(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,children:(0,x.jsx)(`a`,{href:`mailto:${r.email}`,children:`Write to them ↗`})}),(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,children:(0,x.jsx)(`a`,{href:r.obsidianUrl,title:r.path,children:`Open in Obsidian ↗`})})]})})]}),(r.about||r.links)&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`About`}),(0,x.jsxs)(`p`,{className:`muted`,children:[r.about,r.links?` ${r.links}`:``]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`Threads`}),r.threads.length===0?(0,x.jsx)(`p`,{className:`muted`,children:`On no job note yet.`}):(0,x.jsx)(`ul`,{className:`people__threads`,children:r.threads.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(`a`,{className:`people__thread`,href:`#/jobs?q=${encodeURIComponent(e.title.split(` - `)[0]??e.title)}`,children:e.title}),e.status&&(0,x.jsx)(z,{size:`sm`,tone:$g[e.status]??`neutral`,children:e.status}),e.role&&(0,x.jsxs)(`span`,{className:`muted`,children:[` · `,e.role]})]},e.id))})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`Log`}),(0,x.jsx)(dg,{text:r.log||`_Nothing logged yet._`})]}),(0,x.jsx)(Xp,{label:`Log a contact`,rows:3,value:a,onChange:e=>o(e.target.value),placeholder:`A call, a reply, a note to self. Dated today, moves last contact forward. Nothing is sent.`}),(0,x.jsx)(`div`,{className:`form__actions`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:async()=>{if(r&&a.trim()){c(!0);try{i(await $.logContact(r.id,a.trim())),o(``),n(),X({title:`Logged`,description:`On People/${r.id}.md; last contact is today.`,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}c(!1)}},disabled:s||!a.trim(),children:`Log it`})})]}):(0,x.jsx)(`div`,{className:`detail`,children:(0,x.jsx)(zg,{lines:5})})})})}function I_({job:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)([]),[a,o]=(0,b.useState)(``),[s,c]=(0,b.useState)(`recruiter`),[l,u]=(0,b.useState)(``),[d,f]=(0,b.useState)(!1),p=()=>$.jobPeople(e.id).then(n).catch(()=>n([]));(0,b.useEffect)(()=>{p(),$.people().then(i).catch(()=>{})},[e.id]);let m=new Set((t??[]).map(e=>e.id)),h=r.filter(e=>!m.has(e.id));return(0,x.jsxs)(`div`,{className:`detail`,children:[t===null?(0,x.jsx)(zg,{lines:3}):t.length===0?(0,x.jsx)(`p`,{className:`muted`,children:`No one on this thread yet. Confirming an email a person wrote adds them; or add someone below.`}):(0,x.jsx)(`ul`,{className:`people__list`,children:t.map((e,t)=>(0,x.jsxs)(`li`,{className:`people__row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`span`,{children:e.name}),e.role&&(0,x.jsx)(z,{size:`sm`,tone:j_[M_(e.role)],variant:`soft`,children:A_[M_(e.role)]}),e.context&&(0,x.jsx)(`div`,{className:`reasons__detail`,children:e.context})]}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[e.email&&(0,x.jsx)(`a`,{className:`num muted`,href:`mailto:${e.email}`,children:e.email}),e.id&&(0,x.jsx)(`a`,{className:`muted`,href:`#/people`,title:`People/${e.id}.md`,children:`People ↗`})]})]},`${e.id||e.name}-${t}`))}),(0,x.jsxs)(`div`,{className:`people__add`,children:[(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsxs)(J,{size:`sm`,label:`Someone already in People`,value:a||`__none__`,onValueChange:e=>o(e===`__none__`?``:e),children:[(0,x.jsx)(J.Item,{value:`__none__`,children:`Pick a person`}),h.map(e=>(0,x.jsxs)(J.Item,{value:e.id,children:[e.name,e.company?` · ${e.company}`:``]},e.id))]}),(0,x.jsx)(J,{size:`sm`,label:`On this thread as`,value:s,onValueChange:e=>c(e),children:qg.map(e=>(0,x.jsx)(J.Item,{value:e,children:A_[e]},e))})]}),(0,x.jsx)(Zp,{size:`sm`,label:`Context`,placeholder:`A few words: reached out on LinkedIn, ran the screen, knows the team.`,value:l,onChange:e=>u(e.target.value)}),(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{size:`sm`,tone:`primary`,variant:`soft`,disabled:!a||d,onClick:async()=>{if(a){f(!0);try{await $.attachPerson(a,e.id,s,l.trim()),o(``),u(``),p(),X({title:`Added to the note`,description:`Under ## People on ${e.company} - ${e.title}.`,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}f(!1)}},children:`Add to this thread`}),(0,x.jsx)(P_,{job:e,onAdded:()=>{p(),$.people().then(i).catch(()=>{})}})]})]})]})}function L_({job:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),[a,o]=(0,b.useState)(`auto`),[s,c]=(0,b.useState)(``),[l,u]=(0,b.useState)(!1),d=(0,b.useRef)(!1),f=(e,t)=>{n(e),t&&i(e.saved?.text??``)};(0,b.useEffect)(()=>{n(null),$.tailoredResume(e.id).then(e=>f(e,!0)).catch(e=>X({title:`Could not read the resume`,description:e.message,tone:`danger`}))},[e.id]),(0,b.useEffect)(()=>{if(!t?.running){d.current&&t&&(d.current=!1,f(t,!t.error),t.error||X({title:`Resume tailored`,description:`Saved into the note. Read the warnings, then print.`,tone:`success`}));return}d.current=!0;let r=setInterval(()=>$.tailoredResume(e.id).then(e=>n(e)).catch(()=>{}),2500);return()=>clearInterval(r)},[t?.running,e.id]);let p=async()=>{if(!t?.saved||window.confirm(`Tailor again? It replaces the version saved in this note.`))try{f(await $.writeTailoredResume(e.id,{emphasis:a,extra:s}),!1)}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},m=async()=>{u(!0);try{f(await $.saveTailoredResume(e.id,r),!0),X({title:`Saved`,description:`Checked against your resume of record again.`,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}u(!1)};if(!t)return(0,x.jsx)(`div`,{className:`detail`,children:(0,x.jsx)(zg,{lines:6})});let h=t.saved,g=!!h&&r!==h.text,_=h?h.warnings.filter(e=>e.kind===`trace`||e.kind===`claim`||e.kind===`header`||e.kind===`date`).length:0;return(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsxs)(`div`,{className:`letter__options`,children:[(0,x.jsxs)(J,{size:`sm`,label:`Emphasis`,value:a,onValueChange:e=>o(e),disabled:t.running,children:[(0,x.jsx)(J.Item,{value:`auto`,children:`Let the posting decide`}),(0,x.jsx)(J.Item,{value:`design-systems`,children:`Design systems first`}),(0,x.jsx)(J.Item,{value:`ai-product`,children:`AI product surfaces first`})]}),(0,x.jsx)(Zp,{size:`sm`,label:`Anything to bring forward`,description:`Optional. A project, a tool, a role to lead with.`,value:s,onChange:e=>c(e.target.value),disabled:t.running})]}),(0,x.jsxs)(`div`,{className:`form__actions form__actions--start`,children:[(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:p,disabled:t.running,leadingIcon:t.running?(0,x.jsx)(Bg,{size:`sm`}):(0,x.jsx)(H.Sparkles,{}),children:t.running?`Tailoring`:h?`Tailor again`:`Tailor my resume to this posting`}),h&&(0,x.jsx)(B,{asChild:!0,variant:`soft`,size:`sm`,trailingIcon:(0,x.jsx)(H.ExternalLink,{}),children:(0,x.jsx)(`a`,{href:$.resumePrintUrl(e.id),target:`_blank`,rel:`noopener noreferrer`,children:`Print / save as PDF`})}),g&&(0,x.jsx)(B,{variant:`soft`,tone:`primary`,size:`sm`,onClick:m,loading:l,children:`Save edits`})]}),t.running&&(0,x.jsx)(Bg,{showLabel:!0,label:`${t.runner} is reordering your resume for ${e.company}`,size:`sm`}),t.error&&!t.running&&(0,x.jsx)(Vg,{tone:`danger`,size:`sm`,icon:(0,x.jsx)(H.Warning,{}),title:t.errorKind===`auth`?`${t.runner} is signed out`:t.errorKind===`outdated`?`${t.runner} is out of date`:`The resume was not written`,description:t.error}),!h&&!t.running&&!t.error&&(0,x.jsx)(Vg,{size:`sm`,icon:(0,x.jsx)(H.File,{}),title:`Not tailored yet`,description:`Same jobs, dates and numbers as your resume of record. The summary, order and emphasis change for ${e.company}. Nothing is added.`}),h&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`letter__meta`,children:[(0,x.jsxs)(z,{tone:`neutral`,size:`sm`,children:[h.words,` words · `,h.bullets,` bullets`]}),_===0?(0,x.jsx)(z,{tone:`success`,size:`sm`,children:`Every line traces to your resume`}):(0,x.jsxs)(z,{tone:`danger`,size:`sm`,children:[_,` line`,_===1?``:`s`,` not on your resume`]}),h.warnings.length>_&&(0,x.jsxs)(z,{tone:`warning`,size:`sm`,children:[h.warnings.length-_,` style`]}),g&&(0,x.jsx)(z,{tone:`primary`,variant:`outline`,size:`sm`,children:`Unsaved edits`})]}),h.warnings.length>0&&(0,x.jsx)(`ul`,{className:`letter__warnings`,children:h.warnings.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(z,{tone:e.kind===`style`||e.kind===`length`?`warning`:`danger`,size:`sm`,children:e.kind}),(0,x.jsx)(`span`,{children:e.text})]},e.text))}),(0,x.jsxs)(Z,{defaultValue:`preview`,variant:`pill`,size:`sm`,children:[(0,x.jsxs)(Z.List,{"aria-label":`Resume view`,children:[(0,x.jsx)(Z.Trigger,{value:`preview`,children:`Preview`}),(0,x.jsx)(Z.Trigger,{value:`edit`,children:`Edit`})]}),(0,x.jsx)(Z.Content,{value:`preview`,children:(0,x.jsx)(`div`,{className:`resume-preview`,children:(0,x.jsx)(dg,{text:r})})}),(0,x.jsx)(Z.Content,{value:`edit`,children:(0,x.jsx)(Xp,{label:`Tailored resume (Markdown)`,rows:24,resize:`vertical`,font:`mono`,value:r,onChange:e=>i(e.target.value),description:`Keep the headings. Saving re-runs the trace check.`})})]})]}),(0,x.jsx)(`p`,{className:`muted`,children:`Saved under "Tailored resume" in the job note; the packet's Resume variant field points at it. The PDF you upload comes from the print view.`})]})}var R_=e=>e===`tekjobs`;function z_({label:e=`TekJobs`}){return(0,x.jsxs)(z,{tone:`primary`,variant:`solid`,size:`sm`,title:`Posted on TekJobs by the employer`,children:[(0,x.jsx)(`img`,{className:`posted__glyph`,src:t_.logo,alt:``,width:12,height:12}),e]})}function B_({onAdded:e,onOpen:t}){let[n,r]=(0,b.useState)(!1),[i,a]=(0,b.useState)(``),[o,s]=(0,b.useState)(!1),[c,l]=(0,b.useState)(null),u=i.split(/\s+/).map(e=>e.trim()).filter(e=>/^https?:\/\//i.test(e));return(0,x.jsxs)(W,{open:n,onOpenChange:e=>{r(e),e||(a(``),l(null))},size:`md`,children:[(0,x.jsx)(W.Trigger,{asChild:!0,children:(0,x.jsx)(B,{size:`sm`,variant:`soft`,leadingIcon:(0,x.jsx)(H.Plus,{}),children:`Add by link`})}),(0,x.jsxs)(W.Content,{children:[(0,x.jsx)(W.Title,{children:`Add postings by link`}),(0,x.jsx)(W.Description,{children:`One link per line. LinkedIn job pages, company careers pages, and Greenhouse, Lever or Ashby postings. Each is read once, scored like the scan does, and written as a note unless it is already here.`}),(0,x.jsx)(Xp,{label:`Links`,rows:5,value:i,onChange:e=>a(e.target.value),placeholder:`https://www.linkedin.com/jobs/view/…
|
|
75
75
|
https://jobs.lever.co/…`,disabled:o}),c&&(0,x.jsx)(`ul`,{className:`import-results`,children:c.map((e,n)=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(z,{size:`sm`,tone:e.ok?e.added?`success`:`neutral`:`danger`,children:e.ok?e.added?`added`:`already here`:`failed`}),e.ok?(0,x.jsxs)(`span`,{className:`import-results__row`,children:[(0,x.jsxs)(`span`,{children:[e.score,` ·`]}),e.id?(0,x.jsxs)(B,{variant:`link`,size:`sm`,tone:`primary`,onClick:()=>{r(!1),t(e.id)},children:[e.company,` — `,e.title]}):(0,x.jsxs)(`span`,{children:[e.company,` — `,e.title]}),e.link&&(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,trailingIcon:(0,x.jsx)(H.ExternalLink,{}),children:(0,x.jsx)(`a`,{href:e.link,target:`_blank`,rel:`noopener noreferrer`,children:`Open posting`})}),e.reason&&(0,x.jsxs)(`span`,{className:`muted`,children:[`(`,e.reason,`)`]}),e.belowMin&&(0,x.jsx)(`span`,{className:`muted`,children:`· below the scan's minimum, written anyway`})]}):(0,x.jsxs)(`span`,{children:[e.error,` (`,e.url,`)`]})]},n))}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:o,children:`Close`})}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:o||u.length===0,loading:o,onClick:async()=>{s(!0);try{let t=await $.importLinks(u);l(t);let n=t.filter(e=>e.added);n.length?(X({title:`${n.length} job${n.length===1?``:`s`} added`,description:n.map(e=>`${e.company}: ${e.title}`).join(` · `),tone:`success`}),e(n[0]?.id??null)):X({title:`Nothing new`,description:`Every link was already here, or could not be read.`,tone:`warning`})}catch(e){X({title:`Import failed`,description:e.message,tone:`danger`})}finally{s(!1)}},children:o?`Reading…`:`Add ${u.length||``}`.trim()})]})]})]})}function V_({job:e,onAttached:t}){let[n,r]=(0,b.useState)(!1),[i,a]=(0,b.useState)(``),[o,s]=(0,b.useState)(!1),c=e.source===`mail`||e.source===`page`||!e.url||/mail\.google\.com/.test(e.url),l=async(n=!1)=>{s(!0);try{let o=await $.attachPosting(e.id,i.trim(),n);t(o),r(!1),a(``),o.linkOnly?X({title:`${o.company}: link saved`,description:o.warning?`The posting itself could not be read (${o.warning}), so only the link is on the note. Open posting now goes there.`:`Only the link is on the note; nothing else changed.`,tone:`neutral`}):X({title:`${o.company}: posting attached`,description:`Scored ${o.score} from the posting. Status, notes and drafts kept.`,tone:`success`})}catch(e){X({title:`Could not attach`,description:e.message,tone:`danger`})}finally{s(!1)}};return(0,x.jsxs)(W,{open:n,onOpenChange:r,size:`sm`,children:[(0,x.jsx)(W.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:c?`soft`:`ghost`,size:`sm`,leadingIcon:(0,x.jsx)(H.Link,{}),children:c?`Attach posting`:`Replace posting`})}),(0,x.jsxs)(W.Content,{children:[(0,x.jsx)(W.Title,{children:c?`Attach the posting`:`Replace the posting`}),(0,x.jsxs)(W.Description,{children:[c?`This note was created without the posting itself. `:``,`Paste the job's link. Attach reads the posting and replaces the note's facts, score and description; status, notes, packet and drafts stay. Link only just records the link, for a page that cannot be read (LinkedIn, a login wall) or when the note's facts are already right.`]}),(0,x.jsx)(Zp,{label:`Posting link`,placeholder:`https://jobs.ashbyhq.com/… or the company careers page`,value:i,onChange:e=>a(e.target.value),disabled:o}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:o,children:`Cancel`})}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`neutral`,disabled:o||!/^https?:\/\//i.test(i.trim()),onClick:()=>l(!0),children:`Link only`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:o||!/^https?:\/\//i.test(i.trim()),loading:o,onClick:()=>l(!1),children:`Attach`})]})]})]})}var H_=25,U_=[[``,`any time`],[`2`,`2 days`],[`7`,`7 days`],[`14`,`14 days`],[`30`,`30 days`],[`90`,`90 days`]],W_={q:``,location:``,remote:!1,kind:`all`,band:[],status:[],source:[],company:[],minScore:`45`,maxScore:``,payMin:``,payMax:``,payKnown:!1,postedDays:``,foundDays:``},G_=()=>new URLSearchParams(window.location.hash.split(`?`)[1]??``),K_=[{key:`minScore`,label:`Score at least`},{key:`remote`,label:`Remote only`},{key:`location`,label:`Location`},{key:`kind`,label:`Title`},{key:`band`,label:`Pay band`},{key:`status`,label:`Status`},{key:`source`,label:`Source`},{key:`company`,label:`Company`},{key:`payMin`,label:`Pay at least`},{key:`payMax`,label:`Pay at most`},{key:`payKnown`,label:`Stated pay only`},{key:`postedDays`,label:`Posted within`},{key:`foundDays`,label:`Found within`},{key:`maxScore`,label:`Score at most`}],q_=(e,t)=>{let n=e[t];return Array.isArray(n)?n.length>0:typeof n==`boolean`?n:t===`minScore`?n!==``&&n!==`0`:n!==W_[t]};function J_(e){let t=e===void 0?G_():new URLSearchParams(e),n={...W_,band:[],status:[],source:[],company:[]},r=n;for(let e of Object.keys(W_)){let n=t.get(e);if(n===null)continue;let i=W_[e];r[e]=Array.isArray(i)?n.split(`,`).filter(Boolean):typeof i==`boolean`?n===`1`:n}return n}function Y_(e,t,n){let r=new URLSearchParams;for(let t of Object.keys(W_)){let n=e[t];Array.isArray(n)?n.length&&r.set(t,n.join(`,`)):typeof n==`boolean`?n&&r.set(t,`1`):n!==W_[t]&&r.set(t,n)}return t!==`score`&&r.set(`sort`,t),n!==`desc`&&r.set(`dir`,n),r.toString()}function X_(e,t,n){let r=Y_(e,t,n);window.history.replaceState(null,``,`#/jobs${r?`?${r}`:``}`)}var Z_=e=>({q:e.q,location:e.location,remote:e.remote?1:void 0,kind:e.kind===`all`?void 0:e.kind,band:e.band.join(`,`),status:e.status.join(`,`),source:e.source.join(`,`),company:e.company.join(`,`),minScore:e.minScore===`0`||e.minScore===``?void 0:Number(e.minScore),maxScore:e.maxScore?Number(e.maxScore):void 0,payMin:e.payMin?Number(e.payMin):void 0,payMax:e.payMax?Number(e.payMax):void 0,payKnown:e.payKnown?1:void 0,postedDays:e.postedDays?Number(e.postedDays):void 0,foundDays:e.foundDays?Number(e.foundDays):void 0}),Q_=(e,t,n)=>e.map(e=>({value:e,label:n(e),hint:t?String(t[e]??0):void 0})),$_=`tekjobs.jobs.last`,ev=e=>{try{localStorage.setItem($_,e)}catch{}},tv=()=>{let[e,t]=window.location.hash.replace(/^#\/?/,``).split(`?`);if(e!==`jobs`||t)return;let n=``;try{n=localStorage.getItem($_)??``}catch{}n&&window.history.replaceState(null,``,`#/jobs?${n}`)};function nv({initialQuery:e=``}){e||tv();let[t,n]=(0,b.useState)(()=>{let t=J_();return e?{...t,q:e}:t}),[r,i]=(0,b.useState)(()=>G_().get(`sort`)||`score`),[a,o]=(0,b.useState)(()=>G_().get(`dir`)===`asc`?`asc`:`desc`),[s,c]=(0,b.useState)(0),[l,u]=(0,b.useState)(null),[d,f]=(0,b.useState)(0),[p,m]=(0,b.useState)(null),[h,g]=(0,b.useState)(null),[_,v]=(0,b.useState)(null),y=(0,b.useRef)(null),[S,C]=(0,b.useState)([]),[w,T]=(0,b.useState)([]),[E,D]=(0,b.useState)([]),[O,k]=(0,b.useState)(null),[A,j]=(0,b.useState)(()=>{try{return localStorage.getItem(`tekjobs.jobs.condensed`)===`1`}catch{return!1}}),ee=()=>j(e=>{try{localStorage.setItem(`tekjobs.jobs.condensed`,e?`0`:`1`)}catch{}return!e}),[M,N]=(0,b.useState)(()=>G_().get(`open`)),[te,P]=(0,b.useState)(0);(0,b.useEffect)(()=>{$.views().then(T).catch(()=>{}),$.defaultViews().then(D).catch(()=>{}),$.facets({}).then(e=>g(e.total)).catch(()=>{}),$.summary().then(e=>{if(!e.minScore)return;let t=String(e.minScore),r=G_().has(`minScore`);W_.minScore=t,r||n(e=>e.minScore===`45`||e.minScore===``?{...e,minScore:t}:e)}).catch(()=>{})},[]);let F=(e,t)=>{n(n=>({...n,[e]:t})),c(0)},ne=(0,b.useMemo)(()=>Z_(t),[t]),re=JSON.stringify(ne),ie=t.remote;(0,b.useEffect)(()=>{e&&F(`q`,e)},[e]),(0,b.useEffect)(()=>{X_(t,r,a),ev(Y_(t,r,a))},[t,r,a]),(0,b.useEffect)(()=>{let e=()=>{if(window.location.hash.replace(/^#\/?/,``).split(`?`)[0]!==`jobs`)return;tv();let e=J_(),s=G_().get(`sort`)||`score`,l=G_().get(`dir`)===`asc`?`asc`:`desc`;Y_(e,s,l)!==Y_(t,r,a)&&(n(e),i(s),o(l),c(0))};return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[t,r,a]),(0,b.useEffect)(()=>{let e=!0;return $.jobs({...ne,sort:r,dir:a,limit:H_,offset:s*H_}).then(t=>{e&&(u(t.rows),f(t.total))}).catch(e=>X({title:`Could not load jobs`,description:e.message,tone:`danger`})),$.facets(ne).then(t=>{e&&m(t)}).catch(()=>{}),()=>{e=!1}},[re,r,a,s,te]);let ae=Q_(Gg,p?.status,e=>e),oe=Q_([`floor`,`stretch`,`below`,`unknown`],p?.band,e=>Zg[e]),se=Q_(Array.from(new Set([...p?.source.link?[`link`]:[],...Object.entries(p?.source??{}).filter(([e])=>e!==`link`).sort((e,t)=>t[1]-e[1]).map(([e])=>e),...t.source])),p?.source,e=>e===`link`?`added by link`:e),ce=Q_(Array.from(new Set([...t.company,...Object.entries(p?.company??{}).sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).map(([e])=>e)])),p?.company,e=>e),le=p?.pay,ue=Math.max(1,Math.ceil(d/H_)),de=Math.min(s,ue-1),fe=e=>{r===e?o(a===`desc`?`asc`:`desc`):(i(e),o(e===`company`||e===`title`?`asc`:`desc`)),c(0)},pe=(e,t,n)=>(0,x.jsx)(Y.HeadCell,{...n,"aria-sort":r===e?a===`desc`?`descending`:`ascending`:void 0,children:(0,x.jsx)(B,{variant:`link`,size:`sm`,tone:`neutral`,onClick:()=>fe(e),trailingIcon:r===e?a===`desc`?(0,x.jsx)(H.ArrowDown,{}):(0,x.jsx)(H.ArrowUp,{}):void 0,children:(0,x.jsx)(`span`,{className:`col`,children:t})})}),me=e=>u(t=>t&&t.map(t=>t.id===e.id?{...t,status:e.status}:t)),I=e_(`(min-width: 68.75rem)`),he=I&&M!==null,ge=l?l.findIndex(e=>e.id===M):-1,_e=(0,b.useRef)(null);(0,b.useEffect)(()=>{if(!l||!_e.current)return;let e=_e.current;_e.current=null;let t=e===`first`?l[0]:l[l.length-1];t&&N(t.id)},[l]);let ve=e=>{if(!l||l.length===0)return;let t=l[0];if(ge<0){t&&N(t.id);return}let n=ge+e,r=l[n];r?N(r.id):n>=l.length&&de<ue-1?(_e.current=`first`,c(de+1)):n<0&&de>0&&(_e.current=`last`,c(de-1))};(0,b.useEffect)(()=>{if(M===null)return;let e=e=>{let t=e.target;e.defaultPrevented||e.metaKey||e.ctrlKey||e.altKey||t&&(/^(input|textarea|select)$/i.test(t.tagName)||t.isContentEditable)||(e.key===`Escape`?N(null):e.key===`j`||e.key===`ArrowDown`?(e.preventDefault(),ve(1)):(e.key===`k`||e.key===`ArrowUp`)&&(e.preventDefault(),ve(-1)))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)});let L={pos:ge>=0?de*H_+ge:-1,total:d,prev:()=>ve(-1),next:()=>ve(1)},ye=K_.filter(e=>q_(t,e.key)).length+ +!!t.q,be=e=>{switch(e){case`location`:return(0,x.jsx)(Zp,{size:`sm`,label:`Location`,description:`Comma-separated, any of; whole words.`,placeholder:`seattle, wa, united states`,value:t.location,onChange:e=>F(`location`,e.target.value),autoFocus:!0});case`remote`:return(0,x.jsx)(Hp,{size:`sm`,label:`Remote only${p?` (${p.remote.remote})`:``}`,checked:t.remote,onCheckedChange:e=>F(`remote`,e===!0)});case`payKnown`:return(0,x.jsx)(Hp,{size:`sm`,label:`Stated pay only`,checked:t.payKnown,onCheckedChange:e=>F(`payKnown`,e===!0)});case`kind`:return(0,x.jsxs)(J,{size:`sm`,label:`Title`,value:t.kind,onValueChange:e=>F(`kind`,e),children:[(0,x.jsx)(J.Item,{value:`all`,children:`All titles`}),(0,x.jsxs)(J.Item,{value:`design-eng`,children:[`Design engineering`,p?` (${p.kind[`design-eng`]??0})`:``]}),(0,x.jsxs)(J.Item,{value:`adjacent`,children:[`Adjacent`,p?` (${p.kind.adjacent??0})`:``]})]});case`band`:return(0,x.jsx)(Wg,{size:`sm`,multiple:!0,label:`Pay band`,placeholder:`All bands`,emptyMessage:`No band by that name.`,options:oe,value:t.band,onValueChange:e=>F(`band`,e)});case`status`:return(0,x.jsx)(Wg,{size:`sm`,multiple:!0,label:`Status`,placeholder:`All statuses`,emptyMessage:`No status by that name.`,options:ae,value:t.status,onValueChange:e=>F(`status`,e)});case`source`:return(0,x.jsx)(Wg,{size:`sm`,multiple:!0,label:`Source`,placeholder:`All sources`,emptyMessage:`No source by that name.`,options:se,value:t.source,onValueChange:e=>F(`source`,e)});case`company`:return(0,x.jsx)(Wg,{size:`sm`,multiple:!0,label:`Company`,placeholder:`Any company`,emptyMessage:`No company in the current results by that name.`,options:ce,value:t.company,onValueChange:e=>F(`company`,e)});case`payMin`:return(0,x.jsx)(Zp,{size:`sm`,type:`number`,step:1e4,label:`Pay at least`,description:le?`Top of the stated range. Stated on ${le.stated} of ${le.stated+le.unstated}.`:void 0,placeholder:`200000`,value:t.payMin,onChange:e=>F(`payMin`,e.target.value),autoFocus:!0});case`payMax`:return(0,x.jsx)(Zp,{size:`sm`,type:`number`,step:1e4,label:`Pay at most`,description:le&&le.stated?`${Jg(le.min)} to ${Jg(le.max)}, median ${Jg(le.median)}.`:void 0,placeholder:`300000`,value:t.payMax,onChange:e=>F(`payMax`,e.target.value),autoFocus:!0});case`minScore`:return(0,x.jsx)(J,{size:`sm`,label:`Score at least`,value:t.minScore||`0`,onValueChange:e=>F(`minScore`,e),children:[`0`,`45`,`60`,`75`,`90`,`100`].map(e=>(0,x.jsx)(J.Item,{value:e,children:e===`0`?`any`:`${e} pts`},e))});case`maxScore`:return(0,x.jsx)(Zp,{size:`sm`,type:`number`,label:`Score at most`,placeholder:`any`,value:t.maxScore,onChange:e=>F(`maxScore`,e.target.value),autoFocus:!0});case`postedDays`:case`foundDays`:return(0,x.jsx)(J,{size:`sm`,label:e===`postedDays`?`Posted within`:`Found within`,value:t[e],onValueChange:t=>F(e,t),children:U_.map(([e,t])=>(0,x.jsx)(J.Item,{value:e,children:t},e||`any`))})}},xe=e=>{let n=t[e];return Array.isArray(n)?e===`band`?n.map(e=>Zg[e]).join(`, `):n.length>2?`${n.slice(0,2).join(`, `)} +${n.length-2}`:n.join(`, `):typeof n==`boolean`?``:e===`kind`?n===`design-eng`?`design engineering`:n===`adjacent`?`adjacent`:``:e===`payMin`||e===`payMax`?n?Jg(Number(n)):``:e===`minScore`||e===`maxScore`?n&&n!==`0`?`${n} pts`:``:e===`postedDays`||e===`foundDays`?n?`${n} days`:``:n},Se=e=>{let t=W_[e];F(e,e===`minScore`?`0`:Array.isArray(t)?[]:t),v(null),C(t=>t.filter(t=>t!==e))},Ce=e=>{e===`remote`||e===`payKnown`?F(e,!0):e===`kind`?F(e,`design-eng`):e===`postedDays`?F(e,`7`):e===`minScore`&&(!t.minScore||t.minScore===`0`)&&F(e,`45`),C(t=>t.includes(e)?t:[...t,e]),v(e)},we=K_.filter(e=>q_(t,e.key)||_===e.key||S.includes(e.key)),Te=K_.filter(e=>!q_(t,e.key)&&!S.includes(e.key)),Ee=Y_(t,r,a),De=e=>{n(J_(e.query)),c(0)},Oe=async()=>{let e=(O??``).trim();if(e)try{T(await $.saveViews([...w.filter(t=>t.name!==e),{name:e,query:Ee}])),k(null),X({title:`View "${e}" saved`,description:`Targets/Job Views.md`,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}},ke=async e=>{try{T(await $.saveViews(w.filter(t=>t.name!==e)))}catch(e){X({title:`Not removed`,description:e.message,tone:`danger`})}};return(0,x.jsxs)(`div`,{className:he?`jobs jobs--split`:`jobs`,children:[he?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`aside`,{className:`jobs__list`,"aria-label":`Matches`,children:[(0,x.jsxs)(`div`,{className:`ctools`,children:[(0,x.jsxs)(`div`,{className:`ctools__row`,children:[(0,x.jsx)(Zp,{size:`sm`,"aria-label":`Search`,placeholder:`Search company or role`,value:t.q,onChange:e=>F(`q`,e.target.value)}),(0,x.jsx)(Bh,{content:`Back to the full table (Esc)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Back to the full table`,leadingIcon:(0,x.jsx)(H.Grid,{}),onClick:()=>N(null)})})]}),(0,x.jsxs)(`div`,{className:`ctools__row ctools__meta`,children:[(0,x.jsxs)(`span`,{children:[(0,x.jsx)(`b`,{className:`num`,children:d}),h===null?null:(0,x.jsxs)(x.Fragment,{children:[` of `,h]}),` · `,ye,` filter`,ye===1?``:`s`]}),(0,x.jsx)(`span`,{className:`num`,children:`J K move · Esc close`})]})]}),(0,x.jsxs)(`div`,{className:`clist`,children:[(l??[]).map(e=>(0,x.jsx)(B,{asChild:!0,variant:`ghost`,size:`sm`,align:`start`,className:`clist__item`,children:(0,x.jsxs)(`button`,{type:`button`,"aria-current":e.id===M?`true`:void 0,"data-posted":R_(e.source)||void 0,onClick:()=>N(e.id),children:[(0,x.jsx)(`span`,{className:`clist__score num`,children:e.score}),(0,x.jsxs)(`span`,{className:`clist__text`,children:[(0,x.jsx)(`span`,{className:`clist__role`,children:e.title}),(0,x.jsxs)(`span`,{className:`clist__meta`,children:[e.company,` · `,(0,x.jsx)(`span`,{className:`num${e.payBand===`floor`?` clist__pay--floor`:``}`,children:e.salaryMax?Yg(e.salary):`not stated`}),` · `,Xg(e.posted)||`—`]})]})]})},e.id)),l&&l.length===0&&(0,x.jsx)(`p`,{className:`muted`,children:`Nothing matches these filters.`}),l&&ue>1&&(0,x.jsxs)(`div`,{className:`clist__pager`,children:[(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:de===0,onClick:()=>c(de-1),children:`Previous`}),(0,x.jsxs)(`span`,{className:`muted num`,children:[de+1,` / `,ue]}),(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:de>=ue-1,onClick:()=>c(de+1),children:`Next`})]})]})]}),(0,x.jsx)(`section`,{className:`jobs__detail`,"aria-label":`Job`,children:(0,x.jsx)(av,{id:M,inline:!0,nav:L,onClose:()=>N(null),onChanged:me})})]}):(0,x.jsxs)(x.Fragment,{children:[!A&&(0,x.jsxs)(`div`,{className:`views`,children:[(0,x.jsx)(Bh,{content:`Hide the views and filters`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Hide the views and filters`,leadingIcon:(0,x.jsx)(H.ChevronUp,{}),onClick:ee})}),(0,x.jsx)(`span`,{className:`views__label`,children:`Views`}),E.map(e=>(0,x.jsx)(`div`,{className:`chip chip--default${e.query===Ee?` chip--current`:``}`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:e.query===Ee?`primary`:`neutral`,title:`From your criteria: ${e.hint}`,onClick:()=>De(e),children:e.name})},`d:${e.name}`)),w.map(e=>(0,x.jsxs)(`div`,{className:`chip${e.query===Ee?` chip--current`:``}`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:e.query===Ee?`primary`:`neutral`,onClick:()=>De(e),children:e.name}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Remove the view ${e.name}`,onClick:()=>ke(e.name),children:`×`})]},e.name)),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Plus,{}),disabled:!Ee,onClick:()=>k(``),children:`Save current filters as a view`}),(0,x.jsx)(`div`,{className:`toolbar__spacer`})]}),!A&&(0,x.jsxs)(`div`,{className:`filters`,children:[(0,x.jsx)(Zp,{className:`filters__search`,size:`sm`,label:`Search`,placeholder:`company or role`,value:t.q,onChange:e=>F(`q`,e.target.value)}),we.map(e=>{let n=q_(t,e.key),r=xe(e.key);return(0,x.jsxs)(`div`,{className:`chip${n?` chip--on`:``}`,children:[(0,x.jsxs)(fd,{open:_===e.key,onOpenChange:t=>v(t?e.key:null),size:`sm`,children:[(0,x.jsx)(fd.Trigger,{asChild:!0,children:(0,x.jsxs)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,leadingIcon:(0,x.jsx)(`span`,{className:`chip__dot`,"aria-hidden":`true`}),children:[e.label,r&&(0,x.jsx)(`span`,{className:`chip__value num`,children:r})]})}),(0,x.jsx)(fd.Content,{align:`start`,showArrow:!1,children:(0,x.jsx)(`div`,{className:`chip__editor`,children:be(e.key)})})]}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Remove ${e.label}`,onClick:()=>Se(e.key),children:`×`})]},e.key)}),Te.length>0&&(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,leadingIcon:(0,x.jsx)(H.Plus,{}),trailingIcon:(0,x.jsx)(H.ChevronDown,{}),children:`Filter`})}),(0,x.jsx)(Tu.Content,{align:`start`,onCloseAutoFocus:e=>{y.current&&(y.current=null,e.preventDefault())},children:Te.map(e=>(0,x.jsx)(Tu.Item,{onSelect:()=>{y.current=e.key,Ce(e.key)},children:e.label},e.key))})]}),we.some(e=>q_(t,e.key)&&e.key!==`minScore`)||t.q?(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,onClick:()=>{n({...W_,band:[],status:[],source:[],company:[]}),c(0)},children:`Clear`}):null,(0,x.jsx)(`div`,{className:`toolbar__spacer`}),(0,x.jsx)(B_,{onAdded:e=>{P(e=>e+1),e&&N(e)},onOpen:e=>N(e)})]}),(0,x.jsxs)(`div`,{className:`filters__summary`,children:[(0,x.jsxs)(`span`,{children:[A&&(0,x.jsx)(Bh,{content:`Show the views and filters (${we.filter(e=>q_(t,e.key)).length+ +!!t.q} active)`,children:(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`neutral`,"aria-label":`Show the views and filters`,leadingIcon:(0,x.jsx)(H.ChevronDown,{}),onClick:ee})}),(0,x.jsx)(`b`,{className:`num`,children:d}),` of `,(0,x.jsx)(`span`,{className:`num`,children:h??`…`}),` matches`,le&&le.stated>0&&(0,x.jsxs)(x.Fragment,{children:[` · pay stated on `,(0,x.jsx)(`span`,{className:`num`,children:le.stated}),`, median top of range `,(0,x.jsx)(`span`,{className:`num`,children:Jg(le.median)})]})]}),(0,x.jsxs)(`span`,{className:`num filters__query`,children:[`/jobs`,Ee?`?${Ee}`:``]})]}),(0,x.jsx)(W,{open:O!==null,onOpenChange:e=>!e&&k(null),size:`sm`,children:(0,x.jsxs)(W.Content,{children:[(0,x.jsx)(W.Title,{children:`Save these filters as a view`}),(0,x.jsx)(W.Description,{children:`A named link to exactly this filter set, kept in Targets/Job Views.md. Same name replaces the old one.`}),(0,x.jsx)(Zp,{label:`Name`,placeholder:`Design eng at floor`,value:O??``,onChange:e=>k(e.target.value),autoFocus:!0}),(0,x.jsxs)(`p`,{className:`muted num filters__query`,children:[`/jobs?`,Ee]}),(0,x.jsxs)(W.Footer,{children:[(0,x.jsx)(W.Close,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,children:`Cancel`})}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:!O?.trim(),onClick:Oe,children:`Save view`})]})]})}),(0,x.jsx)(V,{padding:`none`,children:(0,x.jsx)(`div`,{className:`jobs-narrow`,children:l===null?(0,x.jsx)(`div`,{className:`loading`,children:(0,x.jsx)(zg,{lines:8})}):(0,x.jsxs)(Y,{"aria-label":`Job matches`,density:`md`,stickyHeader:!0,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[pe(`score`,`Score`,{align:`end`,numeric:!0}),pe(`company`,`Company`),pe(`title`,`Role`),pe(`salaryMax`,`Pay`),(0,x.jsx)(Y.HeadCell,{children:`Location`}),pe(`posted`,`Posted`),(0,x.jsx)(Y.HeadCell,{children:`Status`})]})}),(0,x.jsxs)(Y.Body,{children:[l.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,selected:M===e.id,"data-posted":R_(e.source)||void 0,onClick:()=>N(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(`span`,{className:`num`,children:e.score})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[e.title,e.kind===`design-eng`&&(0,x.jsx)(`small`,{children:`design engineering`}),e.addedBy===`link`&&(0,x.jsx)(`small`,{children:`added by link`})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{tone:Qg[e.payBand],variant:e.payBand===`floor`?`solid`:`soft`,size:`sm`,children:e.salaryMax?Yg(e.salary):Zg[e.payBand]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`where`,children:[(0,x.jsx)(z,{tone:e.remote?`success`:`neutral`,variant:`soft`,size:`sm`,children:e.remote?`remote`:`on-site`}),(0,x.jsx)(`span`,{className:`clamp`,children:e.location})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted num`,children:Xg(e.posted)||`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{tone:$g[e.status],size:`sm`,children:e.status})})]},e.id)),l.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:7,children:(0,x.jsx)(`span`,{className:`muted`,children:`Nothing matches these filters. Loosen one.`})})})]})]})})}),(0,x.jsxs)(`div`,{className:`pager`,children:[(0,x.jsxs)(`span`,{children:[d,` match`,d===1?``:`es`,`, page `,de+1,` of `,ue,ie&&(0,x.jsx)(`span`,{className:`muted`,children:` · on-site and hybrid hidden`})]}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:de===0,onClick:()=>c(de-1),children:`Previous`}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:de>=ue-1,onClick:()=>c(de+1),children:`Next`})]})]})]}),!I&&(0,x.jsx)(iv,{id:M,nav:L,onClose:()=>N(null),onChanged:me})]})}function rv(e){return e.split(`
|
|
76
|
-
`).map(e=>e.replace(/^-\s*/,``).trim()).filter(Boolean).map(e=>{let t=[...e.matchAll(/(?<![\w$])([+-]\d+)\b/g)].reduce((e,t)=>e+Number(t[1]),0),n=e.replace(/(?<![\w$])[+-]\d+\b/g,``).replace(/\(\s*[,\s]*/g,`(`).replace(/[,\s]*\)/g,`)`).replace(/\(\)/g,``).replace(/\s+,/g,`,`).replace(/\s{2,}/g,` `).replace(/\s+:/g,`:`).trim(),r=n.indexOf(`:`),i=(r>=0?n.slice(0,r):n).trim().replace(/[,:]$/,``),a=(r>=0?n.slice(r+1):``).trim();return{label:i.charAt(0).toUpperCase()+i.slice(1),detail:a,points:t}})}function iv(e){return(0,x.jsx)(Sp,{open:e.id!==null,onOpenChange:t=>!t&&e.onClose(),side:`right`,size:`lg`,children:(0,x.jsx)(Sp.Content,{children:(0,x.jsx)(av,{...e})})})}function av({id:e,onClose:t,onChanged:n,nav:r,inline:i=!1}){let[a,o]=(0,b.useState)(null),[s,c]=(0,b.useState)(``),[l,u]=(0,b.useState)(!1);(0,b.useEffect)(()=>{o(null),e&&$.job(e).then(o).catch(e=>X({title:`Could not open the note`,description:e.message,tone:`danger`}))},[e]);let d=async e=>{if(a){u(!0);try{let t=await $.setStatus(a.id,e);o(t),n(t),X({title:`${a.company}: ${e}`,description:`Written to the note's frontmatter and status log.`,tone:`success`})}catch(e){X({title:`Status not saved`,description:e.message,tone:`danger`})}u(!1)}},f=async()=>{if(a&&s.trim()){u(!0);try{let e=await $.addNote(a.id,s);o(e),c(``),X({title:`Note added`,tone:`success`})}catch(e){X({title:`Note not saved`,description:e.message,tone:`danger`})}u(!1)}},[p,m]=(0,b.useState)(null);(0,b.useEffect)(()=>{Promise.all([$.summary(),$.companies()]).then(([e,t])=>m({ceiling:e.ceiling,bar:e.minScore,boards:t.map(e=>({name:e.name,tier:e.tier,status:e.status}))})).catch(()=>{})},[]);let h=(0,b.useMemo)(()=>a?rv(a.sections.why):[],[a]),g=a&&p?.ceiling?Math.max(0,Math.min(100,Math.round(a.score/p.ceiling*100))):null,_=a&&p?p.boards.find(e=>e.name.toLowerCase()===a.company.toLowerCase()):null,v=a?a.sections.description.replace(/^>.*$/m,``).replace(/[#*_`>]/g,``).replace(/\s+/g,` `).trim().slice(0,320):``,y=async e=>{if(a){u(!0);try{let t=await $.setStatus(a.id,`passed`,e);o(t),n(t),X({title:`${a.company}: passed`,description:e,tone:`neutral`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}u(!1)}},S=r&&(0,x.jsxs)(`div`,{className:`sheet-nav`,children:[(0,x.jsx)(Bh,{content:`Previous (K)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Previous job`,leadingIcon:(0,x.jsx)(H.ChevronUp,{}),disabled:r.pos<=0,onClick:r.prev})}),(0,x.jsx)(Bh,{content:`Next (J)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Next job`,leadingIcon:(0,x.jsx)(H.ChevronDown,{}),disabled:r.pos<0?r.total===0:r.pos>=r.total-1,onClick:r.next})}),(0,x.jsx)(`span`,{className:`sheet-nav__count num`,children:r.pos>=0?`${r.pos+1} of ${r.total}`:`not in this view`}),i&&(0,x.jsx)(Bh,{content:`Close (Esc)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Close`,leadingIcon:(0,x.jsx)(H.Close,{}),onClick:t,className:`sheet-nav__close`})})]});return(0,x.jsx)(x.Fragment,{children:a?(0,x.jsxs)(`div`,{className:`detail`,children:[S,(0,x.jsxs)(`div`,{className:`sheet-head`,children:[(0,x.jsxs)(`div`,{className:`sheet-head__main`,children:[(0,x.jsxs)(`p`,{className:`sheet-head__meta`,children:[a.company,` · `,a.location||`location n/a`,` · `,R_(a.source)?`posted on TekJobs`:a.source,` · found `,Xg(a.found)||a.found]}),i?(0,x.jsx)(`h2`,{className:`sheet-head__title`,children:a.title}):(0,x.jsx)(Sp.Title,{children:a.title}),(0,x.jsxs)(`div`,{className:`chips`,children:[R_(a.source)&&(0,x.jsx)(z_,{label:`Posted on TekJobs`}),(0,x.jsx)(z,{tone:a.payBand===`floor`?`primary`:`neutral`,variant:`soft`,size:`sm`,children:(0,x.jsx)(`span`,{className:`num`,children:a.salaryMax?Yg(a.salary):`pay not stated`})}),a.salaryMax>0&&(0,x.jsx)(z,{tone:`neutral`,variant:`outline`,size:`sm`,children:Zg[a.payBand].toLowerCase()}),(0,x.jsx)(z,{tone:a.remote?`success`:`neutral`,variant:a.remote?`soft`:`outline`,size:`sm`,children:a.remote?`remote`:`on-site`}),(0,x.jsx)(z,{tone:$g[a.status],size:`sm`,children:a.status})]})]}),(0,x.jsxs)(`div`,{className:`sheet-head__side`,children:[(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[a.status===`new`&&(0,x.jsx)(B,{tone:`primary`,size:`sm`,disabled:l,onClick:()=>d(`reviewing`),children:`Shortlist`}),(a.status===`new`||a.status===`reviewing`)&&(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:l,trailingIcon:(0,x.jsx)(H.ChevronDown,{}),children:`Pass`})}),(0,x.jsx)(Tu.Content,{align:`end`,children:Kg.map(e=>(0,x.jsx)(Tu.Item,{onSelect:()=>y(e),children:e},e))})]}),(0,x.jsx)(J,{size:`sm`,label:`Status`,value:a.status,onValueChange:e=>d(e),disabled:l,children:Gg.map(e=>(0,x.jsx)(J.Item,{value:e,children:e},e))})]}),(0,x.jsxs)(`div`,{className:`sheet-head__links`,children:[(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,children:(0,x.jsx)(`a`,{href:a.url,target:`_blank`,rel:`noopener noreferrer`,children:`Open posting ↗`})}),(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,children:(0,x.jsx)(`a`,{href:a.obsidianUrl,title:a.path,children:`Open in Obsidian ↗`})}),(0,x.jsx)(B,{variant:`link`,size:`sm`,tone:`neutral`,title:a.path,onClick:()=>$.revealJob(a.id).catch(e=>X({title:`Could not show the file`,description:e.message,tone:`danger`})),children:`Show file`}),(0,x.jsx)(V_,{job:a,onAttached:e=>{o(e),n(e)}})]})]})]}),(0,x.jsxs)(Z,{defaultValue:`why`,variant:`line`,size:`sm`,children:[(0,x.jsxs)(Z.List,{"aria-label":`Job note sections`,children:[(0,x.jsx)(Z.Trigger,{value:`why`,children:`Match reasons`}),(0,x.jsx)(Z.Trigger,{value:`description`,children:`Description`}),(0,x.jsx)(Z.Trigger,{value:`application`,children:`Application packet`}),(0,x.jsx)(Z.Trigger,{value:`resume`,children:`Tailored resume`}),(0,x.jsx)(Z.Trigger,{value:`letter`,children:`Cover letter`}),(0,x.jsx)(Z.Trigger,{value:`people`,children:`People`}),(0,x.jsx)(Z.Trigger,{value:`notes`,children:`Notes`})]}),(0,x.jsx)(Z.Content,{value:`why`,children:(0,x.jsxs)(`div`,{className:`split`,children:[(0,x.jsxs)(`div`,{className:`reasons`,children:[(0,x.jsxs)(`div`,{className:`reasons__head`,children:[(0,x.jsxs)(`span`,{className:`muted`,children:[`Scored `,(0,x.jsx)(`span`,{className:`num`,children:a.score}),p?.ceiling?(0,x.jsxs)(x.Fragment,{children:[` of `,(0,x.jsx)(`span`,{className:`num`,children:p.ceiling}),` possible`]}):null,` with the active criteria`,p?.bar?(0,x.jsxs)(x.Fragment,{children:[` (bar `,(0,x.jsx)(`span`,{className:`num`,children:p.bar}),`)`]}):null,`.`]}),g!==null&&(0,x.jsxs)(`span`,{className:`reasons__fit num`,children:[g,(0,x.jsx)(`small`,{children:` fit`})]})]}),h.map((e,t)=>(0,x.jsxs)(`div`,{className:`reasons__row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{children:e.label}),e.detail&&(0,x.jsx)(`div`,{className:`reasons__detail`,children:e.detail})]}),(0,x.jsxs)(`span`,{className:`num reasons__pts${e.points<0?` reasons__pts--neg`:``}`,children:[e.points<0?`−`:`+`,Math.abs(e.points)]})]},t)),h.length===0&&(0,x.jsx)(`p`,{className:`muted`,children:`No match reasons recorded.`}),(0,x.jsxs)(`details`,{className:`reasons__log`,children:[(0,x.jsx)(`summary`,{children:`Status log`}),(0,x.jsx)(dg,{text:a.sections.log||`_Nothing yet._`})]})]}),(0,x.jsxs)(`aside`,{className:`split__aside`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`From the posting`}),(0,x.jsx)(`p`,{children:v?`${v}${a.sections.description.length>320?`…`:``}`:`The posting had no description text. Open the posting, or attach one.`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`Note`}),(0,x.jsxs)(`p`,{className:`num small`,children:[a.path.split(/[\\/]/).slice(-2).join(`/`),(0,x.jsx)(`br`,{}),`status: `,a.status,` · found `,a.found,a.addedBy===`scan`?``:` · added by ${a.addedBy}`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`Board`}),(0,x.jsx)(`p`,{children:_?`Tier ${_.tier} board, last fetch ${_.status||`not yet run`}.`:`${a.source}; not on the watchlist.`})]})]})]})}),(0,x.jsx)(Z.Content,{value:`description`,children:(0,x.jsx)(dg,{text:a.sections.description||`_The posting had no description text. Open the posting._`})}),(0,x.jsx)(Z.Content,{value:`application`,children:(0,x.jsx)(ov,{job:a,onStatus:d,busy:l})}),(0,x.jsx)(Z.Content,{value:`resume`,children:(0,x.jsx)(L_,{job:a})}),(0,x.jsx)(Z.Content,{value:`letter`,children:(0,x.jsx)(k_,{job:a})}),(0,x.jsx)(Z.Content,{value:`people`,children:(0,x.jsx)(I_,{job:a})}),(0,x.jsx)(Z.Content,{value:`notes`,children:(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(dg,{text:a.sections.notes||`_No notes yet._`}),(0,x.jsx)(Xp,{label:`Add a note`,rows:3,value:s,onChange:e=>c(e.target.value),placeholder:`Appended to the note with today's date.`}),(0,x.jsx)(`div`,{className:`form__actions`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:f,disabled:l||!s.trim(),children:`Save note`})})]})})]})]}):(0,x.jsxs)(`div`,{className:`detail`,children:[S,(0,x.jsx)(zg,{lines:6})]})})}function ov({job:e,onStatus:t,busy:n}){let[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)({}),[s,c]=(0,b.useState)(``),[l,u]=(0,b.useState)([]),d=()=>$.packet(e.id).then(e=>{i(e),o(e.values)}).catch(e=>X({title:`Could not read the packet`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{d(),$.resumes().then(e=>u(e.files.map(e=>e.name))).catch(()=>{})},[e.id]);let f=async(t,n)=>{o(e=>({...e,[t]:n})),c(t);try{await $.saveApplication(e.id,t,n),await d(),X({title:`${t} saved`,description:n,tone:`success`})}catch(e){X({title:`${t} not saved`,description:e.message,tone:`danger`})}finally{c(``)}},p=async t=>{if(r&&a[t]!==r.values[t]){c(t);try{await $.saveApplication(e.id,t,a[t]??``),await d(),X({title:`${t} saved`,description:`Written into the note.`,tone:`success`})}catch(e){X({title:`${t} not saved`,description:e.message,tone:`danger`})}finally{c(``)}}};return r?(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsxs)(`div`,{className:`packet__state`,children:[(0,x.jsxs)(z,{tone:r.ready?`success`:`neutral`,variant:r.ready?`soft`:`outline`,children:[r.filled,` of `,r.total,` filled`]}),r.ready?(0,x.jsx)(`p`,{className:`muted`,children:`Every required field has something in it. Read it before you send it — this says the boxes are full, not that the application is good.`}):(0,x.jsxs)(`p`,{className:`muted`,children:[`Still required: `,r.missing.join(`, `),`.`]})]}),r.ready&&e.status!==`applied`&&(0,x.jsxs)(`div`,{className:`form__actions form__actions--start`,children:[e.status!==`ready`&&(0,x.jsx)(B,{size:`sm`,tone:`primary`,variant:`soft`,disabled:n,onClick:()=>t(`ready`),children:`Mark ready for approval`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:n,onClick:()=>{window.confirm(`Only mark this applied if you have actually sent it to ${e.company}. Nothing here can send an application.`)&&t(`applied`)},children:`I have applied`})]}),r.fields.map(({field:e,hint:t,required:n})=>(0,x.jsxs)(`div`,{className:`packet__field`,children:[(0,x.jsx)(Xp,{label:n?`${e} *`:e,description:t,rows:e===`Tailored summary`||e===`Tailored bullets`||e===`Cover letter`||e===`Outreach message`||e===`Questions`||e===`Risks`?3:1,value:a[e]??``,onChange:t=>o({...a,[e]:t.target.value}),onBlur:()=>p(e),placeholder:n?`Required before this is ready.`:``}),e===`Resume variant`&&l.length>0&&(0,x.jsx)(`div`,{className:`chips`,children:l.map(t=>(0,x.jsx)(B,{size:`sm`,variant:a[e]===t?`soft`:`ghost`,tone:a[e]===t?`primary`:`neutral`,onClick:()=>f(e,t),children:t},t))}),s===e&&(0,x.jsx)(`span`,{className:`muted`,children:`Saving…`})]},e)),(0,x.jsx)(`p`,{className:`muted`,children:`Fields are written into the note's Application section as you leave each one. An agent fills the same fields through the TekJobs MCP server — see Agent access.`})]}):(0,x.jsx)(`div`,{className:`detail`,children:(0,x.jsx)(zg,{lines:6})})}var sv={confirmation:`success`,rejection:`danger`,advance:`primary`,scheduling:`primary`,"info-request":`warning`,other:`neutral`},cv={confirmation:`confirmed`,rejection:`rejected`,advance:`advanced`,scheduling:`scheduling`,"info-request":`asks for more`,other:`other`};function lv(e,t){let n=e.suggestion;return t?n.action===`status`?`mark it ${n.status}${n.appliedOn?` as of ${n.appliedOn}`:``}`:`add the mail to the note${n.appliedOn?`, set Applied on if empty`:``}`:`create a note for ${e.company} and mark it ${n.status}`}function uv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(0);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(fv,{onOpen:t,onChanged:()=>r(e=>e+1)},n),(0,x.jsx)(iv,{id:e,onClose:()=>t(null),onChanged:e=>{}})]})}function dv({onOpen:e}){let[t,n]=(0,b.useState)(null);(0,b.useEffect)(()=>{$.mail().then(n).catch(()=>{})},[]);let r=t?.groups.length??0;return!t||r===0&&!t.running?null:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`mailstrip`,children:[(0,x.jsxs)(`span`,{children:[t.running?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Bg,{size:`sm`}),` Reading the mailbox.`]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`b`,{className:`num`,children:r}),` `,r===1?`email group waits`:`email groups wait`,` for a decision.`]}),t.lastRun&&(0,x.jsxs)(`span`,{className:`muted`,children:[` Last read `,(0,x.jsx)(`span`,{className:`num`,children:t.lastRun.slice(0,16).replace(`T`,` `)}),` UTC.`]})]}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,leadingIcon:(0,x.jsx)(H.Mail,{}),onClick:e,children:`Open Mail`})]})})}function fv({onOpen:e,onChanged:t}){let[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)({}),[o,s]=(0,b.useState)(null),c=()=>$.mail().then(r).catch(()=>{});(0,b.useEffect)(()=>{c()},[]),(0,b.useEffect)(()=>{if(!n?.running)return;let e=setInterval(()=>$.mail().then(e=>{r(e),!e.running&&e.error&&X({title:`Mail check failed`,description:e.error,tone:`danger`})}).catch(()=>{}),4e3);return()=>clearInterval(e)},[n?.running]);let l=async()=>{try{r(await $.mailCheck()),X({title:`Reading the mailbox`,description:`Through the local CLI, Gmail read tools only. A few minutes.`,tone:`neutral`})}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},u=async(e,n)=>{s(e.id);try{let a=e.id in i?i[e.id]:e.noteId;r(n===`confirm`?await $.mailConfirm(e.id,a||void 0):await $.mailDismiss(e.id)),n===`confirm`&&(X({title:`${e.company}: ${lv(e,i[e.id]||e.noteId)}`,description:`Written to the note.`,tone:`success`}),t())}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}finally{s(null)}},d=n?.groups??[],f=(n?.items??[]).filter(e=>e.state!==`pending`).sort((e,t)=>(t.resolved?.at??``).localeCompare(e.resolved?.at??``)),p=f.length,[m,h]=(0,b.useState)(!1),g=e=>e.state===`dismissed`?`dismissed`:e.resolved?.action===`create`?`note created, marked ${e.resolved.status}`:e.resolved?.action===`status`?`marked ${e.resolved.status}`:`recorded on the note`,_=d.filter(e=>e.kind===`confirmation`&&e.match===`exact`&&e.noteId).length;return(0,x.jsxs)(`section`,{className:`today__section`,id:`mail-says`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Mail says`}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[n?.lastRun&&(0,x.jsxs)(`span`,{className:`muted`,children:[`last read `,n.lastRun.slice(0,16).replace(`T`,` `),` UTC, `,n.lastSinceDays,` days back`]}),p>0&&(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:()=>h(e=>!e),children:m?`Hide handled`:`${p} handled`}),_>0&&(0,x.jsxs)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:o===`safe`||!!n?.running,loading:o===`safe`,title:`Confirmations whose note matched by exact title: records the mail, marks still-open notes applied as of the mail's date. Rejections, interviews, company-only matches and creates stay one at a time.`,onClick:async()=>{s(`safe`);try{let e=await $.mailConfirmSafe();r(e),X({title:`${e.confirmed} confirmations recorded`,description:`Exact-title matches only. The rest are still listed.`,tone:`success`}),t()}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}finally{s(null)}},children:[`Confirm the exact matches (`,_,`)`]}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:!!n?.running,leadingIcon:n?.running?(0,x.jsx)(Bg,{size:`sm`}):(0,x.jsx)(H.Mail,{}),onClick:l,children:n?.running?`Reading the mailbox`:`Check mail`})]})]}),!n||d.length===0&&!n.running?(0,x.jsx)(V,{padding:`md`,children:(0,x.jsx)(Vg,{size:`sm`,title:n?.lastRun?`Nothing waiting from the mailbox`:`The mailbox has not been read yet`,description:n?.error?n.error:`The morning task reads application emails through your signed-in CLI (Gmail read tools only) and lists what they say about your applications here. You confirm each one. Check mail reads again now.`})}):(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Application emails waiting for a decision`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Date`}),(0,x.jsx)(Y.HeadCell,{children:`Mail says`}),(0,x.jsx)(Y.HeadCell,{children:`Company and role`}),(0,x.jsx)(Y.HeadCell,{children:`Note`}),(0,x.jsx)(Y.HeadCell,{children:`Confirm`})]})}),(0,x.jsxs)(Y.Body,{children:[d.map(t=>{let n=i[t.id]||t.noteId;return(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:t.date||`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[(0,x.jsxs)(`span`,{className:`chips`,children:[t.kinds.map(e=>(0,x.jsx)(z,{size:`sm`,tone:sv[e],children:cv[e]},e)),t.count>1&&(0,x.jsxs)(`small`,{children:[t.count,` emails`,t.first&&t.first!==t.date?`, ${t.first} to ${t.date}`:``]})]}),(0,x.jsx)(`small`,{title:t.subject,children:t.gist})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[t.company,(0,x.jsx)(`small`,{children:t.role||`role not stated`}),t.person&&(0,x.jsxs)(`small`,{title:`${t.person.email}. Confirming adds them to People and to the note.`,children:[`from `,t.person.name]})]})}),(0,x.jsx)(Y.Cell,{children:t.match===`none`?(0,x.jsx)(`span`,{className:`muted`,children:`no note; confirm creates one`}):t.match===`exact`||t.match===`company`&&t.candidates.length<=1?(0,x.jsxs)(B,{variant:`link`,size:`sm`,tone:`neutral`,onClick:()=>e(t.noteId),children:[t.noteTitle,` · `,t.noteStatus]}):(0,x.jsxs)(J,{size:`sm`,label:t.match===`company-other-role`?`Not a role in the vault`:`Which role`,value:n||`__new__`,onValueChange:e=>a(n=>({...n,[t.id]:e===`__new__`?``:e})),children:[(0,x.jsx)(J.Item,{value:`__new__`,children:`New note for this role`}),t.candidates.map(e=>(0,x.jsxs)(J.Item,{value:e.id,children:[e.title,` · `,e.status]},e.id))]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`today__actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:o===t.id,title:lv(t,n),onClick:()=>u(t,`confirm`),children:n?t.suggestion.action===`record`?`Record`:`Mark ${t.suggestion.status}`:`Create and mark`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,disabled:o===t.id,onClick:()=>u(t,`dismiss`),children:`Dismiss`})]})})]},t.id)}),n.running&&d.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:5,children:(0,x.jsx)(`span`,{className:`muted`,children:`Reading…`})})})]})]})}),m&&(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Application emails already handled`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Mail date`}),(0,x.jsx)(Y.HeadCell,{children:`Mail said`}),(0,x.jsx)(Y.HeadCell,{children:`Company and role`}),(0,x.jsx)(Y.HeadCell,{children:`Note`}),(0,x.jsx)(Y.HeadCell,{children:`What was done`})]})}),(0,x.jsx)(Y.Body,{children:f.map(t=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:t.date||`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:sv[t.kind],children:cv[t.kind]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[t.company,(0,x.jsx)(`small`,{children:t.role||`role not stated`})]})}),(0,x.jsx)(Y.Cell,{children:t.noteId?(0,x.jsx)(B,{variant:`link`,size:`sm`,tone:`neutral`,onClick:()=>e(t.noteId),children:t.noteId.replace(/ \([0-9a-f]+\)$/,``)}):(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`muted`,children:[g(t),t.resolved?.at?`, ${t.resolved.at.slice(0,16).replace(`T`,` `)} UTC`:``]})})]},t.id))})]})})]})}var pv=`Use the tekjobs MCP server. Call onboarding_status, then onboarding_materials, and follow its script: interview me, write my profile with save_profile, set the criteria with set_criteria, run a dry scan, and show me the top matches.`;function mv({onDone:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),[a,o]=(0,b.useState)(!1),s=()=>$.onboarding().then(n).catch(e=>X({title:`Server not answering`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{s()},[]);let c=async()=>{o(!0);try{let e=await $.initProfile();X({title:`Profile folder ready`,description:e.made.length?`Created ${e.made.join(`, `)}`:`It already existed; nothing was overwritten.`,tone:`success`}),await s()}catch(e){X({title:`Could not create the folder`,description:e.message,tone:`danger`})}o(!1)},l=async()=>{if(r.trim()){o(!0);try{X({title:`Resume imported`,description:`${(await $.importResume(r.trim())).chars.toLocaleString()} characters of text extracted.`,tone:`success`}),i(``),await s()}catch(e){X({title:`Import failed`,description:e.message,tone:`danger`})}o(!1)}};if(!t)return(0,x.jsx)(zg,{variant:`rect`,height:`20rem`});let u=t.steps.filter(e=>e.done).length;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[`Five steps from an empty folder to a daily scan that knows who you are. Your profile lives at `,(0,x.jsx)(`code`,{children:t.dir}),`. Nothing leaves this machine.`]})}),(0,x.jsxs)(z,{tone:t.complete?`success`:`primary`,size:`sm`,children:[u,` of `,t.steps.length,` done`]})]}),(0,x.jsx)(`div`,{className:`steps`,children:t.steps.map((e,t)=>(0,x.jsx)(V,{padding:`md`,variant:e.done?`sunken`:`outlined`,children:(0,x.jsxs)(`div`,{className:`step`,children:[(0,x.jsx)(`div`,{className:`step__mark`,children:e.done?(0,x.jsx)(H.Success,{}):(0,x.jsx)(`span`,{className:`step__n`,children:t+1})}),(0,x.jsxs)(`div`,{className:`step__body`,children:[(0,x.jsx)(`span`,{className:`step__label`,children:e.label}),!e.done&&(0,x.jsx)(`p`,{className:`muted`,children:e.how}),!e.done&&e.id===`folder`&&(0,x.jsx)(`div`,{className:`form__actions form__actions--start`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,loading:a,onClick:c,children:`Create the profile folder`})}),!e.done&&e.id===`resume`&&(0,x.jsxs)(`div`,{className:`step__row`,children:[(0,x.jsx)(Zp,{size:`sm`,label:`Path to your resume`,placeholder:`C:\\Users\\you\\Downloads\\resume.pdf`,description:`PDF, DOCX, Markdown or text. The file is copied into Profile/ and its text extracted.`,value:r,onChange:e=>i(e.target.value)}),(0,x.jsx)(B,{tone:`primary`,size:`sm`,loading:a,disabled:!r.trim(),onClick:l,children:`Import`})]}),!e.done&&e.id===`profile`&&(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`The interview runs in your own LLM, not here. Open Claude Code in the app folder (its .mcp.json connects it) and paste:`}),(0,x.jsx)(ag,{code:pv,language:`text`,wrap:!0}),(0,x.jsx)(`p`,{className:`muted`,children:`Claude Desktop, ChatGPT or Cursor work the same way once the tekjobs MCP server is added; see Agent access.`})]}),!e.done&&e.id===`scan`&&(0,x.jsx)(`div`,{className:`form__actions form__actions--start`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:()=>{$.startScan(!1).then(()=>X({title:`Scan started`,description:`Watch it on the Runs screen.`,tone:`success`})).catch(e=>X({title:`Could not start`,description:e.message,tone:`danger`}))},children:`Run the first scan`})})]})]})},e.id))}),t.complete&&(0,x.jsx)(`div`,{className:`form__actions`,children:(0,x.jsx)(B,{tone:`primary`,onClick:e,trailingIcon:(0,x.jsx)(H.ArrowRight,{}),children:`Go to the overview`})})]})}function hv({label:e,value:t,hint:n,tone:r=`neutral`,series:i,onClick:a}){return(0,x.jsx)(V,{padding:`md`,interactive:!!a,onClick:a,children:(0,x.jsxs)(`div`,{className:`stat`,children:[(0,x.jsx)(`span`,{className:`stat__label`,children:e}),(0,x.jsxs)(`div`,{className:`stat__row`,children:[(0,x.jsx)(`span`,{className:`stat__value`,children:t}),i&&i.length>1&&(0,x.jsx)(`div`,{className:`stat__spark`,children:(0,x.jsx)(Cp,{values:i,tone:r===`neutral`?`primary`:r,"aria-label":`${e}, per scan`})})]}),n&&(0,x.jsx)(`div`,{className:`stat__delta`,children:(0,x.jsx)(z,{tone:r,size:`sm`,children:n})})]})})}var gv=e=>e===null?`—`:`${Math.round(e*100)}%`,_v={found:`Found`,reviewed:`Reviewed`,shortlisted:`Shortlisted`,applied:`Applied`,interviewing:`Interviewing`,offer:`Offer`},vv={"design-eng":`Design engineering`,adjacent:`Adjacent titles`};function yv({onNavigate:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)(``);if((0,b.useEffect)(()=>{$.summary().then(n).catch(e=>o(e.message)),$.outcomes().then(i).catch(()=>{})},[]),a)return(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`p`,{className:`muted`,children:[`The server is not answering: `,a,`. Start it with `,(0,x.jsx)(`code`,{children:`npm run server`}),`.`]})});if(!t||!r)return(0,x.jsx)(zg,{variant:`rect`,height:`12rem`});let s=[`floor`,`stretch`,`below`,`unknown`],c=[`new`,`reviewing`,`applying`,`applied`,`interviewing`,`offer`,`rejected`,`passed`],l=r.waiting.buckets[14]??0,u=r.thisWeek.followUps.filter(e=>e.inDays<=0).length,d=r.appliedPerWeek;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`b`,{children:r.funnel.applied}),` applied, `,(0,x.jsx)(`b`,{children:gv(r.responseRate)}),` answered, `,(0,x.jsx)(`b`,{children:r.funnel.interviewing}),` interviewing`,l?(0,x.jsxs)(x.Fragment,{children:[`, `,(0,x.jsx)(`b`,{children:l}),` waiting two weeks or more`]}):null,`.`,` `,`The inventory: `,t.open,` open matches across `,t.companies,` boards, floor `,t.floor?Jg(t.floor):`unset`,`, bar `,t.minScore??`unset`,`.`]})}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,onClick:()=>e(`runs`),children:`Runs`})]}),(0,x.jsxs)(`div`,{className:`stats z-stagger`,children:[(0,x.jsx)(hv,{label:`Applied`,value:String(r.funnel.applied),hint:`${r.funnel.shortlisted} shortlisted, ${r.funnel.reviewed} reviewed`,tone:`primary`,onClick:()=>e(`pipeline`)}),(0,x.jsx)(hv,{label:`Response rate`,value:gv(r.responseRate),hint:r.funnel.applied?`${r.responded} of ${r.funnel.applied} answered, interview or no`:`nothing applied to yet`,tone:r.responseRate&&r.responseRate>0?`success`:`neutral`}),(0,x.jsx)(hv,{label:`Waiting 14 days or more`,value:String(l),hint:`${r.waiting.buckets[7]??0} past 7 days, ${r.waiting.buckets[21]??0} past 21`,tone:(r.waiting.buckets[21]??0)>0?`warning`:`neutral`}),(0,x.jsx)(hv,{label:`Discovery to application`,value:r.medianDaysToApply===null?`—`:`${r.medianDaysToApply}d`,hint:`median, found to applied`})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Funnel`}),(0,x.jsx)(`p`,{children:`Each stage counts everything that reached it, whatever happened after. The rate is the share of the stage before.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Application funnel`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Stage`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Jobs`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Of the stage before`}),(0,x.jsx)(Y.HeadCell,{children:`Share`})]})}),(0,x.jsx)(Y.Body,{children:r.stages.map((e,t)=>{let n=r.stages[0]?.count||1;return(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:_v[e.stage]??e.stage}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.count}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(`span`,{className:e.rate===null?`muted`:``,children:t===0?`—`:gv(e.rate)})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`div`,{className:`funnel__bar`,role:`presentation`,children:(0,x.jsx)(`span`,{style:{width:`${Math.max(e.count?2:0,Math.round(e.count/n*100))}%`}})})})]},e.stage)})})]}),(0,x.jsxs)(`p`,{className:`muted panel--pad`,children:[r.passed,` passed on, `,r.rejected,` rejected.`]})]}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`This week`}),(0,x.jsxs)(`p`,{children:[`Follow-ups due in the next seven days`,u?`, ${u} already past`:``,`, and the interviews in progress. Dates come from each note's packet.`]})]})})}),(0,x.jsxs)(Y,{"aria-label":`This week`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{align:`end`,children:`When`})]})}),(0,x.jsxs)(Y.Body,{children:[r.thisWeek.followUps.map(t=>(0,x.jsxs)(Y.Row,{interactive:!0,onClick:()=>e(`jobs`,t.company),children:[(0,x.jsx)(Y.Cell,{children:t.company}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`clamp`,children:t.title})}),(0,x.jsx)(Y.Cell,{align:`end`,children:(0,x.jsx)(z,{size:`sm`,tone:t.inDays<0?`danger`:t.inDays===0?`warning`:`neutral`,children:t.inDays<0?`follow up, ${-t.inDays}d late`:t.inDays===0?`follow up today`:`follow up in ${t.inDays}d`})})]},t.id)),r.thisWeek.interviewing.map(t=>(0,x.jsxs)(Y.Row,{interactive:!0,onClick:()=>e(`jobs`,t.company),children:[(0,x.jsx)(Y.Cell,{children:t.company}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`clamp`,children:t.title})}),(0,x.jsx)(Y.Cell,{align:`end`,children:(0,x.jsx)(z,{size:`sm`,tone:`primary`,children:`interviewing`})})]},t.id)),r.thisWeek.followUps.length===0&&r.thisWeek.interviewing.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:3,children:(0,x.jsx)(`span`,{className:`muted`,children:`Nothing due this week. Applied roles get a follow-up date in their packet when you mark them applied.`})})})]})]})]})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Applications per week`}),(0,x.jsx)(`p`,{children:`Sent, by the week of the packet's Applied on date.`})]})}),d.length>0?(0,x.jsx)(Ye,{series:[{name:`Applied`,values:d.map(e=>e.n)}],labels:d.map(e=>e.week.slice(5)),height:180,"aria-label":`Applications per week`}):(0,x.jsx)(`p`,{className:`muted`,children:`Nothing applied to yet.`})]})}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`What answers`}),(0,x.jsx)(`p`,{children:`By role family, then by the board that surfaced the job.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Outcomes by role family`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Role family`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Found`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Applied`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Answered`})]})}),(0,x.jsx)(Y.Body,{children:r.byKind.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:vv[e.kind]??e.kind}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.found}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.applied}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.applied?`${e.responded} (${gv(e.responded/e.applied)})`:`—`})]},e.kind))})]}),r.bySource.length>0&&(0,x.jsx)(`div`,{className:`chips panel--pad`,children:r.bySource.map(e=>(0,x.jsxs)(z,{size:`sm`,tone:e.responded?`success`:`neutral`,variant:`soft`,children:[e.source,`: `,e.applied,` applied`,e.responded?`, ${e.responded} answered`:``]},e.source))})]})]}),(0,x.jsxs)(`div`,{className:`stats z-stagger`,children:[(0,x.jsx)(hv,{label:`Open matches`,value:String(t.open),hint:`${t.byStatus.new??0} unreviewed`,onClick:()=>e(`jobs`)}),(0,x.jsx)(hv,{label:`Design-engineer roles at the floor`,value:String(t.designEng.floor),hint:`of ${t.designEng.total} with the title`,tone:`success`,onClick:()=>e(`jobs`)}),(0,x.jsx)(hv,{label:`Pay under the floor, above the stretch line`,value:String(t.byBand.stretch??0),hint:`${t.designEng.stretch} design-engineer`,tone:`warning`}),(0,x.jsx)(hv,{label:`Active applications`,value:String(t.active),hint:t.active?`in flight`:`none yet`,tone:t.active?`primary`:`neutral`,onClick:()=>e(`pipeline`)})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Pipeline`}),(0,x.jsx)(`p`,{children:`Every open note by status. Change a status in Jobs or Pipeline; the note is the record.`})]})}),(0,x.jsx)(Ye,{series:[{name:`Jobs`,values:c.map(e=>t.byStatus[e]??0)}],labels:[...c],height:200,"aria-label":`Jobs by status`})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Stated pay against the floor`}),(0,x.jsx)(`p`,{children:`Open matches by band.`})]})}),(0,x.jsx)(Ye,{series:[{name:`Matches`,values:s.map(e=>t.byBand[e]??0)}],labels:[`Floor`,`Stretch`,`Below`,`Not stated`],height:200,"aria-label":`Matches by pay band`})]})})]})]})}function bv({onNavigate:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),[a,o]=(0,b.useState)(null),[s,c]=(0,b.useState)(null),l=()=>$.today().then(n).catch(e=>i(e.message));(0,b.useEffect)(()=>{l()},[]);let u=async(e,t,n)=>{c(e.id);try{await $.setStatus(e.id,t,n),X({title:`${e.company}: ${t===`reviewing`?`shortlisted`:`passed`}`,description:n,tone:t===`reviewing`?`success`:`neutral`}),await l()}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}finally{c(null)}};if(r)return(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`p`,{className:`muted`,children:[`The server is not answering: `,r,`. Start it with `,(0,x.jsx)(`code`,{children:`npm run server`}),`.`]})});if(!t)return(0,x.jsx)(zg,{variant:`rect`,height:`18rem`});let{counts:d,sections:f}=t,p=[...f.preparing,...f.followUps,...f.interviewing];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h1`,{className:`today__date`,children:new Date().toLocaleDateString(`en-US`,{weekday:`long`,day:`numeric`,month:`long`})}),(0,x.jsx)(`p`,{children:f.triage.length===0?`Today's queue is clear. The next scan refills it.`:`${f.triage.length===1?`One`:f.triage.length} to decide on, best fit first. The other ${d.unreviewed-f.triage.length} unreviewed wait in Jobs and do not count against you. Fit is the share of the ${t.ceiling} points this criteria set can award.`})]}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,onClick:()=>e(`jobs`),children:`See all matches`})]}),(0,x.jsxs)(`div`,{className:`today__figures`,children:[(0,x.jsxs)(`div`,{className:`today__figure`,children:[(0,x.jsx)(`b`,{children:d.open}),(0,x.jsx)(`small`,{children:`open`})]}),(0,x.jsxs)(`div`,{className:`today__figure`,children:[(0,x.jsx)(`b`,{children:d.aging}),(0,x.jsx)(`small`,{children:`waiting 2d+`})]}),(0,x.jsxs)(`div`,{className:`today__figure`,children:[(0,x.jsx)(`b`,{"data-tone":d.closedUnreviewed>0?`danger`:void 0,children:d.closedUnreviewed}),(0,x.jsx)(`small`,{children:`closed unseen`})]})]}),(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsxs)(`div`,{className:`today__section-head`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Decide on these`}),(0,x.jsx)(`span`,{className:`today__hint`,children:`shortlist · pass · open sheet`})]}),f.triage.length===0?(0,x.jsx)(V,{padding:`md`,children:(0,x.jsx)(Vg,{size:`sm`,title:`Inbox clear`,description:`Nothing unreviewed is open right now. The next scan will refill this.`})}):(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Matches to decide on`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Fit`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Pay`}),(0,x.jsx)(Y.HeadCell,{children:`Found`}),(0,x.jsx)(Y.HeadCell,{children:`Decide`})]})}),(0,x.jsx)(Y.Body,{children:f.triage.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,selected:a===e.id,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(Cv,{value:e.fit})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[e.title,e.kind===`design-eng`&&(0,x.jsx)(`small`,{children:`design engineering`})]})}),(0,x.jsx)(Y.Cell,{children:e.salaryMax>0?(0,x.jsx)(z,{tone:Qg[e.payBand],size:`sm`,children:Yg(e.salary)}):(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:Xg(e.found)})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`today__actions`,onClick:e=>e.stopPropagation(),children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:s===e.id,onClick:()=>u(e,`reviewing`),children:`Shortlist`}),(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,disabled:s===e.id,trailingIcon:(0,x.jsx)(H.ChevronDown,{}),children:`Pass`})}),(0,x.jsx)(Tu.Content,{align:`end`,children:Kg.map(t=>(0,x.jsx)(Tu.Item,{onSelect:()=>u(e,`passed`,t),children:t},t))})]})]})})]},e.id))})]})})]}),(0,x.jsx)(dv,{onOpen:()=>e(`mail`)}),f.started.length>0&&(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Already started`}),(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Applications with a packet started`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Fit`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Packet`}),(0,x.jsx)(Y.HeadCell,{children:`Pay`}),(0,x.jsx)(Y.HeadCell,{children:`Status`})]})}),(0,x.jsx)(Y.Body,{children:f.started.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,selected:a===e.id,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(Cv,{value:e.fit})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(z,{size:`sm`,tone:`primary`,variant:`soft`,children:[e.packet,` filled`]})}),(0,x.jsx)(Y.Cell,{children:e.salaryMax>0?(0,x.jsx)(z,{tone:Qg[e.payBand],size:`sm`,children:Yg(e.salary)}):(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:e.closed?(0,x.jsxs)(z,{size:`sm`,tone:`danger`,children:[`closed `,e.closed]}):(0,x.jsx)(z,{size:`sm`,tone:e.status===`ready`?`warning`:`neutral`,children:e.status})})]},e.id))})]})}),(0,x.jsx)(`p`,{className:`muted`,children:`Work you have already put in, wherever it ranks. The fit score knows nothing about a drafted packet, so these would otherwise fall off the bottom of the queue.`})]}),(f.aging.length>0||f.missed.length>0)&&(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Going, and gone`}),(0,x.jsxs)(`div`,{className:`today__cols`,children:[f.aging.length>0&&(0,x.jsxs)(V,{padding:`md`,children:[(0,x.jsx)(`h3`,{className:`today__subheading`,children:`Still open, still unread`}),(0,x.jsx)(`p`,{className:`muted`,children:`Listings here close after two days, at the median.`}),(0,x.jsx)(`ul`,{className:`today__list`,children:f.aging.map(e=>(0,x.jsx)(`li`,{children:(0,x.jsxs)(B,{className:`today__row`,variant:`ghost`,align:`start`,size:`sm`,onClick:()=>o(e.id),children:[(0,x.jsx)(Cv,{value:e.fit}),(0,x.jsx)(`span`,{className:`today__row-text`,children:xv(e.company,e.title,52)}),(0,x.jsxs)(z,{size:`sm`,tone:(e.days??0)>=5?`danger`:`warning`,variant:`outline`,children:[e.days,`d`]})]})},e.id))})]}),f.missed.length>0&&(0,x.jsxs)(V,{padding:`md`,children:[(0,x.jsx)(`h3`,{className:`today__subheading`,children:`Closed before you saw them`}),(0,x.jsxs)(`p`,{className:`muted`,children:[d.closedUnreviewed,` this week. This is what the queue costs when it is skipped.`]}),(0,x.jsx)(`ul`,{className:`today__list`,children:f.missed.map(e=>(0,x.jsx)(`li`,{children:(0,x.jsxs)(B,{className:`today__row`,variant:`ghost`,align:`start`,size:`sm`,onClick:()=>o(e.id),children:[(0,x.jsx)(Cv,{value:e.fit}),(0,x.jsx)(`span`,{className:`today__row-text`,children:xv(e.company,e.title,36)}),(0,x.jsx)(`span`,{className:`muted`,children:e.closed})]})},e.id))})]})]})]}),(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`In flight`}),(0,x.jsx)(V,{padding:p.length?`none`:`md`,children:p.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`Nothing in flight`,description:`Applications being prepared, follow-ups that are due, and interviews appear here once jobs move past Shortlisted.`,action:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:()=>e(`pipeline`),children:`Open the pipeline`})}):(0,x.jsxs)(Y,{"aria-label":`In flight`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Fit`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Status`}),(0,x.jsx)(Y.HeadCell,{children:`Due`}),(0,x.jsx)(Y.HeadCell,{children:`Write to`})]})}),(0,x.jsx)(Y.Body,{children:p.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(Cv,{value:e.fit})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:`primary`,children:e.status})}),(0,x.jsx)(Y.Cell,{children:e.due||(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(Sv,{contact:e.contact})})]},e.id))})]})})]}),(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsxs)(`div`,{className:`today__section-head`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Waiting on a reply`}),(0,x.jsxs)(`span`,{className:`today__hint`,children:[`applied `,d.waitingDays,`d+ ago, nothing back · `,d.waiting,` in all`]})]}),(0,x.jsx)(V,{padding:f.waiting.length===0?`md`:`none`,children:f.waiting.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`Nothing has gone quiet`,description:`Applications with no answer after ${d.waitingDays} days land here, with the person to ask.`}):(0,x.jsxs)(Y,{"aria-label":`Applications waiting on a reply`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Days`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Applied`}),(0,x.jsx)(Y.HeadCell,{children:`Write to`})]})}),(0,x.jsx)(Y.Body,{children:f.waiting.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(`span`,{className:`num`,"data-tone":(e.days??0)>=21?`danger`:void 0,children:e.days})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:e.appliedOn})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(Sv,{contact:e.contact})})]},e.id))})]})})]}),(0,x.jsx)(iv,{id:a,onClose:()=>o(null),onChanged:e=>{l()}})]})}var xv=(e,t,n=64)=>{let r=`${e} — ${t}`.replace(/\s+/g,` `).trim();return r.length>n?`${r.slice(0,n-1).trimEnd()}…`:r};function Sv({contact:e}){return e?(0,x.jsxs)(`span`,{className:`who__text`,children:[e.email?(0,x.jsxs)(`a`,{className:`people__thread`,href:`mailto:${e.email}`,onClick:e=>e.stopPropagation(),children:[e.name,` ↗`]}):e.name,(0,x.jsxs)(`small`,{children:[e.role||`contact`,e.others>0?` · +${e.others}`:``]})]}):(0,x.jsx)(`span`,{className:`muted`,title:`Open the sheet's People tab to add someone.`,children:`no one on the thread`})}function Cv({value:e}){return(0,x.jsx)(z,{size:`sm`,tone:e>=80?`success`:e>=60?`primary`:`neutral`,variant:e>=60?`soft`:`outline`,children:(0,x.jsx)(`span`,{className:`num`,children:e})})}var wv=[{id:`reviewing`,title:`Reviewing`},{id:`applying`,title:`Applying`,limit:5},{id:`ready`,title:`Ready`,limit:5},{id:`applied`,title:`Applied`},{id:`interviewing`,title:`Interviewing`},{id:`offer`,title:`Offer`}],Tv=new Set(wv.map(e=>e.id));function Ev(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)([]),o=()=>$.jobs({status:`all`,limit:2e3}).then(e=>t(e.rows)).catch(e=>X({title:`Could not load the board`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{o()},[]);let s=async(n,r)=>{let i=e?.find(e=>e.id===n);if(i&&i.status!==r){t(e=>e&&e.map(e=>e.id===n?{...e,status:r}:e));try{await $.setStatus(n,r),X({title:`${i.company}: ${r}`,tone:`success`})}catch(e){X({title:`Move not saved`,description:e.message,tone:`danger`}),o()}}},c=e=>t(t=>t&&t.map(t=>t.id===e.id?{...t,status:e.status}:t)),l=(0,b.useMemo)(()=>{let t=new Map;for(let n of e??[])Tv.has(n.status)&&t.set(n.company,(t.get(n.company)??0)+1);return[...t.entries()].sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).map(([e,t])=>({value:e,label:e,hint:`${t} on the board`}))},[e]);if(!e)return(0,x.jsx)(zg,{variant:`rect`,height:`20rem`});let u=new Set(i),d=e.filter(e=>Tv.has(e.status)&&(u.size===0||u.has(e.company))).sort((e,t)=>t.score-e.score),f=e.filter(e=>e.status===`new`).length,p=e.filter(e=>e.status===`rejected`||e.status===`passed`).length;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page__head`,children:(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[`Committed work only. Drag a card, or focus one and press Space to lift it, arrows to move it, Enter to drop. Every move is written to the job note.`,f?` ${f} new matches wait on Today, not here.`:``,p?` ${p} closed are not shown.`:``]})})}),(0,x.jsx)(`div`,{className:`toolbar`,children:(0,x.jsx)(Wg,{className:`toolbar__filter toolbar__filter--wide`,size:`sm`,multiple:!0,label:`Companies`,placeholder:i.length?``:`All companies`,description:`Narrow the board to the companies you are actually working.`,emptyMessage:`No company on the board matches that.`,options:l,value:i,onValueChange:a})}),(0,x.jsx)(Hg,{label:`Job pipeline`,columns:wv,cards:d,cardId:e=>e.id,cardColumn:e=>e.status,cardLabel:e=>`${e.title} at ${e.company}`,onMove:e=>s(e.cardId,e.to),renderCard:e=>(0,x.jsxs)(`div`,{className:`kcard`,"data-posted":R_(e.source)||void 0,onClick:()=>r(e.id),children:[(0,x.jsxs)(`div`,{className:`kcard__head`,children:[(0,x.jsxs)(`span`,{className:`kcard__company posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]}),(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,"aria-label":`Move ${e.title}`,leadingIcon:(0,x.jsx)(H.More,{}),onClick:e=>e.stopPropagation()})}),(0,x.jsx)(Tu.Content,{align:`end`,onClick:e=>e.stopPropagation(),children:Gg.filter(t=>t!==e.status).map(t=>(0,x.jsxs)(Tu.Item,{onSelect:()=>s(e.id,t),children:[`Move to `,t]},t))})]})]}),(0,x.jsx)(`span`,{className:`kcard__title`,children:e.title}),(0,x.jsxs)(`div`,{className:`kcard__meta num`,children:[(0,x.jsx)(`span`,{className:`kcard__score`,children:e.score}),e.salaryMax>0&&(0,x.jsx)(`span`,{className:e.payBand===`floor`?`kcard__pay kcard__pay--floor`:`kcard__pay`,children:Yg(e.salary)})]})]})}),(0,x.jsx)(iv,{id:n,onClose:()=>r(null),onChanged:c})]})}var Dv={ok:`success`,warn:`warning`,missing:`danger`,info:`neutral`};function Ov({s:e}){return(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:e.basics.name||`No name yet`}),(0,x.jsx)(`p`,{children:[e.basics.currentRole,e.basics.location].filter(Boolean).join(` · `)||`The Basics section is empty.`})]}),(0,x.jsxs)(`div`,{className:`chips`,children:[(0,x.jsx)(z,{size:`sm`,tone:e.status===`draft`?`warning`:`success`,children:e.status===`draft`?`draft`:`reviewed`}),e.updated&&(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,variant:`outline`,children:[`updated `,e.updated]})]})]}),e.summary?(0,x.jsx)(`p`,{children:e.summary}):(0,x.jsx)(`p`,{className:`muted`,children:`The three-sentence summary is still the template. It leads every cover letter.`}),(e.basics.email||e.basics.links.length>0)&&(0,x.jsx)(`p`,{className:`muted mono`,children:[e.basics.email,...e.basics.links].filter(Boolean).join(` · `)})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Needs attention`}),(0,x.jsx)(`p`,{children:`What a reader of these notes would trip on. Each line names the note to fix.`})]}),(0,x.jsx)(z,{size:`sm`,tone:e.attention.length?`warning`:`success`,children:e.attention.length?`${e.attention.length} item${e.attention.length===1?``:`s`}`:`nothing stale`})]}),e.attention.length>0?(0,x.jsx)(`ul`,{className:`summary__list`,children:e.attention.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(z,{size:`sm`,tone:Dv[e.level],variant:`soft`,children:e.note}),` `,e.text]},e.text))}):(0,x.jsx)(`p`,{className:`muted`,children:`Every field is filled, the resume of record is fresh, and the criteria agree with the profile.`})]})}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Target roles`}),(0,x.jsx)(`p`,{children:`From the profile's table. "In criteria" means a title term the scan scores on matches the title; a title without one is never found by the scan.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Target roles`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Tier`}),(0,x.jsx)(Y.HeadCell,{children:`Title`}),(0,x.jsx)(Y.HeadCell,{children:`In criteria`})]})}),(0,x.jsxs)(Y.Body,{children:[e.targets.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:e.tier===`A`?`primary`:`neutral`,children:e.tier})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:e.term?(0,x.jsxs)(`span`,{className:`muted`,children:[`yes · `,(0,x.jsx)(`span`,{className:`mono`,children:e.term})]}):(0,x.jsx)(z,{size:`sm`,tone:`warning`,variant:`soft`,children:`no title term`})})]},`${e.tier}-${e.title}`)),e.targets.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:3,children:(0,x.jsx)(`span`,{className:`muted`,children:`The Target roles table is empty.`})})})]})]})]}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Constraints against the criteria`}),(0,x.jsx)(`p`,{children:`What the profile says beside what the scan enforces.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Constraints against the criteria`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Constraint`}),(0,x.jsx)(Y.HeadCell,{children:`Profile`}),(0,x.jsx)(Y.HeadCell,{children:`Criteria`}),(0,x.jsx)(Y.HeadCell,{})]})}),(0,x.jsx)(Y.Body,{children:e.constraints.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:e.label}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:e.profile?``:`muted`,children:e.profile||`not set`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:e.criteria?`num`:`muted`,children:e.criteria||`—`})}),(0,x.jsx)(Y.Cell,{children:e.level!==`info`&&(0,x.jsx)(z,{size:`sm`,tone:Dv[e.level],variant:`soft`,children:e.level===`ok`?`agree`:e.level===`warn`?`differ`:`missing`})})]},e.label))})]})]})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Documents`}),(0,x.jsx)(`p`,{children:`The notes and files the drafts are built from, and how fresh each one is.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Documents`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Document`}),(0,x.jsx)(Y.HeadCell,{children:`State`}),(0,x.jsx)(Y.HeadCell,{children:`Where`})]})}),(0,x.jsx)(Y.Body,{children:e.documents.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:e.label}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:Dv[e.level],variant:`soft`,children:e.state})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted mono`,children:e.where})})]},e.label))})]})]}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`What feeds what`}),(0,x.jsx)(`p`,{children:`Which note each thing the app writes is built from. Change the note, and everything after it changes.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`What feeds what`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Produces`}),(0,x.jsx)(Y.HeadCell,{children:`Reads`})]})}),(0,x.jsx)(Y.Body,{children:e.feeds.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:e.produces}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:e.reads})})]},e.produces))})]})]})]}),e.proofPoints.length>0&&(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Proof points`}),(0,x.jsxs)(`p`,{children:[e.proofPoints.length,` on file; the ones without a number are flagged above. Cover letters quote from these and nothing else.`]})]})}),(0,x.jsx)(`ul`,{className:`summary__list`,children:e.proofPoints.map(e=>(0,x.jsxs)(`li`,{children:[e.hasNumber?null:(0,x.jsx)(z,{size:`sm`,tone:`warning`,variant:`soft`,children:`no number`}),` `,e.text]},e.text))})]})})]})}var kv=e=>e.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/,``);function Av({note:e,onSaved:t}){let[n,r]=(0,b.useState)(e.markdown),[i,a]=(0,b.useState)(!1),[o,s]=(0,b.useState)(e.editable?`edit`:`preview`);(0,b.useEffect)(()=>r(e.markdown),[e.markdown]);let c=n!==e.markdown;return(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{children:e.hint}),(0,x.jsx)(`p`,{className:`muted`,children:(0,x.jsx)(`code`,{children:e.path})})]}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsx)(Z,{value:o,onValueChange:e=>s(e),variant:`pill`,size:`sm`,children:(0,x.jsxs)(Z.List,{"aria-label":`Edit or preview`,children:[(0,x.jsx)(Z.Trigger,{value:`edit`,children:e.editable?`Edit`:`Source`}),(0,x.jsx)(Z.Trigger,{value:`preview`,children:`Preview`})]})}),(0,x.jsx)(B,{asChild:!0,variant:`soft`,size:`sm`,trailingIcon:(0,x.jsx)(H.ExternalLink,{}),children:(0,x.jsx)(`a`,{href:`obsidian://open?path=${encodeURIComponent(e.path)}`,children:`Open in Obsidian`})})]})]}),!e.exists&&(0,x.jsx)(z,{tone:`warning`,size:`sm`,children:`This note does not exist yet; saving creates it.`}),o===`preview`?(0,x.jsx)(`div`,{className:`preview-doc`,children:(0,x.jsx)(dg,{text:kv(n)||`_Nothing here yet._`})}):(0,x.jsx)(Xp,{label:`${e.title} (Markdown)`,font:`mono`,rows:28,resize:`vertical`,value:n,onChange:e=>r(e.target.value),disabled:!e.editable,description:e.editable?void 0:`Read-only here. Pick a variant below, or edit the resume file and run tekjobs resume sync.`}),e.editable&&(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:!c||i,onClick:()=>r(e.markdown),children:`Discard`}),(0,x.jsx)(B,{tone:`primary`,size:`sm`,disabled:!c||i,loading:i,onClick:async()=>{a(!0);try{let r=await $.saveProfileNote(e.key,n);X({title:`${e.title} saved`,description:r.saved,tone:`success`}),t()}catch(t){X({title:`${e.title} not saved`,description:t.message,tone:`danger`})}a(!1)},children:`Save to the vault`})]})]})})}function jv({onChanged:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),a=()=>$.resumes().then(n).catch(e=>X({title:`Could not read the resume folder`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{a()},[]);let o=async t=>{i(t);try{let n=await $.useResume(t);X({title:`${t} is the resume of record`,description:`${n.chars} characters into Profile/Resume.md; ${n.added.length} lines new, ${n.removed.length} gone${n.stale.length?`, ${n.stale.length} drafts quote a removed claim`:``}.`,tone:`success`}),a(),e()}catch(e){X({title:`Not switched`,description:e.message,tone:`danger`})}i(``)},s=e=>`${Math.max(1,Math.round(e/1024))} KB`;return(0,x.jsx)(V,{padding:t&&t.files.length?`none`:`md`,children:t?t.files.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`No resume variants yet`,description:`Drop PDF, DOCX, Markdown or text files into ${t.dir}${t.exists?``:` (the folder does not exist yet)`} and they appear here. The folder is set in Settings.`}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(Y,{"aria-label":`Resume variants`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`File`}),(0,x.jsx)(Y.HeadCell,{children:`Changed`}),(0,x.jsx)(Y.HeadCell,{children:`Size`}),(0,x.jsx)(Y.HeadCell,{children:`Use`})]})}),(0,x.jsx)(Y.Body,{children:t.files.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`chips`,children:[e.name,e.current&&(0,x.jsx)(z,{size:`sm`,tone:`primary`,variant:`soft`,children:`resume of record`})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:e.modified})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:s(e.size)})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,onClick:()=>$.openResume(e.name).catch(e=>X({title:`Could not open`,description:e.message,tone:`danger`})),children:`Open`}),!e.current&&(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:!!r,loading:r===e.name,onClick:()=>o(e.name),children:`Make it the resume of record`})]})})]},e.name))})]}),(0,x.jsxs)(`p`,{className:`muted variants__foot`,children:[`From `,(0,x.jsx)(`code`,{className:`mono`,children:t.dir}),`. Making one the record reads it into Profile/Resume.md, which every tailored resume and letter starts from; the packet's Resume variant field offers these names.`]})]}):(0,x.jsx)(zg,{lines:3})})}function Mv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(null),i=()=>($.profileSummary().then(r).catch(()=>{}),$.profileNotes().then(e=>t(e.notes)).catch(e=>X({title:`Could not load the profile`,description:e.message,tone:`danger`})));return(0,b.useEffect)(()=>{i()},[]),e?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page__head`,children:(0,x.jsx)(`div`,{children:(0,x.jsx)(`p`,{children:`Who you are, how the story is told, and how you write. Cover letters, tailored resumes and application packets read these notes; the scan reads the Criteria page. Saving keeps yesterday's copy beside the note.`})})}),(0,x.jsxs)(Z,{defaultValue:`summary`,variant:`line`,size:`sm`,children:[(0,x.jsxs)(Z.List,{"aria-label":`Profile notes`,children:[(0,x.jsx)(Z.Trigger,{value:`summary`,children:`Summary`}),e.map(e=>(0,x.jsx)(Z.Trigger,{value:e.key,children:e.title},e.key))]}),(0,x.jsx)(Z.Content,{value:`summary`,children:n?(0,x.jsx)(Ov,{s:n}):(0,x.jsx)(zg,{variant:`rect`,height:`12rem`})}),e.map(e=>(0,x.jsx)(Z.Content,{value:e.key,children:(0,x.jsxs)(`div`,{className:`detail`,children:[e.key===`resume`&&(0,x.jsx)(jv,{onChanged:i}),(0,x.jsx)(Av,{note:e,onSaved:i})]})},e.key))]})]}):(0,x.jsx)(zg,{variant:`rect`,height:`24rem`})}var Nv=`__active__`,Pv={success:{label:`Success`,tone:`success`},partial:{label:`Partial`,tone:`warning`},failed:{label:`Failed`,tone:`danger`}},Fv=e=>e.dry?`dry run`:e.via===`schedule`?`scheduled`:e.via===`mcp`?`agent`:e.via===`cli`?`manual, CLI`:e.via===`app`?`manual`:``,Iv=e=>{let t=e.match(/^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}) UTC$/);if(!t)return``;let n=new Date(`${t[1]}T${t[2]}:00Z`);return Number.isNaN(n.getTime())?``:`${n.toLocaleString()} local`};function Lv(e){if(e.running||e.exitCode===null)return null;if(e.exitCode!==0)return`failed`;let t=(e.output.find(e=>/Boards: \d+\/\d+/.test(e))||``).match(/Boards: (\d+)\/(\d+)/),n=e.output.some(e=>/^- .+?: failed: /.test(e)||/^\s+x /.test(e));return t?Number(t[1])===0&&Number(t[2])>0?`failed`:Number(t[1])===Number(t[2])&&!n?`success`:`partial`:`success`}function Rv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)([]),[o,s]=(0,b.useState)(Nv),[c,l]=(0,b.useState)(null),u=()=>$.runs().then(t).catch(()=>t([]));(0,b.useEffect)(()=>{u(),$.scan().then(r).catch(()=>{}),$.criteriaPresets().then(a).catch(()=>a([]))},[]),(0,b.useEffect)(()=>{if(!n?.running)return;let e=setInterval(()=>$.scan().then(e=>{r(e),e.running||u()}).catch(()=>{}),2e3);return()=>clearInterval(e)},[n?.running]);let d=async(e,t=!1)=>{let n=o===Nv?void 0:o;try{r(await $.startScan(e,n,t)),X({title:t?`Retrying the failed boards`:e?`Dry run started`:`Scan started`,description:t?`Only the boards whose last attempt failed, no feeds.`:`Every board, scored with ${n?`the "${n}" preset`:`the active criteria`}.`,tone:`success`})}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},f=(e??[]).flatMap(e=>e.runs.map((t,n)=>({...t,key:`${e.date}-${n}`})).reverse()),p=f[0],m=!!p&&!p.dry&&p.boardsOk<p.boardsTotal,h=n?Lv(n):null;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsx)(`p`,{children:`Each scan fetches every board, scores, and writes new matches to the vault. The morning task runs it with the active criteria; here you can run one now, with the active set or a preset from the Criteria page. Times are UTC; hover one for your clock.`})}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsxs)(J,{size:`sm`,label:`Score with`,value:o,onValueChange:s,disabled:!!n?.running,children:[(0,x.jsx)(J.Item,{value:Nv,children:`Active criteria`}),i.map(e=>(0,x.jsx)(J.Item,{value:e.name,children:e.name},e.name))]}),m&&(0,x.jsx)(Bh,{content:`${p.boardsTotal-p.boardsOk} board${p.boardsTotal-p.boardsOk===1?``:`s`} did not answer last time. Fetch only those; Sources shows each one's health.`,children:(0,x.jsx)(B,{variant:`soft`,tone:`danger`,size:`sm`,disabled:!!n?.running,leadingIcon:(0,x.jsx)(H.Refresh,{}),onClick:()=>d(!1,!0),children:`Retry failed`})}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:!!n?.running,onClick:()=>d(!0),children:`Dry run`}),(0,x.jsx)(B,{tone:`primary`,size:`sm`,disabled:!!n?.running,leadingIcon:n?.running?(0,x.jsx)(Bg,{size:`sm`}):(0,x.jsx)(H.Refresh,{}),onClick:()=>d(!1),children:n?.running?`Scanning`:`Scan now`})]})]}),n&&(n.running||n.output.length>0)&&(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{className:`runs__live`,children:n.running?`Running`:h?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(z,{tone:Pv[h].tone,size:`sm`,children:Pv[h].label}),` `,(0,x.jsx)(`span`,{children:h===`failed`?`exit code ${n.exitCode}`:`finished`})]}):`Finished`}),(0,x.jsxs)(`p`,{children:[n.startedAt?`Started ${n.startedAt.replace(`T`,` `).slice(0,19)} UTC`:``,n.criteria?` · preset "${n.criteria}"`:``]})]}),n.running&&(0,x.jsx)(Bg,{showLabel:!0,label:`Fetching boards`,size:`sm`})]}),(0,x.jsx)(ag,{code:n.output.slice(-40).join(`
|
|
76
|
+
`).map(e=>e.replace(/^-\s*/,``).trim()).filter(Boolean).map(e=>{let t=[...e.matchAll(/(?<![\w$])([+-]\d+)\b/g)].reduce((e,t)=>e+Number(t[1]),0),n=e.replace(/(?<![\w$])[+-]\d+\b/g,``).replace(/\(\s*[,\s]*/g,`(`).replace(/[,\s]*\)/g,`)`).replace(/\(\)/g,``).replace(/\s+,/g,`,`).replace(/\s{2,}/g,` `).replace(/\s+:/g,`:`).trim(),r=n.indexOf(`:`),i=(r>=0?n.slice(0,r):n).trim().replace(/[,:]$/,``),a=(r>=0?n.slice(r+1):``).trim();return{label:i.charAt(0).toUpperCase()+i.slice(1),detail:a,points:t}})}function iv(e){return(0,x.jsx)(Sp,{open:e.id!==null,onOpenChange:t=>!t&&e.onClose(),side:`right`,size:`lg`,children:(0,x.jsx)(Sp.Content,{children:(0,x.jsx)(av,{...e})})})}function av({id:e,onClose:t,onChanged:n,nav:r,inline:i=!1}){let[a,o]=(0,b.useState)(null),[s,c]=(0,b.useState)(``),[l,u]=(0,b.useState)(!1);(0,b.useEffect)(()=>{o(null),e&&$.job(e).then(o).catch(e=>X({title:`Could not open the note`,description:e.message,tone:`danger`}))},[e]);let d=async e=>{if(a){u(!0);try{let t=await $.setStatus(a.id,e);o(t),n(t),X({title:`${a.company}: ${e}`,description:`Written to the note's frontmatter and status log.`,tone:`success`})}catch(e){X({title:`Status not saved`,description:e.message,tone:`danger`})}u(!1)}},f=async()=>{if(a&&s.trim()){u(!0);try{let e=await $.addNote(a.id,s);o(e),c(``),X({title:`Note added`,tone:`success`})}catch(e){X({title:`Note not saved`,description:e.message,tone:`danger`})}u(!1)}},[p,m]=(0,b.useState)(null);(0,b.useEffect)(()=>{Promise.all([$.summary(),$.companies()]).then(([e,t])=>m({ceiling:e.ceiling,bar:e.minScore,boards:t.map(e=>({name:e.name,tier:e.tier,status:e.status}))})).catch(()=>{})},[]);let h=(0,b.useMemo)(()=>a?rv(a.sections.why):[],[a]),g=a&&p?.ceiling?Math.max(0,Math.min(100,Math.round(a.score/p.ceiling*100))):null,_=a&&p?p.boards.find(e=>e.name.toLowerCase()===a.company.toLowerCase()):null,v=a?a.sections.description.replace(/^>.*$/m,``).replace(/[#*_`>]/g,``).replace(/\s+/g,` `).trim().slice(0,320):``,y=async e=>{if(a){u(!0);try{let t=await $.setStatus(a.id,`passed`,e);o(t),n(t),X({title:`${a.company}: passed`,description:e,tone:`neutral`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}u(!1)}},S=r&&(0,x.jsxs)(`div`,{className:`sheet-nav`,children:[(0,x.jsx)(Bh,{content:`Previous (K)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Previous job`,leadingIcon:(0,x.jsx)(H.ChevronUp,{}),disabled:r.pos<=0,onClick:r.prev})}),(0,x.jsx)(Bh,{content:`Next (J)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Next job`,leadingIcon:(0,x.jsx)(H.ChevronDown,{}),disabled:r.pos<0?r.total===0:r.pos>=r.total-1,onClick:r.next})}),(0,x.jsx)(`span`,{className:`sheet-nav__count num`,children:r.pos>=0?`${r.pos+1} of ${r.total}`:`not in this view`}),i&&(0,x.jsx)(Bh,{content:`Close (Esc)`,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,"aria-label":`Close`,leadingIcon:(0,x.jsx)(H.Close,{}),onClick:t,className:`sheet-nav__close`})})]});return(0,x.jsx)(x.Fragment,{children:a?(0,x.jsxs)(`div`,{className:`detail`,children:[S,(0,x.jsxs)(`div`,{className:`sheet-head`,children:[(0,x.jsxs)(`div`,{className:`sheet-head__main`,children:[(0,x.jsxs)(`p`,{className:`sheet-head__meta`,children:[a.company,` · `,a.location||`location n/a`,` · `,R_(a.source)?`posted on TekJobs`:a.source,` · found `,Xg(a.found)||a.found]}),i?(0,x.jsx)(`h2`,{className:`sheet-head__title`,children:a.title}):(0,x.jsx)(Sp.Title,{children:a.title}),(0,x.jsxs)(`div`,{className:`chips`,children:[R_(a.source)&&(0,x.jsx)(z_,{label:`Posted on TekJobs`}),(0,x.jsx)(z,{tone:a.payBand===`floor`?`primary`:`neutral`,variant:`soft`,size:`sm`,children:(0,x.jsx)(`span`,{className:`num`,children:a.salaryMax?Yg(a.salary):`pay not stated`})}),a.salaryMax>0&&(0,x.jsx)(z,{tone:`neutral`,variant:`outline`,size:`sm`,children:Zg[a.payBand].toLowerCase()}),(0,x.jsx)(z,{tone:a.remote?`success`:`neutral`,variant:a.remote?`soft`:`outline`,size:`sm`,children:a.remote?`remote`:`on-site`}),(0,x.jsx)(z,{tone:$g[a.status],size:`sm`,children:a.status})]})]}),(0,x.jsxs)(`div`,{className:`sheet-head__side`,children:[(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[a.status===`new`&&(0,x.jsx)(B,{tone:`primary`,size:`sm`,disabled:l,onClick:()=>d(`reviewing`),children:`Shortlist`}),(a.status===`new`||a.status===`reviewing`)&&(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:l,trailingIcon:(0,x.jsx)(H.ChevronDown,{}),children:`Pass`})}),(0,x.jsx)(Tu.Content,{align:`end`,children:Kg.map(e=>(0,x.jsx)(Tu.Item,{onSelect:()=>y(e),children:e},e))})]}),(0,x.jsx)(J,{size:`sm`,label:`Status`,value:a.status,onValueChange:e=>d(e),disabled:l,children:Gg.map(e=>(0,x.jsx)(J.Item,{value:e,children:e},e))})]}),(0,x.jsxs)(`div`,{className:`sheet-head__links`,children:[(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,children:(0,x.jsx)(`a`,{href:a.url,target:`_blank`,rel:`noopener noreferrer`,children:`Open posting ↗`})}),(0,x.jsx)(B,{asChild:!0,variant:`link`,size:`sm`,tone:`neutral`,children:(0,x.jsx)(`a`,{href:a.obsidianUrl,title:a.path,children:`Open in Obsidian ↗`})}),(0,x.jsx)(B,{variant:`link`,size:`sm`,tone:`neutral`,title:a.path,onClick:()=>$.revealJob(a.id).catch(e=>X({title:`Could not show the file`,description:e.message,tone:`danger`})),children:`Show file`}),(0,x.jsx)(V_,{job:a,onAttached:e=>{o(e),n(e)}})]})]})]}),(0,x.jsxs)(Z,{defaultValue:`why`,variant:`line`,size:`sm`,children:[(0,x.jsxs)(Z.List,{"aria-label":`Job note sections`,children:[(0,x.jsx)(Z.Trigger,{value:`why`,children:`Match reasons`}),(0,x.jsx)(Z.Trigger,{value:`description`,children:`Description`}),(0,x.jsx)(Z.Trigger,{value:`application`,children:`Application packet`}),(0,x.jsx)(Z.Trigger,{value:`resume`,children:`Tailored resume`}),(0,x.jsx)(Z.Trigger,{value:`letter`,children:`Cover letter`}),(0,x.jsx)(Z.Trigger,{value:`people`,children:`People`}),(0,x.jsx)(Z.Trigger,{value:`notes`,children:`Notes`})]}),(0,x.jsx)(Z.Content,{value:`why`,children:(0,x.jsxs)(`div`,{className:`split`,children:[(0,x.jsxs)(`div`,{className:`reasons`,children:[(0,x.jsxs)(`div`,{className:`reasons__head`,children:[(0,x.jsxs)(`span`,{className:`muted`,children:[`Scored `,(0,x.jsx)(`span`,{className:`num`,children:a.score}),p?.ceiling?(0,x.jsxs)(x.Fragment,{children:[` of `,(0,x.jsx)(`span`,{className:`num`,children:p.ceiling}),` possible`]}):null,` with the active criteria`,p?.bar?(0,x.jsxs)(x.Fragment,{children:[` (bar `,(0,x.jsx)(`span`,{className:`num`,children:p.bar}),`)`]}):null,`.`]}),g!==null&&(0,x.jsxs)(`span`,{className:`reasons__fit num`,children:[g,(0,x.jsx)(`small`,{children:` fit`})]})]}),h.map((e,t)=>(0,x.jsxs)(`div`,{className:`reasons__row`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{children:e.label}),e.detail&&(0,x.jsx)(`div`,{className:`reasons__detail`,children:e.detail})]}),(0,x.jsxs)(`span`,{className:`num reasons__pts${e.points<0?` reasons__pts--neg`:``}`,children:[e.points<0?`−`:`+`,Math.abs(e.points)]})]},t)),h.length===0&&(0,x.jsx)(`p`,{className:`muted`,children:`No match reasons recorded.`}),(0,x.jsxs)(`details`,{className:`reasons__log`,children:[(0,x.jsx)(`summary`,{children:`Status log`}),(0,x.jsx)(dg,{text:a.sections.log||`_Nothing yet._`})]})]}),(0,x.jsxs)(`aside`,{className:`split__aside`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`From the posting`}),(0,x.jsx)(`p`,{children:v?`${v}${a.sections.description.length>320?`…`:``}`:`The posting had no description text. Open the posting, or attach one.`})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`Note`}),(0,x.jsxs)(`p`,{className:`num small`,children:[a.path.split(/[\\/]/).slice(-2).join(`/`),(0,x.jsx)(`br`,{}),`status: `,a.status,` · found `,a.found,a.addedBy===`scan`?``:` · added by ${a.addedBy}`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`microlabel`,children:`Board`}),(0,x.jsx)(`p`,{children:_?`Tier ${_.tier} board, last fetch ${_.status||`not yet run`}.`:`${a.source}; not on the watchlist.`})]})]})]})}),(0,x.jsx)(Z.Content,{value:`description`,children:(0,x.jsx)(dg,{text:a.sections.description||`_The posting had no description text. Open the posting._`})}),(0,x.jsx)(Z.Content,{value:`application`,children:(0,x.jsx)(ov,{job:a,onStatus:d,busy:l})}),(0,x.jsx)(Z.Content,{value:`resume`,children:(0,x.jsx)(L_,{job:a})}),(0,x.jsx)(Z.Content,{value:`letter`,children:(0,x.jsx)(k_,{job:a})}),(0,x.jsx)(Z.Content,{value:`people`,children:(0,x.jsx)(I_,{job:a})}),(0,x.jsx)(Z.Content,{value:`notes`,children:(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(dg,{text:a.sections.notes||`_No notes yet._`}),(0,x.jsx)(Xp,{label:`Add a note`,rows:3,value:s,onChange:e=>c(e.target.value),placeholder:`Appended to the note with today's date.`}),(0,x.jsx)(`div`,{className:`form__actions`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:f,disabled:l||!s.trim(),children:`Save note`})})]})})]})]}):(0,x.jsxs)(`div`,{className:`detail`,children:[S,(0,x.jsx)(zg,{lines:6})]})})}function ov({job:e,onStatus:t,busy:n}){let[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)({}),[s,c]=(0,b.useState)(``),[l,u]=(0,b.useState)([]),d=()=>$.packet(e.id).then(e=>{i(e),o(e.values)}).catch(e=>X({title:`Could not read the packet`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{d(),$.resumes().then(e=>u(e.files.map(e=>e.name))).catch(()=>{})},[e.id]);let f=async(t,n)=>{o(e=>({...e,[t]:n})),c(t);try{await $.saveApplication(e.id,t,n),await d(),X({title:`${t} saved`,description:n,tone:`success`})}catch(e){X({title:`${t} not saved`,description:e.message,tone:`danger`})}finally{c(``)}},p=async t=>{if(r&&a[t]!==r.values[t]){c(t);try{await $.saveApplication(e.id,t,a[t]??``),await d(),X({title:`${t} saved`,description:`Written into the note.`,tone:`success`})}catch(e){X({title:`${t} not saved`,description:e.message,tone:`danger`})}finally{c(``)}}};return r?(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsxs)(`div`,{className:`packet__state`,children:[(0,x.jsxs)(z,{tone:r.ready?`success`:`neutral`,variant:r.ready?`soft`:`outline`,children:[r.filled,` of `,r.total,` filled`]}),r.ready?(0,x.jsx)(`p`,{className:`muted`,children:`Every required field has something in it. Read it before you send it — this says the boxes are full, not that the application is good.`}):(0,x.jsxs)(`p`,{className:`muted`,children:[`Still required: `,r.missing.join(`, `),`.`]})]}),r.ready&&e.status!==`applied`&&(0,x.jsxs)(`div`,{className:`form__actions form__actions--start`,children:[e.status!==`ready`&&(0,x.jsx)(B,{size:`sm`,tone:`primary`,variant:`soft`,disabled:n,onClick:()=>t(`ready`),children:`Mark ready for approval`}),(0,x.jsx)(B,{size:`sm`,tone:`primary`,disabled:n,onClick:()=>{window.confirm(`Only mark this applied if you have actually sent it to ${e.company}. Nothing here can send an application.`)&&t(`applied`)},children:`I have applied`})]}),r.fields.map(({field:e,hint:t,required:n})=>(0,x.jsxs)(`div`,{className:`packet__field`,children:[(0,x.jsx)(Xp,{label:n?`${e} *`:e,description:t,rows:e===`Tailored summary`||e===`Tailored bullets`||e===`Cover letter`||e===`Outreach message`||e===`Questions`||e===`Risks`?3:1,value:a[e]??``,onChange:t=>o({...a,[e]:t.target.value}),onBlur:()=>p(e),placeholder:n?`Required before this is ready.`:``}),e===`Resume variant`&&l.length>0&&(0,x.jsx)(`div`,{className:`chips`,children:l.map(t=>(0,x.jsx)(B,{size:`sm`,variant:a[e]===t?`soft`:`ghost`,tone:a[e]===t?`primary`:`neutral`,onClick:()=>f(e,t),children:t},t))}),s===e&&(0,x.jsx)(`span`,{className:`muted`,children:`Saving…`})]},e)),(0,x.jsx)(`p`,{className:`muted`,children:`Fields are written into the note's Application section as you leave each one. An agent fills the same fields through the TekJobs MCP server — see Agent access.`})]}):(0,x.jsx)(`div`,{className:`detail`,children:(0,x.jsx)(zg,{lines:6})})}var sv={confirmation:`success`,rejection:`danger`,advance:`primary`,scheduling:`primary`,"info-request":`warning`,other:`neutral`},cv={confirmation:`confirmed`,rejection:`rejected`,advance:`advanced`,scheduling:`scheduling`,"info-request":`asks for more`,other:`other`};function lv(e,t){let n=e.suggestion;return t?n.action===`status`?`mark it ${n.status}${n.appliedOn?` as of ${n.appliedOn}`:``}`:`add the mail to the note${n.appliedOn?`, set Applied on if empty`:``}`:`create a note for ${e.company} and mark it ${n.status}`}function uv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(0);return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(fv,{onOpen:t,onChanged:()=>r(e=>e+1)},n),(0,x.jsx)(iv,{id:e,onClose:()=>t(null),onChanged:e=>{}})]})}function dv({onOpen:e}){let[t,n]=(0,b.useState)(null);(0,b.useEffect)(()=>{$.mail().then(n).catch(()=>{})},[]);let r=t?.groups.length??0;return!t||r===0&&!t.running?null:(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`mailstrip`,children:[(0,x.jsxs)(`span`,{children:[t.running?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(Bg,{size:`sm`}),` Reading the mailbox.`]}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`b`,{className:`num`,children:r}),` `,r===1?`email group waits`:`email groups wait`,` for a decision.`]}),t.lastRun&&(0,x.jsxs)(`span`,{className:`muted`,children:[` Last read `,(0,x.jsx)(`span`,{className:`num`,children:t.lastRun.slice(0,16).replace(`T`,` `)}),` UTC.`]})]}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,leadingIcon:(0,x.jsx)(H.Mail,{}),onClick:e,children:`Open Mail`})]})})}function fv({onOpen:e,onChanged:t}){let[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)({}),[o,s]=(0,b.useState)(null),c=()=>$.mail().then(r).catch(()=>{});(0,b.useEffect)(()=>{c()},[]),(0,b.useEffect)(()=>{if(!n?.running)return;let e=setInterval(()=>$.mail().then(e=>{r(e),!e.running&&e.error&&X({title:`Mail check failed`,description:e.error,tone:`danger`})}).catch(()=>{}),4e3);return()=>clearInterval(e)},[n?.running]);let l=async()=>{try{r(await $.mailCheck()),X({title:`Reading the mailbox`,description:`Through the local CLI, Gmail read tools only. A few minutes.`,tone:`neutral`})}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},u=async(e,n)=>{s(e.id);try{let a=e.id in i?i[e.id]:e.noteId;r(n===`confirm`?await $.mailConfirm(e.id,a||void 0):await $.mailDismiss(e.id)),n===`confirm`&&(X({title:`${e.company}: ${lv(e,i[e.id]||e.noteId)}`,description:`Written to the note.`,tone:`success`}),t())}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}finally{s(null)}},d=n?.groups??[],f=(n?.items??[]).filter(e=>e.state!==`pending`).sort((e,t)=>(t.resolved?.at??``).localeCompare(e.resolved?.at??``)),p=f.length,[m,h]=(0,b.useState)(!1),g=e=>e.state===`dismissed`?`dismissed`:e.resolved?.action===`create`?`note created, marked ${e.resolved.status}`:e.resolved?.action===`status`?`marked ${e.resolved.status}`:`recorded on the note`,_=d.filter(e=>e.kind===`confirmation`&&e.match===`exact`&&e.noteId).length;return(0,x.jsxs)(`section`,{className:`today__section`,id:`mail-says`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Mail says`}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[n?.lastRun&&(0,x.jsxs)(`span`,{className:`muted`,children:[`last read `,n.lastRun.slice(0,16).replace(`T`,` `),` UTC, `,n.lastSinceDays,` days back`]}),p>0&&(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:()=>h(e=>!e),children:m?`Hide handled`:`${p} handled`}),_>0&&(0,x.jsxs)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:o===`safe`||!!n?.running,loading:o===`safe`,title:`Confirmations whose note matched by exact title: records the mail, marks still-open notes applied as of the mail's date. Rejections, interviews, company-only matches and creates stay one at a time.`,onClick:async()=>{s(`safe`);try{let e=await $.mailConfirmSafe();r(e),X({title:`${e.confirmed} confirmations recorded`,description:`Exact-title matches only. The rest are still listed.`,tone:`success`}),t()}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}finally{s(null)}},children:[`Confirm the exact matches (`,_,`)`]}),(0,x.jsx)(B,{size:`sm`,variant:`soft`,disabled:!!n?.running,leadingIcon:n?.running?(0,x.jsx)(Bg,{size:`sm`}):(0,x.jsx)(H.Mail,{}),onClick:l,children:n?.running?`Reading the mailbox`:`Check mail`})]})]}),!n||d.length===0&&!n.running?(0,x.jsx)(V,{padding:`md`,children:(0,x.jsx)(Vg,{size:`sm`,title:n?.lastRun?`Nothing waiting from the mailbox`:`The mailbox has not been read yet`,description:n?.error?n.error:`The morning task reads application emails through your signed-in CLI (Gmail read tools only) and lists what they say about your applications here. You confirm each one. Check mail reads again now.`})}):(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Application emails waiting for a decision`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Date`}),(0,x.jsx)(Y.HeadCell,{children:`Mail says`}),(0,x.jsx)(Y.HeadCell,{children:`Company and role`}),(0,x.jsx)(Y.HeadCell,{children:`Note`}),(0,x.jsx)(Y.HeadCell,{children:`Confirm`})]})}),(0,x.jsxs)(Y.Body,{children:[d.map(t=>{let n=i[t.id]||t.noteId;return(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:t.date||`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[(0,x.jsxs)(`span`,{className:`chips`,children:[t.kinds.map(e=>(0,x.jsx)(z,{size:`sm`,tone:sv[e],children:cv[e]},e)),t.count>1&&(0,x.jsxs)(`small`,{children:[t.count,` emails`,t.first&&t.first!==t.date?`, ${t.first} to ${t.date}`:``]})]}),(0,x.jsx)(`small`,{title:t.subject,children:t.gist})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[t.company,(0,x.jsx)(`small`,{children:t.role||`role not stated`}),t.person&&(0,x.jsxs)(`small`,{title:`${t.person.email}. Confirming adds them to People and to the note.`,children:[`from `,t.person.name]})]})}),(0,x.jsx)(Y.Cell,{children:t.match===`none`?(0,x.jsx)(`span`,{className:`muted`,children:`no note; confirm creates one`}):t.match===`exact`||t.match===`company`&&t.candidates.length<=1?(0,x.jsxs)(B,{variant:`link`,size:`sm`,tone:`neutral`,onClick:()=>e(t.noteId),children:[t.noteTitle,` · `,t.noteStatus]}):(0,x.jsxs)(J,{size:`sm`,label:t.match===`company-other-role`?`Not a role in the vault`:`Which role`,value:n||`__new__`,onValueChange:e=>a(n=>({...n,[t.id]:e===`__new__`?``:e})),children:[(0,x.jsx)(J.Item,{value:`__new__`,children:`New note for this role`}),t.candidates.map(e=>(0,x.jsxs)(J.Item,{value:e.id,children:[e.title,` · `,e.status]},e.id))]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`today__actions`,children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:o===t.id,title:lv(t,n),onClick:()=>u(t,`confirm`),children:n?t.suggestion.action===`record`?`Record`:`Mark ${t.suggestion.status}`:`Create and mark`}),(0,x.jsx)(B,{size:`sm`,variant:`ghost`,disabled:o===t.id,onClick:()=>u(t,`dismiss`),children:`Dismiss`})]})})]},t.id)}),n.running&&d.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:5,children:(0,x.jsx)(`span`,{className:`muted`,children:`Reading…`})})})]})]})}),m&&(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Application emails already handled`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Mail date`}),(0,x.jsx)(Y.HeadCell,{children:`Mail said`}),(0,x.jsx)(Y.HeadCell,{children:`Company and role`}),(0,x.jsx)(Y.HeadCell,{children:`Note`}),(0,x.jsx)(Y.HeadCell,{children:`What was done`})]})}),(0,x.jsx)(Y.Body,{children:f.map(t=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:t.date||`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:sv[t.kind],children:cv[t.kind]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[t.company,(0,x.jsx)(`small`,{children:t.role||`role not stated`})]})}),(0,x.jsx)(Y.Cell,{children:t.noteId?(0,x.jsx)(B,{variant:`link`,size:`sm`,tone:`neutral`,onClick:()=>e(t.noteId),children:t.noteId.replace(/ \([0-9a-f]+\)$/,``)}):(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`muted`,children:[g(t),t.resolved?.at?`, ${t.resolved.at.slice(0,16).replace(`T`,` `)} UTC`:``]})})]},t.id))})]})})]})}var pv=`Use the tekjobs MCP server. Call onboarding_status, then onboarding_materials, and follow its script: interview me, write my profile with save_profile, set the criteria with set_criteria, run a dry scan, and show me the top matches.`;function mv({onDone:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),[a,o]=(0,b.useState)(!1),s=()=>$.onboarding().then(n).catch(e=>X({title:`Server not answering`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{s()},[]);let c=async()=>{o(!0);try{let e=await $.initProfile();X({title:`Profile folder ready`,description:e.made.length?`Created ${e.made.join(`, `)}`:`It already existed; nothing was overwritten.`,tone:`success`}),await s()}catch(e){X({title:`Could not create the folder`,description:e.message,tone:`danger`})}o(!1)},l=async()=>{if(r.trim()){o(!0);try{X({title:`Resume imported`,description:`${(await $.importResume(r.trim())).chars.toLocaleString()} characters of text extracted.`,tone:`success`}),i(``),await s()}catch(e){X({title:`Import failed`,description:e.message,tone:`danger`})}o(!1)}};if(!t)return(0,x.jsx)(zg,{variant:`rect`,height:`20rem`});let u=t.steps.filter(e=>e.done).length;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[`Five steps from an empty folder to a daily scan that knows who you are. Your profile lives at `,(0,x.jsx)(`code`,{children:t.dir}),`. Nothing leaves this machine.`]})}),(0,x.jsxs)(z,{tone:t.complete?`success`:`primary`,size:`sm`,children:[u,` of `,t.steps.length,` done`]})]}),(0,x.jsx)(`div`,{className:`steps`,children:t.steps.map((e,t)=>(0,x.jsx)(V,{padding:`md`,variant:e.done?`sunken`:`outlined`,children:(0,x.jsxs)(`div`,{className:`step`,children:[(0,x.jsx)(`div`,{className:`step__mark`,children:e.done?(0,x.jsx)(H.Success,{}):(0,x.jsx)(`span`,{className:`step__n`,children:t+1})}),(0,x.jsxs)(`div`,{className:`step__body`,children:[(0,x.jsx)(`span`,{className:`step__label`,children:e.label}),!e.done&&(0,x.jsx)(`p`,{className:`muted`,children:e.how}),!e.done&&e.id===`folder`&&(0,x.jsx)(`div`,{className:`form__actions form__actions--start`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,loading:a,onClick:c,children:`Create the profile folder`})}),!e.done&&e.id===`resume`&&(0,x.jsxs)(`div`,{className:`step__row`,children:[(0,x.jsx)(Zp,{size:`sm`,label:`Path to your resume`,placeholder:`C:\\Users\\you\\Downloads\\resume.pdf`,description:`PDF, DOCX, Markdown or text. The file is copied into Profile/ and its text extracted.`,value:r,onChange:e=>i(e.target.value)}),(0,x.jsx)(B,{tone:`primary`,size:`sm`,loading:a,disabled:!r.trim(),onClick:l,children:`Import`})]}),!e.done&&e.id===`profile`&&(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(`p`,{className:`muted`,children:`The interview runs in your own LLM, not here. Open Claude Code in the app folder (its .mcp.json connects it) and paste:`}),(0,x.jsx)(ag,{code:pv,language:`text`,wrap:!0}),(0,x.jsx)(`p`,{className:`muted`,children:`Codex, Cursor or Claude Desktop work the same way once the tekjobs MCP server is added; see Agent access.`})]}),!e.done&&e.id===`scan`&&(0,x.jsx)(`div`,{className:`form__actions form__actions--start`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,onClick:()=>{$.startScan(!1).then(()=>X({title:`Scan started`,description:`Watch it on the Runs screen.`,tone:`success`})).catch(e=>X({title:`Could not start`,description:e.message,tone:`danger`}))},children:`Run the first scan`})})]})]})},e.id))}),t.complete&&(0,x.jsx)(`div`,{className:`form__actions`,children:(0,x.jsx)(B,{tone:`primary`,onClick:e,trailingIcon:(0,x.jsx)(H.ArrowRight,{}),children:`Go to the overview`})})]})}function hv({label:e,value:t,hint:n,tone:r=`neutral`,series:i,onClick:a}){return(0,x.jsx)(V,{padding:`md`,interactive:!!a,onClick:a,children:(0,x.jsxs)(`div`,{className:`stat`,children:[(0,x.jsx)(`span`,{className:`stat__label`,children:e}),(0,x.jsxs)(`div`,{className:`stat__row`,children:[(0,x.jsx)(`span`,{className:`stat__value`,children:t}),i&&i.length>1&&(0,x.jsx)(`div`,{className:`stat__spark`,children:(0,x.jsx)(Cp,{values:i,tone:r===`neutral`?`primary`:r,"aria-label":`${e}, per scan`})})]}),n&&(0,x.jsx)(`div`,{className:`stat__delta`,children:(0,x.jsx)(z,{tone:r,size:`sm`,children:n})})]})})}var gv=e=>e===null?`—`:`${Math.round(e*100)}%`,_v={found:`Found`,reviewed:`Reviewed`,shortlisted:`Shortlisted`,applied:`Applied`,interviewing:`Interviewing`,offer:`Offer`},vv={"design-eng":`Design engineering`,adjacent:`Adjacent titles`};function yv({onNavigate:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(null),[a,o]=(0,b.useState)(``);if((0,b.useEffect)(()=>{$.summary().then(n).catch(e=>o(e.message)),$.outcomes().then(i).catch(()=>{})},[]),a)return(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`p`,{className:`muted`,children:[`The server is not answering: `,a,`. Start it with `,(0,x.jsx)(`code`,{children:`npm run server`}),`.`]})});if(!t||!r)return(0,x.jsx)(zg,{variant:`rect`,height:`12rem`});let s=[`floor`,`stretch`,`below`,`unknown`],c=[`new`,`reviewing`,`applying`,`applied`,`interviewing`,`offer`,`rejected`,`passed`],l=r.waiting.buckets[14]??0,u=r.thisWeek.followUps.filter(e=>e.inDays<=0).length,d=r.appliedPerWeek;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[(0,x.jsx)(`b`,{children:r.funnel.applied}),` applied, `,(0,x.jsx)(`b`,{children:gv(r.responseRate)}),` answered, `,(0,x.jsx)(`b`,{children:r.funnel.interviewing}),` interviewing`,l?(0,x.jsxs)(x.Fragment,{children:[`, `,(0,x.jsx)(`b`,{children:l}),` waiting two weeks or more`]}):null,`.`,` `,`The inventory: `,t.open,` open matches across `,t.companies,` boards, floor `,t.floor?Jg(t.floor):`unset`,`, bar `,t.minScore??`unset`,`.`]})}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,onClick:()=>e(`runs`),children:`Runs`})]}),(0,x.jsxs)(`div`,{className:`stats z-stagger`,children:[(0,x.jsx)(hv,{label:`Applied`,value:String(r.funnel.applied),hint:`${r.funnel.shortlisted} shortlisted, ${r.funnel.reviewed} reviewed`,tone:`primary`,onClick:()=>e(`pipeline`)}),(0,x.jsx)(hv,{label:`Response rate`,value:gv(r.responseRate),hint:r.funnel.applied?`${r.responded} of ${r.funnel.applied} answered, interview or no`:`nothing applied to yet`,tone:r.responseRate&&r.responseRate>0?`success`:`neutral`}),(0,x.jsx)(hv,{label:`Waiting 14 days or more`,value:String(l),hint:`${r.waiting.buckets[7]??0} past 7 days, ${r.waiting.buckets[21]??0} past 21`,tone:(r.waiting.buckets[21]??0)>0?`warning`:`neutral`}),(0,x.jsx)(hv,{label:`Discovery to application`,value:r.medianDaysToApply===null?`—`:`${r.medianDaysToApply}d`,hint:`median, found to applied`})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Funnel`}),(0,x.jsx)(`p`,{children:`Each stage counts everything that reached it, whatever happened after. The rate is the share of the stage before.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Application funnel`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Stage`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Jobs`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Of the stage before`}),(0,x.jsx)(Y.HeadCell,{children:`Share`})]})}),(0,x.jsx)(Y.Body,{children:r.stages.map((e,t)=>{let n=r.stages[0]?.count||1;return(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:_v[e.stage]??e.stage}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.count}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(`span`,{className:e.rate===null?`muted`:``,children:t===0?`—`:gv(e.rate)})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`div`,{className:`funnel__bar`,role:`presentation`,children:(0,x.jsx)(`span`,{style:{width:`${Math.max(e.count?2:0,Math.round(e.count/n*100))}%`}})})})]},e.stage)})})]}),(0,x.jsxs)(`p`,{className:`muted panel--pad`,children:[r.passed,` passed on, `,r.rejected,` rejected.`]})]}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`This week`}),(0,x.jsxs)(`p`,{children:[`Follow-ups due in the next seven days`,u?`, ${u} already past`:``,`, and the interviews in progress. Dates come from each note's packet.`]})]})})}),(0,x.jsxs)(Y,{"aria-label":`This week`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{align:`end`,children:`When`})]})}),(0,x.jsxs)(Y.Body,{children:[r.thisWeek.followUps.map(t=>(0,x.jsxs)(Y.Row,{interactive:!0,onClick:()=>e(`jobs`,t.company),children:[(0,x.jsx)(Y.Cell,{children:t.company}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`clamp`,children:t.title})}),(0,x.jsx)(Y.Cell,{align:`end`,children:(0,x.jsx)(z,{size:`sm`,tone:t.inDays<0?`danger`:t.inDays===0?`warning`:`neutral`,children:t.inDays<0?`follow up, ${-t.inDays}d late`:t.inDays===0?`follow up today`:`follow up in ${t.inDays}d`})})]},t.id)),r.thisWeek.interviewing.map(t=>(0,x.jsxs)(Y.Row,{interactive:!0,onClick:()=>e(`jobs`,t.company),children:[(0,x.jsx)(Y.Cell,{children:t.company}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`clamp`,children:t.title})}),(0,x.jsx)(Y.Cell,{align:`end`,children:(0,x.jsx)(z,{size:`sm`,tone:`primary`,children:`interviewing`})})]},t.id)),r.thisWeek.followUps.length===0&&r.thisWeek.interviewing.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:3,children:(0,x.jsx)(`span`,{className:`muted`,children:`Nothing due this week. Applied roles get a follow-up date in their packet when you mark them applied.`})})})]})]})]})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Applications per week`}),(0,x.jsx)(`p`,{children:`Sent, by the week of the packet's Applied on date.`})]})}),d.length>0?(0,x.jsx)(Ye,{series:[{name:`Applied`,values:d.map(e=>e.n)}],labels:d.map(e=>e.week.slice(5)),height:180,"aria-label":`Applications per week`}):(0,x.jsx)(`p`,{className:`muted`,children:`Nothing applied to yet.`})]})}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`What answers`}),(0,x.jsx)(`p`,{children:`By role family, then by the board that surfaced the job.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Outcomes by role family`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Role family`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Found`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Applied`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Answered`})]})}),(0,x.jsx)(Y.Body,{children:r.byKind.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:vv[e.kind]??e.kind}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.found}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.applied}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.applied?`${e.responded} (${gv(e.responded/e.applied)})`:`—`})]},e.kind))})]}),r.bySource.length>0&&(0,x.jsx)(`div`,{className:`chips panel--pad`,children:r.bySource.map(e=>(0,x.jsxs)(z,{size:`sm`,tone:e.responded?`success`:`neutral`,variant:`soft`,children:[e.source,`: `,e.applied,` applied`,e.responded?`, ${e.responded} answered`:``]},e.source))})]})]}),(0,x.jsxs)(`div`,{className:`stats z-stagger`,children:[(0,x.jsx)(hv,{label:`Open matches`,value:String(t.open),hint:`${t.byStatus.new??0} unreviewed`,onClick:()=>e(`jobs`)}),(0,x.jsx)(hv,{label:`Design-engineer roles at the floor`,value:String(t.designEng.floor),hint:`of ${t.designEng.total} with the title`,tone:`success`,onClick:()=>e(`jobs`)}),(0,x.jsx)(hv,{label:`Pay under the floor, above the stretch line`,value:String(t.byBand.stretch??0),hint:`${t.designEng.stretch} design-engineer`,tone:`warning`}),(0,x.jsx)(hv,{label:`Active applications`,value:String(t.active),hint:t.active?`in flight`:`none yet`,tone:t.active?`primary`:`neutral`,onClick:()=>e(`pipeline`)})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Pipeline`}),(0,x.jsx)(`p`,{children:`Every open note by status. Change a status in Jobs or Pipeline; the note is the record.`})]})}),(0,x.jsx)(Ye,{series:[{name:`Jobs`,values:c.map(e=>t.byStatus[e]??0)}],labels:[...c],height:200,"aria-label":`Jobs by status`})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Stated pay against the floor`}),(0,x.jsx)(`p`,{children:`Open matches by band.`})]})}),(0,x.jsx)(Ye,{series:[{name:`Matches`,values:s.map(e=>t.byBand[e]??0)}],labels:[`Floor`,`Stretch`,`Below`,`Not stated`],height:200,"aria-label":`Matches by pay band`})]})})]})]})}function bv({onNavigate:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),[a,o]=(0,b.useState)(null),[s,c]=(0,b.useState)(null),l=()=>$.today().then(n).catch(e=>i(e.message));(0,b.useEffect)(()=>{l()},[]);let u=async(e,t,n)=>{c(e.id);try{await $.setStatus(e.id,t,n),X({title:`${e.company}: ${t===`reviewing`?`shortlisted`:`passed`}`,description:n,tone:t===`reviewing`?`success`:`neutral`}),await l()}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}finally{c(null)}};if(r)return(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`p`,{className:`muted`,children:[`The server is not answering: `,r,`. Start it with `,(0,x.jsx)(`code`,{children:`npm run server`}),`.`]})});if(!t)return(0,x.jsx)(zg,{variant:`rect`,height:`18rem`});let{counts:d,sections:f}=t,p=[...f.preparing,...f.followUps,...f.interviewing];return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h1`,{className:`today__date`,children:new Date().toLocaleDateString(`en-US`,{weekday:`long`,day:`numeric`,month:`long`})}),(0,x.jsx)(`p`,{children:f.triage.length===0?`Today's queue is clear. The next scan refills it.`:`${f.triage.length===1?`One`:f.triage.length} to decide on, best fit first. The other ${d.unreviewed-f.triage.length} unreviewed wait in Jobs and do not count against you. Fit is the share of the ${t.ceiling} points this criteria set can award.`})]}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,onClick:()=>e(`jobs`),children:`See all matches`})]}),(0,x.jsxs)(`div`,{className:`today__figures`,children:[(0,x.jsxs)(`div`,{className:`today__figure`,children:[(0,x.jsx)(`b`,{children:d.open}),(0,x.jsx)(`small`,{children:`open`})]}),(0,x.jsxs)(`div`,{className:`today__figure`,children:[(0,x.jsx)(`b`,{children:d.aging}),(0,x.jsx)(`small`,{children:`waiting 2d+`})]}),(0,x.jsxs)(`div`,{className:`today__figure`,children:[(0,x.jsx)(`b`,{"data-tone":d.closedUnreviewed>0?`danger`:void 0,children:d.closedUnreviewed}),(0,x.jsx)(`small`,{children:`closed unseen`})]})]}),(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsxs)(`div`,{className:`today__section-head`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Decide on these`}),(0,x.jsx)(`span`,{className:`today__hint`,children:`shortlist · pass · open sheet`})]}),f.triage.length===0?(0,x.jsx)(V,{padding:`md`,children:(0,x.jsx)(Vg,{size:`sm`,title:`Inbox clear`,description:`Nothing unreviewed is open right now. The next scan will refill this.`})}):(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Matches to decide on`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Fit`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Pay`}),(0,x.jsx)(Y.HeadCell,{children:`Found`}),(0,x.jsx)(Y.HeadCell,{children:`Decide`})]})}),(0,x.jsx)(Y.Body,{children:f.triage.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,selected:a===e.id,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(Cv,{value:e.fit})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`who__text`,children:[e.title,e.kind===`design-eng`&&(0,x.jsx)(`small`,{children:`design engineering`})]})}),(0,x.jsx)(Y.Cell,{children:e.salaryMax>0?(0,x.jsx)(z,{tone:Qg[e.payBand],size:`sm`,children:Yg(e.salary)}):(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:Xg(e.found)})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`today__actions`,onClick:e=>e.stopPropagation(),children:[(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:s===e.id,onClick:()=>u(e,`reviewing`),children:`Shortlist`}),(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,disabled:s===e.id,trailingIcon:(0,x.jsx)(H.ChevronDown,{}),children:`Pass`})}),(0,x.jsx)(Tu.Content,{align:`end`,children:Kg.map(t=>(0,x.jsx)(Tu.Item,{onSelect:()=>u(e,`passed`,t),children:t},t))})]})]})})]},e.id))})]})})]}),(0,x.jsx)(dv,{onOpen:()=>e(`mail`)}),f.started.length>0&&(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Already started`}),(0,x.jsx)(V,{padding:`none`,children:(0,x.jsxs)(Y,{"aria-label":`Applications with a packet started`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Fit`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Packet`}),(0,x.jsx)(Y.HeadCell,{children:`Pay`}),(0,x.jsx)(Y.HeadCell,{children:`Status`})]})}),(0,x.jsx)(Y.Body,{children:f.started.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,selected:a===e.id,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(Cv,{value:e.fit})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(z,{size:`sm`,tone:`primary`,variant:`soft`,children:[e.packet,` filled`]})}),(0,x.jsx)(Y.Cell,{children:e.salaryMax>0?(0,x.jsx)(z,{tone:Qg[e.payBand],size:`sm`,children:Yg(e.salary)}):(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:e.closed?(0,x.jsxs)(z,{size:`sm`,tone:`danger`,children:[`closed `,e.closed]}):(0,x.jsx)(z,{size:`sm`,tone:e.status===`ready`?`warning`:`neutral`,children:e.status})})]},e.id))})]})}),(0,x.jsx)(`p`,{className:`muted`,children:`Work you have already put in, wherever it ranks. The fit score knows nothing about a drafted packet, so these would otherwise fall off the bottom of the queue.`})]}),(f.aging.length>0||f.missed.length>0)&&(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Going, and gone`}),(0,x.jsxs)(`div`,{className:`today__cols`,children:[f.aging.length>0&&(0,x.jsxs)(V,{padding:`md`,children:[(0,x.jsx)(`h3`,{className:`today__subheading`,children:`Still open, still unread`}),(0,x.jsx)(`p`,{className:`muted`,children:`Listings here close after two days, at the median.`}),(0,x.jsx)(`ul`,{className:`today__list`,children:f.aging.map(e=>(0,x.jsx)(`li`,{children:(0,x.jsxs)(B,{className:`today__row`,variant:`ghost`,align:`start`,size:`sm`,onClick:()=>o(e.id),children:[(0,x.jsx)(Cv,{value:e.fit}),(0,x.jsx)(`span`,{className:`today__row-text`,children:xv(e.company,e.title,52)}),(0,x.jsxs)(z,{size:`sm`,tone:(e.days??0)>=5?`danger`:`warning`,variant:`outline`,children:[e.days,`d`]})]})},e.id))})]}),f.missed.length>0&&(0,x.jsxs)(V,{padding:`md`,children:[(0,x.jsx)(`h3`,{className:`today__subheading`,children:`Closed before you saw them`}),(0,x.jsxs)(`p`,{className:`muted`,children:[d.closedUnreviewed,` this week. This is what the queue costs when it is skipped.`]}),(0,x.jsx)(`ul`,{className:`today__list`,children:f.missed.map(e=>(0,x.jsx)(`li`,{children:(0,x.jsxs)(B,{className:`today__row`,variant:`ghost`,align:`start`,size:`sm`,onClick:()=>o(e.id),children:[(0,x.jsx)(Cv,{value:e.fit}),(0,x.jsx)(`span`,{className:`today__row-text`,children:xv(e.company,e.title,36)}),(0,x.jsx)(`span`,{className:`muted`,children:e.closed})]})},e.id))})]})]})]}),(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`In flight`}),(0,x.jsx)(V,{padding:p.length?`none`:`md`,children:p.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`Nothing in flight`,description:`Applications being prepared, follow-ups that are due, and interviews appear here once jobs move past Shortlisted.`,action:(0,x.jsx)(B,{size:`sm`,variant:`ghost`,onClick:()=>e(`pipeline`),children:`Open the pipeline`})}):(0,x.jsxs)(Y,{"aria-label":`In flight`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Fit`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Status`}),(0,x.jsx)(Y.HeadCell,{children:`Due`}),(0,x.jsx)(Y.HeadCell,{children:`Write to`})]})}),(0,x.jsx)(Y.Body,{children:p.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(Cv,{value:e.fit})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:`primary`,children:e.status})}),(0,x.jsx)(Y.Cell,{children:e.due||(0,x.jsx)(`span`,{className:`muted`,children:`—`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(Sv,{contact:e.contact})})]},e.id))})]})})]}),(0,x.jsxs)(`section`,{className:`today__section`,children:[(0,x.jsxs)(`div`,{className:`today__section-head`,children:[(0,x.jsx)(`h2`,{className:`today__heading`,children:`Waiting on a reply`}),(0,x.jsxs)(`span`,{className:`today__hint`,children:[`applied `,d.waitingDays,`d+ ago, nothing back · `,d.waiting,` in all`]})]}),(0,x.jsx)(V,{padding:f.waiting.length===0?`md`:`none`,children:f.waiting.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`Nothing has gone quiet`,description:`Applications with no answer after ${d.waitingDays} days land here, with the person to ask.`}):(0,x.jsxs)(Y,{"aria-label":`Applications waiting on a reply`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Days`}),(0,x.jsx)(Y.HeadCell,{children:`Company`}),(0,x.jsx)(Y.HeadCell,{children:`Role`}),(0,x.jsx)(Y.HeadCell,{children:`Applied`}),(0,x.jsx)(Y.HeadCell,{children:`Write to`})]})}),(0,x.jsx)(Y.Body,{children:f.waiting.map(e=>(0,x.jsxs)(Y.Row,{interactive:!0,"data-posted":R_(e.source)||void 0,onClick:()=>o(e.id),children:[(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:(0,x.jsx)(`span`,{className:`num`,"data-tone":(e.days??0)>=21?`danger`:void 0,children:e.days})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:e.appliedOn})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(Sv,{contact:e.contact})})]},e.id))})]})})]}),(0,x.jsx)(iv,{id:a,onClose:()=>o(null),onChanged:e=>{l()}})]})}var xv=(e,t,n=64)=>{let r=`${e} — ${t}`.replace(/\s+/g,` `).trim();return r.length>n?`${r.slice(0,n-1).trimEnd()}…`:r};function Sv({contact:e}){return e?(0,x.jsxs)(`span`,{className:`who__text`,children:[e.email?(0,x.jsxs)(`a`,{className:`people__thread`,href:`mailto:${e.email}`,onClick:e=>e.stopPropagation(),children:[e.name,` ↗`]}):e.name,(0,x.jsxs)(`small`,{children:[e.role||`contact`,e.others>0?` · +${e.others}`:``]})]}):(0,x.jsx)(`span`,{className:`muted`,title:`Open the sheet's People tab to add someone.`,children:`no one on the thread`})}function Cv({value:e}){return(0,x.jsx)(z,{size:`sm`,tone:e>=80?`success`:e>=60?`primary`:`neutral`,variant:e>=60?`soft`:`outline`,children:(0,x.jsx)(`span`,{className:`num`,children:e})})}var wv=[{id:`reviewing`,title:`Reviewing`},{id:`applying`,title:`Applying`,limit:5},{id:`ready`,title:`Ready`,limit:5},{id:`applied`,title:`Applied`},{id:`interviewing`,title:`Interviewing`},{id:`offer`,title:`Offer`}],Tv=new Set(wv.map(e=>e.id));function Ev(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)([]),o=()=>$.jobs({status:`all`,limit:2e3}).then(e=>t(e.rows)).catch(e=>X({title:`Could not load the board`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{o()},[]);let s=async(n,r)=>{let i=e?.find(e=>e.id===n);if(i&&i.status!==r){t(e=>e&&e.map(e=>e.id===n?{...e,status:r}:e));try{await $.setStatus(n,r),X({title:`${i.company}: ${r}`,tone:`success`})}catch(e){X({title:`Move not saved`,description:e.message,tone:`danger`}),o()}}},c=e=>t(t=>t&&t.map(t=>t.id===e.id?{...t,status:e.status}:t)),l=(0,b.useMemo)(()=>{let t=new Map;for(let n of e??[])Tv.has(n.status)&&t.set(n.company,(t.get(n.company)??0)+1);return[...t.entries()].sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0])).map(([e,t])=>({value:e,label:e,hint:`${t} on the board`}))},[e]);if(!e)return(0,x.jsx)(zg,{variant:`rect`,height:`20rem`});let u=new Set(i),d=e.filter(e=>Tv.has(e.status)&&(u.size===0||u.has(e.company))).sort((e,t)=>t.score-e.score),f=e.filter(e=>e.status===`new`).length,p=e.filter(e=>e.status===`rejected`||e.status===`passed`).length;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page__head`,children:(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[`Committed work only. Drag a card, or focus one and press Space to lift it, arrows to move it, Enter to drop. Every move is written to the job note.`,f?` ${f} new matches wait on Today, not here.`:``,p?` ${p} closed are not shown.`:``]})})}),(0,x.jsx)(`div`,{className:`toolbar`,children:(0,x.jsx)(Wg,{className:`toolbar__filter toolbar__filter--wide`,size:`sm`,multiple:!0,label:`Companies`,placeholder:i.length?``:`All companies`,description:`Narrow the board to the companies you are actually working.`,emptyMessage:`No company on the board matches that.`,options:l,value:i,onValueChange:a})}),(0,x.jsx)(Hg,{label:`Job pipeline`,columns:wv,cards:d,cardId:e=>e.id,cardColumn:e=>e.status,cardLabel:e=>`${e.title} at ${e.company}`,onMove:e=>s(e.cardId,e.to),renderCard:e=>(0,x.jsxs)(`div`,{className:`kcard`,"data-posted":R_(e.source)||void 0,onClick:()=>r(e.id),children:[(0,x.jsxs)(`div`,{className:`kcard__head`,children:[(0,x.jsxs)(`span`,{className:`kcard__company posted-co`,children:[e.company,R_(e.source)&&(0,x.jsx)(z_,{})]}),(0,x.jsxs)(Tu,{children:[(0,x.jsx)(Tu.Trigger,{asChild:!0,children:(0,x.jsx)(B,{variant:`ghost`,size:`sm`,"aria-label":`Move ${e.title}`,leadingIcon:(0,x.jsx)(H.More,{}),onClick:e=>e.stopPropagation()})}),(0,x.jsx)(Tu.Content,{align:`end`,onClick:e=>e.stopPropagation(),children:Gg.filter(t=>t!==e.status).map(t=>(0,x.jsxs)(Tu.Item,{onSelect:()=>s(e.id,t),children:[`Move to `,t]},t))})]})]}),(0,x.jsx)(`span`,{className:`kcard__title`,children:e.title}),(0,x.jsxs)(`div`,{className:`kcard__meta num`,children:[(0,x.jsx)(`span`,{className:`kcard__score`,children:e.score}),e.salaryMax>0&&(0,x.jsx)(`span`,{className:e.payBand===`floor`?`kcard__pay kcard__pay--floor`:`kcard__pay`,children:Yg(e.salary)})]})]})}),(0,x.jsx)(iv,{id:n,onClose:()=>r(null),onChanged:c})]})}var Dv={ok:`success`,warn:`warning`,missing:`danger`,info:`neutral`};function Ov({s:e}){return(0,x.jsxs)(`div`,{className:`detail`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:e.basics.name||`No name yet`}),(0,x.jsx)(`p`,{children:[e.basics.currentRole,e.basics.location].filter(Boolean).join(` · `)||`The Basics section is empty.`})]}),(0,x.jsxs)(`div`,{className:`chips`,children:[(0,x.jsx)(z,{size:`sm`,tone:e.status===`draft`?`warning`:`success`,children:e.status===`draft`?`draft`:`reviewed`}),e.updated&&(0,x.jsxs)(z,{size:`sm`,tone:`neutral`,variant:`outline`,children:[`updated `,e.updated]})]})]}),e.summary?(0,x.jsx)(`p`,{children:e.summary}):(0,x.jsx)(`p`,{className:`muted`,children:`The three-sentence summary is still the template. It leads every cover letter.`}),(e.basics.email||e.basics.links.length>0)&&(0,x.jsx)(`p`,{className:`muted mono`,children:[e.basics.email,...e.basics.links].filter(Boolean).join(` · `)})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Needs attention`}),(0,x.jsx)(`p`,{children:`What a reader of these notes would trip on. Each line names the note to fix.`})]}),(0,x.jsx)(z,{size:`sm`,tone:e.attention.length?`warning`:`success`,children:e.attention.length?`${e.attention.length} item${e.attention.length===1?``:`s`}`:`nothing stale`})]}),e.attention.length>0?(0,x.jsx)(`ul`,{className:`summary__list`,children:e.attention.map(e=>(0,x.jsxs)(`li`,{children:[(0,x.jsx)(z,{size:`sm`,tone:Dv[e.level],variant:`soft`,children:e.note}),` `,e.text]},e.text))}):(0,x.jsx)(`p`,{className:`muted`,children:`Every field is filled, the resume of record is fresh, and the criteria agree with the profile.`})]})}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Target roles`}),(0,x.jsx)(`p`,{children:`From the profile's table. "In criteria" means a title term the scan scores on matches the title; a title without one is never found by the scan.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Target roles`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Tier`}),(0,x.jsx)(Y.HeadCell,{children:`Title`}),(0,x.jsx)(Y.HeadCell,{children:`In criteria`})]})}),(0,x.jsxs)(Y.Body,{children:[e.targets.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:e.tier===`A`?`primary`:`neutral`,children:e.tier})}),(0,x.jsx)(Y.Cell,{children:e.title}),(0,x.jsx)(Y.Cell,{children:e.term?(0,x.jsxs)(`span`,{className:`muted`,children:[`yes · `,(0,x.jsx)(`span`,{className:`mono`,children:e.term})]}):(0,x.jsx)(z,{size:`sm`,tone:`warning`,variant:`soft`,children:`no title term`})})]},`${e.tier}-${e.title}`)),e.targets.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:3,children:(0,x.jsx)(`span`,{className:`muted`,children:`The Target roles table is empty.`})})})]})]})]}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Constraints against the criteria`}),(0,x.jsx)(`p`,{children:`What the profile says beside what the scan enforces.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Constraints against the criteria`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Constraint`}),(0,x.jsx)(Y.HeadCell,{children:`Profile`}),(0,x.jsx)(Y.HeadCell,{children:`Criteria`}),(0,x.jsx)(Y.HeadCell,{})]})}),(0,x.jsx)(Y.Body,{children:e.constraints.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:e.label}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:e.profile?``:`muted`,children:e.profile||`not set`})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:e.criteria?`num`:`muted`,children:e.criteria||`—`})}),(0,x.jsx)(Y.Cell,{children:e.level!==`info`&&(0,x.jsx)(z,{size:`sm`,tone:Dv[e.level],variant:`soft`,children:e.level===`ok`?`agree`:e.level===`warn`?`differ`:`missing`})})]},e.label))})]})]})]}),(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Documents`}),(0,x.jsx)(`p`,{children:`The notes and files the drafts are built from, and how fresh each one is.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`Documents`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Document`}),(0,x.jsx)(Y.HeadCell,{children:`State`}),(0,x.jsx)(Y.HeadCell,{children:`Where`})]})}),(0,x.jsx)(Y.Body,{children:e.documents.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:e.label}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(z,{size:`sm`,tone:Dv[e.level],variant:`soft`,children:e.state})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted mono`,children:e.where})})]},e.label))})]})]}),(0,x.jsxs)(V,{padding:`none`,children:[(0,x.jsx)(`div`,{className:`panel panel--pad`,children:(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`What feeds what`}),(0,x.jsx)(`p`,{children:`Which note each thing the app writes is built from. Change the note, and everything after it changes.`})]})})}),(0,x.jsxs)(Y,{"aria-label":`What feeds what`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Produces`}),(0,x.jsx)(Y.HeadCell,{children:`Reads`})]})}),(0,x.jsx)(Y.Body,{children:e.feeds.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:e.produces}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:e.reads})})]},e.produces))})]})]})]}),e.proofPoints.length>0&&(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Proof points`}),(0,x.jsxs)(`p`,{children:[e.proofPoints.length,` on file; the ones without a number are flagged above. Cover letters quote from these and nothing else.`]})]})}),(0,x.jsx)(`ul`,{className:`summary__list`,children:e.proofPoints.map(e=>(0,x.jsxs)(`li`,{children:[e.hasNumber?null:(0,x.jsx)(z,{size:`sm`,tone:`warning`,variant:`soft`,children:`no number`}),` `,e.text]},e.text))})]})})]})}var kv=e=>e.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/,``);function Av({note:e,onSaved:t}){let[n,r]=(0,b.useState)(e.markdown),[i,a]=(0,b.useState)(!1),[o,s]=(0,b.useState)(e.editable?`edit`:`preview`);(0,b.useEffect)(()=>r(e.markdown),[e.markdown]);let c=n!==e.markdown;return(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`p`,{children:e.hint}),(0,x.jsx)(`p`,{className:`muted`,children:(0,x.jsx)(`code`,{children:e.path})})]}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsx)(Z,{value:o,onValueChange:e=>s(e),variant:`pill`,size:`sm`,children:(0,x.jsxs)(Z.List,{"aria-label":`Edit or preview`,children:[(0,x.jsx)(Z.Trigger,{value:`edit`,children:e.editable?`Edit`:`Source`}),(0,x.jsx)(Z.Trigger,{value:`preview`,children:`Preview`})]})}),(0,x.jsx)(B,{asChild:!0,variant:`soft`,size:`sm`,trailingIcon:(0,x.jsx)(H.ExternalLink,{}),children:(0,x.jsx)(`a`,{href:`obsidian://open?path=${encodeURIComponent(e.path)}`,children:`Open in Obsidian`})})]})]}),!e.exists&&(0,x.jsx)(z,{tone:`warning`,size:`sm`,children:`This note does not exist yet; saving creates it.`}),o===`preview`?(0,x.jsx)(`div`,{className:`preview-doc`,children:(0,x.jsx)(dg,{text:kv(n)||`_Nothing here yet._`})}):(0,x.jsx)(Xp,{label:`${e.title} (Markdown)`,font:`mono`,rows:28,resize:`vertical`,value:n,onChange:e=>r(e.target.value),disabled:!e.editable,description:e.editable?void 0:`Read-only here. Pick a variant below, or edit the resume file and run tekjobs resume sync.`}),e.editable&&(0,x.jsxs)(`div`,{className:`form__actions`,children:[(0,x.jsx)(B,{variant:`ghost`,size:`sm`,disabled:!c||i,onClick:()=>r(e.markdown),children:`Discard`}),(0,x.jsx)(B,{tone:`primary`,size:`sm`,disabled:!c||i,loading:i,onClick:async()=>{a(!0);try{let r=await $.saveProfileNote(e.key,n);X({title:`${e.title} saved`,description:r.saved,tone:`success`}),t()}catch(t){X({title:`${e.title} not saved`,description:t.message,tone:`danger`})}a(!1)},children:`Save to the vault`})]})]})})}function jv({onChanged:e}){let[t,n]=(0,b.useState)(null),[r,i]=(0,b.useState)(``),a=()=>$.resumes().then(n).catch(e=>X({title:`Could not read the resume folder`,description:e.message,tone:`danger`}));(0,b.useEffect)(()=>{a()},[]);let o=async t=>{i(t);try{let n=await $.useResume(t);X({title:`${t} is the resume of record`,description:`${n.chars} characters into Profile/Resume.md; ${n.added.length} lines new, ${n.removed.length} gone${n.stale.length?`, ${n.stale.length} drafts quote a removed claim`:``}.`,tone:`success`}),a(),e()}catch(e){X({title:`Not switched`,description:e.message,tone:`danger`})}i(``)},s=e=>`${Math.max(1,Math.round(e/1024))} KB`;return(0,x.jsx)(V,{padding:t&&t.files.length?`none`:`md`,children:t?t.files.length===0?(0,x.jsx)(Vg,{size:`sm`,title:`No resume variants yet`,description:`Drop PDF, DOCX, Markdown or text files into ${t.dir}${t.exists?``:` (the folder does not exist yet)`} and they appear here. The folder is set in Settings.`}):(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(Y,{"aria-label":`Resume variants`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`File`}),(0,x.jsx)(Y.HeadCell,{children:`Changed`}),(0,x.jsx)(Y.HeadCell,{children:`Size`}),(0,x.jsx)(Y.HeadCell,{children:`Use`})]})}),(0,x.jsx)(Y.Body,{children:t.files.map(e=>(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`span`,{className:`chips`,children:[e.name,e.current&&(0,x.jsx)(z,{size:`sm`,tone:`primary`,variant:`soft`,children:`resume of record`})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:e.modified})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num muted`,children:s(e.size)})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsx)(B,{size:`sm`,variant:`ghost`,tone:`neutral`,onClick:()=>$.openResume(e.name).catch(e=>X({title:`Could not open`,description:e.message,tone:`danger`})),children:`Open`}),!e.current&&(0,x.jsx)(B,{size:`sm`,variant:`soft`,tone:`primary`,disabled:!!r,loading:r===e.name,onClick:()=>o(e.name),children:`Make it the resume of record`})]})})]},e.name))})]}),(0,x.jsxs)(`p`,{className:`muted variants__foot`,children:[`From `,(0,x.jsx)(`code`,{className:`mono`,children:t.dir}),`. Making one the record reads it into Profile/Resume.md, which every tailored resume and letter starts from; the packet's Resume variant field offers these names.`]})]}):(0,x.jsx)(zg,{lines:3})})}function Mv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(null),i=()=>($.profileSummary().then(r).catch(()=>{}),$.profileNotes().then(e=>t(e.notes)).catch(e=>X({title:`Could not load the profile`,description:e.message,tone:`danger`})));return(0,b.useEffect)(()=>{i()},[]),e?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page__head`,children:(0,x.jsx)(`div`,{children:(0,x.jsx)(`p`,{children:`Who you are, how the story is told, and how you write. Cover letters, tailored resumes and application packets read these notes; the scan reads the Criteria page. Saving keeps yesterday's copy beside the note.`})})}),(0,x.jsxs)(Z,{defaultValue:`summary`,variant:`line`,size:`sm`,children:[(0,x.jsxs)(Z.List,{"aria-label":`Profile notes`,children:[(0,x.jsx)(Z.Trigger,{value:`summary`,children:`Summary`}),e.map(e=>(0,x.jsx)(Z.Trigger,{value:e.key,children:e.title},e.key))]}),(0,x.jsx)(Z.Content,{value:`summary`,children:n?(0,x.jsx)(Ov,{s:n}):(0,x.jsx)(zg,{variant:`rect`,height:`12rem`})}),e.map(e=>(0,x.jsx)(Z.Content,{value:e.key,children:(0,x.jsxs)(`div`,{className:`detail`,children:[e.key===`resume`&&(0,x.jsx)(jv,{onChanged:i}),(0,x.jsx)(Av,{note:e,onSaved:i})]})},e.key))]})]}):(0,x.jsx)(zg,{variant:`rect`,height:`24rem`})}var Nv=`__active__`,Pv={success:{label:`Success`,tone:`success`},partial:{label:`Partial`,tone:`warning`},failed:{label:`Failed`,tone:`danger`}},Fv=e=>e.dry?`dry run`:e.via===`schedule`?`scheduled`:e.via===`mcp`?`agent`:e.via===`cli`?`manual, CLI`:e.via===`app`?`manual`:``,Iv=e=>{let t=e.match(/^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}) UTC$/);if(!t)return``;let n=new Date(`${t[1]}T${t[2]}:00Z`);return Number.isNaN(n.getTime())?``:`${n.toLocaleString()} local`};function Lv(e){if(e.running||e.exitCode===null)return null;if(e.exitCode!==0)return`failed`;let t=(e.output.find(e=>/Boards: \d+\/\d+/.test(e))||``).match(/Boards: (\d+)\/(\d+)/),n=e.output.some(e=>/^- .+?: failed: /.test(e)||/^\s+x /.test(e));return t?Number(t[1])===0&&Number(t[2])>0?`failed`:Number(t[1])===Number(t[2])&&!n?`success`:`partial`:`success`}function Rv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)(null),[i,a]=(0,b.useState)([]),[o,s]=(0,b.useState)(Nv),[c,l]=(0,b.useState)(null),u=()=>$.runs().then(t).catch(()=>t([]));(0,b.useEffect)(()=>{u(),$.scan().then(r).catch(()=>{}),$.criteriaPresets().then(a).catch(()=>a([]))},[]),(0,b.useEffect)(()=>{if(!n?.running)return;let e=setInterval(()=>$.scan().then(e=>{r(e),e.running||u()}).catch(()=>{}),2e3);return()=>clearInterval(e)},[n?.running]);let d=async(e,t=!1)=>{let n=o===Nv?void 0:o;try{r(await $.startScan(e,n,t)),X({title:t?`Retrying the failed boards`:e?`Dry run started`:`Scan started`,description:t?`Only the boards whose last attempt failed, no feeds.`:`Every board, scored with ${n?`the "${n}" preset`:`the active criteria`}.`,tone:`success`})}catch(e){X({title:`Could not start`,description:e.message,tone:`danger`})}},f=(e??[]).flatMap(e=>e.runs.map((t,n)=>({...t,key:`${e.date}-${n}`})).reverse()),p=f[0],m=!!p&&!p.dry&&p.boardsOk<p.boardsTotal,h=n?Lv(n):null;return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`div`,{className:`page__head`,children:[(0,x.jsx)(`div`,{children:(0,x.jsx)(`p`,{children:`Each scan fetches every board, scores, and writes new matches to the vault. The morning task runs it with the active criteria; here you can run one now, with the active set or a preset from the Criteria page. Times are UTC; hover one for your clock.`})}),(0,x.jsxs)(`div`,{className:`pager__buttons`,children:[(0,x.jsxs)(J,{size:`sm`,label:`Score with`,value:o,onValueChange:s,disabled:!!n?.running,children:[(0,x.jsx)(J.Item,{value:Nv,children:`Active criteria`}),i.map(e=>(0,x.jsx)(J.Item,{value:e.name,children:e.name},e.name))]}),m&&(0,x.jsx)(Bh,{content:`${p.boardsTotal-p.boardsOk} board${p.boardsTotal-p.boardsOk===1?``:`s`} did not answer last time. Fetch only those; Sources shows each one's health.`,children:(0,x.jsx)(B,{variant:`soft`,tone:`danger`,size:`sm`,disabled:!!n?.running,leadingIcon:(0,x.jsx)(H.Refresh,{}),onClick:()=>d(!1,!0),children:`Retry failed`})}),(0,x.jsx)(B,{variant:`soft`,size:`sm`,disabled:!!n?.running,onClick:()=>d(!0),children:`Dry run`}),(0,x.jsx)(B,{tone:`primary`,size:`sm`,disabled:!!n?.running,leadingIcon:n?.running?(0,x.jsx)(Bg,{size:`sm`}):(0,x.jsx)(H.Refresh,{}),onClick:()=>d(!1),children:n?.running?`Scanning`:`Scan now`})]})]}),n&&(n.running||n.output.length>0)&&(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{className:`runs__live`,children:n.running?`Running`:h?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(z,{tone:Pv[h].tone,size:`sm`,children:Pv[h].label}),` `,(0,x.jsx)(`span`,{children:h===`failed`?`exit code ${n.exitCode}`:`finished`})]}):`Finished`}),(0,x.jsxs)(`p`,{children:[n.startedAt?`Started ${n.startedAt.replace(`T`,` `).slice(0,19)} UTC`:``,n.criteria?` · preset "${n.criteria}"`:``]})]}),n.running&&(0,x.jsx)(Bg,{showLabel:!0,label:`Fetching boards`,size:`sm`})]}),(0,x.jsx)(ag,{code:n.output.slice(-40).join(`
|
|
77
77
|
`)||`…`,language:`text`,showCopy:!1,wrap:!0})]})}),f.length>1&&(0,x.jsxs)(`div`,{className:`charts`,children:[(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsx)(`div`,{className:`panel__head`,children:(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`New matches per scan`}),(0,x.jsx)(`p`,{children:`What each of the last twelve runs added, most recent on the right.`})]})}),(0,x.jsx)(Fi,{series:[{name:`New matches`,values:[...f].slice(0,12).reverse().map(e=>e.newMatches)}],labels:[...f].slice(0,12).reverse().map(e=>e.when.slice(5,16)),area:!0,height:200,"aria-label":`New matches per scan`})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`panel`,children:[(0,x.jsxs)(`div`,{className:`panel__head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{children:`Last scan`}),(0,x.jsx)(`p`,{children:p?p.when:``})]}),p&&(0,x.jsx)(z,{tone:Pv[p.outcome].tone,size:`sm`,children:Pv[p.outcome].label})]}),p&&(0,x.jsxs)(`dl`,{className:`detail__grid`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`Postings scanned`}),(0,x.jsx)(`dd`,{children:p.scanned.toLocaleString()})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`Above the bar`}),(0,x.jsx)(`dd`,{children:p.matched})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`New notes`}),(0,x.jsx)(`dd`,{children:p.dry?`dry run`:p.newMatches})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`Closed listings`}),(0,x.jsx)(`dd`,{children:p.dry?`—`:p.closed})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`Duration`}),(0,x.jsxs)(`dd`,{children:[p.seconds,`s`]})]}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`dt`,{children:`Boards`}),(0,x.jsxs)(`dd`,{children:[p.boardsOk,`/`,p.boardsTotal]})]})]})]})})]}),(0,x.jsx)(V,{padding:`none`,children:e===null?(0,x.jsx)(`div`,{className:`loading`,children:(0,x.jsx)(zg,{lines:6})}):(0,x.jsxs)(Y,{"aria-label":`Scan history`,density:`md`,children:[(0,x.jsx)(Y.Head,{children:(0,x.jsxs)(Y.Row,{children:[(0,x.jsx)(Y.HeadCell,{children:`Outcome`}),(0,x.jsx)(Y.HeadCell,{children:`When`}),(0,x.jsx)(Y.HeadCell,{children:`Boards`}),(0,x.jsx)(Y.HeadCell,{children:`Criteria`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Scanned`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Above bar`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`New`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Closed`}),(0,x.jsx)(Y.HeadCell,{align:`end`,numeric:!0,children:`Seconds`})]})}),(0,x.jsxs)(Y.Body,{children:[f.map(e=>{let t=[...e.failed?e.failed.split(/;\s*/).filter(Boolean).map(e=>`board: ${e}`):[],...(e.feedsFailed||[]).map(e=>`feed: ${e}`)],n=t.length>0,r=c===e.key;return[(0,x.jsxs)(Y.Row,{interactive:n,onClick:n?()=>l(r?null:e.key):void 0,"aria-expanded":n?r:void 0,children:[(0,x.jsx)(Y.Cell,{children:(0,x.jsxs)(`div`,{className:`runs__outcome`,children:[(0,x.jsx)(z,{tone:Pv[e.outcome].tone,variant:e.outcome===`success`?`soft`:`solid`,size:`sm`,children:Pv[e.outcome].label}),Fv(e)&&(0,x.jsx)(`small`,{className:`muted`,children:Fv(e)})]})}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`num`,title:Iv(e.when),children:e.when})}),(0,x.jsxs)(Y.Cell,{children:[(0,x.jsxs)(`span`,{className:`num`,children:[e.boardsOk,`/`,e.boardsTotal]}),n&&(0,x.jsxs)(`span`,{className:`muted`,children:[` · `,t.length,` problem`,t.length===1?``:`s`,` `,r?`▾`:`▸`]})]}),(0,x.jsx)(Y.Cell,{children:(0,x.jsx)(`span`,{className:`muted`,children:e.criteria||`—`})}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.scanned.toLocaleString()}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.matched}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.dry?(0,x.jsx)(`span`,{className:`muted`,children:`—`}):e.newMatches}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.dry?(0,x.jsx)(`span`,{className:`muted`,children:`—`}):e.closed}),(0,x.jsx)(Y.Cell,{align:`end`,numeric:!0,children:e.seconds})]},e.key),n&&r?(0,x.jsx)(Y.Row,{children:(0,x.jsxs)(Y.Cell,{colSpan:9,children:[(0,x.jsx)(`ul`,{className:`runs__problems`,children:t.map(e=>(0,x.jsx)(`li`,{className:`mono`,children:e},e))}),(0,x.jsx)(`p`,{className:`muted`,children:`A board that fails once is usually a hiccup; one that fails every run has moved. Sources shows each board's health and last success.`})]})},`${e.key}-problems`):null]}),f.length===0&&(0,x.jsx)(Y.Row,{children:(0,x.jsx)(Y.Cell,{colSpan:9,children:(0,x.jsx)(`span`,{className:`muted`,children:`No scans logged yet.`})})})]})]})})]})}function zv(){let[e,t]=(0,b.useState)(null),[n,r]=(0,b.useState)({profile:``,resumeDir:``,llmCommand:``,llmArgs:``,contact:``}),[i,a]=(0,b.useState)(!1),[o,s]=(0,b.useState)(!1),c=()=>$.settings().then(e=>{t(e),r({profile:e.profile.configured||e.profile.active,resumeDir:e.resumeDir.configured||e.resumeDir.path,llmCommand:e.llm.command,llmArgs:e.llm.args,contact:e.contact})}).catch(e=>X({title:`Could not read the settings`,description:e.message,tone:`danger`}));return(0,b.useEffect)(()=>{c()},[]),e?(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`page__head`,children:(0,x.jsx)(`div`,{children:(0,x.jsxs)(`p`,{children:[`Where things live. These are the only settings kept outside the profile folder, in `,(0,x.jsx)(`code`,{className:`mono`,children:e.configFile}),`; everything about the search itself is a note in the folder.`]})})}),(0,x.jsxs)(`div`,{className:`detail`,children:[o&&(0,x.jsxs)(z,{tone:`warning`,size:`md`,children:[`The profile folder changed. Restart the server (`,(0,x.jsx)(`code`,{className:`mono`,children:`npm run server`}),`, or the scheduled task's next run) to switch; until then the app keeps reading `,e.profile.active,`.`]}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{className:`settings__h`,children:`Profile folder`}),(0,x.jsxs)(`p`,{className:`muted`,children:[`Your job search: profile, resume, criteria, watchlist, one note per job, logs. Plain markdown; point Obsidian at it. Reading now: `,(0,x.jsx)(`code`,{className:`mono`,children:e.profile.active}),e.profile.fromEnv?` (set by TEKJOBS_PROFILE in the environment, which wins over this file)`:``,`.`]})]}),(0,x.jsx)(Zp,{label:`Folder`,value:n.profile,onChange:e=>r({...n,profile:e.target.value}),description:`Must exist. To start a new profile somewhere, run tekjobs init <dir> instead; it writes the starter notes. Takes effect on the next server start.`})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{className:`settings__h`,children:`Resume variants folder`}),(0,x.jsxs)(`p`,{className:`muted`,children:[`PDF, DOCX, Markdown or text files, one per variant. The Profile page lists them and makes any one the resume of record; the packet's Resume variant field offers their names. `,e.resumeDir.exists?``:`This folder does not exist yet.`]})]}),(0,x.jsx)(Zp,{label:`Folder`,value:n.resumeDir,onChange:e=>r({...n,resumeDir:e.target.value}),description:`Default: Templates/Resume inside the profile folder. Resume of record now: ${e.resumeSource||`not set`}.`})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{className:`settings__h`,children:`Writing CLI`}),(0,x.jsx)(`p`,{className:`muted`,children:`The local coding CLI that writes letters and tailored resumes and reads the mailbox. It must be signed in on this machine. Claude Code by default; another CLI works if it takes the prompt on stdin and prints the answer.`})]}),(0,x.jsxs)(`div`,{className:`form__row`,children:[(0,x.jsx)(Zp,{label:`Command`,value:n.llmCommand,onChange:e=>r({...n,llmCommand:e.target.value})}),(0,x.jsx)(Zp,{label:`Arguments`,value:n.llmArgs,onChange:e=>r({...n,llmArgs:e.target.value}),font:`mono`})]})]})}),(0,x.jsx)(V,{padding:`md`,children:(0,x.jsxs)(`div`,{className:`form`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h2`,{className:`settings__h`,children:`Contact for scans`}),(0,x.jsx)(`p`,{className:`muted`,children:`Optional. Added to the user agent on every request the scan makes, so a site can reach the person running it.`})]}),(0,x.jsx)(Zp,{label:`Email`,type:`email`,value:n.contact,onChange:e=>r({...n,contact:e.target.value})})]})}),(0,x.jsx)(`div`,{className:`form__actions`,children:(0,x.jsx)(B,{tone:`primary`,size:`sm`,loading:i,onClick:async()=>{a(!0);try{let e=await $.saveSettings(n);t(e),s(e.restart||o),X({title:`Settings saved`,description:e.configFile,tone:`success`})}catch(e){X({title:`Not saved`,description:e.message,tone:`danger`})}a(!1)},children:`Save settings`})})]})]}):(0,x.jsx)(zg,{variant:`rect`,height:`20rem`})}function Bv(){let[e,t]=(0,b.useState)(()=>{let e=new URLSearchParams(window.location.search).get(`theme`);if(e===`light`||e===`dark`)return e;let t=document.documentElement.dataset.theme;return t===`light`||t===`dark`?t:window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`});return(0,b.useEffect)(()=>{document.documentElement.dataset.theme=e},[e]),[e,()=>t(e=>e===`light`?`dark`:`light`)]}function Vv(){let e=()=>{let[e,t]=window.location.hash.replace(/^#\/?/,``).split(`?`);return{page:[`onboarding`,`today`,`overview`,`jobs`,`pipeline`,`mail`,`people`,`companies`,`criteria`,`profile`,`runs`,`agent`,`settings`].includes(e??``)?e:`today`,q:new URLSearchParams(t).get(`q`)??``}},[t,n]=(0,b.useState)(e);return(0,b.useEffect)(()=>{let t=()=>n(e());return window.addEventListener(`hashchange`,t),()=>window.removeEventListener(`hashchange`,t)},[]),[t.page,t.q,(e,t)=>{window.location.hash=t?`/${e}?q=${encodeURIComponent(t)}`:`/${e}`}]}function Hv(){let[e,t,n]=Vv(),[r,i]=Bv(),[a,o]=(0,b.useState)(!0),[s,c]=(0,b.useState)({}),[l,u]=(0,b.useState)(``);return(0,b.useEffect)(()=>{$.onboarding().then(e=>{o(e.complete),!e.complete&&!window.location.hash&&n(`onboarding`)}).catch(()=>{})},[]),(0,b.useEffect)(()=>{$.summary().then(e=>{c(t=>({...t,jobs:e.open,companies:e.companies})),e.lastRun&&u(`Last scan ${e.lastRun.when.slice(11,16)} · ${e.lastRun.boardsOk}/${e.lastRun.boardsTotal} boards`)}).catch(()=>{}),$.today().then(e=>c(t=>({...t,today:e.sections.triage.length}))).catch(()=>{}),$.mail().then(e=>c(t=>({...t,mail:e.groups.length}))).catch(()=>{})},[e]),(0,x.jsx)(Bh.Provider,{children:(0,x.jsx)($m.Provider,{position:`bottom-right`,children:(0,x.jsx)(c_,{page:e,onNavigate:e=>n(e),onSearch:e=>n(`jobs`,e),theme:r,onToggleTheme:i,onboarded:a,counts:s,lastScan:l,children:(0,x.jsxs)(`div`,{className:`page z-enter-fade`,children:[e===`onboarding`&&(0,x.jsx)(mv,{onDone:()=>n(`overview`)}),e===`today`&&(0,x.jsx)(bv,{onNavigate:n}),e===`overview`&&(0,x.jsx)(yv,{onNavigate:n}),e===`jobs`&&(0,x.jsx)(nv,{initialQuery:t}),e===`pipeline`&&(0,x.jsx)(Ev,{}),e===`mail`&&(0,x.jsx)(uv,{}),e===`people`&&(0,x.jsx)(N_,{}),e===`companies`&&(0,x.jsx)(__,{}),e===`criteria`&&(0,x.jsx)(O_,{}),e===`profile`&&(0,x.jsx)(Mv,{}),e===`runs`&&(0,x.jsx)(Rv,{}),e===`agent`&&(0,x.jsx)(f_,{}),e===`settings`&&(0,x.jsx)(zv,{})]},e)})})})}(0,y.createRoot)(document.getElementById(`root`)).render((0,x.jsx)(b.StrictMode,{children:(0,x.jsx)(Hv,{})}));
|
package/app/dist/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<meta name="theme-color" content="#0d1a14" />
|
|
8
8
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
9
9
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:wght@500;600&family=Hanken+Grotesk:wght@400;500;600&family=Azeret+Mono:wght@400;500&display=swap" data-zengin="fonts" />
|
|
10
|
-
<script type="module" crossorigin src="/assets/index
|
|
10
|
+
<script type="module" crossorigin src="/assets/index--cO0sfK7.js"></script>
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/index-DzGgV6NF.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
package/cli.mjs
CHANGED
|
@@ -35,7 +35,7 @@ const HELP = `tekjobs — a local job-search machine
|
|
|
35
35
|
(07:30 by default), or prints the crontab or launchd line for macOS and
|
|
36
36
|
Linux; --print shows the command without installing anything
|
|
37
37
|
tekjobs serve the app + API on http://127.0.0.1:8787
|
|
38
|
-
tekjobs mcp the MCP server on stdio (
|
|
38
|
+
tekjobs mcp the MCP server on stdio (Claude Code, Codex, Cursor, Claude Desktop)
|
|
39
39
|
|
|
40
40
|
The profile folder is resolved from TEKJOBS_PROFILE, then ~/.tekjobs/config.json, then ~/.tekjobs/profile.
|
|
41
41
|
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timurtekb/tekjobs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "A local-first job-search machine: watches hundreds of company job boards, scores every posting against your profile, and files matches into a folder of markdown notes you own. Bring your own LLM through MCP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"node": ">=20"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"tekjobs": "
|
|
12
|
+
"tekjobs": "cli.mjs"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"prepare": "husky || true",
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"check": "node run.mjs --dry --check-slugs",
|
|
23
23
|
"serve": "node app/server/index.mjs",
|
|
24
24
|
"mcp": "node app/server/mcp.mjs",
|
|
25
|
-
"sample": "node tools/make-sample-vault.mjs"
|
|
25
|
+
"sample": "node tools/make-sample-vault.mjs",
|
|
26
|
+
"counts": "node tools/counts.mjs"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
29
|
"pdf-parse": "^2.4.5"
|
|
@@ -70,5 +71,10 @@
|
|
|
70
71
|
],
|
|
71
72
|
"publishConfig": {
|
|
72
73
|
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"overrides": {
|
|
76
|
+
"semantic-release": {
|
|
77
|
+
"@semantic-release/npm": "$@semantic-release/npm"
|
|
78
|
+
}
|
|
73
79
|
}
|
|
74
80
|
}
|