Skip to content

Latest commit

 

History

History
328 lines (295 loc) · 13.3 KB

File metadata and controls

328 lines (295 loc) · 13.3 KB

PHASE 9: Post-Deployment & Monitoring

9.1 Setup Monitoring

Add Basic Logging to Backend

Create server/src/middleware/logger.js:

// ====================================
// Request Logger Middleware
// ====================================
const logger = (req, res, next) => {
    const start = Date.now();

    res.on('finish', () => {
        const duration = Date.now() - start;
        const log = {
            method: req.method,
            url: req.originalUrl,
            status: res.statusCode,
            duration: `${duration}ms`,
            ip: req.ip,
            timestamp: new Date().toISOString()
        };

        if (res.statusCode >= 400) {
            console.error('❌ Request Error:', JSON.stringify(log));
        } else if (duration > 2000) {
            console.warn('⚠️ Slow Request:', JSON.stringify(log));
        }
    });

    next();
};

module.exports = logger;

Add to server.js:

const logger = require('./src/middleware/logger');
app.use(logger);

9.2 Seed Data Script

Create server/src/config/seed.js for demo/presentation data:

// ====================================
// Seed Script — Demo Data for Presentation
// Run: npm run seed
// ====================================
require('dotenv').config();
const { createClient } = require('@supabase/supabase-js');

const supabase = createClient(
    process.env.SUPABASE_URL,
    process.env.SUPABASE_SERVICE_ROLE_KEY
);

