tractatus/scripts/init-koha.js
TheFlow ebc05daa9a feat: implement Koha donation system frontend (Phase 3)
Complete donation form, transparency dashboard, and success pages.

**Frontend Pages:**

Donation Form (public/koha.html):
- Three monthly tiers: $5, $15, $50 NZD
- One-time custom donations
- Anonymous by default with opt-in public acknowledgement
- Donor information form (name optional, email required)
- Stripe Checkout integration
- Allocation transparency (40/30/20/10 breakdown)
- Māori cultural acknowledgement (Koha meaning)
- Comprehensive FAQ section
- Accessible design (WCAG 2.1 AA compliant)

Transparency Dashboard (public/koha/transparency.html):
- Live metrics: total received, monthly supporters, recurring revenue
- Allocation breakdown with animated progress bars
- Recent public donor acknowledgements
- One-time donation statistics
- Auto-refresh every 5 minutes
- Call-to-action to donate

Success Page (public/koha/success.html):
- Animated success confirmation with checkmark
- Donation details verification via session ID
- Next steps explanation (receipt, allocation, dashboard)
- Monthly donor management information
- Links to transparency dashboard and docs
- Error state handling

**Database & Scripts:**

Initialization Script (scripts/init-koha.js):
- Creates MongoDB indexes for koha_donations collection
- Verifies Stripe configuration (keys, price IDs)
- Tests transparency metrics calculation
- Validates database setup
- Provides next steps guide
- npm script: `npm run init:koha`

Package Updates:
- Added Stripe SDK dependency (v14.25.0)
- Added init:koha script to package.json

**Features:**

Privacy-First Design:
 Anonymous donations by default
 Opt-in public acknowledgement
 Email only for receipts
 No payment details stored

User Experience:
 Responsive mobile design
 Keyboard navigation support
 Focus indicators for accessibility
 Loading/error states
 Form validation

Transparency:
 Public metrics API integration
 Real-time donor acknowledgements
 Clear allocation breakdown
 Automatic dashboard updates

Cultural Sensitivity:
 Māori term "Koha" explained
 Te Tiriti acknowledgement
 Indigenous partnership values

**API Integration:**

- POST /api/koha/checkout - Create donation session
- GET /api/koha/transparency - Fetch public metrics
- GET /api/koha/verify/:sessionId - Verify payment status

**Testing Checklist:**

□ Form validation (email required, minimum amount)
□ Tier selection (monthly $5/$15/$50)
□ One-time custom amount input
□ Anonymous vs public acknowledgement toggle
□ Stripe Checkout redirect
□ Success page verification
□ Transparency dashboard data display
□ Mobile responsiveness
□ Keyboard navigation

**Next Steps:**

1. Create Stripe products with currency_options (all 10 currencies)
2. Test with Stripe test cards
3. Implement multi-currency support
4. Add Privacy Policy page
5. Deploy to production

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-08 13:56:56 +13:00

97 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Initialize Koha Donation System
* Creates database indexes and verifies setup
*/
require('dotenv').config();
const { connect, close, getCollection } = require('../src/utils/db.util');
const Donation = require('../src/models/Donation.model');
async function initializeKoha() {
console.log('\n🎁 Koha Donation System Initialization\n');
try {
// Connect to MongoDB
console.log('📦 Connecting to MongoDB...');
await connect();
console.log('✅ Connected to database:', process.env.MONGODB_DB);
// Create indexes
console.log('\n📊 Creating database indexes...');
await Donation.createIndexes();
console.log('✅ Indexes created successfully');
// Verify collection exists
const collection = await getCollection('koha_donations');
const indexes = await collection.indexes();
console.log(`\n✅ Collection 'koha_donations' ready with ${indexes.length} indexes:`);
indexes.forEach((index, i) => {
const keys = Object.keys(index.key).join(', ');
console.log(` ${i + 1}. ${index.name} (${keys})`);
});
// Check for existing donations
const count = await collection.countDocuments();
console.log(`\n📈 Current donations in database: ${count}`);
// Test transparency metrics calculation
console.log('\n🔍 Testing transparency metrics...');
const metrics = await Donation.getTransparencyMetrics();
console.log('✅ Transparency metrics calculated:');
console.log(` - Total received: $${metrics.total_received.toFixed(2)} NZD`);
console.log(` - Monthly supporters: ${metrics.monthly_supporters}`);
console.log(` - One-time donations: ${metrics.one_time_donations}`);
console.log(` - Monthly recurring revenue: $${metrics.monthly_recurring_revenue.toFixed(2)} NZD`);
console.log(` - Public donors: ${metrics.recent_donors.length}`);
// Verify Stripe configuration
console.log('\n🔑 Verifying Stripe configuration...');
const stripeConfig = {
secretKey: process.env.STRIPE_SECRET_KEY ? '✅ Set' : '❌ Missing',
publishableKey: process.env.STRIPE_PUBLISHABLE_KEY ? '✅ Set' : '❌ Missing',
webhookSecret: process.env.STRIPE_KOHA_WEBHOOK_SECRET ? '✅ Set' : '❌ Missing',
price5: process.env.STRIPE_KOHA_5_PRICE_ID ? '✅ Set' : '⚠️ Missing (needs Stripe Dashboard setup)',
price15: process.env.STRIPE_KOHA_15_PRICE_ID ? '✅ Set' : '⚠️ Missing (needs Stripe Dashboard setup)',
price50: process.env.STRIPE_KOHA_50_PRICE_ID ? '✅ Set' : '⚠️ Missing (needs Stripe Dashboard setup)'
};
console.log(` - Secret Key: ${stripeConfig.secretKey}`);
console.log(` - Publishable Key: ${stripeConfig.publishableKey}`);
console.log(` - Webhook Secret: ${stripeConfig.webhookSecret}`);
console.log(` - $5 NZD Price ID: ${stripeConfig.price5}`);
console.log(` - $15 NZD Price ID: ${stripeConfig.price15}`);
console.log(` - $50 NZD Price ID: ${stripeConfig.price50}`);
// Warning if price IDs not set
if (stripeConfig.price5.includes('Missing') ||
stripeConfig.price15.includes('Missing') ||
stripeConfig.price50.includes('Missing')) {
console.log('\n⚠ WARNING: Stripe Price IDs not configured!');
console.log(' Follow the guide: docs/KOHA_STRIPE_SETUP.md');
console.log(' Create products in Stripe Dashboard and update .env');
}
// Summary
console.log('\n✅ Koha system initialized successfully!');
console.log('\n📋 Next steps:');
console.log(' 1. Create Stripe products (if not done): docs/KOHA_STRIPE_SETUP.md');
console.log(' 2. Start server: npm run dev');
console.log(' 3. Test donation form: http://localhost:9000/koha.html');
console.log(' 4. View transparency dashboard: http://localhost:9000/koha/transparency.html');
console.log(' 5. Test API endpoint: POST /api/koha/checkout\n');
} catch (error) {
console.error('\n❌ Initialization failed:', error.message);
console.error(error);
process.exit(1);
} finally {
await close();
}
}
// Run if called directly
if (require.main === module) {
initializeKoha();
}
module.exports = initializeKoha;