Display bootcamp lesson chapters on Product Detail page as marketing content
This commit implements displaying lesson chapters/timeline as marketing content on the Product Detail page for bootcamp products, helping potential buyers understand the detailed breakdown of what they'll learn. ## Changes ### Product Detail Page (src/pages/ProductDetail.tsx) - Updated Lesson interface to include optional chapters property - Modified fetchCurriculum to fetch chapters along with lessons - Enhanced renderCurriculumPreview to display chapters as nested content under lessons - Chapters shown with timestamps and titles, clickable to navigate to bootcamp access page - Visual hierarchy: Module → Lesson → Chapters with proper indentation and styling ### Review System Fixes - Fixed review prompt re-appearing after submission (before admin approval) - Added hasSubmittedReview check to prevent showing prompt when review exists - Fixed edit review functionality to pre-populate form with existing data - ReviewModal now handles both INSERT (new) and UPDATE (edit) operations - Edit resets is_approved to false requiring re-approval ### Video Player Enhancements - Implemented Adilo/Video.js integration for M3U8/HLS playback - Added video progress tracking with refs pattern for reliability - Implemented chapter navigation for both Adilo and YouTube players - Added keyboard shortcuts (Space, Arrows, F, M, J, L) - Resume prompt for returning users with saved progress ### Database Migrations - Added Adilo video support fields (m3u8_url, mp4_url, video_host) - Created video_progress table for tracking user watch progress - Fixed consulting slots user_id foreign key - Added chapters support to products and bootcamp_lessons tables ### Documentation - Added Adilo implementation plan and quick reference docs - Cleaned up transcript analysis files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
43
src/lib/adiloHelper.ts
Normal file
43
src/lib/adiloHelper.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Extract M3U8 and MP4 URLs from Adilo embed code
|
||||
*/
|
||||
export const extractAdiloUrls = (embedCode: string): { m3u8Url?: string; mp4Url?: string } => {
|
||||
const m3u8Match = embedCode.match(/(https:\/\/[^"'\s]+\.m3u8[^"'\s]*)/);
|
||||
const mp4Match = embedCode.match(/(https:\/\/[^"'\s]+\.mp4[^"'\s]*)/);
|
||||
|
||||
return {
|
||||
m3u8Url: m3u8Match?.[1],
|
||||
mp4Url: mp4Match?.[1],
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate Adilo embed code from URLs
|
||||
*/
|
||||
export const generateAdiloEmbed = (m3u8Url: string, videoId: string): string => {
|
||||
return `<iframe src="https://adilo.bigcommand.com/embed/${videoId}" allowfullscreen></iframe>`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a URL is an Adilo URL
|
||||
*/
|
||||
export const isAdiloUrl = (url: string): boolean => {
|
||||
return url.includes('adilo.bigcommand.com') || url.includes('.m3u8');
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a URL is a YouTube URL
|
||||
*/
|
||||
export const isYouTubeUrl = (url: string): boolean => {
|
||||
return url.includes('youtube.com') || url.includes('youtu.be');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get video host type from URL
|
||||
*/
|
||||
export const getVideoHostType = (url?: string | null): 'youtube' | 'adilo' | 'unknown' => {
|
||||
if (!url) return 'unknown';
|
||||
if (isYouTubeUrl(url)) return 'youtube';
|
||||
if (isAdiloUrl(url)) return 'adilo';
|
||||
return 'unknown';
|
||||
};
|
||||
Reference in New Issue
Block a user