201 lines
7.4 KiB
JavaScript
201 lines
7.4 KiB
JavaScript
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 (
|
|
<>
|
|
<Col span={24}>
|
|
<Form onFinish={handleFinish} autoComplete={"no"} initialValues={currentUser} layout="vertical">
|
|
<Card
|
|
title={t("user.labels.profileinfo")}
|
|
extra={
|
|
<Button type="primary" key="submit" htmlType="submit">
|
|
{t("user.actions.updateprofile")}
|
|
</Button>
|
|
}
|
|
>
|
|
<LayoutFormRow noDivider>
|
|
<Form.Item
|
|
label={t("user.fields.displayname")}
|
|
rules={[
|
|
{
|
|
required: true
|
|
//message: t("general.validation.required"),
|
|
}
|
|
]}
|
|
name="displayName"
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item label={t("user.fields.photourl")} name="photoURL">
|
|
<Input />
|
|
</Form.Item>
|
|
</LayoutFormRow>
|
|
</Card>
|
|
</Form>
|
|
</Col>
|
|
|
|
<Col span={24}>
|
|
<Form onFinish={handleChangePassword} autoComplete={"no"} initialValues={currentUser} layout="vertical">
|
|
<Card
|
|
title={t("user.labels.changepassword")}
|
|
extra={
|
|
<Button type="primary" key="submit" htmlType="submit">
|
|
{t("user.actions.changepassword")}
|
|
</Button>
|
|
}
|
|
>
|
|
<LayoutFormRow>
|
|
<Form.Item label={t("general.labels.newpassword")} name="password">
|
|
<Input prefix={<LockOutlined />} type="password" placeholder={t("general.labels.password")} />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label={t("general.labels.confirmpassword")}
|
|
name="password-confirm"
|
|
dependencies={["password"]}
|
|
rules={[
|
|
{
|
|
required: true
|
|
//message: t("general.validation.required"),
|
|
},
|
|
({ getFieldValue }) => ({
|
|
validator(rule, value) {
|
|
if (!value || getFieldValue("password") === value) {
|
|
return Promise.resolve();
|
|
}
|
|
return Promise.reject(t("general.labels.passwordsdonotmatch"));
|
|
}
|
|
})
|
|
]}
|
|
>
|
|
<Input prefix={<LockOutlined />} type="password" placeholder={t("general.labels.password")} />
|
|
</Form.Item>
|
|
</LayoutFormRow>
|
|
</Card>
|
|
</Form>
|
|
</Col>
|
|
|
|
{association && (
|
|
<Col span={24}>
|
|
<Card title={t("user.labels.user_settings")}>
|
|
<Space align="center" size="large">
|
|
<Typography.Text>{t("user.labels.play_sound_for_new_messages")}</Typography.Text>
|
|
<Tooltip
|
|
title={soundEnabled ? t("user.labels.notification_sound_on") : t("user.labels.notification_sound_off")}
|
|
>
|
|
<Switch
|
|
checkedChildren={<SoundOutlined />}
|
|
unCheckedChildren={<AudioMutedOutlined />}
|
|
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" });
|
|
});
|
|
}}
|
|
/>
|
|
</Tooltip>
|
|
</Space>
|
|
<Typography.Paragraph type="secondary" style={{ marginTop: 8 }}>
|
|
{t("user.labels.notification_sound_help")}
|
|
</Typography.Paragraph>
|
|
</Card>
|
|
</Col>
|
|
)}
|
|
|
|
{scenarioNotificationsOn && (
|
|
<Col span={24}>
|
|
<NotificationSettingsForm />
|
|
</Col>
|
|
)}
|
|
</>
|
|
);
|
|
});
|