-- ====================================================== -- Complete Course Management Seed Data -- Covers: categories, courses, sub-courses, videos, -- question sets, questions, options, prerequisites, -- and user progress for admin panel integration -- ====================================================== -- ====================================================== -- Course Categories (supplement existing 3 categories) -- Existing: 1=Programming, 2=Data Science, 3=Web Development -- ====================================================== INSERT INTO course_categories (id, name, is_active, created_at) VALUES (4, 'Mobile Development', TRUE, CURRENT_TIMESTAMP), (5, 'DevOps & Cloud', TRUE, CURRENT_TIMESTAMP), (6, 'Cybersecurity', FALSE, CURRENT_TIMESTAMP) ON CONFLICT (id) DO NOTHING; -- ====================================================== -- Courses (supplement existing 7 courses) -- Existing: 1-7 in categories 1-3 -- ====================================================== INSERT INTO courses (id, category_id, title, description, thumbnail, intro_video_url, is_active) VALUES (8, 4, 'Flutter App Development', 'Build cross-platform mobile apps with Flutter and Dart', 'https://example.com/thumbnails/flutter.jpg', 'https://example.com/intro/flutter.mp4', TRUE), (9, 4, 'React Native Essentials', 'Create native mobile apps using React Native', 'https://example.com/thumbnails/react-native.jpg', NULL, TRUE), (10, 5, 'Docker & Kubernetes', 'Container orchestration and deployment strategies', 'https://example.com/thumbnails/docker-k8s.jpg', 'https://example.com/intro/docker.mp4', TRUE), (11, 5, 'CI/CD Pipeline Mastery', 'Automate your build, test, and deployment workflows', 'https://example.com/thumbnails/cicd.jpg', NULL, FALSE), (12, 6, 'Ethical Hacking Fundamentals', 'Learn penetration testing and security analysis', 'https://example.com/thumbnails/ethical-hacking.jpg', NULL, FALSE) ON CONFLICT (id) DO NOTHING; -- ====================================================== -- Sub-courses (supplement existing 17 sub-courses: IDs 1-17) -- ====================================================== INSERT INTO sub_courses (id, course_id, title, description, thumbnail, display_order, level, sub_level, is_active) VALUES -- Flutter sub-courses (course 8) — IDs 18-21 (18, 8, 'Dart Language Basics', 'Learn Dart programming language fundamentals', NULL, 1, 'BEGINNER', 'A1', TRUE), (19, 8, 'Flutter UI Widgets', 'Build beautiful UIs with Flutter widgets', NULL, 2, 'BEGINNER', 'A2', TRUE), (20, 8, 'State Management', 'Manage app state with Provider and Riverpod', NULL, 3, 'INTERMEDIATE', 'B1', TRUE), (21, 8, 'Flutter Networking & APIs', 'HTTP requests, REST APIs, and data persistence', NULL, 4, 'ADVANCED', 'C1', TRUE), -- React Native sub-courses (course 9) — IDs 22-24 (22, 9, 'React Native Setup', 'Environment setup and first app', NULL, 1, 'BEGINNER', 'A1', TRUE), (23, 9, 'Navigation & Routing', 'React Navigation and screen management', NULL, 2, 'INTERMEDIATE', 'B1', TRUE), (24, 9, 'Native Modules', 'Bridge native code with React Native', NULL, 3, 'ADVANCED', 'C1', TRUE), -- Docker & Kubernetes sub-courses (course 10) — IDs 25-27 (25, 10, 'Docker Fundamentals', 'Containers, images, and Dockerfiles', NULL, 1, 'BEGINNER', 'A1', TRUE), (26, 10, 'Docker Compose', 'Multi-container applications', NULL, 2, 'INTERMEDIATE', 'B1', TRUE), (27, 10, 'Kubernetes Basics', 'Pods, services, and deployments', NULL, 3, 'ADVANCED', 'C1', TRUE), -- CI/CD sub-courses (course 11) — IDs 28-29 (28, 11, 'Git Workflows', 'Branching strategies and pull requests', NULL, 1, 'BEGINNER', 'A1', TRUE), (29, 11, 'GitHub Actions', 'Automate workflows with GitHub Actions', NULL, 2, 'INTERMEDIATE', 'B1', TRUE), -- Cybersecurity sub-courses (course 12) — IDs 30-31 (30, 12, 'Network Security Basics', 'Firewalls, VPNs, and network protocols', NULL, 1, 'BEGINNER', 'A1', TRUE), (31, 12, 'Penetration Testing', 'Tools and techniques for pen testing', NULL, 2, 'ADVANCED', 'C1', TRUE) ON CONFLICT (id) DO NOTHING; -- ====================================================== -- Sub-course Videos (supplement existing 5 videos: IDs 1-5) -- ====================================================== INSERT INTO sub_course_videos ( id, sub_course_id, title, description, video_url, duration, resolution, visibility, display_order, status, video_host_provider, vimeo_id, vimeo_embed_url, vimeo_status ) VALUES -- Dart Language Basics videos (sub_course 18) (6, 18, 'Introduction to Dart', 'Overview of Dart programming language', 'https://example.com/dart-intro.mp4', 720, '1080p', 'public', 1, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), (7, 18, 'Variables and Data Types', 'Dart variables, constants, and types', 'https://example.com/dart-variables.mp4', 900, '1080p', 'public', 2, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), (8, 18, 'Control Flow in Dart', 'If/else, loops, and switch statements', 'https://example.com/dart-control.mp4', 1100, '720p', 'public', 3, 'DRAFT', 'DIRECT', NULL, NULL, NULL), -- Flutter UI Widgets videos (sub_course 19) (9, 19, 'Widget Tree Basics', 'Understanding the Flutter widget tree', 'https://player.vimeo.com/video/100000001', 1500, '1080p', 'public', 1, 'PUBLISHED', 'VIMEO', '100000001', 'https://player.vimeo.com/video/100000001', 'available'), (10, 19, 'Layout Widgets', 'Row, Column, Stack, and Container widgets', 'https://player.vimeo.com/video/100000002', 1800, '1080p', 'public', 2, 'PUBLISHED', 'VIMEO', '100000002', 'https://player.vimeo.com/video/100000002', 'available'), (11, 19, 'Custom Widgets', 'Building reusable custom widgets', 'https://player.vimeo.com/video/100000003', 2100, '1080p', 'public', 3, 'DRAFT', 'VIMEO', '100000003', 'https://player.vimeo.com/video/100000003', 'transcoding'), -- State Management videos (sub_course 20) (12, 20, 'setState and Stateful Widgets', 'Managing local state in Flutter', 'https://example.com/flutter-setstate.mp4', 1200, '1080p', 'public', 1, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), (13, 20, 'Provider Pattern', 'Global state management with Provider', 'https://example.com/flutter-provider.mp4', 1600, '1080p', 'public', 2, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), -- Docker Fundamentals videos (sub_course 25) (14, 25, 'What is Docker?', 'Introduction to containerization', 'https://example.com/docker-intro.mp4', 600, '1080p', 'public', 1, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), (15, 25, 'Building Docker Images', 'Writing Dockerfiles and building images', 'https://example.com/docker-images.mp4', 1400, '1080p', 'public', 2, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), -- Docker Compose videos (sub_course 26) (16, 26, 'Docker Compose Basics', 'Defining multi-container applications', 'https://example.com/compose-basics.mp4', 1300, '1080p', 'public', 1, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), -- React Native Setup videos (sub_course 22) (17, 22, 'Setting Up React Native', 'Installing React Native CLI and Expo', 'https://example.com/rn-setup.mp4', 900, '1080p', 'public', 1, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL), (18, 22, 'Your First React Native App', 'Creating and running a basic app', 'https://example.com/rn-first-app.mp4', 1100, '1080p', 'public', 2, 'PUBLISHED', 'DIRECT', NULL, NULL, NULL) ON CONFLICT (id) DO NOTHING; -- ====================================================== -- Question Options for existing practice questions (17-20) -- These were missing from the initial seed -- ====================================================== INSERT INTO question_options (question_id, option_text, option_order, is_correct) VALUES -- Q17: What is the correct way to print "Hello World" in Python? (17, 'print("Hello World")', 1, TRUE), (17, 'echo "Hello World"', 2, FALSE), (17, 'console.log("Hello World")', 3, FALSE), (17, 'System.out.println("Hello World")', 4, FALSE), -- Q18: Which is a valid Python variable name? (18, '2name', 1, FALSE), (18, 'my_name', 2, TRUE), (18, 'my-name', 3, FALSE), (18, 'class', 4, FALSE), -- Q19: How do you convert "123" to an integer? (19, 'int("123")', 1, TRUE), (19, 'integer("123")', 2, FALSE), (19, 'str(123)', 3, FALSE), (19, 'toInt("123")', 4, FALSE), -- Q20: How many times does range(3) loop run? (20, '2', 1, FALSE), (20, '3', 2, TRUE), (20, '4', 3, FALSE), (20, '1', 4, FALSE); -- ====================================================== -- Additional Practice Questions for new sub-courses -- ====================================================== INSERT INTO questions (id, question_text, question_type, tips, status) VALUES (21, 'What keyword is used to declare a variable in Dart?', 'MCQ', 'Dart uses var, final, or const', 'PUBLISHED'), (22, 'Which widget is the root of every Flutter app?', 'MCQ', 'Think about the main() function', 'PUBLISHED'), (23, 'What is a StatefulWidget?', 'MCQ', 'Consider mutable state', 'PUBLISHED'), (24, 'What command creates a Docker container from an image?', 'MCQ', 'Think about docker run', 'PUBLISHED'), (25, 'What file defines a Docker Compose application?', 'MCQ', 'It is a YAML file', 'PUBLISHED'), (26, 'Which tool is used to create a new React Native project?', 'MCQ', 'Consider npx or expo', 'PUBLISHED') ON CONFLICT (id) DO NOTHING; INSERT INTO question_options (question_id, option_text, option_order, is_correct) VALUES -- Q21: Dart variable declaration (21, 'var', 1, TRUE), (21, 'let', 2, FALSE), (21, 'dim', 3, FALSE), (21, 'define', 4, FALSE), -- Q22: Root Flutter widget (22, 'MaterialApp', 1, TRUE), (22, 'Container', 2, FALSE), (22, 'Scaffold', 3, FALSE), (22, 'AppBar', 4, FALSE), -- Q23: StatefulWidget (23, 'A widget that can change its state during its lifetime', 1, TRUE), (23, 'A widget that never changes', 2, FALSE), (23, 'A widget for static content only', 3, FALSE), (23, 'A widget that cannot have children', 4, FALSE), -- Q24: Docker container creation (24, 'docker run', 1, TRUE), (24, 'docker create', 2, FALSE), (24, 'docker start', 3, FALSE), (24, 'docker build', 4, FALSE), -- Q25: Docker Compose file (25, 'docker-compose.yml', 1, TRUE), (25, 'Dockerfile', 2, FALSE), (25, 'docker.json', 3, FALSE), (25, 'compose.xml', 4, FALSE), -- Q26: React Native project creation (26, 'npx react-native init', 1, TRUE), (26, 'npm create react-native', 2, FALSE), (26, 'react-native new', 3, FALSE), (26, 'rn init', 4, FALSE); -- ====================================================== -- Question Sets for new sub-courses -- ====================================================== INSERT INTO question_sets (id, title, description, set_type, owner_type, owner_id, persona, status) VALUES (5, 'Dart Basics Quiz', 'Test your Dart fundamentals', 'PRACTICE', 'SUB_COURSE', 18, 'beginner', 'PUBLISHED'), (6, 'Flutter Widgets Assessment', 'Assess Flutter widget knowledge', 'PRACTICE', 'SUB_COURSE', 19, 'beginner', 'PUBLISHED'), (7, 'State Management Quiz', 'Test state management concepts', 'PRACTICE', 'SUB_COURSE', 20, 'intermediate', 'DRAFT'), (8, 'Docker Fundamentals Quiz', 'Test Docker basics', 'PRACTICE', 'SUB_COURSE', 25, 'beginner', 'PUBLISHED'), (9, 'Docker Compose Assessment', 'Assess Docker Compose skills', 'PRACTICE', 'SUB_COURSE', 26, 'intermediate', 'PUBLISHED'), (10, 'React Native Setup Quiz', 'Test React Native setup knowledge', 'PRACTICE', 'SUB_COURSE', 22, 'beginner', 'PUBLISHED') ON CONFLICT (id) DO NOTHING; -- Ensure every sub-course has at least one practice set INSERT INTO question_sets (title, description, set_type, owner_type, owner_id, status) SELECT sc.title || ' Practice', 'Default practice set for ' || sc.title, 'PRACTICE', 'SUB_COURSE', sc.id, 'DRAFT' FROM sub_courses sc WHERE NOT EXISTS ( SELECT 1 FROM question_sets qs WHERE qs.owner_type = 'SUB_COURSE' AND qs.owner_id = sc.id AND qs.set_type = 'PRACTICE' AND qs.status != 'ARCHIVED' ); -- Ensure every sub-course has one initial assessment set INSERT INTO question_sets (title, description, set_type, owner_type, owner_id, status) SELECT sc.title || ' Entry Assessment', 'Initial assessment used before learners start ' || sc.title, 'INITIAL_ASSESSMENT', 'SUB_COURSE', sc.id, 'DRAFT' FROM sub_courses sc WHERE NOT EXISTS ( SELECT 1 FROM question_sets qs WHERE qs.owner_type = 'SUB_COURSE' AND qs.owner_id = sc.id AND qs.set_type = 'INITIAL_ASSESSMENT' AND qs.status != 'ARCHIVED' ); -- Link questions to question sets INSERT INTO question_set_items (set_id, question_id, display_order) VALUES (5, 21, 1), (6, 22, 1), (7, 23, 1), (8, 24, 1), (9, 25, 1), (10, 26, 1) ON CONFLICT (set_id, question_id) DO NOTHING; -- Link personas to question sets INSERT INTO question_set_personas (question_set_id, user_id, display_order) VALUES (5, 10, 1), (5, 11, 2), (6, 10, 1), (6, 12, 2), (8, 11, 1), (10, 10, 1) ON CONFLICT (question_set_id, user_id) DO NOTHING; -- ====================================================== -- Sub-course Prerequisites -- Defines the learning path / dependency graph -- ====================================================== INSERT INTO sub_course_prerequisites (sub_course_id, prerequisite_sub_course_id) VALUES -- Python course (IDs 1-5): linear progression -- "Python Basics - Data Types" requires "Python Basics - Getting Started" (2, 1), -- "Python Intermediate - Functions" requires "Python Basics - Data Types" (3, 2), -- "Python Intermediate - Collections" requires "Python Intermediate - Functions" (4, 3), -- "Python Advanced - Best Practices" requires "Python Intermediate - Collections" (5, 4), -- JavaScript course (IDs 6-7): linear -- "DOM Manipulation Basics" requires "JavaScript Fundamentals" (7, 6), -- Java course (IDs 8-9): linear -- "Spring Framework Intro" requires "Java Core Concepts" (9, 8), -- Data Science course (IDs 10-11): linear -- "Advanced Data Analysis" requires "Data Analysis Fundamentals" (11, 10), -- ML course (IDs 12-13): linear -- "ML Algorithms" requires "ML Basics" (13, 12), -- Full Stack course (IDs 14-15): linear -- "Backend Development" requires "Frontend Fundamentals" (15, 14), -- React course (IDs 16-17): linear -- "React Advanced Patterns" requires "React Basics" (17, 16), -- Flutter course (IDs 18-21): structured path -- "Flutter UI Widgets" requires "Dart Language Basics" (19, 18), -- "State Management" requires "Flutter UI Widgets" (20, 19), -- "Flutter Networking & APIs" requires "State Management" (21, 20), -- React Native course (IDs 22-24): linear -- "Navigation & Routing" requires "React Native Setup" (23, 22), -- "Native Modules" requires "Navigation & Routing" (24, 23), -- Docker & Kubernetes course (IDs 25-27): structured -- "Docker Compose" requires "Docker Fundamentals" (26, 25), -- "Kubernetes Basics" requires "Docker Compose" (27, 26), -- CI/CD course (IDs 28-29): linear -- "GitHub Actions" requires "Git Workflows" (29, 28), -- Cybersecurity course (IDs 30-31): linear -- "Penetration Testing" requires "Network Security Basics" (31, 30) ON CONFLICT (sub_course_id, prerequisite_sub_course_id) DO NOTHING; -- ====================================================== -- User Sub-course Progress -- Simulate realistic student progress for admin panel -- ====================================================== INSERT INTO user_sub_course_progress (user_id, sub_course_id, status, progress_percentage, started_at, completed_at) VALUES -- Student 10 (Demo Student): working through Python course (10, 1, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '30 days', CURRENT_TIMESTAMP - INTERVAL '20 days'), (10, 2, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '20 days', CURRENT_TIMESTAMP - INTERVAL '12 days'), (10, 3, 'IN_PROGRESS', 65, CURRENT_TIMESTAMP - INTERVAL '12 days', NULL), -- Student 10: started Flutter (10, 18, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '15 days', CURRENT_TIMESTAMP - INTERVAL '8 days'), (10, 19, 'IN_PROGRESS', 40, CURRENT_TIMESTAMP - INTERVAL '8 days', NULL), -- Student 11 (Abebe): completed Python, started JavaScript (11, 1, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '45 days', CURRENT_TIMESTAMP - INTERVAL '35 days'), (11, 2, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '35 days', CURRENT_TIMESTAMP - INTERVAL '25 days'), (11, 3, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '25 days', CURRENT_TIMESTAMP - INTERVAL '15 days'), (11, 4, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '15 days', CURRENT_TIMESTAMP - INTERVAL '5 days'), (11, 5, 'IN_PROGRESS', 30, CURRENT_TIMESTAMP - INTERVAL '5 days', NULL), (11, 6, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '20 days', CURRENT_TIMESTAMP - INTERVAL '10 days'), (11, 7, 'IN_PROGRESS', 50, CURRENT_TIMESTAMP - INTERVAL '10 days', NULL), -- Student 11: Docker course (11, 25, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '10 days', CURRENT_TIMESTAMP - INTERVAL '3 days'), (11, 26, 'IN_PROGRESS', 20, CURRENT_TIMESTAMP - INTERVAL '3 days', NULL), -- Student 12 (Sara): just started (12, 1, 'IN_PROGRESS', 25, CURRENT_TIMESTAMP - INTERVAL '7 days', NULL), (12, 18, 'IN_PROGRESS', 10, CURRENT_TIMESTAMP - INTERVAL '3 days', NULL), (12, 22, 'COMPLETED', 100, CURRENT_TIMESTAMP - INTERVAL '14 days', CURRENT_TIMESTAMP - INTERVAL '7 days'), (12, 23, 'IN_PROGRESS', 60, CURRENT_TIMESTAMP - INTERVAL '7 days', NULL) ON CONFLICT (user_id, sub_course_id) DO NOTHING; -- ====================================================== -- Reset sequences to avoid ID conflicts after seeding -- ====================================================== SELECT setval(pg_get_serial_sequence('course_categories', 'id'), COALESCE((SELECT MAX(id) FROM course_categories), 1), true); SELECT setval(pg_get_serial_sequence('courses', 'id'), COALESCE((SELECT MAX(id) FROM courses), 1), true); SELECT setval(pg_get_serial_sequence('sub_courses', 'id'), COALESCE((SELECT MAX(id) FROM sub_courses), 1), true); SELECT setval(pg_get_serial_sequence('sub_course_videos', 'id'), COALESCE((SELECT MAX(id) FROM sub_course_videos), 1), true); SELECT setval(pg_get_serial_sequence('questions', 'id'), COALESCE((SELECT MAX(id) FROM questions), 1), true); SELECT setval(pg_get_serial_sequence('question_options', 'id'), COALESCE((SELECT MAX(id) FROM question_options), 1), true); SELECT setval(pg_get_serial_sequence('question_sets', 'id'), COALESCE((SELECT MAX(id) FROM question_sets), 1), true); SELECT setval(pg_get_serial_sequence('question_set_items', 'id'), COALESCE((SELECT MAX(id) FROM question_set_items), 1), true); SELECT setval(pg_get_serial_sequence('question_set_personas', 'id'), COALESCE((SELECT MAX(id) FROM question_set_personas), 1), true); SELECT setval(pg_get_serial_sequence('sub_course_prerequisites', 'id'), COALESCE((SELECT MAX(id) FROM sub_course_prerequisites), 1), true); SELECT setval(pg_get_serial_sequence('user_sub_course_progress', 'id'), COALESCE((SELECT MAX(id) FROM user_sub_course_progress), 1), true);