import React from 'react'
import { Link, router, usePage } from '@inertiajs/react'
import SeoHead from '../../components/seo/SeoHead'
import NovaSelect from '../../components/ui/NovaSelect'
import { trackAcademySearchResultClick, trackUpgradeClick, useAcademyPageAnalytics } from '../../lib/academyAnalytics'
function Breadcrumbs({ items = [] }) {
if (!items.length) {
return null
}
return (
)
}
function formatAccessDate(value) {
if (!value) {
return null
}
const parsed = new Date(value)
if (Number.isNaN(parsed.getTime())) {
return null
}
return new Intl.DateTimeFormat(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
}).format(parsed)
}
function academyAccessHeading(access) {
switch (access?.status) {
case 'staff_access':
return 'You currently have full staff access to the Academy.'
case 'grace_period':
return `${access.tierLabel} access is still active.`
case 'trialing':
return `${access.tierLabel} trial is active right now.`
case 'active':
return access?.hasPaidAccess ? `${access.tierLabel} access is active.` : 'Your Academy access is active.'
case 'free':
return 'You currently have Free access to the Academy.'
default:
return null
}
}
function academyAccessMeta(access) {
if (!access?.signedIn) {
return []
}
const items = [
{ label: 'Current tier', value: access?.tierLabel || 'Free' },
{ label: 'Status', value: access?.statusLabel || 'Free access' },
]
const formattedDate = formatAccessDate(access?.expiresAt)
if (formattedDate && access?.dateLabel) {
items.push({ label: access.dateLabel, value: formattedDate })
} else if (access?.renewsAutomatically) {
items.push({ label: 'Billing', value: 'Renews automatically' })
} else if (!access?.hasPaidAccess) {
items.push({ label: 'Upgrade', value: 'Creator and Pro unlock premium lessons and courses' })
}
return items
}
function CourseCard({ course, analytics = null, searchContext = null, position = null }) {
const progress = course?.progress || null
const cover = course?.cover_image_url || course?.teaser_image_url || course?.cover_image || course?.teaser_image || ''
const trackSearchClick = () => {
if (!searchContext?.query) {
return
}
trackAcademySearchResultClick(analytics, searchContext, {
contentType: 'academy_course',
contentId: course?.id,
position,
})
}
return (
{cover ?

: null}
{course?.difficulty ? {course.difficulty} : null}
{course?.access_level ? {course.access_level} : null}
{course.is_featured ? Featured : null}
{course?.lessons_count || 0} lessons
{course?.estimated_minutes ? `${course.estimated_minutes} min` : 'Flexible pace'}
Academy course
{course?.subtitle ?
{course.subtitle} : null}
{course.title}
{course.excerpt || course.description || 'Structured Academy course.'}
{progress ? `${progress.percent}% complete` : 'Start fresh'}{course?.access_level ? ` ยท ${course.access_level}` : ''}
)
}
export default function AcademyCoursesIndex({ seo, title, description, items, featuredCourses = [], filters = {}, pricingUrl, lessonsUrl, promptLibraryUrl, academyAccess = null, analytics }) {
const flash = usePage().props.flash || {}
useAcademyPageAnalytics(analytics)
const breadcrumbs = [
{ label: 'Academy', href: '/academy' },
{ label: 'Courses', href: '/academy/courses' },
]
const visibleItems = Array.isArray(items?.data) ? items.data : []
const totalCourses = Number(items?.total || items?.data?.length || 0)
const featuredCount = featuredCourses.length
const featuredCourse = featuredCourses.find((course) => course?.cover_image_url || course?.teaser_image_url || course?.cover_image || course?.teaser_image) || featuredCourses[0] || visibleItems[0] || null
const featuredCover = featuredCourse?.cover_image_url || featuredCourse?.teaser_image_url || featuredCourse?.cover_image || featuredCourse?.teaser_image || ''
const showSignedInAccess = Boolean(academyAccess?.signedIn)
const accessHeading = academyAccessHeading(academyAccess)
const accessMeta = academyAccessMeta(academyAccess)
const useBillingAction = showSignedInAccess && academyAccess?.hasPaidAccess && academyAccess?.billingUrl
const primaryActionLabel = useBillingAction ? (academyAccess?.status === 'grace_period' ? 'Renew now' : 'Manage billing') : 'See plans'
const primaryActionIcon = useBillingAction ? (academyAccess?.status === 'grace_period' ? 'fa-solid fa-rotate-right' : 'fa-solid fa-sliders') : 'fa-solid fa-arrow-up-right-from-square'
const primaryActionHref = useBillingAction ? academyAccess.billingUrl : pricingUrl
const searchContext = analytics?.search ? {
query: analytics.search.query,
normalizedQuery: analytics.search.normalizedQuery,
resultsCount: analytics.search.resultsCount,
filters,
} : null
const difficultyOptions = [
{ value: '', label: 'All levels' },
{ value: 'beginner', label: 'Beginner' },
{ value: 'intermediate', label: 'Intermediate' },
{ value: 'advanced', label: 'Advanced' },
]
const accessOptions = [
{ value: '', label: 'All access' },
{ value: 'free', label: 'Free' },
{ value: 'premium', label: 'Premium' },
{ value: 'mixed', label: 'Mixed' },
]
const handlePrimaryAction = () => {
if (!useBillingAction) {
trackUpgradeClick(analytics, { source: 'academy_courses_index_hero_primary' })
}
}
return (
Skinbase AI Academy
Courses
{totalCourses} guided paths
Library
{totalCourses} guided courses
Focus
Sequenced learning + tracked completion
Structured progression
Tracked completion
Reusable lesson paths
Browse lessons
Prompt library
{primaryActionLabel}
Featured course
{featuredCourse?.difficulty ?
{featuredCourse.difficulty} : null}
{featuredCover ?

: null}
{featuredCourse?.access_level ? {featuredCourse.access_level} : null}
{featuredCourse?.is_featured ? Spotlight : null}
{featuredCourse?.subtitle || 'Guided learning path'}
{featuredCourse?.title || 'Explore courses'}
{featuredCourse?.excerpt || featuredCourse?.description || 'Open a structured Academy course built from reusable lessons.'}
{showSignedInAccess ? 'Your Academy access' : 'Upgrade for full access'}
{showSignedInAccess ? accessHeading : 'Unlock the full course library, premium lesson paths, and the broader Academy learning track.'}
{showSignedInAccess ? (
{accessMeta.map((item) => (
{item.label}
{item.value}
))}
) : null}
{primaryActionLabel}
Browse lessons
{academyAccess?.status === 'grace_period' ?
Opens billing account to restore renewal before access ends.
: null}
{flash.success ?
{flash.success}
: null}
{flash.error ?
{flash.error}
: null}
router.get(window.location.pathname, { ...filters, difficulty: nextValue || undefined }, { preserveScroll: true, preserveState: true })}
options={difficultyOptions}
searchable={false}
className="rounded-2xl bg-white/[0.04]"
/>
router.get(window.location.pathname, { ...filters, access: nextValue || undefined }, { preserveScroll: true, preserveState: true })}
options={accessOptions}
searchable={false}
className="rounded-2xl bg-white/[0.04]"
/>
{visibleItems.length === 0 ? (
No published Academy courses matched these filters.
) : (
{visibleItems.map((course, index) => )}
)}
)
}