Files
meet-hub/supabase/migrations/20250101000004_video_progress.sql
dwindown 60baf32f73 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>
2026-01-01 23:54:32 +07:00

60 lines
2.0 KiB
PL/PgSQL

-- Video progress tracking table
-- Stores user's playback position for lessons and webinars
CREATE TABLE IF NOT EXISTS video_progress (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
video_id TEXT NOT NULL, -- lesson_id or webinar/product_id
video_type TEXT NOT NULL CHECK (video_type IN ('lesson', 'webinar')),
last_position DECIMAL(10,2) NOT NULL DEFAULT 0, -- seconds
total_duration DECIMAL(10,2), -- total video duration in seconds
completed BOOLEAN DEFAULT FALSE,
last_watched_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, video_id, video_type)
);
-- Indexes for fast queries
CREATE INDEX IF NOT EXISTS idx_video_progress_user ON video_progress(user_id);
CREATE INDEX IF NOT EXISTS idx_video_progress_user_type ON video_progress(user_id, video_type);
CREATE INDEX IF NOT EXISTS idx_video_progress_completed ON video_progress(user_id, completed) WHERE completed = TRUE;
-- Enable RLS
ALTER TABLE video_progress ENABLE ROW LEVEL SECURITY;
-- Drop existing policies if any
DROP POLICY IF EXISTS "Users manage own progress" ON video_progress;
DROP POLICY IF EXISTS "Service role full access" ON video_progress;
-- Users can manage their own progress
CREATE POLICY "Users manage own progress"
ON video_progress
FOR ALL
TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- Service role has full access
CREATE POLICY "Service role full access"
ON video_progress
FOR ALL
TO service_role
USING (true)
WITH CHECK (true);
-- Function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_video_progress_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Trigger to auto-update updated_at
DROP TRIGGER IF EXISTS update_video_progress_updated_at ON video_progress;
CREATE TRIGGER update_video_progress_updated_at
BEFORE UPDATE ON video_progress
FOR EACH ROW
EXECUTE FUNCTION update_video_progress_updated_at();