source being extracted

This commit is contained in:
DaKheera47 2025-12-14 19:12:58 +00:00
parent acc015ea7f
commit 4a00b3b900
6 changed files with 32 additions and 1 deletions

View File

@ -16,6 +16,7 @@ import {
XCircle,
} from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import type { Job } from "../../shared/types";
@ -52,6 +53,10 @@ export const JobCard: React.FC<JobCardProps> = ({
onProcess,
isProcessing,
}) => {
const sourceLabel: Record<Job["source"], string> = {
gradcracker: "Gradcracker",
};
const hasPdf = !!job.pdfPath;
const canApply = job.status === "ready";
const canProcess = job.status === "discovered";
@ -72,6 +77,9 @@ export const JobCard: React.FC<JobCardProps> = ({
<div className="flex flex-wrap items-center gap-3">
<ScoreIndicator score={job.suitabilityScore} />
<Badge variant="outline" className="uppercase tracking-wide">
{sourceLabel[job.source]}
</Badge>
<StatusBadge status={job.status} />
</div>
</div>
@ -181,4 +189,3 @@ export const JobCard: React.FC<JobCardProps> = ({
</Card>
);
};

View File

@ -25,6 +25,7 @@ const sqlite = new Database(DB_PATH);
const migrations = [
`CREATE TABLE IF NOT EXISTS jobs (
id TEXT PRIMARY KEY,
source TEXT NOT NULL DEFAULT 'gradcracker',
title TEXT NOT NULL,
employer TEXT NOT NULL,
employer_url TEXT,
@ -60,6 +61,10 @@ const migrations = [
error_message TEXT
)`,
// Add source column for existing databases (safe to skip if already present)
`ALTER TABLE jobs ADD COLUMN source TEXT NOT NULL DEFAULT 'gradcracker'`,
`UPDATE jobs SET source = 'gradcracker' WHERE source IS NULL OR source = ''`,
`CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status)`,
`CREATE INDEX IF NOT EXISTS idx_jobs_discovered_at ON jobs(discovered_at)`,
`CREATE INDEX IF NOT EXISTS idx_pipeline_runs_started_at ON pipeline_runs(started_at)`,
@ -72,6 +77,16 @@ for (const migration of migrations) {
sqlite.exec(migration);
console.log('✅ Migration applied');
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
const isDuplicateSourceColumn =
migration.includes('ALTER TABLE jobs ADD COLUMN source') &&
message.toLowerCase().includes('duplicate column name');
if (isDuplicateSourceColumn) {
console.log('↩️ Migration skipped (source column already exists)');
continue;
}
console.error('❌ Migration failed:', error);
process.exit(1);
}

View File

@ -9,6 +9,7 @@ export const jobs = sqliteTable('jobs', {
id: text('id').primaryKey(),
// From crawler
source: text('source', { enum: ['gradcracker'] }).notNull().default('gradcracker'),
title: text('title').notNull(),
employer: text('employer').notNull(),
employerUrl: text('employer_url'),

View File

@ -60,6 +60,7 @@ export async function createJob(input: CreateJobInput): Promise<Job> {
await db.insert(jobs).values({
id,
source: input.source,
title: input.title,
employer: input.employer,
employerUrl: input.employerUrl ?? null,
@ -171,6 +172,7 @@ export async function getJobsForProcessing(limit: number = 10): Promise<Job[]> {
function mapRowToJob(row: typeof jobs.$inferSelect): Job {
return {
id: row.id,
source: row.source as Job['source'],
title: row.title,
employer: row.employer,
employerUrl: row.employerUrl,

View File

@ -144,6 +144,7 @@ async function readCrawledJobs(): Promise<CreateJobInput[]> {
// Map crawler output to our job input format
jobs.push({
source: 'gradcracker',
title: data.title || 'Unknown Title',
employer: data.employer || 'Unknown Employer',
employerUrl: data.employerUrl,

View File

@ -10,10 +10,14 @@ export type JobStatus =
| 'rejected' // User rejected this job
| 'expired'; // Deadline passed
export type JobSource =
| 'gradcracker';
export interface Job {
id: string;
// From crawler
source: JobSource;
title: string;
employer: string;
employerUrl: string | null;
@ -44,6 +48,7 @@ export interface Job {
}
export interface CreateJobInput {
source: JobSource;
title: string;
employer: string;
employerUrl?: string;