source being extracted
This commit is contained in:
parent
acc015ea7f
commit
4a00b3b900
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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'),
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user