Commit Graph

237 Commits

Author SHA1 Message Date
dwindown
952bb209cf Fix mobile bottom navigation wording to match desktop sidebar
Updated mobile navigation labels to be consistent with desktop sidebar:
- User nav: "Home" → "Dashboard", "Kelas" → "Akses", "Pesanan" → "Order"
- Admin nav: "Pengguna" → "Member" (matches sidebar exactly)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 01:14:29 +07:00
dwindown
a8341a42ee Fix badge color function name in Dashboard
Changed getStatusColor to getPaymentStatusColor to match the imported helper function from statusHelpers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 01:00:02 +07:00
dwindown
2f198a4d72 Fix consulting slot status label to use 'Pending'
Changed getConsultingSlotStatusLabel to return 'Pending' instead of 'Menunggu Pembayaran' for pending_payment status, making it consistent with payment status labels and more suitable for badge display.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 00:55:08 +07:00
dwindown
0a299466d8 Replace dropdown filters with tab buttons across admin pages
Update all admin pages to use tab button filters instead of dropdown selects, following the pattern from MemberAccess.tsx:

Changes:
- AdminProducts: Tab buttons for product type (only bootcamp/webinar shown) and status (active/inactive)
- AdminConsulting: Added status filter with tab buttons (pending payment, confirmed, completed, cancelled)
- AdminOrders: Tab buttons for status filter (all, paid, pending, refunded)
- AdminMembers: Tab buttons for role filter (all, admin, member)
- AdminReviews: Tab buttons for both type (all, consulting, bootcamp, webinar, general) and status (all, pending, approved)

Features added:
- Clear button (X) on search input when text is present
- Reset button appears when any filter is active
- Consistent styling with shadow-sm for active tabs and border-2 for outline tabs
- All filters in vertical stack layout for better mobile responsiveness
- Active state visually distinct with default variant and shadow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 00:33:43 +07:00
dwindown
c993abe1e9 Add search and filter features to admin pages
Implement comprehensive search and filter functionality across all admin dashboard pages:

- AdminProducts: Search by title/description, filter by type/status
- AdminBootcamp: Search by bootcamp title
- AdminConsulting: Search by client name, email, category, or order ID
- AdminOrders: Search by order ID/email, filter by payment status
- AdminMembers: Search by name/email, filter by role (admin/member)
- AdminReviews: Enhanced with search by title, body, reviewer, product; existing filters maintained

Features:
- Consistent UI pattern with search icon and border styling
- Result count display showing filtered vs total items
- Contextual empty state messages
- Responsive grid layout for filters
- Real-time filtering without page reload

Also fix admin page reload redirect race condition where pages would redirect to /dashboard instead of staying on current page after reload. The loading state now properly waits for admin role check to complete.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 00:17:53 +07:00
dwindown
690268362a feat: add search to AdminConsulting page
- Add search by client name, email, category, or order ID
- Show result count for filtered data
- Integrate with existing upcoming/past tabs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 00:08:21 +07:00
dwindown
3e418759a1 feat: add search and filter to admin pages
- 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>
2025-12-28 00:07:07 +07:00
dwindown
0e3a45cfe2 fix: prevent admin page reload redirect to dashboard
Wait for admin role check to complete before setting loading to false.
This prevents race condition where:
1. authLoading becomes false after session loads
2. isAdmin is still false (async check in progress)
3. Page redirects to /dashboard before isAdmin is set to true

Now loading stays true until BOTH session and admin role are loaded,
ensuring admin pages don't redirect on reload.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 23:55:46 +07:00
dwindown
79e1bd82fc fix: consulting slots display and auth reload redirect
- Group consulting slots by date in admin order detail modal
- Show time range from first slot start to last slot end
- Display session count badge for multi-slot orders
- Fix page reload redirecting to main page by ensuring loading state
  is properly synchronized with Supabase session initialization
