Skip to content

Commit

Permalink
Merge pull request #3050 from woocommerce/PCP-4124-dynamic-logic-for-…
Browse files Browse the repository at this point in the history
…things-to-do-next-ver3

Settings UI: Add Things To Do enhancements (4124)
  • Loading branch information
Dinamiko authored Feb 4, 2025
2 parents d6fa196 + 05c7330 commit eacfee9
Show file tree
Hide file tree
Showing 27 changed files with 1,077 additions and 354 deletions.
1 change: 0 additions & 1 deletion modules/ppcp-applepay/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,5 +308,4 @@ static function( ContainerInterface $container ): AppleProductStatus {
$container->get( 'woocommerce.logger.woocommerce' )
);
},

);
111 changes: 92 additions & 19 deletions modules/ppcp-settings/resources/css/components/screens/_settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,44 @@
}

// Todo List and Feature Items
.ppcp-r-todo-items {
display: flex;
flex-direction: column;
}

.ppcp-r-todo-item {
position: relative;
display: flex;
align-items: center;
gap: 18px;
width: 100%;
border-bottom: 1px solid $color-gray-300;
padding-bottom: 16px;
padding-top: 16px;
opacity: 1;
transform: translateY(0);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

&:first-child, &.is-dismissing:first-child + .ppcp-r-todo-item {
padding-top: 0;
}

&:last-child,
&:not(.is-dismissing):has(+ .is-dismissing:last-child) {
border-bottom: none;
padding-bottom: 0;
}

&.is-dismissing {
opacity: 0;
transform: translateY(-4px);
height: 0;
margin: 0;
padding: 0;
border: 0;

.ppcp-r-todo-item__inner {
height: 0;
padding: 0;
margin: 0;
}
}

&:hover {
cursor: pointer;
Expand All @@ -32,15 +64,6 @@
}
}

&:not(:last-child) {
border-bottom: 1px solid $color-gray-400;
padding-bottom: 16px;
}

&:not(:first-child) {
padding-top: 16px;
}

&.is-completed {
.ppcp-r-todo-item__icon {
border-style: solid;
Expand Down Expand Up @@ -68,17 +91,46 @@

&__inner {
position: relative;
height: auto;
overflow: hidden;
display: flex;
align-items: center;
gap: 18px;
}

&__close {
margin-left: auto;
width: 100%;
padding-right: 36px;
transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

&__dismiss {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
background-color: transparent;
border: none;
padding: 4px;
cursor: pointer;
color: $color-gray-400;
border-radius: 50%;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
opacity: 1;

&:hover {
cursor: pointer;
color: $color-blueberry;
background-color: $color-gray-100;
color: $color-gray-700;
}

.dashicons {
font-size: 14px;
width: 14px;
height: 14px;
display: flex;
align-items: center;
justify-content: center;
}
}

Expand All @@ -104,6 +156,7 @@
border-radius: 50%;
width: 24px;
height: 24px;
flex-shrink: 0;
}
}

Expand Down Expand Up @@ -180,3 +233,23 @@
gap: 48px;
}

.ppcp-highlight {
animation: ppcp-highlight-fade 2s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid $color-blueberry;
border-radius: var(--container-border-radius);
position: relative;
z-index: 1;
}

