pediatric-ai-scribe-v3/scripts/import-milestones.js
ifedan-ed a7dd08c9d1 Add admin dashboard for developmental milestones management
Features:
- Admin can add, edit, and delete developmental milestones via dashboard
- Milestones stored in PostgreSQL (developmental_milestones table)
- Client-side loads milestones from API instead of static file
- Import script to migrate existing static data to database
- Organized by age group and domain
- Supports sorting and filtering

Admin UI:
- New section in Admin panel for milestone management
- Filter by age group
- Add/Edit modal with validation
- Delete with confirmation
- Auto-complete for age groups and domains

API Endpoints:
- GET /api/milestones-data - Public endpoint for authenticated users
- GET /api/admin/milestones - List all milestones (admin only)
- GET /api/admin/milestones/meta - Get age groups and domains
- POST /api/admin/milestones - Create milestone
- PUT /api/admin/milestones/:id - Update milestone
- DELETE /api/admin/milestones/:id - Delete milestone
- POST /api/admin/milestones/bulk-import - Bulk import

Usage:
1. Run import script: node scripts/import-milestones.js
2. Access Admin dashboard → Developmental Milestones section
3. Add/Edit/Delete milestones as needed
2026-03-31 20:55:41 +00:00

197 lines
5.9 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* Import developmental milestones from static data file into database
* Run: node scripts/import-milestones.js
*/
require('dotenv').config();
const db = require('../src/db/database');
// Import static data
const MILESTONES_DATA = {
"Newborn / 1 month": {
"Gross Motor": [
"Moves arms and legs equally",
"Lifts head briefly when on tummy (prone)",
"Strong flexion posture (arms and legs tucked)",
"Turns head side to side when lying on back"
],
"Fine Motor": [
"Hands mostly fisted",
"Strong grasp reflex when palm is touched",
"Brings hands near face"
],
"Language": [
"Cries to express needs",
"Startles or quiets to sounds",
"Makes brief throaty sounds"
],
"Social/Emotional": [
"Recognizes caregiver voice",
"Briefly fixates on faces at close range (8-12 inches)",
"Calms when held or hears familiar voice",
"Shows brief alert periods"
],
"Cognitive": [
"Focuses on faces briefly",
"Follows objects briefly to midline",
"Prefers black and white or high-contrast patterns",
"Responds to loud sounds (Moro reflex)"
]
},
"2 months": {
"Gross Motor": [
"Lifts head when prone (45 degrees)",
"Holds head steady when held upright briefly",
"Moves both arms and both legs",
"Pushes up on tummy"
],
"Fine Motor": [
"Opens hands briefly",
"Holds rattle if placed in hand briefly",
"Brings hands to midline"
],
"Language": [
"Coos and makes gurgling sounds",
"Makes sounds other than crying",
"Turns head toward sounds"
],
"Social/Emotional": [
"Social smile (responsive to faces)",
"Begins to self-soothe (hands to mouth)",
"Tries to look at parent",
"Calms when spoken to or picked up"
],
"Cognitive": [
"Pays attention to faces",
"Begins to follow things with eyes",
"Recognizes people at a distance"
]
},
"4 months": {
"Gross Motor": [
"Holds head steady unsupported",
"Pushes up to elbows when on tummy",
"May roll over tummy to back",
"Pushes down on legs when feet on hard surface"
],
"Fine Motor": [
"Reaches for toys with one hand",
"Uses hands and eyes together",
"Grasps and shakes hand toys"
],
"Language": [
"Babbles with expression and copies sounds",
"Cries differently for hunger pain and tiredness",
"Makes vowel sounds ah eh oh"
],
"Social/Emotional": [
"Smiles spontaneously especially at people",
"Likes to play and may cry when playing stops",
"Copies movements and facial expressions"
],
"Cognitive": [
"Lets you know if happy or sad",
"Follows moving things with eyes side to side",
"Watches faces closely",
"Recognizes familiar people at a distance"
]
},
"6 months": {
"Gross Motor": [
"Rolls over in both directions",
"Begins to sit without support",
"Supports weight on legs and might bounce",
"Rocks back and forth on hands and knees"
],
"Fine Motor": [
"Reaches for and grasps objects",
"Transfers objects hand to hand",
"Raking grasp to pick up objects",
"Brings things to mouth"
],
"Language": [
"Responds to own name",
"Responds to sounds by making sounds",
"Strings vowels together when babbling",
"Begins consonant sounds m and b",
"Makes sounds to show joy and displeasure"
],
"Social/Emotional": [
"Knows familiar faces and recognizes strangers",
"Likes to play with others especially parents",
"Responds to other peoples emotions",
"Likes to look at self in mirror"
],
"Cognitive": [
"Looks around at things nearby",
"Shows curiosity and tries to get things out of reach",
"Begins to pass things from one hand to the other"
]
}
// Add more age groups as needed...
};
async function importMilestones() {
console.log('🚀 Starting milestones import...\n');
try {
// Check if milestones already exist
const existing = await db.query('SELECT COUNT(*) as count FROM developmental_milestones');
if (parseInt(existing.rows[0].count) > 0) {
console.log(`⚠️ Database already contains ${existing.rows[0].count} milestones.`);
console.log(' Clear existing data first or skip import.');
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
await new Promise((resolve) => {
rl.question('Clear existing data and re-import? (yes/no): ', (answer) => {
rl.close();
if (answer.toLowerCase() !== 'yes') {
console.log('Import cancelled.');
process.exit(0);
}
resolve();
});
});
await db.query('DELETE FROM developmental_milestones');
console.log('✅ Cleared existing milestones\n');
}
let imported = 0;
let sortOrder = 0;
for (const ageGroup in MILESTONES_DATA) {
console.log(`📋 Importing: ${ageGroup}`);
for (const domain in MILESTONES_DATA[ageGroup]) {
const milestones = MILESTONES_DATA[ageGroup][domain];
for (const milestone of milestones) {
await db.query(
`INSERT INTO developmental_milestones (age_group, domain, milestone_text, sort_order)
VALUES ($1, $2, $3, $4)`,
[ageGroup, domain, milestone, sortOrder]
);
sortOrder++;
imported++;
}
}
}
console.log(`\n✅ Import complete!`);
console.log(` Imported: ${imported} milestones`);
console.log(`\nYou can now manage milestones via the Admin dashboard.\n`);
process.exit(0);
} catch (err) {
console.error('❌ Import failed:', err.message);
process.exit(1);
}
}
importMilestones();