- Add mounted flag to prevent state updates after unmount

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 23:47:53 +07:00
dwindown
777d989d34 feat: improve consulting booking UX - allow single slot selection
- Add pending slot state to distinguish between selected and confirmed slots
- First click: slot shows as pending (amber) with "Pilih" label
- Second click (same slot): confirms single slot selection
- Second click (different slot): creates range from pending to clicked slot
- Fix "Body already consumed" error in OAuth token refresh
- Enhance admin consulting slot display with category and notes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 23:40:54 +07:00
dwindown
4d8f66ed3a Fix meet link creation to use edge function instead of n8n webhook
Changes:
1. AdminConsulting.tsx: Update createMeetLink to call Supabase edge function
   - Remove dependency on n8n webhook URL
   - Call create-google-meet-event edge function directly
   - Use environment variables for Supabase URL and anon key
   - Improve error handling and user feedback

2. handle-order-paid: Add comprehensive error logging
   - Log meet response status
   - Log full response data
   - Log errors when meet_link update fails
   - Log error response text when request fails
   - Better debugging for troubleshooting meet creation issues

This fixes:
- CORS issues when calling n8n webhook
- 404 errors from deleted /webhook-test/create-link endpoint
- Manual meet link creation now uses same flow as automatic
- Better visibility into meet creation failures via logs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 08:46:55 +07:00
dwindown
47d78cbd98 Fix consulting slots ordering and add debug logging
Changes:
- Sort consulting slots by start_time before processing
- Ensures correct first/last slot selection for calendar events
- Add debug logging to track time slot calculations
- Fixes end time calculation for multi-slot consulting orders

This ensures that when multiple slots are booked:
- Slots are processed in chronological order
- Calendar event uses first slot's start and last slot's end
- Event duration correctly covers all booked slots

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 08:27:34 +07:00
dwindown
42d6bd98e2 Fix calendar timezone and group consulting slots by order
Calendar Timezone Fix:
- Add +07:00 timezone offset to date strings in create-google-meet-event
- Fixes 13:00 appearing as 20:00 in Google Calendar
- Now treats times as Asia/Jakarta time explicitly

Single Calendar Event per Order:
- handle-order-paid now creates ONE event for all slots in an order
- Uses first slot's start time and last slot's end time
- Updates all slots with the same meet_link
- Prevents duplicate calendar events for multi-slot orders

Admin Consulting Page Improvements:
- Group consulting slots by order_id
- Display as single row with continuous time range (start-end)
- Show session count when multiple slots (e.g., "2 sesi")
- Consistent with member-facing ConsultingHistory component
- Updated both desktop table and mobile card layouts
- Updated both upcoming and past tabs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 01:34:40 +07:00
dwindown
3f0acca658 Fix admin consulting page query
Change from relationship query to manual join to avoid foreign key issues with profiles table

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 01:22:15 +07:00
dwindown
17440cdf89 Fix consulting order processing and display
- 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>
2025-12-27 01:17:47 +07:00
dwindown
73c03285ea Debug: Add extensive logging to handle-order-paid
Added detailed logging to diagnose why consulting slots aren't being updated:
- Log order details including consulting_slots count
- Log whether order is detected as consulting order
- Log slot update result and any errors

This will help identify where the process is failing.
2025-12-27 00:07:00 +07:00
dwindown
293d5bd65d Fix: Call handle-order-paid directly from webhook instead of relying on DB trigger
The database trigger approach wasn't working because the trigger either doesn't
exist or the required database settings (app.base_url, app.service_role_key) aren't
configured.

This is a simpler, more reliable solution:
- pakasir-webhook updates order to 'paid' status
- pakasir-webhook then directly calls handle-order-paid edge function
- No dependency on database triggers or settings

This matches how other parts of the system work - direct function calls with
environment variables, not database triggers.
2025-12-26 23:54:13 +07:00
dwindown
390fde9bf2 Fix: Handle consulting orders properly in handle-order-paid edge function
Critical bug fix: Consulting orders were not being processed after payment because
the function checked order_items for consulting products, but consulting orders
don't have order_items - they have consulting_slots instead.

