init
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* 알림 컨트롤러
|
||||
*
|
||||
* 볼링 클럽 매니저에서 지원하는 알림 유형:
|
||||
* 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;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user