Add public bootcamp curriculum access migration
- Created migration to enable public read access to bootcamp curriculum - RLS policies on bootcamp_modules and bootcamp_lessons for public/authenticated roles - Allows kurikulum card to display on product detail pages for unauthenticated users - Users can now see curriculum preview before purchasing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -388,4 +388,8 @@ All colors MUST be HSL.
|
|||||||
@apply bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono;
|
@apply bg-slate-100 text-slate-800 px-1 py-0.5 rounded text-xs font-mono;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex .flex-1 code {
|
||||||
|
background-color: #dedede;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -227,6 +227,11 @@ export default function ProductDetail() {
|
|||||||
return `${mins}:${String(secs).padStart(2, '0')}`;
|
return `${mins}:${String(secs).padStart(2, '0')}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isLastTimelineItem = (length: number, chapterIndex: number)=> {
|
||||||
|
const calcLength = length - 1;
|
||||||
|
return calcLength !== chapterIndex;
|
||||||
|
}
|
||||||
|
|
||||||
const renderWebinarChapters = () => {
|
const renderWebinarChapters = () => {
|
||||||
if (product?.type !== 'webinar' || !product.chapters || product.chapters.length === 0) return null;
|
if (product?.type !== 'webinar' || !product.chapters || product.chapters.length === 0) return null;
|
||||||
|
|
||||||
@@ -238,7 +243,7 @@ export default function ProductDetail() {
|
|||||||
{product.chapters.map((chapter, index) => (
|
{product.chapters.map((chapter, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="flex items-center gap-3 p-3 rounded-lg transition-colors cursor-not-allowed opacity-75"
|
className="flex items-start gap-3 p-3 rounded-lg transition-colors cursor-not-allowed opacity-75"
|
||||||
title="Beli webinar untuk mengakses konten ini"
|
title="Beli webinar untuk mengakses konten ini"
|
||||||
>
|
>
|
||||||
<div className="flex-shrink-0 w-12 text-center">
|
<div className="flex-shrink-0 w-12 text-center">
|
||||||
@@ -420,13 +425,13 @@ export default function ProductDetail() {
|
|||||||
{lesson.chapters.map((chapter, chapterIndex) => (
|
{lesson.chapters.map((chapter, chapterIndex) => (
|
||||||
<div
|
<div
|
||||||
key={chapterIndex}
|
key={chapterIndex}
|
||||||
className="flex items-center gap-2 py-1 px-2 text-xs text-muted-foreground rounded transition-colors cursor-not-allowed opacity-60"
|
className={`flex items-start gap-2 py-1 px-2 text-xs text-muted-foreground rounded transition-colors cursor-not-allowed opacity-60${isLastTimelineItem(lesson.chapters.length, chapterIndex) ? ' border-b-2 border-[#dedede] rounded-none' : ''}`}
|
||||||
title="Beli bootcamp untuk mengakses materi ini"
|
title="Beli bootcamp untuk mengakses materi ini"
|
||||||
>
|
>
|
||||||
<span className="font-mono w-10 text-center">
|
<span className="font-mono w-10 text-center">
|
||||||
{formatChapterTime(chapter.time)}
|
{formatChapterTime(chapter.time)}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-1">{chapter.title}</span>
|
<span className="flex-1" dangerouslySetInnerHTML={{ __html: chapter.title }} />
|
||||||
<Lock className="w-3 h-3 flex-shrink-0" />
|
<Lock className="w-3 h-3 flex-shrink-0" />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user