/** * External dependencies */ import { __, _n, sprintf } from '@wordpress/i18n'; import { useEffect, useRef, useState } from '@wordpress/element'; import { Button, Card, CardHeader } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import { EllipsisMenu, Badge } from '@woocommerce/components'; import { updateQueryString } from '@woocommerce/navigation'; import { OPTIONS_STORE_NAME, ONBOARDING_STORE_NAME } from '@woocommerce/data'; import { recordEvent } from '@woocommerce/tracks'; import { Text, List, CollapsibleList, TaskItem, } from '@woocommerce/experimental'; /** * Internal dependencies */ import './task-list.scss'; const DAY_IN_MS = 24 * 60 * 60 * 1000; export const TaskList = ( { query, name, eventName, isComplete, dismissedTasks, remindMeLaterTasks, tasks, trackedCompletedTasks: totalTrackedCompletedTasks, title: listTitle, collapsible = false, onComplete, onHide, expandingItems = false, } ) => { const { createNotice } = useDispatch( 'core/notices' ); const { updateOptions } = useDispatch( OPTIONS_STORE_NAME ); const { profileItems } = useSelect( ( select ) => { const { getProfileItems } = select( ONBOARDING_STORE_NAME ); return { profileItems: getProfileItems(), }; } ); const prevQueryRef = useRef( query ); useEffect( () => { recordTaskListView(); }, [] ); useEffect( () => { const { task: prevTask } = prevQueryRef.current; const { task } = query; if ( prevTask !== task ) { window.document.documentElement.scrollTop = 0; prevQueryRef.current = query; } possiblyCompleteTaskList(); possiblyTrackCompletedTasks(); }, [ query ] ); const nowTimestamp = Date.now(); const visibleTasks = tasks.filter( ( task ) => task.visible && ! dismissedTasks.includes( task.key ) && ( ! remindMeLaterTasks[ task.key ] || remindMeLaterTasks[ task.key ] < nowTimestamp ) ); const completedTaskKeys = visibleTasks .filter( ( task ) => task.completed ) .map( ( task ) => task.key ); const incompleteTasks = tasks.filter( ( task ) => task.visible && ! task.completed && ! dismissedTasks.includes( task.key ) ); const [ currentTask, setCurrentTask ] = useState( incompleteTasks[ 0 ]?.key ); const possiblyCompleteTaskList = () => { const taskListVariableName = `woocommerce_${ name }_complete`; const taskListToComplete = isComplete ? { [ taskListVariableName ]: 'no' } : { [ taskListVariableName ]: 'yes' }; if ( ( ! incompleteTasks.length && ! isComplete ) || ( incompleteTasks.length && isComplete ) ) { updateOptions( { ...taskListToComplete, } ); if ( typeof onComplete === 'function' ) { onComplete(); } } }; const getTrackedIncompletedTasks = ( partialCompletedTasks, allTrackedTask ) => { return visibleTasks .filter( ( task ) => allTrackedTask.includes( task.key ) && ! partialCompletedTasks.includes( task.key ) ) .map( ( task ) => task.key ); }; const possiblyTrackCompletedTasks = () => { const trackedCompletedTasks = getTrackedCompletedTasks( completedTaskKeys, totalTrackedCompletedTasks ); const trackedIncompleteTasks = getTrackedIncompletedTasks( trackedCompletedTasks, totalTrackedCompletedTasks ); if ( shouldUpdateCompletedTasks( trackedCompletedTasks, trackedIncompleteTasks, completedTaskKeys ) ) { updateOptions( { woocommerce_task_list_tracked_completed_tasks: getTasksForUpdate( completedTaskKeys, totalTrackedCompletedTasks, trackedIncompleteTasks ), } ); } }; const dismissTask = ( { key, onDismiss } ) => { createNotice( 'success', __( 'Task dismissed' ), { actions: [ { label: __( 'Undo', 'woocommerce-admin' ), onClick: () => undoDismissTask( key ), }, ], } ); recordEvent( `${ eventName }_dismiss_task`, { task_name: key } ); updateOptions( { woocommerce_task_list_dismissed_tasks: [ ...dismissedTasks, key ], } ); if ( onDismiss ) { onDismiss(); } }; const undoDismissTask = ( key ) => { const updatedDismissedTasks = dismissedTasks.filter( ( task ) => task !== key ); updateOptions( { woocommerce_task_list_dismissed_tasks: updatedDismissedTasks, } ); recordEvent( `${ eventName }_undo_dismiss_task`, { task_name: key, } ); }; const remindTaskLater = ( { key, onDismiss } ) => { createNotice( 'success', __( 'Task postponed until tomorrow', 'woocommerce-admin' ), { actions: [ { label: __( 'Undo', 'woocommerce-admin' ), onClick: () => undoRemindTaskLater( key ), }, ], } ); recordEvent( `${ eventName }_remindmelater_task`, { task_name: key, } ); const dismissTime = Date.now() + DAY_IN_MS; updateOptions( { woocommerce_task_list_remind_me_later_tasks: { ...remindMeLaterTasks, [ key ]: dismissTime, }, } ); if ( onDismiss ) { onDismiss(); } }; const undoRemindTaskLater = ( key ) => { const { // eslint-disable-next-line no-unused-vars [ key ]: oldValue, ...updatedRemindMeLaterTasks } = remindMeLaterTasks; updateOptions( { woocommerce_task_list_remind_me_later_tasks: updatedRemindMeLaterTasks, } ); recordEvent( `${ eventName }_undo_remindmelater_task`, { task_name: key, } ); }; const recordTaskListView = () => { if ( query.task ) { return; } recordEvent( `${ eventName }_view`, { number_tasks: visibleTasks.length, store_connected: profileItems.wccom_connected, } ); }; const hideTaskCard = ( action ) => { const updateOptionsParams = { [ `woocommerce_${ name }_hidden` ]: 'yes', }; recordEvent( `${ eventName }_completed`, { action, completed_task_count: completedTaskKeys.length, incomplete_task_count: incompleteTasks.length, } ); updateOptions( { ...updateOptionsParams, } ); if ( typeof onHide === 'function' ) { onHide(); } }; const renderMenu = () => { return (