import { Button, Card, Col, Form, Input, Space, Switch, Tooltip, Typography } from "antd"; import { AudioMutedOutlined, LockOutlined, SoundOutlined } from "@ant-design/icons"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { updateUserDetails } from "../../redux/user/user.actions"; import { selectCurrentUser } from "../../redux/user/user.selectors"; import { logImEXEvent, updateCurrentPassword } from "../../firebase/firebase.utils"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; import { useSocket } from "../../contexts/SocketIO/useSocket.js"; import NotificationSettingsForm from "../notification-settings/notification-settings-form.component.jsx"; import { useMutation, useQuery } from "@apollo/client"; import { QUERY_ACTIVE_ASSOCIATION_SOUND, UPDATE_NEW_MESSAGE_SOUND } from "../../graphql/user.queries.js"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ updateUserDetails: (userDetails) => dispatch(updateUserDetails(userDetails)) }); export default connect( mapStateToProps, mapDispatchToProps )(function ProfileMyComponent({ currentUser, updateUserDetails }) { const { t } = useTranslation(); const notification = useNotification(); const { scenarioNotificationsOn } = useSocket(); const handleFinish = (values) => { logImEXEvent("profile_update"); updateUserDetails({ displayName: values.displayName, photoURL: values.photoURL }); }; const handleChangePassword = async ({ password }) => { logImEXEvent("password_update"); try { await updateCurrentPassword(password); notification.success({ message: t("user.successess.passwordchanged") }); } catch (error) { notification.error({ message: error.message }); } }; // ---- Notification sound (associations.new_message_sound) ---- const email = currentUser?.email; const { data: assocData, loading: assocLoading } = useQuery(QUERY_ACTIVE_ASSOCIATION_SOUND, { variables: { email }, skip: !email, fetchPolicy: "network-only", nextFetchPolicy: "cache-first" }); const association = assocData?.associations?.[0]; // Treat null/undefined as ON for backward-compat const soundEnabled = association?.new_message_sound === true; const [updateNewMessageSound, { loading: updatingSound }] = useMutation(UPDATE_NEW_MESSAGE_SOUND, { update(cache, { data }) { const updated = data?.update_associations_by_pk; if (!updated) return; cache.modify({ id: cache.identify({ __typename: "associations", id: updated.id }), fields: { new_message_sound: () => updated.new_message_sound } }); } }); return ( <>
{t("user.actions.updateprofile")} } >
{t("user.actions.changepassword")} } > } type="password" placeholder={t("general.labels.password")} /> ({ validator(rule, value) { if (!value || getFieldValue("password") === value) { return Promise.resolve(); } return Promise.reject(t("general.labels.passwordsdonotmatch")); } }) ]} > } type="password" placeholder={t("general.labels.password")} />
{association && ( {t("user.labels.play_sound_for_new_messages")} } unCheckedChildren={} checked={!!soundEnabled} loading={assocLoading || updatingSound} onChange={(checked) => { updateNewMessageSound({ variables: { id: association.id, value: checked }, optimisticResponse: { update_associations_by_pk: { __typename: "associations", id: association.id, new_message_sound: checked } } }) .then(() => { notification.success({ message: checked ? t("user.labels.notification_sound_enabled") : t("user.labels.notification_sound_disabled") }); }) .catch((e) => { notification.error({ message: e.message || "Failed to update setting" }); }); }} /> {t("user.labels.notification_sound_help")} )} {scenarioNotificationsOn && ( )} ); });