카테고리 없음

Web Notifycation으로 알림 보내기

순코딩 2025. 3. 21. 16:42
"use client";

import { useState, useEffect } from "react";
import { Switch, FormControlLabel, Typography, Box } from "@mui/material";
import { NotificationsActive, NotificationsOff } from "@mui/icons-material";
import { requestNotificationPermission, getNotificationPermissionStatus } from "@/service/notification";
import { enqueueSnackbar } from "notistack";

const NotificationToggle = () => {
  const [notificationsEnabled, setNotificationsEnabled] = useState(false);
  const [permissionStatus, setPermissionStatus] = useState<string>("default");

  useEffect(() => {
    // 컴포넌트 마운트 시 권한 상태 확인
    const status = getNotificationPermissionStatus();
    setPermissionStatus(status);
    setNotificationsEnabled(status === "granted");
  }, []);

  const handleToggleNotifications = async () => {
    if (notificationsEnabled) {
      // 알림 비활성화 (실제로는 권한을 취소할 수 없으므로 안내만 제공)
      enqueueSnackbar("브라우저 설정에서 알림 권한을 변경할 수 있습니다.", { variant: "info" });
      return;
    }

    // 알림 권한 요청
    const granted = await requestNotificationPermission();
    setNotificationsEnabled(granted);
    setPermissionStatus(getNotificationPermissionStatus());

    if (granted) {
      enqueueSnackbar("알림이 활성화되었습니다.", { variant: "success" });
    } else {
      enqueueSnackbar("알림 권한이 거부되었습니다.", { variant: "warning" });
    }
  };

  return (
    <Box sx={{ mb: 2 }}>
      <FormControlLabel
        control={<Switch checked={notificationsEnabled} onChange={handleToggleNotifications} color="primary" />}
        label={
          <Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
            {notificationsEnabled ? <NotificationsActive color="primary" /> : <NotificationsOff />}
            <Typography>알림 {notificationsEnabled ? "활성화" : "비활성화"}</Typography>
          </Box>
        }
      />
      {permissionStatus === "denied" && (
        <Typography variant="caption" color="error" sx={{ display: "block", mt: 1 }}>
          브라우저 설정에서 알림 권한을 허용해주세요.
        </Typography>
      )}
    </Box>
  );
};

export default NotificationToggle;
// 알림 권한 상태 확인
export function getNotificationPermissionStatus(): string {
  if (!("Notification" in window)) {
    return "not-supported";
  }
  return Notification.permission;
}

// 알림 권한 요청
export async function requestNotificationPermission(): Promise<boolean> {
  // 브라우저가 알림을 지원하는지 확인
  if (!('Notification' in window)) {
    console.log('이 브라우저는 알림을 지원하지 않습니다.');
    return false;
  }

  // 이미 권한이 있는 경우
  if (Notification.permission === 'granted') {
    return true;
  }

  // 권한 요청
  const permission = await Notification.requestPermission();
  return permission === 'granted';
}

// 알림 보내기
export function sendNotification(title: string, options?: NotificationOptions){
  // 브라우저가 알림을 지원하는지 확인
  if (!('Notification' in window)) {
    return {data : null, error : "이 브라우저는 알림을 지원하지 않습니다."}
  }

  // 권한이 없는 경우
  if (Notification.permission !== 'granted') {
    return {data : null, error : "알림 권한이 없습니다."}
  }

  // 알림 생성
  const notification = new Notification(title, options);
  
  // 알림 클릭 이벤트
  notification.onclick = function() {
    window.focus();
    if (options?.data?.url) {
      window.location.href = options.data.url;
    }
    notification.close();
  };
  
  return notification;
}
 // 웹 알림 보내기
  sendNotification("판결 생성 완료", {
    body: `"${caseData.title}" 사례의 AI 판결이 완료되었습니다.`,
    icon: "/icons/gavel-icon.png",
    data: {
      url: `/case/${caseResponse.data[0].id}`
    }
  });