Files
bowlingManager/backend/controllers/notificationController.js
2025-04-17 23:32:39 +09:00

218 lines
6.1 KiB
JavaScript

/**
* 알림 컨트롤러
*
* 볼링 클럽 매니저에서 지원하는 알림 유형:
* 1. 시스템 알림
* - 시스템 업데이트, 유지보수 공지 등
* - 아이콘: pi pi-info-circle
* - 타입: info
*
* 2. 클럽 관련 알림
* - 새 회원 가입, 클럽 정보 변경 등
* - 아이콘: pi pi-users
* - 타입: info 또는 success
*
* 3. 모임/대회 알림
* - 모임 생성, 대회 일정, 참가 신청 등
* - 아이콘: pi pi-calendar 또는 pi pi-flag
* - 타입: info 또는 warning
*
* 4. 점수 관련 알림
* - 새 점수 등록, 평균 점수 갱신 등
* - 아이콘: pi pi-chart-bar
* - 타입: success
*
* 5. 결제/구독 알림
* - 결제 완료, 구독 만료 예정 등
* - 아이콘: pi pi-credit-card 또는 pi pi-clock
* - 타입: success 또는 warning
*
* 6. 오류/경고 알림
* - 시스템 오류, 보안 경고 등
* - 아이콘: pi pi-exclamation-triangle
* - 타입: error 또는 warning
*
* 알림 생성 방법:
* 1. API 엔드포인트를 통한 생성: POST /api/notifications
* 2. 내부 함수를 통한 생성: createSystemNotification()
*
* 알림 필드:
* - user: 알림을 받을 사용자 ID (필수)
* - title: 알림 제목 (필수)
* - message: 알림 내용 (필수)
* - icon: 알림 아이콘 (PrimeIcons 사용)
* - type: 알림 타입 (info, success, warning, error)
* - link: 알림 클릭 시 이동할 링크 (옵션)
* - read: 읽음 상태 (기본값: false)
*/
const User = require('../models/User');
const Notification = require('../models/Notification');
const { validationResult } = require('express-validator');
// 사용자의 알림 목록 조회
exports.getUserNotifications = async (req, res) => {
try {
const userId = req.user.id;
// 사용자의 알림 목록 조회 (최신순으로 정렬)
const notifications = await Notification.findAll({
where: { userId },
order: [['createdAt', 'DESC']],
limit: 10
});
res.status(200).json(notifications);
} catch (error) {
console.error('알림 조회 오류:', error);
res.status(500).json({ message: '서버 오류가 발생했습니다.' });
}
};
// 알림 읽음 표시
exports.markAsRead = async (req, res) => {
try {
const { notificationId } = req.params;
const userId = req.user.id;
const notification = await Notification.findOne({
where: {
id: notificationId,
userId
}
});
if (!notification) {
return res.status(404).json({ message: '알림을 찾을 수 없습니다.' });
}
notification.read = true;
await notification.save();
res.status(200).json({ message: '알림이 읽음 처리되었습니다.' });
} catch (error) {
console.error('알림 읽음 표시 오류:', error);
res.status(500).json({ message: '서버 오류가 발생했습니다.' });
}
};
// 모든 알림 읽음 표시
exports.markAllAsRead = async (req, res) => {
try {
const userId = req.user.id;
await Notification.update(
{ read: true },
{ where: { userId, read: false } }
);
res.status(200).json({ message: '모든 알림이 읽음 처리되었습니다.' });
} catch (error) {
console.error('모든 알림 읽음 표시 오류:', error);
res.status(500).json({ message: '서버 오류가 발생했습니다.' });
}
};
// 알림 생성 (관리자용)
exports.createNotification = async (req, res) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { userId, title, message, icon, type, link } = req.body;
const newNotification = await Notification.create({
userId,
title,
message,
icon: icon || 'pi pi-info-circle',
type: type || 'info',
link,
read: false
});
// Socket.IO를 통해 실시간 알림 전송
const io = req.app.get('io');
if (io) {
io.to(`user:${userId}`).emit('notification', {
id: newNotification.id,
title: newNotification.title,
message: newNotification.message,
icon: newNotification.icon,
type: newNotification.type,
link: newNotification.link,
createdAt: newNotification.createdAt
});
}
res.status(201).json(newNotification);
} catch (error) {
console.error('알림 생성 오류:', error);
res.status(500).json({ message: '서버 오류가 발생했습니다.' });
}
};
// 알림 삭제
exports.deleteNotification = async (req, res) => {
try {
const { notificationId } = req.params;
const userId = req.user.id;
const notification = await Notification.findOne({
where: {
id: notificationId,
userId
}
});
if (!notification) {
return res.status(404).json({ message: '알림을 찾을 수 없습니다.' });
}
await notification.destroy();
res.status(200).json({ message: '알림이 삭제되었습니다.' });
} catch (error) {
console.error('알림 삭제 오류:', error);
res.status(500).json({ message: '서버 오류가 발생했습니다.' });
}
};
// 시스템 알림 생성 (내부 함수)
exports.createSystemNotification = async (userId, title, message, options = {}) => {
try {
const { icon, type, link } = options;
const newNotification = await Notification.create({
userId,
title,
message,
icon: icon || 'pi pi-info-circle',
type: type || 'info',
link,
read: false
});
// Socket.IO를 통해 실시간 알림 전송
const io = global.io;
if (io) {
io.to(`user:${userId}`).emit('notification', {
id: newNotification.id,
title: newNotification.title,
message: newNotification.message,
icon: newNotification.icon,
type: newNotification.type,
link: newNotification.link,
createdAt: newNotification.createdAt
});
}
return newNotification;
} catch (error) {
console.error('시스템 알림 생성 오류:', error);
return null;
}
};