PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Assist / components / dashboard / DesktopCards.jsx

DesktopCards.jsx in Extendify 3.0.4, at src/Assist/components/dashboard/DesktopCards.jsx

139 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { CardContent } from '@assist/components/dashboard/CardContent';
2 import { CardsTitle } from '@assist/components/dashboard/CardsTitle';
3 import { useTours } from '@assist/hooks/useTours';
4 import { useTasksStore } from '@assist/state/tasks';
5 import { Bullet, Check } from '@assist/svg';
6 import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '@headlessui/react';
7 import {
8 forwardRef,
9 useCallback,
10 useEffect,
11 useRef,
12 useState,
13 } from '@wordpress/element';
14 import { Icon } from '@wordpress/icons';
15 import classNames from 'classnames';
16
17 export const DesktopCards = ({ className, tasks, totalCompleted }) => {
18 const { isCompleted } = useTasksStore();
19 const { finishedTour } = useTours();
20 const [nextTask, setNextTask] = useState(-1);
21 const tabRefs = useRef([]);
22
23 const findNextTask = useCallback(
24 (currentIndex = 0) => {
25 // Re sort based on current index
26 const sortedTasks = tasks
27 .slice(currentIndex)
28 .concat(tasks.slice(0, currentIndex));
29 const next = sortedTasks.findIndex(({ slug }) => !isCompleted(slug));
30 // Find the index of the next incomplete task from the original list
31 return tasks.findIndex(({ slug }) => slug === sortedTasks?.[next]?.slug);
32 },
33 [tasks, isCompleted],
34 );
35
36 useEffect(() => {
37 if (totalCompleted === tasks.length || totalCompleted === 0) return;
38 setNextTask((prev) => findNextTask(prev + 1));
39 }, [tasks?.length, totalCompleted, findNextTask]);
40
41 useEffect(() => {
42 tabRefs.current?.[nextTask]?.scrollIntoView({
43 behavior: 'smooth',
44 block: 'nearest',
45 inline: 'start',
46 });
47 }, [nextTask]);
48
49 return (
50 <div
51 data-test="assist-tasks-module"
52 id="assist-tasks-module"
53 className={classNames(
54 className,
55 'mb-6 h-full w-full rounded-sm border border-gray-300 bg-white text-base',
56 )}
57 >
58 {tasks && (
59 <TabGroup
60 defaultIndex={nextTask}
61 selectedIndex={nextTask}
62 onChange={setNextTask}
63 vertical
64 as="div"
65 className="flex h-[472px] min-h-96 grow flex-row-reverse justify-between rtl:flex-row"
66 >
67 <TabList
68 as="div"
69 className="w-96 overflow-auto border-l border-gray-100"
70 >
71 <CardsTitle totalCompleted={totalCompleted} total={tasks.length} />
72
73 {tasks.map((task, index) => (
74 <TabItem
75 key={task.slug}
76 ref={(el) => {
77 tabRefs.current[index] = el;
78 }}
79 task={task}
80 isCompleted={
81 task.type === 'tour'
82 ? finishedTour(task.slug) || isCompleted(task.slug)
83 : isCompleted(task.slug)
84 }
85 />
86 ))}
87 </TabList>
88
89 <TabPanels as="div" className="w-3/4">
90 {tasks.map((task) => (
91 <TabPanel
92 key={task.slug}
93 as="div"
94 data-test="assist-task-card-wrapper"
95 className="h-full"
96 >
97 <CardContent task={task} />
98 </TabPanel>
99 ))}
100 </TabPanels>
101 </TabGroup>
102 )}
103 </div>
104 );
105 };
106
107 const TabItem = forwardRef(({ task, isCompleted }, ref) => (
108 <Tab as="div" data-test={`assist-task-${task.slug}`}>
109 {({ selected }) => (
110 <div
111 ref={ref}
112 className={classNames(
113 'group flex w-full items-center justify-between border-b border-gray-300 py-4 pl-2 pr-4 text-sm hover:cursor-pointer hover:bg-gray-100',
114 {
115 'bg-gray-100 font-semibold': selected,
116 },
117 )}
118 >
119 <div className="flex w-full items-center">
120 <Icon
121 icon={isCompleted ? Check : Bullet}
122 size={12}
123 data-test={
124 isCompleted ? 'completed-task-icon' : 'uncompleted-task-icon'
125 }
126 className={classNames('mx-2 flex-shrink-0', {
127 'stroke-current text-design-main':
128 (isCompleted && selected) || (isCompleted && !selected),
129 'fill-current text-design-main': selected && !isCompleted,
130 'text-center text-gray-400': !isCompleted && !selected,
131 })}
132 />
133 <span>{task?.sidebarTitle ?? task.title}</span>
134 </div>
135 </div>
136 )}
137 </Tab>
138 ));
139