@keyframes ppcp-highlight-fade {
0%, 20% {
background-color: rgba($color-blueberry, 0.08);
border-color: $color-blueberry;
border-width: 1px;
}
100% {
background-color: transparent;
border-color: $color-gray-300;
border-width: 1px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import classNames from 'classnames';
import { Description, Header, Title, TitleExtra, Content } from './Elements';

const SettingsBlock = ( {
id,
className,
children,
title,
Expand All @@ -15,14 +16,18 @@ const SettingsBlock = ( {
'ppcp--horizontal': horizontalLayout,
} );

const props = {
className: blockClassName,
...( id && { id } ),
};

return (
<div className={ blockClassName } id={ className }>
<div { ...props }>
<BlockTitle
blockTitle={ title }
blockSuffix={ titleSuffix }
blockDescription={ description }
/>

<Content asCard={ false }>{ children }</Content>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ToggleControl, Icon, Button } from '@wordpress/components';
import { cog } from '@wordpress/icons';
import { useEffect } from '@wordpress/element';
import { useActiveHighlight } from '../../../data/common/hooks';

import SettingsBlock from '../SettingsBlock';
import PaymentMethodIcon from '../PaymentMethodIcon';
Expand All @@ -10,8 +12,28 @@ const PaymentMethodItemBlock = ( {
onSelect,
isSelected,
} ) => {
const { activeHighlight, setActiveHighlight } = useActiveHighlight();
const isHighlighted = activeHighlight === paymentMethod.id;

// Reset the active highlight after 2 seconds
useEffect( () => {
if ( isHighlighted ) {
const timer = setTimeout( () => {
setActiveHighlight( null );
}, 2000 );

return () => clearTimeout( timer );
}
}, [ isHighlighted, setActiveHighlight ] );

return (
<SettingsBlock className="ppcp--method-item" separatorAndGap={ false }>
<SettingsBlock
id={ paymentMethod.id }
className={ `ppcp--method-item ${
isHighlighted ? 'ppcp-highlight' : ''
}` }
separatorAndGap={ false }
>
<div className="ppcp--method-inner">
<div className="ppcp--method-title-wrapper">
{ paymentMethod?.icon && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,64 @@
import { selectTab, TAB_IDS } from '../../../utils/tabSelector';
import { useEffect, useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { STORE_NAME as TODOS_STORE_NAME } from '../../../data/todos';

const TodoSettingsBlock = ( {
todosData,
className = '',
setActiveModal,
setActiveHighlight,
onDismissTodo,
} ) => {
const [ dismissingIds, setDismissingIds ] = useState( new Set() );
const { completedTodos, dismissedTodos } = useSelect(
( select ) => ( {
completedTodos:
select( TODOS_STORE_NAME ).getCompletedTodos() || [],
dismissedTodos:
select( TODOS_STORE_NAME ).getDismissedTodos() || [],
} ),
[]
);

useEffect( () => {
if ( dismissedTodos.length === 0 ) {
setDismissingIds( new Set() );
}
}, [ dismissedTodos ] );

const TodoSettingsBlock = ( { todosData, className = '' } ) => {
if ( todosData.length === 0 ) {
return null;
}

const handleDismiss = ( todoId, e ) => {
e.preventDefault();
e.stopPropagation();
setDismissingIds( ( prev ) => new Set( [ ...prev, todoId ] ) );

setTimeout( () => {
onDismissTodo( todoId );
}, 300 );
};

// Filter out dismissed todos for display
const visibleTodos = todosData.filter(
( todo ) => ! dismissedTodos.includes( todo.id )
);

return (
<div
className={ `ppcp-r-settings-block__todo ppcp-r-todo-items ${ className }` }
>
{ todosData.slice( 0, 5 ).map( ( todo ) => (
{ visibleTodos.map( ( todo ) => (
<TodoItem
key={ todo.id }
id={ todo.id }
title={ todo.title }
description={ todo.description }
isCompleted={ todo.isCompleted }
isCompleted={ completedTodos.includes( todo.id ) }
isDismissing={ dismissingIds.has( todo.id ) }
onDismiss={ ( e ) => handleDismiss( todo.id, e ) }
onClick={ async () => {
if ( todo.action.type === 'tab' ) {
const tabId =
Expand All @@ -23,19 +67,33 @@ const TodoSettingsBlock = ( { todosData, className = '' } ) => {
} else if ( todo.action.type === 'external' ) {
window.open( todo.action.url, '_blank' );
}

if ( todo.action.modal ) {
setActiveModal( todo.action.modal );
}
if ( todo.action.highlight ) {
setActiveHighlight( todo.action.highlight );
}
} }
/>
) ) }
</div>
);
};

const TodoItem = ( { title, description, isCompleted, onClick } ) => {
const TodoItem = ( {
title,
description,
isCompleted,
isDismissing,
onClick,
onDismiss,
} ) => {
return (
<div
className={ `ppcp-r-todo-item ${
isCompleted ? 'is-completed' : ''
}` }
} ${ isDismissing ? 'is-dismissing' : '' }` }
onClick={ onClick }
>
<div className="ppcp-r-todo-item__inner">
Expand All @@ -54,6 +112,13 @@ const TodoItem = ( { title, description, isCompleted, onClick } ) => {
</div>
) }
</div>
<button
className="ppcp-r-todo-item__dismiss"
onClick={ onDismiss }
aria-label="Dismiss todo item"
>
<span className="dashicons dashicons-no-alt"></span>
</button>
</div>
</div>
);
Expand Down
Loading

0 comments on commit eacfee9

Please sign in to comment.