Skip to content

Commit

Permalink
Merge branch 'fix/navigation-on-stepper' of github.com:Automattic/wp-…
Browse files Browse the repository at this point in the history
…calypso into fix/navigation-on-stepper
  • Loading branch information
alshakero committed Dec 10, 2024
2 parents 4638710 + e5fe5d4 commit 8eb5f65
Show file tree
Hide file tree
Showing 115 changed files with 1,253 additions and 1,352 deletions.
Original file line number Diff line number Diff line change
@@ -1,95 +1,112 @@
import page from '@automattic/calypso-router';
import { addQueryArgs } from '@wordpress/url';
import { removeQueryArgs } from '@wordpress/url';
import { useTranslate } from 'i18n-calypso';
import { useCallback, useMemo } from 'react';
import { useCallback, useMemo, useState } from 'react';
import useUrlQueryParam from 'calypso/a8c-for-agencies/hooks/use-url-query-param';
import { useDispatch, useSelector } from 'calypso/state';
import { recordTracksEvent } from 'calypso/state/analytics/actions';
import { savePreference } from 'calypso/state/preferences/actions';
import { getPreference } from '../../../../state/preferences/selectors';
import { Props as A4AFeedbackProps } from '../index';
import { getA4AfeedbackProps } from '../lib/get-a4a-feedback-props';
import { FeedbackQueryData, FeedbackType } from '../types';
import type { Props as A4AFeedbackProps } from '../index';
import type { FeedbackQueryData, FeedbackType, FeedbackProps } from '../types';

const FEEDBACK_URL_HASH_FRAGMENT = '#feedback';
const FEEDBACK_SENT_PREFERENCE_PREFIX = 'a4a-feedback-sent__';
const FEEDBACK_PREFERENCE = 'a4a-feedback';

const redirectToDefaultUrl = ( redirectArgs: Record< string, string > ) => {
const currentUrl = new URL( window.location.href );
currentUrl.hash = '';
currentUrl.search = '';
page.redirect( addQueryArgs( currentUrl.toString(), redirectArgs ) );
const redirectToDefaultUrl = ( redirectUrl?: string ) => {
if ( redirectUrl ) {
page.redirect( redirectUrl );
return;
}
page.redirect( removeQueryArgs( window.location.pathname + window.location.search, 'args' ) );
};

const getUpdatedPreference = (
feedbackTimestamp: Record< string, Record< string, number > > | undefined,
type: FeedbackType,
paramType: string
) => {
return {
...( feedbackTimestamp ?? {} ),
[ type ]: {
...feedbackTimestamp?.[ type ],
[ paramType ]: Date.now(),
},
};
};

const useShowFeedbackModal = ( type: FeedbackType ) => {
const useShowFeedback = ( type: FeedbackType ) => {
const translate = useTranslate();
const dispatch = useDispatch();

const [ feedbackInteracted, setFeedbackInteracted ] = useState( false );

// Let's use hash #feedback if we want to show the feedback
const feedbackFormHash = window.location.hash === FEEDBACK_URL_HASH_FRAGMENT;

// Additional args, like email for invite flow
const urlParams = new URLSearchParams( window.location.search );
const args = JSON.parse( urlParams.get( 'args' ) ?? '{}' );
const redirectArgs = JSON.parse( urlParams.get( 'redirectArgs' ) ?? '{}' );

// Preference name, eg a4a-feedback-sent__referral-complete
const preference = FEEDBACK_SENT_PREFERENCE_PREFIX + type;
const { value: args } = useUrlQueryParam( 'args' );

// We are storing the timestamp when last feedback for given preference was sent
const feedbackTimestamp = useSelector( ( state ) => getPreference( state, preference ) );
// We are storing the timestamp when last feedback for given preference was submitted or skipped
const feedbackTimestamp = useSelector( ( state ) => getPreference( state, FEEDBACK_PREFERENCE ) );

const feedbackSubmitTimestamp = feedbackTimestamp?.submitted;
const feedbackSkipTimestamp = feedbackTimestamp?.skipped;
const feedbackSubmitTimestamp = feedbackTimestamp?.[ type ]?.lastSubmittedAt;
const feedbackSkipTimestamp = feedbackTimestamp?.[ type ]?.lastSkippedAt;

// Checking if hash for feedback is present in the url and if it was more than 7 days ago since last feedback was sent
// Checking if the feedback was submitted or skipped
const showFeedback = useMemo( () => {
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
return (
feedbackFormHash &&
( ! feedbackSubmitTimestamp ||
feedbackSubmitTimestamp < sevenDaysAgo ||
! feedbackSkipTimestamp ||
feedbackSkipTimestamp < sevenDaysAgo )
);
}, [ feedbackFormHash, feedbackSubmitTimestamp, feedbackSkipTimestamp ] );
return ! feedbackSubmitTimestamp && ! feedbackSkipTimestamp;
}, [ feedbackSubmitTimestamp, feedbackSkipTimestamp ] );

const feedbackProps: FeedbackProps = useMemo(
() => getA4AfeedbackProps( type, translate, args ),
[ type, translate, args ]
);

// Do the action when submitting feedback
const onSubmitFeedback = useCallback(
( data: FeedbackQueryData ) => {
dispatch( savePreference( preference, { submitted: Date.now() } ) );
dispatch( recordTracksEvent( 'calypso_a4a_feedback_submit', { type } ) );
if ( data ) {
// TODO: Send feedback data to the backend
}
redirectToDefaultUrl( redirectArgs );
setFeedbackInteracted( true );
const updatedPreference = getUpdatedPreference( feedbackTimestamp, type, 'lastSubmittedAt' );
dispatch( savePreference( FEEDBACK_PREFERENCE, updatedPreference ) );
},
[ dispatch, preference, redirectArgs ]
[ dispatch, feedbackTimestamp, type ]
);

// Do action when skipping feedback
const onSkipFeedback = useCallback( () => {
dispatch( savePreference( preference, { skipped: Date.now() } ) );
redirectToDefaultUrl( redirectArgs );
}, [ dispatch, preference, redirectArgs ] );
dispatch( recordTracksEvent( 'calypso_a4a_feedback_skip', { type } ) );
const updatedPreference = getUpdatedPreference( feedbackTimestamp, type, 'lastSkippedAt' );
setFeedbackInteracted( true );
dispatch( savePreference( FEEDBACK_PREFERENCE, updatedPreference ) );
}, [ dispatch, feedbackTimestamp, type ] );

