diff --git a/client/src/components/profile-my/notification-settings.component.jsx b/client/src/components/profile-my/notification-settings.component.jsx index f1a2a1e73..054092025 100644 --- a/client/src/components/profile-my/notification-settings.component.jsx +++ b/client/src/components/profile-my/notification-settings.component.jsx @@ -1,6 +1,6 @@ import { useMutation, useQuery } from "@apollo/client"; import { useEffect, useState } from "react"; -import { Button, Card, Col, Form, Row } from "antd"; +import { Button, Card, Form, Checkbox, Table } from "antd"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -8,31 +8,44 @@ import { createStructuredSelector } from "reselect"; import { selectCurrentUser } from "../../redux/user/user.selectors"; import AlertComponent from "../alert/alert.component"; import { QUERY_NOTIFICATION_SETTINGS, UPDATE_NOTIFICATION_SETTINGS } from "../../graphql/user.queries.js"; -import { notificationScenarios, notificationChannels } from "../../utils/jobNotificationScenarios.js"; +import { notificationScenarios } from "../../utils/jobNotificationScenarios.js"; import LoadingSpinner from "../loading-spinner/loading-spinner.component.jsx"; -const NotificationMethodButtonGroup = ({ value = {}, onChange }) => { +/** + * ColumnHeaderCheckbox + * + * A header checkbox for a given channel that toggles the state for all scenarios. + * + * Props: + * - channel: The notification channel (e.g. "app", "email", "fcm"). + * - form: The Ant Design form instance. + * - disabled: (Optional) If true, the checkbox will be disabled. + */ +const ColumnHeaderCheckbox = ({ channel, form, disabled = false }) => { const { t } = useTranslation(); - const toggleMethod = (method) => { - const newValue = { ...value, [method]: !value[method] }; - if (onChange) { - onChange(newValue); - } + // Watch the entire form values so that this component re-renders on changes. + const formValues = Form.useWatch([], form) || {}; + + // Use the known scenarios list to decide if every row has this channel enabled. + const allChecked = + notificationScenarios.length > 0 && notificationScenarios.every((scenario) => formValues[scenario]?.[channel]); + + const onChange = (e) => { + const checked = e.target.checked; + // Get current form values. + const currentValues = form.getFieldsValue(); + // Update each scenario for this channel. + const newValues = { ...currentValues }; + notificationScenarios.forEach((scenario) => { + newValues[scenario] = { ...newValues[scenario], [channel]: checked }; + }); + form.setFieldsValue(newValues); }; return ( - - {notificationChannels.map((method) => ( - - ))} - + + {t(`notifications.channels.${channel}`)} + ); }; @@ -91,6 +104,52 @@ function NotificationSettingsForm({ currentUser }) { if (error) return ; if (loading) return ; + const columns = [ + { + title: t("notifications.labels.scenario"), + dataIndex: "scenarioLabel", + key: "scenario", + render: (_, record) => t(`notifications.scenarios.${record.key}`), + width: "90%" + }, + { + title: , + dataIndex: "app", + key: "app", + align: "center", // Center the cell content + render: (_, record) => ( + + + + ) + }, + { + title: , + dataIndex: "email", + key: "email", + align: "center", // Center the cell content + render: (_, record) => ( + + + + ) + }, + { + title: , + dataIndex: "fcm", + key: "fcm", + align: "center", // Center the cell content + render: (_, record) => ( + + + + ) + } + ]; + + // Create dataSource from the list of scenarios. + const dataSource = notificationScenarios.map((scenario) => ({ key: scenario })); + return (
} > - - {notificationScenarios.map((scenario) => ( - - - - - - ))} - + ); diff --git a/client/src/components/profile-my/profile-my.component.jsx b/client/src/components/profile-my/profile-my.component.jsx index 7e8ce078c..24f26c6f7 100644 --- a/client/src/components/profile-my/profile-my.component.jsx +++ b/client/src/components/profile-my/profile-my.component.jsx @@ -81,10 +81,6 @@ export default connect( - - - - + + + ); }); diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index 08d38f9aa..32a93980f 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -34,7 +34,6 @@ export const QUERY_BODYSHOP = gql` authlevel useremail default_prod_list_view - notification_settings user { authid email diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index f4a3a9f2b..0479c2ece 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -3761,6 +3761,7 @@ }, "notifications": { "labels": { + "scenario": "Scenario", "notificationscenarios": "Job Notification Scenarios", "save": "Save Scenarios", "watching-issue": "Watching", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 18fde0bbc..5ea6ac409 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -3761,6 +3761,7 @@ }, "notifications": { "labels": { + "scenario": "", "notificationscenarios": "", "save": "", "watching-issue": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 5c0b4396a..8fe8fd383 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -3761,6 +3761,7 @@ }, "notifications": { "labels": { + "scenario": "", "notificationscenarios": "", "save": "", "watching-issue": "", diff --git a/client/src/utils/jobNotificationScenarios.js b/client/src/utils/jobNotificationScenarios.js index 1f5fddfab..52519977b 100644 --- a/client/src/utils/jobNotificationScenarios.js +++ b/client/src/utils/jobNotificationScenarios.js @@ -16,6 +16,4 @@ const notificationScenarios = [ "alternate-transport-changed" ]; -const notificationChannels = ["app", "email", "fcm"]; - -export { notificationScenarios, notificationChannels }; +export { notificationScenarios }; diff --git a/server/notifications/utils/scenarioMapperr.js b/server/notifications/utils/scenarioMapperr.js index 0323bbaba..38eb24b44 100644 --- a/server/notifications/utils/scenarioMapperr.js +++ b/server/notifications/utils/scenarioMapperr.js @@ -6,7 +6,12 @@ const tasksUpdatedCreatedBuilder = require("../scenarioBuilders/tasksUpdatedCreatedBuilder"); const notificationScenarios = [ - { key: "job-assigned-to-me", table: "jobs", fields: ["scheduled_in", "scheduled_completion", "scheduled_delivery"] }, + { + key: "job-assigned-to-me", + table: "jobs", + fields: ["employee_pre", "employee_body", "employee_csr", "employee_refinish"], + matchEmployee: true + }, { key: "bill-posted", table: "bills" }, { key: "new-note-added", table: "notes", onNew: true }, {