Changes:
- Fetch consulting_slots along with order_items in the query
- Check for consulting_slots.length > 0 to detect consulting orders
- Update consulting_slots status from 'pending_payment' to 'confirmed'
- Create Google Meet events for each consulting slot
- Send consulting_scheduled notification

This fixes the issue where:
- Consulting slots stayed in 'pending_payment' status after payment
- No meet links were generated
- No access was granted
- Schedules didn't show up in admin or member dashboard
2025-12-26 23:25:55 +07:00
dwindown
1743f95000 Fix: Add missing payment_method to consulting order creation
The consulting booking flow was missing payment_method: 'qris' when creating
orders. This caused the OrderDetail page to skip rendering the QR code section
because it checks order.payment_method === 'qris'.

Product orders already had this field, which is why QR codes displayed correctly
for them but not for consulting orders.

The root cause was in ConsultingBooking.tsx line 303-314 where the order insert
was missing the payment_method field that was present in Checkout.tsx.
2025-12-26 22:49:09 +07:00
dwindown
a567b683af Fix consulting order QR display and remove duplicate slots card
1. QR Code Display Fix:
   - Removed qr_string from required condition
   - Added fallback for when QR is still processing
   - Shows payment_url button if QR string not available yet
   - Helps users pay while QR code is being generated

2. Consulting Slots Display Fix:
   - Removed duplicate "Detail Jadwal" card
   - Slots now only shown once in main session card
   - Displays as continuous time range (start to end)
   - Shows total duration (e.g., "3 blok (135 menit)")

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 22:24:21 +07:00
dwindown
2dae2fdc33 Fix consulting order detail to show slots and QR code
Fixed isConsultingOrder detection:
- Now checks consultingSlots.length > 0 instead of only checking order_items
- Consulting orders don't have order_items, only consulting_slots

Always fetch consulting slots:
- Removed conditional check that only fetched slots for consulting products
- Now always queries consulting_slots table for any order
- This ensures consulting booking info displays correctly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:32:13 +07:00
dwindown
c09d8b0c2a Fix consulting booking flow and export CSV format
1. CSV Export: Use raw numbers for Total and Refund Amount columns
   - Changed from formatted IDR (with dots) to plain numbers
   - Prevents Excel from breaking values with thousand separators

2. Consulting Booking Flow:
   - Fixed "Booking Sekarang" to navigate to order detail instead of redirecting to Pakasir
   - Payment QR code now displays in OrderDetail page
   - Consulting orders show slot details instead of empty items list

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:09:06 +07:00
dwindown
bf212fb973 Add CSV export functionality for admin orders
- Created exportCSV utility with convertToCSV, downloadCSV, formatExportDate, formatExportIDR
- Added export button to AdminOrders page with loading state
- Export includes all order fields: ID, email, total, status, payment method, date, refund info
- CSV format compatible with Excel and Google Sheets

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:25:43 +07:00
dwindown
5a05203f2b Update all pages to use centralized status helpers
Changes:
- Update MemberOrders to use getPaymentStatusLabel and getPaymentStatusColor
- Update OrderDetail to use centralized helpers
- Remove duplicate getStatusColor and getStatusLabel functions
- Dashboard.tsx already using imported helpers

Benefits:
- DRY principle - single source of truth
- Consistent Indonesian labels everywhere
- Easy to update status styling in one place

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:19:23 +07:00
dwindown
d089fcc769 Create centralized status management system
- Add statusHelpers.ts with single source of truth for all status labels/colors
- Update AdminOrders to use centralized helpers
- Add utility functions: canRefundOrder, canCancelOrder, canMarkAsPaid
- Improve consistency across payment status handling

Benefits:
- Consistent Indonesian labels everywhere
- DRY principle - no more duplicate switch statements
- Easy to update status styling in one place
- Reusable across all components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:07:56 +07:00
dwindown
81bbafcff0 Add refund system and meet link management
Refund System:
- Add refund processing with amount and reason tracking
- Auto-revoke product access on refund
- Support full and partial refunds
- Add database fields for refund tracking