// Combine props passed to Feedback component
const feedbackProps: A4AFeedbackProps = useMemo(
const updatedFeedbackProps: A4AFeedbackProps = useMemo(
() => ( {
...getA4AfeedbackProps( type, translate, args ),
...feedbackProps,
onSubmit: onSubmitFeedback,
onSkip: onSkipFeedback,
} ),
[ type, onSubmitFeedback, onSkipFeedback, args, translate ]
[ feedbackProps, onSubmitFeedback, onSkipFeedback ]
);

// Some pages have banners and require url params
// we need to find an elegant way to pass these.
if ( feedbackFormHash && ! showFeedback ) {
redirectToDefaultUrl( redirectArgs );
// If the feedback form hash is present but we don't want to show the feedback form, redirect to the default URL
// If feedback was interacted, redirect to the URL passed in the feedbackProps
redirectToDefaultUrl( feedbackInteracted ? feedbackProps.redirectUrl : undefined );
}

return {
showFeedback,
feedbackProps,
isFeedbackShown: ! showFeedback,
showFeedback: feedbackFormHash && showFeedback,
feedbackProps: updatedFeedbackProps,
};
};

export default useShowFeedbackModal;
export default useShowFeedback;
6 changes: 6 additions & 0 deletions client/a8c-for-agencies/components/a4a-feedback/icons/bad.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 3 additions & 7 deletions client/a8c-for-agencies/components/a4a-feedback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@ import IconGood from 'calypso/assets/images/a8c-for-agencies/feedback/good.svg';
import IconNeutral from 'calypso/assets/images/a8c-for-agencies/feedback/neutral.svg';
import FormFieldset from 'calypso/components/forms/form-fieldset';
import FormTextarea from 'calypso/components/forms/form-textarea';
import { FeedbackQueryData } from './types';
import type { FeedbackQueryData, FeedbackProps } from './types';

