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>
51 lines
1.8 KiB
SQL
51 lines
1.8 KiB
SQL
-- Clean up ALL consulting_slots RLS policies and recreate with simple working policies
|
|
-- This fixes the 400 error caused by conflicting policies using has_role() function
|
|
|
|
-- Drop ALL existing policies (including the problematic ones with has_role)
|
|
DROP POLICY IF EXISTS "Users see own slots" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "Admin manage slots" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "Users create own slots" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "consulting_slots_select_own" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "consulting_slots_insert_own" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "consulting_slots_update_own" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "consulting_slots_select_all" ON consulting_slots;
|
|
DROP POLICY IF EXISTS "consulting_slots_service_role" ON consulting_slots;
|
|
|
|
-- Create simple, working policies
|
|
-- Users can see their own consulting slots
|
|
CREATE POLICY "Users can view own consulting slots"
|
|
ON consulting_slots
|
|
FOR SELECT
|
|
TO authenticated
|
|
USING (auth.uid() = user_id);
|
|
|
|
-- Users can insert their own consulting slots
|
|
CREATE POLICY "Users can insert own consulting slots"
|
|
ON consulting_slots
|
|
FOR INSERT
|
|
TO authenticated
|
|
WITH CHECK (auth.uid() = user_id);
|
|
|
|
-- Users can update their own consulting slots
|
|
CREATE POLICY "Users can update own consulting slots"
|
|
ON consulting_slots
|
|
FOR UPDATE
|
|
TO authenticated
|
|
USING (auth.uid() = user_id)
|
|
WITH CHECK (auth.uid() = user_id);
|
|
|
|
-- Users can delete their own consulting slots
|
|
CREATE POLICY "Users can delete own consulting slots"
|
|
ON consulting_slots
|
|
FOR DELETE
|
|
TO authenticated
|
|
USING (auth.uid() = user_id);
|
|
|
|
-- Service role (for edge functions and admin operations) can do everything
|
|
CREATE POLICY "Service role full access"
|
|
ON consulting_slots
|
|
FOR ALL
|
|
TO service_role
|
|
USING (true)
|
|
WITH CHECK (true);
|