最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - My Notifications Snackbar can't overlap a modal(MUI) - Stack Overflow

programmeradmin1浏览0评论

I want this notifications display above modal but it didnt. I try to change zIndex but its not useful. Please help me make the notification show on top of other components. In the Header, I create a button that trigger modal have register/login form and fot password, I pass a set alert to login component to set alert for notifications because if notifications place in modal, its will be affected by modal size Here my code: -Snackbar:

import { Snackbar, Alert } from "@mui/material";
/**
 * NotificationSnackbar 
 * Display message, notifications
 */
export default function NotificationSnackbar({ alert, onClose }) {
  return (
    <Snackbar
      open={alert.open}
      autoHideDuration={3000}
      onClose={onClose}
      anchorOrigin={{
        vertical: "top",
        horizontal: "right",
      }}
      sx={{
        top: { xs: 64, sm: "70px" },
        width: { xs: "90%", sm: "auto" },
        zIndex: 1501,
        position: "fixed"
      }}
    >
      <Alert
        severity={alert.severity || "info"}
        onClose={onClose}
        sx={{
          fontWeight: "bold",
          border: "2px solid",
          borderColor:
            alert.severity === "success"
              ? "#05ce80"
              : alert.severity === "error"
                ? "#d32f2f"
                : "#ff9800",
          boxShadow: 2,
          marginTop: { xs: 2, sm: 8 },
          width: { xs: "100%", sm: "auto" },
        }}
      >
        {alert.message || "Something went wrong!"}
      </Alert>
    </Snackbar>
  );
}

And Header:

 import React from "react";
import { AppBar, Toolbar, Box, Button, Divider, Stack, Modal, IconButton, Drawer, List, ListItem } from "@mui/material";
import { Link } from "react-router-dom";
import { Menu as MenuIcon } from "@mui/icons-material";
import logo from "../../assets/logo.png";
import UserMenu from "../User/UserMenu";
import { ModalClose, ModalDialog } from "@mui/joy";
import Login from "../User/Login";
import Register from "../User/Register";
import * as Mui from "@mui/material";
import { useMediaQuery } from "@mui/material";
import { useState } from "react";
import NotificationSnackbar from "./NotificationSnackbar";
const Header = () => {
  const [alert, setAlert] = useState({ open: false, message: "", severity: "success" });
  const isLoggedIn = Boolean(localStorage.getItem("role"));
  const [open, setOpen] = React.useState(false);
  const [drawerOpen, setDrawerOpen] = React.useState(false);
  const isMobile = useMediaQuery("(max-width: 768px)"); // Check if screen width is less than 768px

  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);
  const toggleDrawer = () => setDrawerOpen(!drawerOpen);

  return (
    <AppBar position="sticky" color="transparent" elevation={1} sx={{ backgroundColor: "white" }}>
      <Toolbar sx={{ justifyContent: "space-between", mx: "auto", maxWidth: "1200px", width: "100%", py: 1, px: 2, boxSizing: "border-box", }}>
        {/* Logo */}
        <Box>
          <Link to="/" style={{ textDecoration: "none" }}>
            <img src={logo} alt="logo" style={{ maxWidth: isMobile ? "150px" : "250px", height: "auto" }} />
          </Link>
        </Box>

        {/* Desktop Menu */}
        {!isMobile ? (
          <Stack direction="row" spacing={3} alignItems="center">
            <Link to="/aboutus" style={{ textDecoration: "none" }}>
              <Button sx={{ fontWeight: 500, textTransform: "none", color: "black", "&:hover": { color: "#05ce80" } }}>
                About Karental
              </Button>
            </Link>
            <Divider orientation="vertical" flexItem />

            {!isLoggedIn ? (
              <>
                <Button onClick={handleOpen} id="open-register-button" sx={{ fontWeight: 500, textTransform: "none", color: "black", "&:hover": { color: "#05ce80" } }}>
                  Sign Up
                </Button>
                <Divider orientation="vertical" flexItem sx={{ width: "1px", height: "25px", alignSelf: "center" }} />
                <Button onClick={handleOpen} id="open-login-button" variant="outlined" sx={{ px: 4, py: 1.5, borderRadius: 2, borderColor: "black", color: "black", fontWeight: 500, textTransform: "none", "&:hover": { borderColor: "#05ce80", color: "#05ce80" } }}>
                  Login
                </Button>
              </>
            ) : (
              <UserMenu />
            )}
          </Stack>
        ) : (
          // Mobile Menu Button
          <IconButton onClick={toggleDrawer} sx={{ color: "black" }}>
            <MenuIcon />
          </IconButton>
        )}

        {/* Mobile Drawer */}
        <Drawer anchor="right" open={drawerOpen} onClose={toggleDrawer}>
          <List sx={{ width: "250px" }}>
            <ListItem button component={Link} to="/aboutus" onClick={toggleDrawer}>
              About Karental
            </ListItem>
            {!isLoggedIn ? (
              <>
                <ListItem button onClick={handleOpen}>Sign Up</ListItem>
                <ListItem button onClick={handleOpen}>Login</ListItem>
              </>
            ) : (
              <UserMenu />
            )}
          </List>
        </Drawer>

        {/* Login/Register Modal */}
        <Modal open={open} onClose={handleClose}>
          <ModalDialog sx={{ width: "65vw", maxWidth: "lg", maxHeight: "100vh", overflowY: "auto", zIndex: 1200, }}>
            <ModalClose onClick={handleClose} />
            <Mui.Container sx={{ display: "flex", flexDirection: isMobile ? "column" : "row", gap: 2 }}>
              <Login onLoginSuccess={handleClose} setAlert={setAlert} />
              {!isMobile && <Mui.Divider orientation="vertical" flexItem />}
              <Register onRegisterSucess={handleClose} setAlert={setAlert} />
            </Mui.Container>
          </ModalDialog>
        </Modal>
        {/* Notification Snackbar */}
        <NotificationSnackbar alert={alert} onClose={() => setAlert({ ...alert, open: false })} disablePortal={false} // Thử để false để snackbar render trong cùng DOM
          sx={{ zIndex: 2000 }} />
      </Toolbar>
    </AppBar>
  );
};