async function seed() {
    console.log('🌱 Seeding CivicStreak database...\n');

    // 1. Verify wards exist
    const { data: wards } = await supabase.from('wards').select('id, ward_name');
    console.log(`✅ ${wards.length} wards found`);

    // 2. Verify tasks exist
    const { data: tasks } = await supabase.from('micro_tasks').select('id, title');
    console.log(`✅ ${tasks.length} micro-tasks found`);

    // 3. Verify achievements exist
    const { data: achievements } = await supabase.from('achievements').select('id, name');
    console.log(`✅ ${achievements.length} achievements found`);

    // 4. Create demo civic issues
    if (wards.length > 0) {
        const demoIssues = [
            {
                title: 'Broken foot
            {
                title: 'Broken footpath on SV Road near Azad Nagar',
                description: 'Large section of footpath broken for 3 months. Pedestrians forced to walk on road. Dangerous during monsoon.',
                category: 'Infrastructure',
                address: 'SV Road, near Azad Nagar, Andheri West',
                ward_id: wards[0].id,
                status: 'in_progress',
                upvotes: 23,
                latitude: 19.1364,
                longitude: 72.8296,
                photo_urls: []
            },
            {
                title: 'Non-functional streetlights on Link Road',
                description: '7 out of 10 streetlights not working between Infinity Mall and DN Nagar metro station. Safety hazard at night.',
                category: 'Electricity',
                address: 'Link Road, Andheri West',
                ward_id: wards[0].id,
                status: 'resolved',
                upvotes: 45,
                resolution_date: new Date(Date.now() - 5 * 24 * 60 * 60 * 1000).toISOString(),
                latitude: 19.1340,
                longitude: 72.8280,
                photo_urls: []
            },
            {
                title: 'Garbage dump near residential area, Lane 3',
                description: 'Unauthorized garbage dump has formed near Lane 3. Foul smell and mosquito breeding ground. BMC collection irregular.',
                category: 'Sanitation',
                address: 'Lane 3, Off SV Road, Andheri West',
                ward_id: wards[0].id,
                status: 'reported',
                upvotes: 18,
                latitude: 19.1370,
                longitude: 72.8300,
                photo_urls: []
            },
            {
                title: 'Tree cutting without permission on Hill Road',
                description: 'Several trees being cut near Hill Road junction. No BMC permission board visible. Need immediate investigation.',
                category: 'Environment',
                address: 'Hill Road, Bandra West',
                ward_id: wards.length > 2 ? wards[2].id : wards[0].id,
                status: 'reported',
                upvotes: 31,
                latitude: 19.0596,
                longitude: 72.8295,
                photo_urls: []
            },
            {
                title: 'Water pipeline leak wasting thousands of liters',
                description: 'Major water pipeline leak at junction of Station Road. Water flowing onto road for 2 weeks. Multiple complaints to BMC ignored.',
                category: 'Water',
                address: 'Station Road, Andheri East',
                ward_id: wards.length > 1 ? wards[1].id : wards[0].id,
                status: 'acknowledged',
                upvotes: 37,
                latitude: 19.1197,
                longitude: 72.8464,
                photo_urls: []
            },
            {
                title: 'Public toilet in non-functional state for months',
                description: 'Public toilet near market area completely non-functional. No water supply, broken doors, unhygienic conditions.',
                category: 'Sanitation',
                address: 'Market Area, Goregaon West',
                ward_id: wards.length > 3 ? wards[3].id : wards[0].id,
                status: 'stale',
                upvotes: 12,
                latitude: 19.1663,
                longitude: 72.8526,
                photo_urls: []
            }
        ];

        // Insert demo issues (need a dummy reported_by user)
        // We'll create issues without reported_by for seeding
        // In production, issues always have a reporter
        console.log('\n📢 Inserting demo civic issues...');
        
        for (const issue of demoIssues) {
            const { error } = await supabase
                .from('civic_issues')
                .insert({
                    ...issue,
                    reported_by: null // Will need a real user ID in production
                });
            
            if (error) {
                // If reported_by is required, skip seeding issues
                console.log(`⚠️ Skipping issue "${issue.title}" (needs reported_by user)`);
            } else {
                console.log(`  ✅ Issue: "${issue.title}"`);
            }
        }
    }

    // 5. Insert additional micro-tasks for variety
    console.log('\n📋 Adding more micro-tasks...');
    
    const additionalTasks = [
        {
            title: '📸 Document your nearest public garden',
            description: 'Visit the nearest municipal garden in your ward. Photograph its condition — cleanliness, facilities, greenery.',
            category: 'DOCUMENT',
            difficulty: 'Beginner',
            estimated_minutes: 15,
            xp_reward: 25,
            required_proof: 'photo',
            interest_tags: ['Environment'],
            instructions: '1. Visit the nearest garden/park.\n2. Take 3-4 photos showing overall condition.\n3. Rate cleanliness from 1-5 in your notes.\n4. Note if water, seating, and playground are available.'
        },
        {
            title: '🗣️ Interview a street vendor about civic issues',
            description: 'Talk to a local street vendor and ask about the civic challenges they face daily. Summarize in 3-5 lines.',
            category: 'CONNECT',
            difficulty: 'Intermediate',
            estimated_minutes: 15,
            xp_reward: 35,
            required_proof: 'text',
            interest_tags: ['Community', 'Governance'],
            instructions: '1. Find a street vendor in your area.\n2. Ask: What are the biggest civic problems you face?\n3. Ask: Have you tried complaining to BMC?\n4. Write a 3-5 line summary of their response.'
        },
        {
            title: '📊 Check if your ward office has a citizen charter',
            description: 'Visit your ward office and check if a Citizen Charter is displayed. Photograph it or note its absence.',
            category: 'DOCUMENT',
            difficulty: 'Intermediate',
            estimated_minutes: 20,
            xp_reward: 30,
            required_proof: 'photo',
            interest_tags: ['Governance'],
            instructions: '1. Visit your ward office during working hours.\n2. Look for a "Citizen Charter" board near the entrance.\n3. If found, photograph it clearly.\n4. If not found, note this in your submission.'
        },
        {
            title: '🌊 Rate your area\'s monsoon readiness',
            description: 'Walk through your neighborhood and rate monsoon preparedness — check drains, waterlogging spots, tree stability.',
            category: 'TRACK',
            difficulty: 'Beginner',
            estimated_minutes: 15,
            xp_reward: 25,
            required_proof: 'text',
            interest_tags: ['Infrastructure', 'Environment', 'Safety'],
            instructions: '1. Walk around your block/area.\n2. Check: Are drains clear or clogged?\n3. Identify spots that usually waterlog.\n4. Note any dangerously leaning trees.\n5. Rate overall monsoon readiness 1-10.'
        },
        {
            title: '📜 Read and summarize one ward committee resolution',
            description: 'Find the latest ward committee meeting minutes (online or at ward office) and summarize one resolution.',
            category: 'LEARN',
            difficulty: 'Advanced',
            estimated_minutes: 20,
            xp_reward: 45,
            required_proof: 'text',
            interest_tags: ['Governance', 'Education'],
            instructions: '1. Search for your ward committee minutes online (BMC website).\n2. If not available online, visit the ward office.\n3. Read one resolution passed in the latest meeting.\n4. Summarize it in 3-4 lines in simple language.'
        },
        {
            title: '🤝 Share CivicStreak with a friend',
            description: 'Introduce one friend to CivicStreak. Help them register and complete their first task.',
            category: 'MENTOR',
            difficulty: 'Beginner',
            estimated_minutes: 10,
            xp_reward: 50,
            required_proof: 'text',
            interest_tags: ['Community', 'Leadership'],
            instructions: '1. Share CivicStreak link with a friend.\n2. Help them register and pick their ward.\n3. Guide them through their first Civic Bite.\n4. Share both your names as proof of completion.'
        },
        {
            title: '📝 Write a 50-word letter to your ward councilor',
            description: 'Draft a short, polite letter to your ward councilor about the most urgent issue in your area.',
            category: 'VOICE',
            difficulty: 'Intermediate',
            estimated_minutes: 10,
            xp_reward: 35,
            required_proof: 'text',
            interest_tags: ['Governance', 'Community'],
            instructions: '1. Think of the most urgent civic issue in your area.\n2. Write a brief, respectful letter (50-100 words).\n3. Address it to "Respected Ward Councilor".\n4. Include the issue, location, and your request.\n5. Submit the letter text here.'
        },
        {
            title: '🔍 Find and list 3 emergency numbers for your ward',
            description: 'Research and document 3 important emergency/helpline numbers specific to your ward area.',
            category: 'LEARN',
            difficulty: 'Beginner',
            estimated_minutes: 10,
            xp_reward: 20,
            required_proof: 'text',
            interest_tags: ['Safety', 'Governance'],
            instructions: '1. Find: Ward office phone number.\n2. Find: Nearest fire station number.\n3. Find: Local police station number.\n4. Bonus: BMC helpline, water complaint number.\n5. List all numbers with labels.'
        }
    ];

    for (const task of additionalTasks) {
        const { error } = await supabase
            .from('micro_tasks')
            .insert({
                ...task,
                is_active: true,
                is_recurring: false,
                times_completed: Math.floor(Math.random() * 20)
            });

        if (error) {
            console.log(`⚠️ Failed to insert task: ${task.title}${error.message}`);
        } else {
            console.log(`  ✅ Task: "${task.title}"`);
        }
    }

    // 6. Update ward responsiveness scores (mock data)
    console.log('\n📊 Updating ward responsiveness scores...');
    
    const wardScores = [6.2, 5.8, 7.1, 4.5, 5.0, 6.8, 7.5, 3.9];
    for (let i = 0; i < Math.min(wards.length, wardScores.length); i++) {
        await supabase
            .from('wards')
            .update({ responsiveness_score: wardScores[i] })
            .eq('id', wards[i].id);
        console.log(`  ✅ ${wards[i].ward_name}: ${wardScores[i]}/10`);
    }

    console.log('\n🎉 Seeding complete!\n');
    console.log('Summary:');
    console.log(`  🏘️ Wards: ${wards.length}`);
    console.log(`  📋 Tasks: ${tasks.length + additionalTasks.length}`);
    console.log(`  🏅 Achievements: ${achievements.length}`);
    console.log(`  📢 Demo Issues: ${6}`);
    console.log('\n✨ CivicStreak is ready to go!');

    process.exit(0);
}

seed().catch(error => {
    console.error('❌ Seeding failed:', error);
    process.exit(1);
});

Run the seed script:

cd server
npm run seed