Meet Link Management:
- Show meet link status badge (Ready/Not Ready)
- Add manual meet link creation/update form
- Allow admin to create meet links if auto-creation fails

Database Migration:
- Add refund_amount, refund_reason, refunded_at, refunded_by to orders
- Add cancellation_reason to orders and consulting_slots

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:05:25 +07:00
dwindown
b955445dea Add filters to Member Access and Member Orders pages
- Member Access: Add product kind filter pills + search input
- Member Orders: Add order status filter pills with counts
- Both pages show results count and empty state when no results
- Include reset filter button and clear search functionality

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 16:10:26 +07:00
dwindown
a824e101ed Use live profile data for reviews instead of frozen reviewer_name
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>
2025-12-26 15:39:58 +07:00
dwindown
74b7dd09ea Fix reviewer name priority to use live profile data first
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>
2025-12-26 09:36:54 +07:00
dwindown
9b2ac9beee Hide Quick Access section when no scheduled events available
- Check if quickAccessItems has any items before rendering section
- If no consulting/webinar events qualify, entire section is hidden
- Prevents empty "Akses Cepat" section from showing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 01:53:30 +07:00
dwindown
734aa967ac Refactor quick access section to only show scheduled events
Changes:
- Add consulting slots fetching to get confirmed upcoming sessions
- Update getQuickAction logic:
  * Consulting: Only show if has confirmed upcoming slot with meet_link
  * Webinar: Only show if event_start + duration hasn't ended
  * Bootcamp: Removed from quick access (self-paced, not scheduled)
- Filter out items without valid quick actions
- Remove unused Calendar and BookOpen imports

Quick access now truly means "it is scheduled, here's the shortcut to join"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 01:40:52 +07:00
dwindown
91bec42c4b Add missing Badge import to Bootcamp page
Fixes "Badge is not defined" error in bootcamp focus page.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 01:14:43 +07:00
dwindown
e512956444 Add celebratory review UI to Bootcamp page & fix access page
Bootcamp page changes:
- Add UserReview interface to store full review data
- Fetch review data with is_approved status
- Add celebratory UI when review is approved:
  - Gradient background with brand accent
  - "Ulasan Anda Terbit!" heading with "Disetujui" badge
  - Display user's review with stars, title, body
  - Publication date
- Show pending state with clock icon while waiting approval
- Update onSuccess callback to refresh review data

MemberAccess page changes:
- Change "Lanjutkan Bootcamp" to "Mulai Bootcamp" (clearer)
- Fix webinar action buttons:
  - Check if event_start has passed
  - Only show "Gabung Webinar" if webinar hasn't ended
  - Show "Tonton Rekaman" button if recording_url exists
  - Show "Rekaman segera tersedia" badge for passed webinars without recording

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 01:11:11 +07:00
dwindown
f1fb2758f8 Fix webinar join logic to use event_start + duration
Users can now join webinar even if it's already started:
- isWebinarJoinable(): returns true if current time <= event_start + duration
- isWebinarEnded(): returns true if current time > event_start + duration
- "Gabung Webinar" button shows as long as webinar hasn't ended
- This allows latecomers to join immediately

Previously used only event_start which prevented joining after start time.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 00:56:03 +07:00
dwindown
ae2a0bf3a1 Fix bootcamp and webinar action buttons
Bootcamp fixes:
- Change "Sudah Selesai" to "Selesai" (shorter, cleaner)
- Replace "Selanjutnya" button with "Beri Ulasan" when all lessons completed
- Makes more sense than "Lanjutkan" when there's nothing to continue

