Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added scripts/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
153 changes: 136 additions & 17 deletions scripts/generateSeeds.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env tsx
/**
* NOTE: Make sure to set CLIENT_URL in .env to the correct deployment URL
* Script to generate N seeds for a given location
* Usage: npm run generate-seeds -- <hubName|objectId> <count>
* Example: npm run generate-seeds -- "Main Hub" 10
Expand All @@ -21,6 +22,7 @@ const __dirname = dirname(__filename);
const serverRequire = createRequire(path.join(__dirname, '../server/package.json'));
const QRCode = serverRequire('qrcode');
const PDFDocument = serverRequire('pdfkit');
const logoPath = path.join(__dirname, 'assets/logo.png');

// ===== PDF Generation Helper Functions =====

Expand Down Expand Up @@ -69,33 +71,144 @@ async function addQRCodePage(
}

const pageWidth = doc.page.width;
const pageHeight = doc.page.height;
const qrSize = 200;
const margin = 50;
const contentWidth = pageWidth - (margin * 2);

let currentY = margin;

// Generate and position QR code
const qrBuffer = await generateQRCodeBuffer(surveyCode, baseUrl, qrSize);
const qrX = (pageWidth - qrSize) / 2;
const qrY = (pageHeight - qrSize) / 2 - 50;
if (fs.existsSync(logoPath)) {
const logoWidth = 60;
doc.image(logoPath, (pageWidth - logoWidth) / 2, currentY, {
fit: [logoWidth, logoWidth],
});
currentY += logoWidth + 10;
}

doc.image(qrBuffer, qrX, qrY, {
// Title
doc.fontSize(18)
.font('Helvetica-Bold')
.text('Understanding Unsheltered Homelessness', margin, currentY, {
align: 'center',
width: contentWidth
});

currentY += 40;

// Instructions
doc.fontSize(12)
.font('Helvetica')
.text(
'Bring this coupon to one of the locations below to complete a survey about your experience being unsheltered (including living in an RV or car/vehicle) and to receive a ',
margin,
currentY,
{
align: 'left',
width: contentWidth,
continued: true
}
)
.font('Helvetica-Bold')
.text('$20', { continued: true })
.font('Helvetica')
.text(' Gift Card.');

currentY += 50;

doc.fontSize(12)
.font('Helvetica')
.text(
'Our locations are accessible with free parking and bike racks unless marked otherwise.',
margin,
currentY,
{
align: 'left',
width: contentWidth
}
);

currentY += 25;

doc.text('Pets and service animals welcome.', margin, currentY, {
align: 'left',
width: contentWidth
});

currentY += 50;

// QR Code and Referral Code
const qrSize = 100;
const qrX = (pageWidth - qrSize) / 2;

const qrBuffer = await generateQRCodeBuffer(surveyCode, baseUrl, qrSize);
doc.image(qrBuffer, qrX, currentY, {
width: qrSize,
height: qrSize
});

// Add referral code text
doc.fontSize(20)
currentY += qrSize + 15;

doc.fontSize(16)
.font('Helvetica-Bold')
.text(`Referral Code: ${surveyCode}`, 0, qrY + qrSize + 30, {
.text(`Referral Code: ${surveyCode}`, margin, currentY, {
align: 'center',
width: pageWidth
width: contentWidth
});

// Add location text
currentY += 50;

// Locations section
doc.fontSize(12)
.font('Helvetica-Bold')
.text('Locations', margin, currentY, {
align: 'left',
width: contentWidth
});

currentY += 20;

doc.fontSize(11)
.font('Helvetica')
.text(`Location: ${locationName}`, 0, pageHeight - 80, {
.text('β€’ Highline United Methodist Church', margin + 10, currentY, {
align: 'left',
width: contentWidth - 10
});

currentY += 15;

doc.text(' 13015 1st AVE S, Burien, WA 98168', margin + 10, currentY, {
align: 'left',
width: contentWidth - 10
});

currentY += 20;

doc.text('β€’ Interview Dates and Hours:', margin + 10, currentY, {
align: 'left',
width: contentWidth - 10
});

currentY += 15;

doc.text(' Monday - Friday (11/17 - 11/21)', margin + 10, currentY, {
align: 'left',
width: contentWidth - 10
});

currentY += 15;

doc.text(' 10am to 3pm', margin + 10, currentY, {
align: 'left',
width: contentWidth - 10
});

currentY += 50;

// Contact info
doc.fontSize(10)
.font('Helvetica')
.text('For questions, please call +1 (833) 393-1621', margin, currentY, {
align: 'center',
width: pageWidth
width: contentWidth
});
}

Expand All @@ -112,9 +225,6 @@ async function generatePDF(seeds: any[], locationName: string): Promise<void> {
const stream = fs.createWriteStream(filepath);
doc.pipe(stream);

// BE SURE TO SET THIS TO CORRECT URL IN ENV
const baseUrl = process.env.CLIENT_URL || 'http://localhost:3000';

// Generate one page per seed
for (let i = 0; i < seeds.length; i++) {
await addQRCodePage(doc, seeds[i].surveyCode, locationName, baseUrl, i === 0);
Expand Down Expand Up @@ -236,6 +346,15 @@ async function generateSeeds(locationIdentifier: string, count: number): Promise
}
}

// Require CLIENT_URL to be set
const baseUrl = process.env.CLIENT_URL;
if (!baseUrl) {
console.error('\nβœ— Error: CLIENT_URL environment variable is not set');
console.error(' Please set CLIENT_URL in your .env file before running this script.');
console.error(' Example: CLIENT_URL=https://your-domain.com\n');
process.exit(1);
}

// Parse command line arguments
const args = process.argv.slice(2);

Expand Down
Loading