PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.3.2
Presto Player v4.3.2
4.3.2 4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / dashboard / pages / learn / ChapterCard.js
presto-player / src / admin / dashboard / pages / learn Last commit date
ChapterCard.js 2 months ago LearnPage.js 2 months ago LearnPageSkeleton.js 2 months ago ProgressPill.js 2 months ago ScreenshotDialog.js 2 months ago SetupCompleteCard.js 2 months ago StepItem.js 2 months ago useLearnProgress.js 2 months ago
ChapterCard.js
91 lines
1 import { useState } from '@wordpress/element';
2 import { ChevronDown, ChevronUp, ArrowUpRight } from 'lucide-react';
3 import StepItem from './StepItem';
4 import ProgressPill from './ProgressPill';
5
6 const { __ } = wp.i18n;
7
8 const ChapterCard = ( { chapter, defaultOpen = false, onStepToggle } ) => {
9 const [ open, setOpen ] = useState( defaultOpen );
10
11 const totalSteps = chapter.steps?.length || 0;
12 const completedSteps =
13 chapter.steps?.filter( ( step ) => step.completed ).length || 0;
14
15 const handleDocsClick = ( e ) => {
16 e.stopPropagation();
17 if ( chapter.docsUrl ) {
18 window.open( chapter.docsUrl, '_blank', 'noopener,noreferrer' );
19 }
20 };
21
22 return (
23 <div className="rounded-lg border border-solid border-border-subtle bg-background-primary overflow-hidden">
24 { /* Header */ }
25 <button
26 type="button"
27 onClick={ () => setOpen( ( v ) => ! v ) }
28 aria-expanded={ open }
29 className="w-full flex items-start justify-between gap-4 px-5 py-4 bg-transparent border-0 cursor-pointer text-left hover:bg-background-secondary/40 transition-colors"
30 >
31 <div className="flex-1 min-w-0">
32 <h3 className="m-0 text-base font-semibold text-text-primary">
33 { chapter.title }
34 </h3>
35 { chapter.description && (
36 <p className="m-0 mt-1 text-sm text-text-secondary leading-relaxed">
37 { chapter.description }
38 </p>
39 ) }
40 </div>
41
42 <div className="shrink-0 flex items-center gap-3 pt-1">
43 { chapter.docsUrl && (
44 <span
45 role="button"
46 tabIndex={ 0 }
47 onClick={ handleDocsClick }
48 onKeyDown={ ( e ) => {
49 if ( e.key === 'Enter' || e.key === ' ' ) {
50 handleDocsClick( e );
51 }
52 } }
53 className="inline-flex items-center gap-1 text-xs font-medium text-brand-primary-600 hover:text-brand-hover-700 cursor-pointer"
54 >
55 { __( 'Learn how', 'presto-player' ) }
56 <ArrowUpRight className="w-3.5 h-3.5" />
57 </span>
58 ) }
59
60 <ProgressPill
61 completed={ completedSteps }
62 total={ totalSteps }
63 />
64
65 { open ? (
66 <ChevronUp className="w-5 h-5 text-text-secondary" />
67 ) : (
68 <ChevronDown className="w-5 h-5 text-text-secondary" />
69 ) }
70 </div>
71 </button>
72
73 { /* Steps */ }
74 { open && (
75 <div className="border-0 border-t border-solid border-border-subtle p-4 flex flex-col gap-3 bg-background-secondary/20">
76 { chapter.steps?.map( ( step ) => (
77 <StepItem
78 key={ step.id }
79 chapterId={ chapter.id }
80 step={ step }
81 onToggle={ onStepToggle }
82 />
83 ) ) }
84 </div>
85 ) }
86 </div>
87 );
88 };
89
90 export default ChapterCard;
91