diff --git a/client/src/Pages/Notifications/create/index.jsx b/client/src/Pages/Notifications/create/index.jsx
new file mode 100644
index 000000000..c188aca22
--- /dev/null
+++ b/client/src/Pages/Notifications/create/index.jsx
@@ -0,0 +1,324 @@
+// Components
+import Stack from "@mui/material/Stack";
+import Typography from "@mui/material/Typography";
+import Breadcrumbs from "../../../Components/Breadcrumbs";
+import Button from "@mui/material/Button";
+import ConfigBox from "../../../Components/ConfigBox";
+import Box from "@mui/material/Box";
+import Select from "../../../Components/Inputs/Select";
+import TextInput from "../../../Components/Inputs/TextInput";
+
+// Utils
+import { useState } from "react";
+import { useSelector } from "react-redux";
+import { useTheme } from "@emotion/react";
+import { useCreateNotification } from "../../../Hooks/useNotifications";
+import {
+ notificationEmailValidation,
+ notificationWebhookValidation,
+ notificationPagerDutyValidation,
+} from "../../../Validation/validation";
+import { createToast } from "../../../Utils/toastUtils";
+import { useTranslation } from "react-i18next";
+
+// Setup
+
+const NOTIFICATION_TYPES = [
+ { _id: 1, name: "E-mail", value: "email" },
+ { _id: 2, name: "Slack", value: "webhook" },
+ { _id: 3, name: "PagerDuty", value: "pager_duty" },
+];
+
+const CreateNotifications = () => {
+ const theme = useTheme();
+ const [createNotification, isLoading, error] = useCreateNotification();
+ const BREADCRUMBS = [
+ { name: "notifications", path: "/notifications" },
+ { name: "create", path: "/notifications/create" },
+ ];
+
+ // Redux state
+ const { user } = useSelector((state) => state.auth);
+
+ // local state
+ const [notification, setNotification] = useState({
+ userId: user._id,
+ teamId: user.teamId,
+ notificationName: "",
+ address: "",
+ type: NOTIFICATION_TYPES[0]._id,
+ config: {
+ webhookUrl: "",
+ platform: "",
+ routingKey: "",
+ },
+ });
+ const [errors, setErrors] = useState({});
+ const { t } = useTranslation();
+
+ // handlers
+ const onSubmit = (e) => {
+ e.preventDefault();
+ const form = {
+ ...notification,
+ type: NOTIFICATION_TYPES.find((type) => type._id === notification.type).value,
+ };
+
+ if (notification.type === 2) {
+ form.type = "webhook";
+ }
+
+ let error = null;
+
+ if (form.type === "email") {
+ error = notificationEmailValidation.validate(
+ { notificationName: form.notificationName, address: form.address },
+ { abortEarly: false }
+ ).error;
+ } else if (form.type === "webhook") {
+ form.config = {
+ platform: form.config.platform,
+ webhookUrl: form.config.webhookUrl,
+ };
+ error = notificationWebhookValidation.validate(
+ { notificationName: form.notificationName, config: form.config },
+ { abortEarly: false }
+ ).error;
+ } else if (form.type === "pager_duty") {
+ form.config = {
+ platform: form.config.platform,
+ routingKey: form.config.routingKey,
+ };
+ error = notificationPagerDutyValidation.validate(
+ { notificationName: form.notificationName, config: form.config },
+ { abortEarly: false }
+ ).error;
+ }
+
+ if (error) {
+ const newErrors = {};
+ error.details.forEach((err) => {
+ newErrors[err.path[0]] = err.message;
+ });
+ createToast({ body: "Please check the form for errors." });
+ setErrors(newErrors);
+ return;
+ }
+
+ createNotification(form);
+ };
+
+ const onChange = (e) => {
+ const { name, value } = e.target;
+
+ const newNotification = { ...notification, [name]: value };
+
+ // Handle config/platform initialization if type is webhook
+
+ if (newNotification.type === 1) {
+ newNotification.config = null;
+ } else if (newNotification.type === 2) {
+ newNotification.address = "";
+ newNotification.config = newNotification.config || {};
+ if (name === "config") {
+ newNotification.config = value;
+ }
+ newNotification.config.platform = "slack";
+ } else if (newNotification.type === 3) {
+ newNotification.config = newNotification.config || {};
+ if (name === "config") {
+ newNotification.config = value;
+ }
+ newNotification.config.platform = "pager_duty";
+ }
+
+ // Field-level validation
+ let fieldError;
+
+ if (name === "notificationName") {
+ const { error } = notificationEmailValidation.extract(name).validate(value);
+ fieldError = error?.message;
+ }
+
+ if (newNotification.type === 1 && name === "address") {
+ const { error } = notificationEmailValidation.extract(name).validate(value);
+ fieldError = error?.message;
+ }
+
+ if (newNotification.type === 2 && name === "config") {
+ // Validate only webhookUrl inside config
+ const { error } = notificationWebhookValidation.extract("config").validate(value);
+ fieldError = error?.message;
+ }
+
+ // Set field-level error
+ setErrors((prev) => ({
+ ...prev,
+ [name]: fieldError,
+ }));
+
+ setNotification(newNotification);
+ };
+
+ return (
+
+
+ {t("createNotifications.title")}
+
+
+
+
+ {t("createNotifications.nameSettings.title")}
+
+
+ {t("createNotifications.nameSettings.description")}
+
+
+
+
+
+
+
+
+
+ {t("createNotifications.typeSettings.title")}
+
+
+ {t("createNotifications.typeSettings.description")}
+
+
+
+
+
+
+ {notification.type === 1 && (
+
+
+
+ {t("createNotifications.emailSettings.title")}
+
+
+ {t("createNotifications.emailSettings.description")}
+
+
+
+
+
+
+ )}
+ {notification.type === 2 && (
+
+
+
+ {t("createNotifications.slackSettings.title")}
+
+
+ {t("createNotifications.slackSettings.description")}
+
+
+
+ {
+ const updatedConfig = {
+ ...notification.config,
+ webhookUrl: e.target.value,
+ };
+
+ onChange({
+ target: {
+ name: "config",
+ value: updatedConfig,
+ },
+ });
+ }}
+ />
+
+
+ )}
+ {notification.type === 3 && (
+
+
+
+ {t("createNotifications.pagerdutySettings.title")}
+
+
+ {t("createNotifications.pagerdutySettings.description")}
+
+
+
+ {
+ const updatedConfig = {
+ ...notification.config,
+ routingKey: e.target.value,
+ };
+
+ onChange({
+ target: {
+ name: "config",
+ value: updatedConfig,
+ },
+ });
+ }}
+ />
+
+
+ )}
+
+
+
+
+
+ );
+};
+
+export default CreateNotifications;
diff --git a/client/src/Pages/Notifications/index.jsx b/client/src/Pages/Notifications/index.jsx
new file mode 100644
index 000000000..d55bca297
--- /dev/null
+++ b/client/src/Pages/Notifications/index.jsx
@@ -0,0 +1,121 @@
+// Components
+import Stack from "@mui/material/Stack";
+import Typography from "@mui/material/Typography";
+import Breadcrumbs from "../../Components/Breadcrumbs";
+import Button from "@mui/material/Button";
+import DataTable from "../../Components/Table";
+import Fallback from "../../Components/Fallback";
+// Utils
+import { useIsAdmin } from "../../Hooks/useIsAdmin";
+import { useState } from "react";
+import { useTheme } from "@emotion/react";
+import { useNavigate } from "react-router-dom";
+import {
+ useGetNotificationsByTeamId,
+ useDeleteNotification,
+} from "../../Hooks/useNotifications";
+import { useTranslation } from "react-i18next";
+// Setup
+
+const Notifications = () => {
+ const navigate = useNavigate();
+ const theme = useTheme();
+ const BREADCRUMBS = [{ name: "notifications", path: "/notifications" }];
+ const [updateTrigger, setUpdateTrigger] = useState(false);
+ const isAdmin = useIsAdmin();
+ const [notifications, isLoading, error] = useGetNotificationsByTeamId(updateTrigger);
+ const [deleteNotification, isDeleting, deleteError] = useDeleteNotification();
+ const { t } = useTranslation();
+ // Handlers
+ const triggerUpdate = () => {
+ setUpdateTrigger(!updateTrigger);
+ };
+
+ const onDelete = (id) => {
+ deleteNotification(id, triggerUpdate);
+ };
+
+ const headers = [
+ {
+ id: "name",
+ content: "Name",
+ render: (row) => {
+ return row.notificationName;
+ },
+ },
+ {
+ id: "type",
+ content: "Type",
+ render: (row) => {
+ return row.type;
+ },
+ },
+ {
+ id: "target",
+ content: "Target",
+ render: (row) => {
+ return row.address || row.config?.webhookUrl || row.config?.routingKey;
+ },
+ },
+ {
+ id: "platform",
+ content: "Platform",
+ render: (row) => {
+ return row?.config?.platform || row.type;
+ },
+ },
+
+ {
+ id: "actions",
+ content: "Actions",
+ render: (row) => {
+ return (
+
+ );
+ },
+ },
+ ];
+
+ if (notifications?.length === 0) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ {t("notifications.createTitle")}
+
+
+ );
+};
+
+export default Notifications;