export default Header;

And last is Login component:

import * as React from "react";
import * as Mui from "@mui/material";
import normalForm from "../../styles/FormStyles.js";
import { fotPasswordEmailFunction, login } from '../../services/UserServices.js';
import * as Icons from "@mui/icons-material";
import { useState } from "react";
import { ModalClose, ModalDialog } from '@mui/joy';
import { useNavigate } from "react-router-dom";
const Login = ({ onLoginSuccess, setAlert }) => {

  const [formLogin, setFormLogin] = useState({
    email: "",
    password: "",
  });
  const handleChange = (e) => {
    setFormLogin({
      ...formLogin,
      [e.target.name]: e.target.value
    })
  }
  // state for showing password or not
  const [showPassword, setShowPassword] = useState(false);
  const handleClickShowPassword = () => setShowPassword((show) => !show);
  const nav = useNavigate();
  const handleSubmit = async (event) => {
    event.preventDefault();
    try {
      const response = await login(formLogin); // Await the login call
      console.log("Login Response:", response);
      //set role into localStorage
      if (response.code === 1000) {
        localStorage.setItem("role", response.data.userRole);
        localStorage.setItem("name", response.data.fullName);
        localStorage.setItem("csrfToken", response.data.csrfToken);
        setAlert({ open: true, message: "Welcome to Our Community", severity: "success" });
        setTimeout(() => {
          nav("/", { replace: true });
          onLoginSuccess();
        }, 1000);
      } else {
        setAlert({ open: true, message: response.message, severity: "error" });
      }
    } catch (error) {
      console.log(error)
    }
  }
  const handleMouseUp = (event) => {
    event.preventDefault();
  };
  const handleMouseDown = (event) => {
    event.preventDefault();
  };
  const [openModalFot, setOpenModalFot] = useState(false)
  const [fotPasswordEmail, setFotPasswordEmail] = useState("");
  const handleFotPassword = async () => {
    console.log("Fot password clicked, email:", fotPasswordEmail);

    if (!fotPasswordEmail) {
      setAlert({ open: true, message: "Please enter your email", severity: "warning" });
      return;
    }

    try {
      const response = await fotPasswordEmailFunction(fotPasswordEmail);
      console.log("Fot Password Response:", response);

      if (response?.message) {
        setAlert({ open: true, message: response.data.message, severity: "success" });
      } else {
        setAlert({ open: true, message: "Failed to send email. Try again.", severity: "error" });
      }

      setOpenModalFot(false); // Đóng modal sau khi gửi email thành công
    } catch (error) {
      console.error("Fot password error:", error);
      setAlert({ open: true, message: error.message || "An error occurred", severity: "error" });
    }
  };

  return (
    <>
      <Mui.Box component="form" sx={normalForm}>
        <Mui.Typography
          variant="h5"
          textAlign={"center"}
          sx={{ color: "#05ce80" }}
        >
          LOG IN USING YOUR ACCOUNT
        </Mui.Typography>
        <Mui.Box sx={{ display: "flex", flexDirection: "column", gap: 2, alignItems: "start" }}>
          <Mui.TextField
            id="login-email"
            name="email"
            variant="standard"
            label="Your email address"
            //error={!!errors.name}
            //helperText={errors.name}
            value={formLogin.email}
            onChange={handleChange}
            fullWidth
          />
          <Mui.TextField
            id="login-password"
            name="password"
            variant="standard"
            label="Password"
            //error={!!errors.password}
            //helperText={errors.password}
            value={formLogin.password}
            onChange={handleChange}
            type={showPassword ? "text" : "password"}
            fullWidth
            required
            InputProps={{
              endAdornment: (
                <Mui.InputAdornment position="end">
                  <Mui.IconButton
                    onClick={handleClickShowPassword}
                    onMouseUp={handleMouseUp}
                    onMouseDown={handleMouseDown}
                  >
                    {showPassword ? (
                      <Icons.VisibilityOff />
                    ) : (
                      <Icons.Visibility />
                    )}
                  </Mui.IconButton>
                </Mui.InputAdornment>
              ),
            }}
          />
          <Mui.Link id="login-fotPassword" href="#"
            onClick={(e) => {
              setOpenModalFot(true);
              e.preventDefault();
            }}>
            Fot your password?</Mui.Link>
          <Mui.Modal open={openModalFot} >
            <ModalDialog>
              <ModalClose onClick={() => setOpenModalFot(false)} />
              <Mui.Box textAlign={"center"}>
                <Mui.Typography variant={"h6"}>Fot your password?</Mui.Typography>
                <Mui.TextField variant='standard' onChange={(e) => (setFotPasswordEmail(e.target.value))} label="Your email" value={fotPasswordEmail}></Mui.TextField>
                <br />
                <Mui.Button
                  sx={{
                    width: 150,
                    height: 50,
                    borderRadius: 2,
                    border: "solid white",
                    backgroundColor: "#05ce80",
                    marginInline: 2,
                    color: "white",
                    transition: " 0.3s",
                    "&:hover": {
                      backgroundColor: "white",
                      borderRadius: 2,
                      borderColor: "#05ce80",
                      color: "#05ce80",
                    },
                  }}
                  onClick={handleFotPassword}
                >
                  Send Email
                </Mui.Button>
              </Mui.Box>
            </ModalDialog>
          </Mui.Modal>
          <Mui.Box sx={{ display: "flex", justifyContent: "center", width: "100%" }}>
            <Mui.Button
              id="login"
              variant="outlined"
              onClick={handleSubmit}
              sx={{
                width: '150px',
                borderRadius: 2,
                borderColor: "black",
                color: "black",
                fontWeight: 500,
                textTransform: "none",
                transition: " 0.3s",
                "&:hover": {
                  borderColor: "#05ce80",
                  color: "#05ce80",
                },
              }}
            >
              LOGIN
            </Mui.Button>
          </Mui.Box>
        </Mui.Box>
      </Mui.Box>
    </>
  );
};

export default Login;

notifications covered by backdrop

发布评论

评论列表(0)

  1. 暂无评论