Webinar fixes:
- Check if webinar has ended based on event_start date
- Only show "Gabung Webinar" button if webinar hasn't ended AND has meeting link
- Show "Rekaman segera tersedia" badge for passed webinars without recording
- Only show recording player/video if recording_url exists

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 00:53:54 +07:00
dwindown
ed0d1b0ac8 Add celebratory review display after approval
Changes:
- Fetch user's full review data (not just approval status)
- Show celebratory UI when review is approved:
  - Gradient background with brand accent colors
  - "Ulasan Anda Terbit!" heading with approval badge
  - Display user's review with star rating
  - Thank you message for contributing
- Show pending state with clock icon while waiting approval
- Update review modal to refresh data after submission

This creates a proud moment for users when their review is approved!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 00:41:12 +07:00
dwindown
b4d3b1a580 Remove debug console logs from review components
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 00:33:29 +07:00
dwindown
50a642b07b Fix reviewer name display in TestimonialsSection
- 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>
2025-12-26 00:29:39 +07:00
dwindown
a412baad53 Add enhanced debugging for review API response
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>
2025-12-26 00:10:07 +07:00
dwindown
196d3e9211 Fix review name capture with auth metadata fallback
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>
2025-12-25 23:35:40 +07:00
dwindown
2dd9d544ee Add webinar recording page with embedded video player
Changes:
- Create WebinarRecording page with embedded video player
- Supports YouTube, Vimeo, Google Drive, and direct MP4
- Check access via user_access or paid orders
- Update webinar recording buttons to navigate to page instead of new tab
- Add route /webinar/:slug

This keeps users on the platform for better UX instead of
redirecting to external video sites.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 23:05:32 +07:00
dwindown
e347a780f8 Fix review system: display real names and check approval status
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>
2025-12-25 22:29:48 +07:00
dwindown
466cca5cb4 Make all status badges pill-shaped and standardize pending color
- 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>
2025-12-25 21:23:56 +07:00
dwindown
24826a3ea4 Fix badge colors and show paid webinars in access pages
- Change "Lunas" badge to use brand accent color instead of hardcoded green
- Fix "Aktif" badge with white text and border for better contrast
- Update MemberAccess page to fetch from paid orders (webinars now show)
- Remove payment_provider filter completely since only Pakasir is used

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 18:08:37 +07:00
dwindown
fe9a8bde1d Fix member dashboard issues and webinar datetime loading
- Remove payment_provider filter to show all paid products (webinars now appear)
- Fix webinar event_start field loading in AdminProducts (format to datetime-local)
- Update order status badge colors for better visibility (green for paid, amber for pending)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 17:56:51 +07:00
dwindown
f381c68371 Fix paragraph spacing in Tiptap editor output
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>
2025-12-25 14:06:17 +07:00
dwindown
4ccd1cb96f Add paragraph spacing to prose content styling
Add proper margin (my-4) to paragraphs in Tiptap-rendered content.
This ensures proper spacing between paragraphs when displaying
rich text content in product detail pages and other areas.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 13:57:53 +07:00
dwindown
711a5c5d6b Add webinar calendar integration and consulting slot blocking
- Fix webinar duration field reference in Calendar (duration_minutes)
- Calculate and display webinar end times in calendar view
- Fetch webinars for selected date in consulting booking
- Block consulting slots that overlap with webinar times
- Show warning when webinars are scheduled on selected date
- Properly handle webinar time range conflicts

This prevents booking conflicts when users try to schedule
consulting sessions during webinar times.

Example: Webinar 20:15-22:15 blocks consulting slots 20:00-22:30

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 13:46:03 +07:00
dwindown
eea3a1f8d8 Add Tiptap enhancements and webinar date/time fields
- Add text alignment controls to Tiptap editor (left, center, right, justify)
- Add horizontal rule/spacer button to Tiptap toolbar
- Add event_start and duration_minutes fields to webinar products
- Add webinar status badges (Recording Available, Coming Soon, Ended)
- Install @tiptap/extension-text-align package

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 13:41:51 +07:00
dwindown
fa274bd8cc Hide cart for admin users and remove confirmation from view-only modals
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>
2025-12-25 13:21:06 +07:00