feat: implented notification preference UI for cadence (#1013)
* feat: implented notification preference UI for cadence * refactor: refactored code * refactor: refactored code * refactor: clean code after adding email cadence * refactor: refactored and restructured notificationPreferences page * refactor: refactored and implemented mobile view --------- Co-authored-by: Awais Ansari <awais.ansari63@gmail.com>
This commit is contained in:
124
src/notification-preferences/NotificationPreferenceColumn.jsx
Normal file
124
src/notification-preferences/NotificationPreferenceColumn.jsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { NavItem } from '@openedx/paragon';
|
||||
import messages from './messages';
|
||||
import ToggleSwitch from './ToggleSwitch';
|
||||
import {
|
||||
selectNonEditablePreferences,
|
||||
selectSelectedCourseId,
|
||||
selectUpdatePreferencesStatus,
|
||||
selectPreferencesOfApp,
|
||||
} from './data/selectors';
|
||||
import { updatePreferenceToggle, updateChannelPreferenceToggle } from './data/thunks';
|
||||
import { LOADING_STATUS } from '../constants';
|
||||
import EmailCadences from './EmailCadences';
|
||||
import { useIsOnMobile } from '../hooks';
|
||||
|
||||
const NotificationPreferenceColumn = ({ appId, channel, appPreference }) => {
|
||||
const dispatch = useDispatch();
|
||||
const intl = useIntl();
|
||||
const courseId = useSelector(selectSelectedCourseId());
|
||||
const appPreferences = useSelector(selectPreferencesOfApp(appId));
|
||||
const nonEditable = useSelector(selectNonEditablePreferences(appId));
|
||||
const updatePreferencesStatus = useSelector(selectUpdatePreferencesStatus());
|
||||
const mobileView = useIsOnMobile();
|
||||
|
||||
const onChannelToggle = useCallback((event) => {
|
||||
const { id: notificationChannel } = event.target;
|
||||
const isPreferenceNonEditable = (preference) => nonEditable?.[preference.id]?.includes(notificationChannel);
|
||||
|
||||
const hasActivePreferences = appPreferences.some(
|
||||
(preference) => preference[notificationChannel] && !isPreferenceNonEditable(preference),
|
||||
);
|
||||
|
||||
dispatch(updateChannelPreferenceToggle(courseId, appId, notificationChannel, !hasActivePreferences));
|
||||
}, [appId, appPreferences, courseId, dispatch, nonEditable]);
|
||||
|
||||
const onToggle = useCallback((event, notificationType) => {
|
||||
const { name: notificationChannel } = event.target;
|
||||
const value = notificationChannel === 'email_cadence' ? event.target.innerText : event.target.checked;
|
||||
|
||||
dispatch(updatePreferenceToggle(
|
||||
courseId,
|
||||
appId,
|
||||
notificationType,
|
||||
notificationChannel,
|
||||
value,
|
||||
));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appId]);
|
||||
|
||||
const renderPreference = (preference) => (
|
||||
<div
|
||||
key={`${preference.id}-${channel}`}
|
||||
id={`${preference.id}-${channel}`}
|
||||
className={classNames(
|
||||
'd-flex align-items-center justify-content-center mb-2 h-4.5 column-padding',
|
||||
{
|
||||
'pr-0': channel === 'email',
|
||||
'pl-0': channel === 'web' && mobileView,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<ToggleSwitch
|
||||
name={channel}
|
||||
value={preference[channel]}
|
||||
onChange={(event) => onToggle(event, preference.id)}
|
||||
disabled={nonEditable?.[preference.id]?.includes(channel) || updatePreferencesStatus === LOADING_STATUS}
|
||||
id={`${preference.id}-${channel}`}
|
||||
className="my-1"
|
||||
/>
|
||||
{channel === 'email' && (
|
||||
<EmailCadences
|
||||
email={preference.email}
|
||||
onToggle={onToggle}
|
||||
emailCadence={preference.emailCadence}
|
||||
notificationType={preference.id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classNames('d-flex flex-column', { 'border-right': channel !== 'email' })}>
|
||||
<NavItem
|
||||
id={channel}
|
||||
key={channel}
|
||||
role="button"
|
||||
onClick={onChannelToggle}
|
||||
className={classNames('mb-3 header-label column-padding', {
|
||||
'pr-0': channel === 'email',
|
||||
'pl-0': channel === 'web' && mobileView,
|
||||
})}
|
||||
>
|
||||
{intl.formatMessage(messages.notificationChannel, { text: channel })}
|
||||
</NavItem>
|
||||
{appPreference
|
||||
? renderPreference(appPreference)
|
||||
: appPreferences.map((preference) => (renderPreference(preference)))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
NotificationPreferenceColumn.propTypes = {
|
||||
appId: PropTypes.string.isRequired,
|
||||
channel: PropTypes.string.isRequired,
|
||||
appPreference: PropTypes.shape({
|
||||
id: PropTypes.string,
|
||||
emailCadence: PropTypes.string,
|
||||
appId: PropTypes.string,
|
||||
info: PropTypes.string,
|
||||
email: PropTypes.bool,
|
||||
push: PropTypes.bool,
|
||||
web: PropTypes.bool,
|
||||
}),
|
||||
};
|
||||
|
||||
NotificationPreferenceColumn.defaultProps = {
|
||||
appPreference: null,
|
||||
};
|
||||
|
||||
export default React.memo(NotificationPreferenceColumn);
|
||||
Reference in New Issue
Block a user