PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.4.0
Presto Player v4.4.0
4.4.1 4.4.0 4.3.3 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 1 week ago LearnPage.js 1 week ago LearnPageSkeleton.js 3 months ago ProgressPill.js 3 months ago ScreenshotDialog.js 3 months ago SetupCompleteCard.js 3 months ago StepItem.js 1 week ago useLearnProgress.js 3 months ago
ChapterCard.js
95 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 <div className="flex items-start gap-1.5">
33 <h3 className="m-0 text-base font-semibold text-text-primary">
34 { chapter.title }
35 </h3>
36 { chapter.isNew && (
37 <span className="mt-0.5 shrink-0 rounded-full bg-brand-primary-600 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-white">
38 { __( 'New', 'presto-player' ) }
39 </span>
40 ) }
41 </div>
42 { chapter.description && (
43 <p className="m-0 mt-1 text-sm text-text-secondary leading-relaxed">
44 { chapter.description }
45 </p>
46 ) }
47 </div>
48
49 <div className="shrink-0 flex items-center gap-3 pt-1">
50 { chapter.docsUrl && (
51 <span
52 role="button"
53 tabIndex={ 0 }
54 onClick={ handleDocsClick }
55 onKeyDown={ ( e ) => {
56 if ( e.key === 'Enter' || e.key === ' ' ) {
57 handleDocsClick( e );
58 }
59 } }
60 className="inline-flex items-center gap-1 text-xs font-medium text-brand-primary-600 hover:text-brand-hover-700 cursor-pointer"
61 >
62 { __( 'Learn how', 'presto-player' ) }
63 <ArrowUpRight className="w-3.5 h-3.5" />
64 </span>
65 ) }
66
67 <ProgressPill completed={ completedSteps } total={ totalSteps } />
68
69 { open ? (
70 <ChevronUp className="w-5 h-5 text-text-secondary" />
71 ) : (
72 <ChevronDown className="w-5 h-5 text-text-secondary" />
73 ) }
74 </div>
75 </button>
76
77 { /* Steps */ }
78 { open && (
79 <div className="border-0 border-t border-solid border-border-subtle p-4 flex flex-col gap-3 bg-background-secondary/20">
80 { chapter.steps?.map( ( step ) => (
81 <StepItem
82 key={ step.id }
83 chapterId={ chapter.id }
84 step={ step }
85 onToggle={ onStepToggle }
86 />
87 ) ) }
88 </div>
89 ) }
90 </div>
91 );
92 };
93
94 export default ChapterCard;
95