Files
tenderpilot/init-db.js.bak
Peter Foster f969ecae04 feat: visual polish, nav login link, pricing badge fix, cursor fix, button contrast
- Hero mockup: enhanced 3D perspective and shadow
- Testimonials: illustrated SVG avatars
- Growth pricing card: visual prominence (scale, gradient, badge)
- Most Popular badge: repositioned to avoid overlapping heading
- Nav: added Log In link next to Start Free Trial
- Fixed btn-primary text colour on anchor tags (white on blue)
- Fixed cursor: default on all non-interactive elements
- Disabled user-select on non-form content to prevent text caret
2026-02-14 14:17:15 +00:00

102 lines
3.2 KiB
JavaScript
Executable File

import pg from 'pg';
import dotenv from 'dotenv';
dotenv.config();
async function setupDatabase() {
try {
// First connect as postgres to create tables
const adminClient = new pg.Client({
host: 'localhost',
port: 5432,
database: 'tenderpilot',
user: 'tenderpilot',
password: 'tenderpilot123'
});
await adminClient.connect();
console.log('Connected to tenderpilot database');
// Create tables
await adminClient.query(`
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
company_name VARCHAR(255),
tier VARCHAR(50) DEFAULT 'free',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
verified BOOLEAN DEFAULT false
);
`);
console.log('Created users table');
await adminClient.query(`
CREATE TABLE IF NOT EXISTS tenders (
id SERIAL PRIMARY KEY,
source VARCHAR(100) NOT NULL,
source_id VARCHAR(255) UNIQUE NOT NULL,
title VARCHAR(500) NOT NULL,
description TEXT,
summary TEXT,
cpv_codes TEXT[],
value_low DECIMAL(15,2),
value_high DECIMAL(15,2),
currency VARCHAR(3) DEFAULT 'GBP',
published_date TIMESTAMP,
deadline TIMESTAMP,
authority_name VARCHAR(255),
authority_type VARCHAR(100),
location VARCHAR(255),
documents_url TEXT,
notice_url TEXT,
status VARCHAR(50) DEFAULT 'open',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
console.log('Created tenders table');
await adminClient.query(`
CREATE TABLE IF NOT EXISTS profiles (
id SERIAL PRIMARY KEY,
user_id INTEGER UNIQUE REFERENCES users(id) ON DELETE CASCADE,
sectors TEXT[],
keywords TEXT[],
min_value DECIMAL(15,2),
max_value DECIMAL(15,2),
locations TEXT[],
authority_types TEXT[],
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
console.log('Created profiles table');
await adminClient.query(`
CREATE TABLE IF NOT EXISTS matches (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
tender_id INTEGER REFERENCES tenders(id) ON DELETE CASCADE,
sent BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, tender_id)
);
`);
console.log('Created matches table');
// Create indexes
await adminClient.query('CREATE INDEX IF NOT EXISTS idx_tenders_source_id ON tenders(source_id);');
await adminClient.query('CREATE INDEX IF NOT EXISTS idx_tenders_deadline ON tenders(deadline);');
await adminClient.query('CREATE INDEX IF NOT EXISTS idx_matches_user_id ON matches(user_id);');
console.log('Created indexes');
await adminClient.end();
console.log('Database setup complete!');
} catch (error) {
console.error('Error setting up database:', error.message);
process.exit(1);
}
}
setupDatabase();