카테고리 없음
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}`
}
});