Job search tracker: CRUD, AI parse/tailor/cover via OmniRoute, legacy import

This commit is contained in:
Jonathan Sykes
2026-08-16 19:05:19 +08:00
parent 8aebc279db
commit 9ba9ae675a
31 changed files with 2294 additions and 85 deletions

BIN
prisma/dev.db Normal file

Binary file not shown.

View File

@@ -0,0 +1,91 @@
-- CreateTable
CREATE TABLE "Job" (
"id" TEXT NOT NULL PRIMARY KEY,
"title" TEXT NOT NULL,
"company" TEXT NOT NULL,
"source" TEXT,
"url" TEXT,
"applyUrl" TEXT,
"payMin" REAL,
"payMax" REAL,
"payCurrency" TEXT,
"payPeriod" TEXT,
"location" TEXT,
"remoteType" TEXT,
"phEligibility" TEXT NOT NULL DEFAULT 'unclear',
"description" TEXT,
"requirements" TEXT,
"tags" TEXT,
"status" TEXT NOT NULL DEFAULT 'prospect',
"notes" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "Resume" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"kind" TEXT NOT NULL DEFAULT 'tailored',
"markdown" TEXT NOT NULL,
"htmlRendered" TEXT,
"version" INTEGER NOT NULL DEFAULT 1,
"jobId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Resume_jobId_fkey" FOREIGN KEY ("jobId") REFERENCES "Job" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "CoverLetter" (
"id" TEXT NOT NULL PRIMARY KEY,
"markdown" TEXT NOT NULL,
"version" INTEGER NOT NULL DEFAULT 1,
"jobId" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "CoverLetter_jobId_fkey" FOREIGN KEY ("jobId") REFERENCES "Job" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "Application" (
"id" TEXT NOT NULL PRIMARY KEY,
"jobId" TEXT NOT NULL,
"method" TEXT NOT NULL DEFAULT 'manual',
"submittedAt" DATETIME,
"confirmation" TEXT,
"answers" TEXT,
"log" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "Application_jobId_fkey" FOREIGN KEY ("jobId") REFERENCES "Job" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "Profile" (
"id" TEXT NOT NULL PRIMARY KEY DEFAULT 'main',
"fullName" TEXT NOT NULL,
"email" TEXT,
"phone" TEXT,
"location" TEXT,
"linkedin" TEXT,
"github" TEXT,
"portfolio" TEXT,
"headline" TEXT,
"summary" TEXT,
"skills" TEXT,
"workHistory" TEXT,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "AiRun" (
"id" TEXT NOT NULL PRIMARY KEY,
"type" TEXT NOT NULL,
"model" TEXT,
"inputSummary" TEXT,
"resultRef" TEXT,
"ok" BOOLEAN NOT NULL DEFAULT true,
"error" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "sqlite"

97
prisma/schema.prisma Normal file
View File

@@ -0,0 +1,97 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Job {
id String @id @default(cuid())
title String
company String
source String?
url String?
applyUrl String?
payMin Float?
payMax Float?
payCurrency String? // USD, PHP
payPeriod String? // hour, month, year
location String?
remoteType String? // remote, hybrid, onsite
phEligibility String @default("unclear") // yes, unclear, no
description String?
requirements String?
tags String? // comma-separated
status String @default("prospect") // prospect, reviewing, tailoring, ready, applied, interviewing, offer, rejected, dead
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
resumes Resume[]
coverLetters CoverLetter[]
applications Application[]
}
model Resume {
id String @id @default(cuid())
name String
kind String @default("tailored") // base, tailored
markdown String
htmlRendered String?
version Int @default(1)
jobId String?
job Job? @relation(fields: [jobId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model CoverLetter {
id String @id @default(cuid())
markdown String
version Int @default(1)
jobId String
job Job @relation(fields: [jobId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Application {
id String @id @default(cuid())
jobId String
job Job @relation(fields: [jobId], references: [id], onDelete: Cascade)
method String @default("manual") // manual, semi, auto
submittedAt DateTime?
confirmation String?
answers String? // JSON: [{question, answer}]
log String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Profile {
id String @id @default("main")
fullName String
email String?
phone String?
location String?
linkedin String?
github String?
portfolio String?
headline String?
summary String?
skills String? // JSON array
workHistory String? // JSON array of {position, company, unit, start, end, supervisor, bullets[]}
updatedAt DateTime @updatedAt
}
model AiRun {
id String @id @default(cuid())
type String // parse, tailor, cover, answers
model String?
inputSummary String?
resultRef String? // id of created entity
ok Boolean @default(true)
error String?
createdAt DateTime @default(now())
}