@shopgate/engage
Version:
Shopgate's ENGAGE library.
153 lines (150 loc) • 4.67 kB
JavaScript
import React, { useEffect, useState, useMemo, useCallback, useRef } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { css } from 'glamor';
import { getCommentDialogSettings } from '@shopgate/pwa-common-commerce/favorites/selectors';
import { i18n, usePrevious } from '@shopgate/engage/core';
import { Dialog, TextField } from '@shopgate/engage/components';
import { broadcastLiveMessage } from '@shopgate/engage/a11y';
import { closeFavoritesCommentDialog } from '@shopgate/pwa-common-commerce/favorites/action-creators';
import { themeName } from '@shopgate/pwa-common/helpers/config';
import { updateFavorite } from '@shopgate/pwa-common-commerce/favorites/actions/toggleFavorites';
import I18n from '@shopgate/pwa-common/components/I18n';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const isIos = themeName.includes('ios');
/**
* @param {Object} state State.
* @returns {Object}
*/
const mapStateToProps = state => ({
settings: getCommentDialogSettings(state)
});
/**
* @param {Object} dispatch Dispatch.
* @returns {Object}
*/
const mapDispatchToProps = dispatch => ({
close: () => dispatch(closeFavoritesCommentDialog()),
updateFavoriteItem: (productId, listId, quantity, notes) => {
dispatch(updateFavorite(productId, listId, quantity, notes));
}
});
const styles = {
root: css({
display: 'flex',
flexDirection: 'column'
}),
input: css({
textAlign: 'left',
fontSize: '1rem'
}).toString(),
characterCount: css({
textAlign: 'right',
marginTop: -16,
fontSize: '0.875rem',
color: 'var(--color-text-medium-emphasis)'
}).toString()
};
const MAX_CHARACTER_COUNT = 250;
/**
* @param {Object} props Props.
* @returns {JSX}
*/
const CommentDialog = ({
settings,
close,
updateFavoriteItem
}) => {
const isVisible = !!settings;
const {
productId,
listId,
item
} = settings || {};
const prevProdId = usePrevious(productId);
const [value, setValue] = useState(item?.notes);
// Reference to the element that triggered the dialog
const triggerRef = useRef(null);
useEffect(() => {
if (prevProdId !== productId) {
setValue(item?.notes);
}
}, [item, prevProdId, productId]);
useEffect(() => {
if (isVisible) {
triggerRef.current = document.activeElement;
}
}, [isVisible]);
const handleClose = useCallback(() => {
setTimeout(() => {
if (triggerRef?.current) {
// Focus the element that triggered the dialog after dialog (a11y improvement)
triggerRef.current.focus();
}
if (!item?.notes && !!value) {
broadcastLiveMessage('favorites.comments.added');
}
if (item?.notes && value !== item.notes) {
broadcastLiveMessage('favorites.comments.updated');
}
}, 300);
close();
}, [close, item, value]);
const handleSubmit = useCallback(() => {
if (item?.notes !== value) {
updateFavoriteItem(productId, listId, undefined, value);
}
handleClose();
}, [handleClose, item, listId, productId, updateFavoriteItem, value]);
const handleChange = useCallback(newValue => {
setValue(newValue);
}, []);
const attributes = useMemo(() => ({
style: {
maxHeight: 150,
placeholder: i18n.text('favorites.comment_modal.label')
},
maxLength: MAX_CHARACTER_COUNT
}), []);
if (!isVisible) {
return null;
}
return /*#__PURE__*/_jsx(Dialog, {
onConfirm: handleSubmit,
onDismiss: handleClose,
modal: {
title: i18n.text(`favorites.comment_modal.${(item?.notes || '').length === 0 ? 'titleAdd' : 'titleEdit'}`),
dismiss: i18n.text('favorites.comment_modal.dismiss'),
confirm: i18n.text('favorites.comment_modal.confirm')
},
children: /*#__PURE__*/_jsxs("div", {
className: styles.root,
children: [/*#__PURE__*/_jsx(TextField, {
name: "name",
...(isIos ? {
placeholder: i18n.text('favorites.comment_modal.label')
} : {
label: i18n.text('favorites.comment_modal.label')
}),
onChange: handleChange,
value: value,
className: styles.input,
attributes: attributes,
multiLine: true,
tabIndex: 0
}), /*#__PURE__*/_jsx(I18n.Text, {
className: styles.characterCount,
string: "favorites.comment_modal.characterCount",
"aria-hidden": true,
params: {
maxCount: MAX_CHARACTER_COUNT,
count: value?.length || 0
}
})]
})
});
};
CommentDialog.defaultProps = {
settings: null
};
export default connect(mapStateToProps, mapDispatchToProps)(CommentDialog);