|
|
import express from 'express'; |
|
|
import cloudinary from '../config/cloudinary.js'; |
|
|
import User from '../models/User.js'; |
|
|
import { updateKarma } from '../services/KarmaService.js'; |
|
|
import CallSession from '../models/CallSession.js'; |
|
|
import SupportTicket from '../models/SupportTicket.js'; |
|
|
import { requireAdmin } from '../middleware/requireAdmin.js'; |
|
|
import axios from 'axios'; |
|
|
|
|
|
const router = express.Router(); |
|
|
|
|
|
|
|
|
const requireAuth = (req, res, next) => { |
|
|
if (!req.user) return res.status(401).send({ error: 'You must log in!' }); |
|
|
next(); |
|
|
}; |
|
|
|
|
|
|
|
|
router.get('/upload-signature', requireAuth, (req, res) => { |
|
|
if ( |
|
|
!process.env.CLOUDINARY_CLOUD_NAME || |
|
|
!process.env.CLOUDINARY_API_KEY || |
|
|
!process.env.CLOUDINARY_API_SECRET |
|
|
) { |
|
|
return res.status(500).json({ |
|
|
error: 'Cloudinary environment variables not configured' |
|
|
}); |
|
|
} |
|
|
|
|
|
const timestamp = Math.round((new Date()).getTime() / 1000); |
|
|
|
|
|
const signature = cloudinary.utils.api_sign_request({ |
|
|
timestamp: timestamp, |
|
|
folder: 'cragy_profiles', |
|
|
}, process.env.CLOUDINARY_API_SECRET); |
|
|
|
|
|
res.json({ |
|
|
signature, |
|
|
timestamp, |
|
|
cloudName: process.env.CLOUDINARY_CLOUD_NAME, |
|
|
apiKey: process.env.CLOUDINARY_API_KEY |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
router.post('/update-profile', requireAuth, async (req, res) => { |
|
|
try { |
|
|
const user = await User.findById(req.user._id); |
|
|
if (!user) return res.status(404).send({ error: 'User not found' }); |
|
|
|
|
|
const { |
|
|
gender, |
|
|
college, |
|
|
city, |
|
|
relationshipStatus, |
|
|
photos, |
|
|
bio, |
|
|
socials |
|
|
} = req.body; |
|
|
|
|
|
|
|
|
if (gender !== undefined) user.profile.gender = gender; |
|
|
if (college !== undefined) user.profile.college = college; |
|
|
if (city !== undefined) user.profile.city = city; |
|
|
if (relationshipStatus !== undefined) user.profile.relationshipStatus = relationshipStatus; |
|
|
if (photos !== undefined) user.profile.photos = photos; |
|
|
if (bio !== undefined) user.profile.bio = bio; |
|
|
if (socials !== undefined) user.profile.socials = socials; |
|
|
|
|
|
|
|
|
if (!user.profile.isComplete) { |
|
|
if (!user.profile.gender || !user.profile.college || !user.profile.photos?.length) { |
|
|
return res.status(400).send({ error: 'Missing required onboarding fields' }); |
|
|
} |
|
|
user.profile.isComplete = true; |
|
|
} |
|
|
|
|
|
await user.save(); |
|
|
res.send(user); |
|
|
} catch (err) { |
|
|
console.error(err); |
|
|
res.status(500).send({ error: 'Update failed' }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
router.post('/rate', requireAuth, async (req, res) => { |
|
|
const { targetUserId, rating } = req.body; |
|
|
|
|
|
if (!targetUserId || !rating) return res.status(400).send({ error: 'Invalid data' }); |
|
|
|
|
|
|
|
|
if (req.user._id.toString() === targetUserId) { |
|
|
return res.status(400).send({ error: "Cannot rate yourself" }); |
|
|
} |
|
|
|
|
|
try { |
|
|
if (rating === 'UP') { |
|
|
await updateKarma(targetUserId, 1, 'Good Conversation'); |
|
|
} else if (rating === 'DOWN') { |
|
|
await updateKarma(targetUserId, -5, 'Bad Experience'); |
|
|
} |
|
|
|
|
|
res.send({ success: true }); |
|
|
} catch (err) { |
|
|
res.status(500).send({ error: 'Rating failed' }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
router.get('/recent-match', requireAuth, async (req, res) => { |
|
|
try { |
|
|
|
|
|
const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000); |
|
|
|
|
|
const lastSession = await CallSession.findOne({ |
|
|
participants: req.user._id, |
|
|
endTime: { $gte: fiveMinutesAgo } |
|
|
}) |
|
|
.sort({ endTime: -1 }) |
|
|
.populate('participants', 'displayName profile.photos'); |
|
|
|
|
|
if (!lastSession) return res.send(null); |
|
|
|
|
|
|
|
|
const partner = lastSession.participants.find(p => !p._id.equals(req.user._id)); |
|
|
|
|
|
res.send({ |
|
|
sessionId: lastSession._id, |
|
|
partner: { |
|
|
_id: partner._id, |
|
|
name: partner.displayName, |
|
|
photo: partner.profile.photos[0] |
|
|
} |
|
|
}); |
|
|
} catch (err) { |
|
|
res.status(500).send({ error: 'Fetch failed' }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
router.post('/contact', async (req, res) => { |
|
|
const { email, message, category } = req.body; |
|
|
|
|
|
if (!email || !message) { |
|
|
return res.status(400).send({ error: 'Missing required fields' }); |
|
|
} |
|
|
|
|
|
try { |
|
|
const ticket = await SupportTicket.create({ |
|
|
email, |
|
|
message, |
|
|
category, |
|
|
user: req.user?._id || null, |
|
|
}); |
|
|
|
|
|
console.log(`📩 Support ticket saved: ${ticket._id}`); |
|
|
|
|
|
res.send({ success: true }); |
|
|
} catch (err) { |
|
|
console.error('Support ticket failed', err); |
|
|
res.status(500).send({ error: 'Failed to submit ticket' }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
router.get('/turn-credentials', requireAuth, async (req, res) => { |
|
|
try { |
|
|
|
|
|
const response = await axios.get(`https://www.metered.ca/api/v1/turn/credentials?apiKey=${process.env.METERED_API_KEY}`); |
|
|
|
|
|
|
|
|
res.send(response.data); |
|
|
} catch (err) { |
|
|
console.error("TURN Fetch Error:", err); |
|
|
|
|
|
res.send([ |
|
|
{ urls: "stun:stun.l.google.com:19302" } |
|
|
]); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
router.get( |
|
|
'/admin/support-tickets', |
|
|
requireAuth, |
|
|
requireAdmin, |
|
|
async (req, res) => { |
|
|
try { |
|
|
const tickets = await SupportTicket.find() |
|
|
.sort({ createdAt: -1 }) |
|
|
.populate('user', 'displayName email'); |
|
|
|
|
|
res.send(tickets); |
|
|
} catch (err) { |
|
|
res.status(500).send({ error: 'Failed to load tickets' }); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
|
|
|
router.post( |
|
|
'/admin/support-tickets/:id/status', |
|
|
requireAuth, |
|
|
requireAdmin, |
|
|
async (req, res) => { |
|
|
const { status } = req.body; |
|
|
|
|
|
if (!['open', 'resolved'].includes(status)) { |
|
|
return res.status(400).send({ error: 'Invalid status' }); |
|
|
} |
|
|
|
|
|
try { |
|
|
const ticket = await SupportTicket.findByIdAndUpdate( |
|
|
req.params.id, |
|
|
{ status }, |
|
|
{ new: true } |
|
|
); |
|
|
|
|
|
res.send(ticket); |
|
|
} catch (err) { |
|
|
res.status(500).send({ error: 'Failed to update ticket' }); |
|
|
} |
|
|
} |
|
|
); |
|
|
|
|
|
|
|
|
export default router; |
|
|
|