Track playback state and show overlay with pointer-events:auto when paused,
pointer-events:none when playing. This blocks YouTube UI (copy link, logo)
when video is paused or initially loaded, while allowing Plyr controls.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed overlay to use pointer-events: none instead of pointer-events-auto.
This allows Plyr controls to receive clicks while still blocking YouTube iframe interactions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Changes
### Video Player CSS Overlay Fix
- Moved overlay inside plyr__video-embed container
- Added check for plyr__control--overlaid (play button)
- Now only blocks YouTube iframe, not Plyr controls
- Preserves full functionality of play button, progress bar, etc.
### Site Settings Permissions
- Added RLS policy to make site_settings publicly readable
- All authenticated users can now access brand_accent_color
- Fixes 404 error when members try to fetch accent color
## Technical Details
- Overlay now properly allows clicks through to Plyr controls
- Site settings now accessible via public RLS policy for authenticated users
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Changes
- Added max-height of 400px to chapter list container
- Added overflow-y-auto for vertical scrolling
- Added custom scrollbar styling (thin, with hover effects)
- Added pr-2 padding for scrollbar space
## Benefits
- Prevents timeline from becoming too tall for long videos
- Maintains consistent layout regardless of chapter count
- Better UX for 2-3+ hour videos with many chapters
- Smooth scrolling with styled scrollbar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Changes
### Chapter Time Format Support
- Added HH:MM:SS format support in addition to MM:SS
- Updated time parsing to handle variable-length inputs
- Updated time display formatter to show hours when > 0
- Updated input placeholder and validation pattern
- Updated help text to mention both formats
### Video Player Improvements
- Added fullscreen button to Plyr controls
- Added quality/settings control to Plyr controls
- Fixed accent color theming with !important CSS rules
- Removed hardcoded default accent color (#f97316)
- Updated Bootcamp and WebinarRecording pages to use empty string initial state
### Access Control & Security
- Added transparent CSS overlay to block YouTube UI interactions
- Disabled YouTube native controls (controls=0, disablekb=1, fs=0)
- Set iframe pointer-events-none to prevent direct interaction
- Prevents members from copying/sharing YouTube URLs directly
- Preserves Plyr controls functionality through click handler
### Files Modified
- src/components/admin/ChaptersEditor.tsx: Time format HH:MM:SS support
- src/components/VideoPlayerWithChapters.tsx: Security overlay & theming fixes
- src/pages/Bootcamp.tsx: Accent color initialization fix
- src/pages/WebinarRecording.tsx: Accent color initialization fix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement timeline chapters for webinar and bootcamp videos with click-to-jump functionality:
**Components:**
- VideoPlayerWithChapters: Plyr.io-based player with chapter support
- TimelineChapters: Clickable chapter markers with active state
- ChaptersEditor: Admin UI for managing video chapters
**Features:**
- YouTube videos: Clickable timestamps that jump to specific time
- Embed videos: Static timeline display (non-clickable)
- Real-time chapter tracking during playback
- Admin-defined accent color for Plyr theme
- Auto-hides timeline when no chapters configured
**Database:**
- Add chapters JSONB column to products table (webinars)
- Add chapters JSONB column to bootcamp_lessons table
- Create indexes for faster queries
**Updated Pages:**
- WebinarRecording: Two-column layout (video + timeline)
- Bootcamp: Per-lesson chapter support
- AdminProducts: Chapter editor for webinars
- CurriculumEditor: Chapter editor for lessons
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed issues:
- Added isAvailable parameter to handleSlotClick to prevent clicks on unavailable slots
- Added validation to prevent selecting past dates in date picker
- Added validation in handlePreviousDay to block navigating to past dates
- Added warning message when trying to view past dates
- Prevents the "slot is not defined" error when clicking disabled slots
Now the modal properly:
- Blocks selecting dates before today
- Shows clear error messages for past dates
- Prevents clicks on unavailable time slots
- Handles edge cases like passed sessions being rescheduled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhanced TimeSlotPickerModal with:
- Date selection via date input and navigation arrows
- Passed time slots filtered out (only show future slots for today)
- Complete schedule picker (date + time in one modal)
- Dynamic slot availability based on selected date
- Better UX with date/time sections clearly separated
Updated AdminConsulting to:
- Use editSessionDate when opening time slot picker
- Pass selected date back from modal to parent
- Handle date changes during rescheduling
Fixes the issue where admins could only select time slots for the original
session date, not the new rescheduled date.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Problem: Passed consulting sessions stayed in "Dikonfirmasi" status indefinitely,
showing JOIN button to members even after session ended, with no admin action buttons.
Solution:
1. Admin UI (AdminConsulting.tsx):
- Add isSessionPassed() helper to check if session end time has passed
- Add "Sesi Terlewat" alert card at top with quick action buttons
- Add "Perlu Update" stat card (orange) for passed confirmed sessions
- Existing action buttons (Selesai/Batal) already work for confirmed sessions
2. Member UI (ConsultingHistory.tsx):
- Move passed confirmed sessions from "Sesi Mendatang" to new "Sesi Terlewat" section
- Remove JOIN button for passed sessions
- Show "Menunggu konfirmasi admin" status message
- Display with orange styling to indicate needs attention
3. Order Detail (OrderDetail.tsx):
- Add isConsultingSessionPassed check
- Show orange alert for passed paid sessions: "Sesi telah berakhir. Menunggu konfirmasi admin"
- Keep green alert for upcoming paid sessions
Flow:
- Session ends → Still shows "confirmed" status
- Admin sees orange alert → Clicks Selesai or Batal
- Member sees passed session → No JOIN button → Waits for admin
- Admin updates status → Session moves to completed/cancelled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add video source toggle UI (YouTube/Embed) to product edit form for bootcamps
- Remove Bootcamp menu from admin navigation (curriculum managed via Products page)
- Remove tabs from product add/edit modal (simplified to single form)
- Improve ProductCurriculum layout from 3-column (3|5|4) to 2-column (4|8)
- Modules and lessons now in left sidebar with accordion-style expansion
- Lesson editor takes 67% width instead of 33% for better content editing UX
- Add helpful tip about configuring both video sources for redundancy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 1: Rich Text Editor with Code Syntax Highlighting
- Add TipTap CodeBlock extension with lowlight for syntax highlighting
- Support multiple languages (JavaScript, TypeScript, Python, Java, C++, HTML, CSS, JSON)
- Add copy-to-clipboard button on code blocks
- Add line numbers display with CSS
- Replace textarea with RichTextEditor in CurriculumEditor
- Add DOMPurify sanitization in Bootcamp display
- Add dark theme syntax highlighting styles
Phase 2: Admin Curriculum Management Page
- Create dedicated ProductCurriculum page at /admin/products/:id/curriculum
- Three-column layout: Modules (3) | Lessons (5) | Editor (4)
- Full-page UX with drag-and-drop reordering
- Add "Manage Curriculum" button for bootcamp products in AdminProducts
- Breadcrumb navigation back to products
Phase 3: Product-Level Video Source Toggle
- Add youtube_url and embed_code columns to bootcamp_lessons table
- Add video_source and video_source_config columns to products table
- Update ProductCurriculum with separate YouTube URL and Embed Code fields
- Create smart VideoPlayer component in Bootcamp.tsx
- Support YouTube ↔ Embed switching with smart fallback
- Show "Konten tidak tersedia" warning when no video configured
- Maintain backward compatibility with existing video_url field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add availability checking and calendar sync to admin session editing:
**New Features:**
- Admin can now select time slots using visual picker with availability checking
- Time slot picker respects confirmed sessions and excludes current session from conflict check
- Calendar events are automatically updated when session time changes
- consulting_time_slots table is updated when time changes (old slots deleted, new slots created)
**New Component:**
- src/components/admin/TimeSlotPickerModal.tsx
- Reusable modal for time slot selection
- Shows visual grid of available time slots
- Range selection for multi-slot sessions
- Availability checking against consulting_sessions
- Supports editing (excludes current session from conflicts)
**Enhanced AdminConsulting.tsx:**
- Replaced simple time inputs with TimeSlotPickerModal
- Added state: timeSlotPickerOpen, editTotalBlocks, editTotalDuration
- Added handleTimeSlotSelect callback
- Enhanced saveMeetLink to:
- Update consulting_time_slots when time changes
- Call update-calendar-event edge function
- Update calendar event time via Google Calendar API
- Button shows selected time with duration and blocks count
**New Edge Function:**
- supabase/functions/update-calendar-event/index.ts
- Updates existing Google Calendar events when session time changes
- Uses PATCH method to update event (preserves event_id and history)
- Handles OAuth token refresh with caching
- Only updates start/end time (keeps title, description, meet link)
**Flow:**
1. Admin clicks "Edit" on session → Opens dialog
2. Admin clicks time button → Opens TimeSlotPickerModal
3. Admin selects new time → Only shows available slots
4. On save:
- consulting_sessions updated with new time
- Old consulting_time_slots deleted
- New consulting_time_slots created
- Google Calendar event updated (same event_id)
- Meet link preserved
**Benefits:**
- ✅ Prevents double-booking with availability checking
- ✅ Visual time slot selection (same UX as booking page)
- ✅ Calendar events stay in sync (no orphaned events)
- ✅ Time slots table properly maintained
- ✅ Meet link and event_id preserved during time changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Migrate consulting_slots to consulting_sessions structure
- Add calendar_event_id to track Google Calendar events
- Create delete-calendar-event edge function for auto-cleanup
- Add "Tambah ke Kalender" button for members (OrderDetail, ConsultingHistory)
- Update create-google-meet-event to store calendar event ID
- Update handle-order-paid to use consulting_sessions table
- Remove deprecated create-meet-link function
- Add comprehensive documentation (CALENDAR_INTEGRATION.md, MIGRATION_GUIDE.md)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add search and filter (type, status) to AdminProducts
- Add search to AdminBootcamp
- Change mobile admin nav "Pesanan" to "Order"
- Show result counts for filtered data
- Handle empty states with helpful messages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix consulting history to show continuous time range (09:00 - 11:00) instead of listing individual slots
- Add foreign key relationships for consulting_slots (order_id and user_id)
- Fix handle-order-paid to query profiles(email, name) instead of full_name
- Add completed consulting sessions with recordings to Member Access page
- Add user_id foreign key constraint to consulting_slots table
- Add orders foreign key constraint for consulting_slots relationship
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- Revert to using profiles!user_id (name, avatar_url) JOIN for reviews
- Remove reviewer_name storage from ReviewModal (no longer needed)
- Add avatar display to ReviewCard component
- Reviews now sync automatically with profile changes
- Public queries safely expose only name + avatar via RLS
This ensures:
- Name/avatar changes update across all reviews automatically
- No frozen/outdated reviewer data
- Only public profile fields exposed (secure)
- Reviews serve as live, credible social proof
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed fallback order from:
reviewer_name || profiles.name || 'Anonymous'
To:
profiles.name || reviewer_name || 'Anonymous'
This ensures:
1. Live profile name is always shown (current data)
2. Falls back to stored reviewer_name if profile deleted
3. Shows "Anonymous" as last resort
Fixes issue where name changes don't reflect on old reviews
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Change from INNER JOIN to LEFT JOIN (profiles:user_id → profiles!user_id)
- Add reviewer_name to SELECT clause
- Update fallback logic to prioritize reviewer_name over profiles.name
- Add debug console logging
This fixes the "Anonymous" reviewer name issue on homepage.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added console logging to track:
- When fetchReviews is called
- Raw API response data
- Any errors from Supabase
This will help debug why reviewer_name is not appearing
in the API response.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- ReviewModal now fetches name from profiles, auth metadata, or email
- Added console logging to debug review data
- Falls back to email username if no name found
- This ensures reviewer_name is always populated
For existing reviews without names, run:
UPDATE reviews r
SET reviewer_name = (
SELECT COALESCE(
raw_user_meta_data->>'name',
SPLIT_PART(email, '@', 1)
)
FROM auth.users WHERE id = r.user_id
)
WHERE reviewer_name IS NULL;
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- ProductReviews.tsx: Use LEFT JOIN and fetch reviewer_name field
- ReviewModal.tsx: Store reviewer_name at submission time
- ProductDetail.tsx: Check is_approved=true in checkUserReview()
- Add migration for reviewer_name column and approval index
This fixes two issues:
1. Reviews now show real account names instead of "Anonymous"
2. Members no longer see "menunggu moderasi" after approval
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add rounded-full to all status badges across admin and member pages
- Change Pending badge color from bg-secondary to bg-amber-500 text-white
- Update AdminDashboard to use Badge component instead of inline span
- Standardize badge colors everywhere:
- Paid (Lunas): bg-brand-accent text-white
- Pending: bg-amber-500 text-white
- Cancelled: bg-destructive text-white
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add [&_p]:my-4 to EditorContent className to ensure paragraphs
rendered from Tiptap editor have proper vertical spacing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Admin Cart Visibility:
- Hide cart icon/badge in mobile header for admin users
- Cart was already hidden in desktop sidebar
- Admins don't need to purchase products
Modal Confirmation Improvements:
- Removed confirmation from AdminOrders detail dialog (view-only)
- Removed confirmation from AdminMembers detail dialog (view-only)
- Kept confirmation on AdminProducts form dialog (has form inputs)
- Kept confirmation on AdminEvents form dialogs (Event and Block forms)
- Kept confirmation on AdminConsulting meet link dialog (has form input)
This prevents annoying confirmations on simple view/close actions while
still protecting users from accidentally closing forms with unsaved data.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Public Header Mobile Menu:
- Added hamburger menu for non-logged-in visitors on mobile
- Desktop shows full navigation, mobile shows slide-out menu with icons
- Cart icon remains visible on mobile alongside hamburger
Tiptap Editor List Formatting:
- Added visual styling for bullet lists (disc markers, padding, spacing)
- Added visual styling for ordered lists (decimal markers, padding, spacing)
- List markers now use primary color for better visibility
Product Content HTML Formatting:
- Enhanced prose styling with proper heading sizes (h1, h2, h3)
- Improved list formatting with proper indentation and markers
- Added blockquote styling with left border and italic text
- Added code and preformatted text styling
- Ensures all formatted content displays properly on product detail pages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Tiptap Editor Improvements:
- Active toolbar buttons now use primary background (black) instead of accent (gray) for better visibility
- Added visual formatting for headings (h1: 2xl bold, h2: xl bold with proper spacing)
- Added visual styling for blockquotes (left border, italic, muted foreground)
Badge Contrast Fixes:
- Product detail page badges now use primary background (black with white text) instead of secondary/accent (gray)
- Fixed product type badge and "Anda memiliki akses" badge
- Fixed "Rekaman segera tersedia" badge
API Query Fix:
- Fixed consulting_slots 400 error by removing unsupported nested relationship filter
- Changed to filter in JavaScript after fetching data from Supabase
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Mobile Card Layout Improvements:
- Remove redundant Card/CardContent wrappers in mobile layouts
- Use simple div with border-2 border-border rounded-lg p-4 space-y-3 bg-card
- This provides wider cards without extra padding from wrapper div
- Applied to all admin pages: AdminProducts, AdminOrders, AdminMembers, AdminConsulting, AdminEvents
Integration Tab Fix:
- Remove redundant Calendar ID display in Alert component
- The Calendar ID is already visible in the input field above
- This Alert was causing horizontal overflow on mobile
- Alert showed 'OAuth configured. Calendar ID: {long_email}@group.calendar.google.com'
- Removing this eliminates the overflow issue
AdminMembers.tsx:
- Wrap table in overflow-x-auto div for horizontal scrolling
- Add whitespace-nowrap to TableHead cells
AdminConsulting.tsx:
- Wrap both tables (upcoming and past) in overflow-x-auto div
- Add whitespace-nowrap to all TableHead cells
- Change stats grid from grid-cols-1 md:grid-cols-4 to grid-cols-2 md:grid-cols-4 for better mobile layout
AdminEvents.tsx:
- Wrap both tables (events and availability) in overflow-x-auto div
- Add whitespace-nowrap to all TableHead cells
- Change dialog form grids from grid-cols-2 to grid-cols-1 md:grid-cols-2
CurriculumEditor.tsx:
- Make curriculum header responsive (flex-col sm:flex-row)
- Make module card headers responsive (stack title and buttons on mobile)
- Make lesson items responsive (stack title and buttons on mobile)
All admin pages are now fully responsive with proper horizontal scrolling for tables on mobile and stacked layouts for forms and button groups.
- Update AppLayout to display logo and brand name together in all headers (sidebar, public, mobile)
- Improve favicon update in useBranding to create link element if not exists
- Update opengraph metadata to use local image instead of lovable.dev URL
- Change author/meta to WithDwindi branding
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add console.log to track URL generation
- Use functional setState to avoid stale closure issues
- Log settings state before save
This will help diagnose why URLs are empty in save payload
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Issue 1 - Logo/Favicon Upload:
- Add preview before upload (user must confirm)
- Show selected file preview with confirm/cancel buttons
- Fallback to current image if preview cancelled
- File size validation (2MB logo, 1MB favicon)
- Add STORAGE_RLS_FIX.sql for storage policy setup
Issue 2 - Badge Colors:
- Already implemented correctly in all files
- All "Lunas" badges use bg-brand-accent class
- Verified: OrderDetail, MemberOrders, Dashboard, MemberDashboard
Issue 3 - Page Title Error:
- Change .single() to .maybeSingle() in useBranding hook
- Handle error case gracefully with default branding
- Set default title even when platform_settings is empty
- This fixes the "JSON object requested, multiple (or no) rows returned" error
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Features implemented:
1. Expired QRIS order handling with dual-path approach
- Product orders: QR regeneration button
- Consulting orders: Immediate cancellation with slot release
2. Standardized status badge wording to "Pending"
3. Fixed TypeScript error in MemberDashboard
4. Dynamic badge colors from branding settings
5. Dynamic page title from branding settings
6. Logo/favicon file upload with auto-delete
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add state-based lock (isTestRunning) to prevent duplicate API calls
- Update error handling in edge function for body consumption
- Add OAuth2 token generation helper tool (get-google-token-local.html)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Disable button while request is in progress
- Re-enable button after request completes (success or error)
- Prevents React Strict Mode from firing duplicate simultaneous requests
- Fixes 'Body already consumed' error from parallel edge function calls
- Replace JWT service account authentication with OAuth2 refresh token flow
- Service accounts cannot create Google Meet links for personal Gmail accounts
- Update edge function to use OAuth2 token exchange
- Change database column from google_service_account_json to google_oauth_config
- Add helper tool (get-google-refresh-token.html) to generate OAuth credentials
- Update IntegrasiTab UI to show OAuth config instead of service account
- Add SQL migration file for new google_oauth_config column
OAuth2 Config format:
{
"client_id": "...",
"client_secret": "...",
"refresh_token": "..."
}
This approach works with personal @gmail.com accounts without requiring
Google Workspace or Domain-Wide Delegation.
- Change integration_google_service_account_json to google_service_account_json
- Matches actual database column name
- Remove schema cache workaround since column name now matches
- Update all frontend references to use correct column name
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add fallback RPC method when PostgREST schema cache fails
- Save service account JSON separately via raw SQL
- Show warning message if manual save needed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create new create-google-meet-event edge function
- Use service account authentication (no OAuth needed)
- Add google_service_account_json field to platform_settings
- Add admin UI for service account JSON configuration
- Include test connection button in Integrasi tab
- Add comprehensive setup documentation
- Keep n8n workflows as alternative option
Features:
- Direct Google Calendar API integration
- JWT authentication with service account
- Auto-create Google Meet links
- No external dependencies needed
- Simple configuration via admin panel
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add test/production toggle for n8n webhook URLs in IntegrasiTab
- Update create-meet-link function to use database test_mode setting
- Add send-email-v2 edge function for Mailketing API integration
- Update daily-reminders and send-consultation-reminder to use send-email-v2
- Remove deprecated branding field from BrandingTab
- Update domain references from hub.dwindi.com to with.dwindi.com
- Add environment variables for Coolify deployment
- Add comprehensive edge function test script
- Update payment flow redirect to order detail page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
🔄 Better UX Flow:
- After successful payment: redirect to /orders/{order_id} instead of /access
- This shows the specific order details where users can see their purchase
- Users can then proceed to payment if needed or access their content
📧 Updated Shortcodes:
- {thank_you_page} now uses dynamic URL pattern: /orders/{order_id}
- {order_id} will be replaced with actual order ID by ShortcodeProcessor
- Added {thank_you_page} to order_created and payment_reminder templates
🎯 User Journey:
1. User receives email with payment link
2. After successful payment → redirected to specific order detail page
3. If not logged in → redirects to login, then back to order detail
4. Order detail page shows payment status and access information
Much better user experience than generic dashboard redirect!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
✨ UI Improvements:
- Completely redesigned shortcode display with clean categorization
- Added collapsible section for all available shortcodes
- Used emoji icons for better visual organization
- Improved color coding and typography
- Added "Used in this template" section with visual distinction
➕ New Shortcodes:
- Added {payment_link} for direct payment links in emails
- Added {thank_you_page} for public thank you page access
- Updated relevant templates to include new payment shortcodes
🎯 Key Features:
- Shortcodes organized by category (User, Order, Product, Access, etc.)
- Visual hierarchy with proper spacing and borders
- Hover effects and smooth transitions
- Better readability with proper contrast
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix "nama is not defined" error by properly escaping shortcode text
- Wrap template literals with backticks in JSX to prevent variable interpretation
- This prevents shortcode braces from being treated as JavaScript variables
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace insert() with upsert() to handle existing templates
- Add onConflict: 'key' to update duplicates instead of failing
- This resolves "duplicate key value violates unique constraint" error
- Templates will now be properly updated/seeded on first visit
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
🎯 **Shortcode Organization:**
- Replace overwhelming all-shortcodes display with per-template relevant shortcodes
- Each notification type now shows only shortcodes that make sense for that context
- Examples:
- Payment templates: order info, amounts, payment details
- Access templates: login credentials, access links
- Consulting templates: meeting details, consultation topics
- Event templates: event info, schedules, locations
🐛 **Template Content Debugging:**
- Auto-detect templates with empty content and force reseed
- Add "Reset Template Default" button for manual debugging
- Enhanced console logging for template loading issues
- Force reseed functionality to delete and recreate templates
✨ **UI Improvements:**
- Remove unused Textarea import
- Cleaner shortcode display within each template card
- Better user experience with focused, relevant information
🔧 **Debug Features:**
- Check for empty email_subject or email_body_html fields
- Automatic content repair when empty templates are detected
- Manual reset option for troubleshooting
- Detailed console logging for development
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
✨ Enhanced shortcode organization and display:
**NotifikasiTab improvements:**
- Organized shortcodes into 9 categories with color-coded badges
- User Info (blue), Order Info (green), Product Info (yellow), Access Info (purple)
- Consulting (orange), Event Info (pink), Bootcamp Info (indigo), Company Info (gray), Payment Info (red)
- Added scrollable container with max-height for better UX
- Better visual hierarchy with category headers
**EmailTemplatePreview improvements:**
- Scrollable shortcode list with grid layout (2-3 columns)
- Show only shortcodes used in current template
- Add "All Available Shortcodes" summary section
- Improved visual organization with consistent styling
🎨 UI/UX Benefits:
- Easier to find relevant shortcodes by category
- Visual distinction between different data types
- Better space utilization with scrollable areas
- More informative and scannable layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>