import './style.scss';

export type Props = {
title: string;
description: string;
questionDetails: string;
ctaText: string;
export interface Props extends FeedbackProps {
onSubmit: ( data: FeedbackQueryData ) => void;
onSkip: () => void;
};
}

export function A4AFeedback( {
title,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { FeedbackType } from '../types';

type A4AfeedbackProps = {
title: string;
description: string;
questionDetails: string;
ctaText: string;
};
import { TAB_INVITED_MEMBERS } from 'calypso/a8c-for-agencies/sections/team/constants';
import { A4A_TEAM_LINK, A4A_PARTNER_DIRECTORY_LINK } from '../../sidebar-menu/lib/constants';
import type { FeedbackProps, FeedbackType } from '../types';

export const getA4AfeedbackProps = (
type: FeedbackType,
translate: ( key: string, args?: Record< string, unknown > ) => string,
args?: Record< string, unknown >
): A4AfeedbackProps => {
): FeedbackProps => {
switch ( type ) {
case 'referral-complete':
return {
Expand All @@ -31,6 +26,7 @@ export const getA4AfeedbackProps = (
),
questionDetails: translate( "How was your experience adding your agency's details?" ),
ctaText: translate( 'Submit and continue to Partner Directory' ),
redirectUrl: A4A_PARTNER_DIRECTORY_LINK,
};
case 'member-invite-sent':
return {
Expand All @@ -41,6 +37,7 @@ export const getA4AfeedbackProps = (
) as string,
questionDetails: translate( 'How was your experience inviting a team member?' ),
ctaText: translate( 'Submit and continue to Team' ),
redirectUrl: `${ A4A_TEAM_LINK }/${ TAB_INVITED_MEMBERS }`,
};
default:
return {
Expand Down
8 changes: 8 additions & 0 deletions client/a8c-for-agencies/components/a4a-feedback/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,11 @@ export type FeedbackQueryData = {
experience: string;
comments: string;
};

export type FeedbackProps = {
title: string;
description: string;
questionDetails: string;
ctaText: string;
redirectUrl?: string;
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import clsx from 'clsx';
import emailValidator from 'email-validator';
import { useTranslate } from 'i18n-calypso';
import { ChangeEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import useShowFeedback from 'calypso/a8c-for-agencies/components/a4a-feedback/hooks/use-show-a4a-feedback';
import { A4A_REFERRALS_DASHBOARD } from 'calypso/a8c-for-agencies/components/sidebar-menu/lib/constants';
import { REFERRAL_EMAIL_QUERY_PARAM_KEY } from 'calypso/a8c-for-agencies/constants';
import FormFieldset from 'calypso/components/forms/form-fieldset';
Expand Down Expand Up @@ -144,24 +145,24 @@ function RequestClientPayment( { checkoutItems }: Props ) {
translate,
] );

const { isFeedbackShown } = useShowFeedback( 'referral-complete' );
const isProductFeedbackEnabled = isEnabled( 'a4a-product-feedback' );

useEffect( () => {
if ( isSuccess && !! email ) {
sessionStorage.setItem( MARKETPLACE_TYPE_SESSION_STORAGE_KEY, MARKETPLACE_TYPE_REGULAR );
page.redirect(
isProductFeedbackEnabled
isProductFeedbackEnabled && ! isFeedbackShown
? addQueryArgs( A4A_REFERRALS_DASHBOARD, {
args: { email },
redirectArgs: { [ REFERRAL_EMAIL_QUERY_PARAM_KEY ]: email },
} ) + '#feedback'
: addQueryArgs( A4A_REFERRALS_DASHBOARD, { [ REFERRAL_EMAIL_QUERY_PARAM_KEY ]: email } )
);
setEmail( '' );
setMessage( '' );
onClearCart();
}
}, [ email, isProductFeedbackEnabled, isSuccess, onClearCart ] );
}, [ email, isProductFeedbackEnabled, isSuccess, onClearCart, isFeedbackShown ] );

return (
<>
Expand Down
Loading

0 comments on commit 8eb5f65

Please sign in to comment.