216 lines
8 KiB
JavaScript
216 lines
8 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const express_1 = require("express");
|
|
const index_1 = require("../index");
|
|
const auth_1 = require("../middleware/auth");
|
|
const router = (0, express_1.Router)();
|
|
router.get('/me', auth_1.authenticate, async (req, res) => {
|
|
try {
|
|
const user = await index_1.prisma.user.findUnique({
|
|
where: { id: req.user.id },
|
|
select: {
|
|
id: true,
|
|
email: true,
|
|
name: true,
|
|
screenName: true,
|
|
avatarUrl: true,
|
|
unitPreference: true,
|
|
createdAt: true
|
|
}
|
|
});
|
|
if (!user) {
|
|
return res.status(404).json({ error: 'User not found' });
|
|
}
|
|
res.json(user);
|
|
}
|
|
catch (error) {
|
|
console.error('Get user error:', error);
|
|
res.status(500).json({ error: 'Failed to get user' });
|
|
}
|
|
});
|
|
router.put('/me', auth_1.authenticate, async (req, res) => {
|
|
try {
|
|
const { name, screenName, avatarUrl, unitPreference } = req.body;
|
|
const updated = await index_1.prisma.user.update({
|
|
where: { id: req.user.id },
|
|
data: {
|
|
name: name || undefined,
|
|
screenName: screenName !== undefined ? screenName || null : undefined,
|
|
avatarUrl: avatarUrl !== undefined ? avatarUrl || null : undefined,
|
|
unitPreference: unitPreference || undefined
|
|
},
|
|
select: {
|
|
id: true,
|
|
email: true,
|
|
name: true,
|
|
screenName: true,
|
|
avatarUrl: true,
|
|
unitPreference: true,
|
|
createdAt: true
|
|
}
|
|
});
|
|
res.json(updated);
|
|
}
|
|
catch (error) {
|
|
console.error('Update user error:', error);
|
|
res.status(500).json({ error: 'Failed to update user' });
|
|
}
|
|
});
|
|
router.get('/me/location-history', auth_1.authenticate, async (req, res) => {
|
|
try {
|
|
const locations = await index_1.prisma.locationHistory.findMany({
|
|
where: { userId: req.user.id },
|
|
include: {
|
|
game: {
|
|
select: { id: true, name: true }
|
|
}
|
|
},
|
|
orderBy: { recordedAt: 'desc' }
|
|
});
|
|
const games = await index_1.prisma.game.findMany({
|
|
where: {
|
|
teams: {
|
|
some: {
|
|
members: {
|
|
some: { userId: req.user.id }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
select: { id: true, name: true }
|
|
});
|
|
const locationByGame = games.map(game => {
|
|
const gameLocations = locations.filter(l => l.gameId === game.id);
|
|
return {
|
|
game: game,
|
|
locations: gameLocations,
|
|
locationCount: gameLocations.length
|
|
};
|
|
}).filter(g => g.locationCount > 0);
|
|
res.json({
|
|
totalLocations: locations.length,
|
|
byGame: locationByGame
|
|
});
|
|
}
|
|
catch (error) {
|
|
console.error('Get location history error:', error);
|
|
res.status(500).json({ error: 'Failed to get location history' });
|
|
}
|
|
});
|
|
router.get('/me/games', auth_1.authenticate, async (req, res) => {
|
|
try {
|
|
const memberships = await index_1.prisma.teamMember.findMany({
|
|
where: { userId: req.user.id },
|
|
include: {
|
|
team: {
|
|
include: {
|
|
game: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
status: true,
|
|
startDate: true,
|
|
locationLat: true,
|
|
locationLng: true,
|
|
gameMasterId: true,
|
|
gameMaster: { select: { name: true } }
|
|
}
|
|
},
|
|
teamRoutes: {
|
|
include: {
|
|
route: {
|
|
include: {
|
|
routeLegs: {
|
|
orderBy: { sequenceNumber: 'asc' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
photoSubmissions: true
|
|
}
|
|
}
|
|
}
|
|
});
|
|
const gamesWithDetails = memberships.map(m => {
|
|
const team = m.team;
|
|
const game = team.game;
|
|
const teamRoute = team.teamRoutes[0];
|
|
const route = teamRoute?.route;
|
|
const photoSubmissions = team.photoSubmissions;
|
|
const routeLegs = route?.routeLegs || [];
|
|
const proofLocations = routeLegs.filter(leg => photoSubmissions.some(p => p.routeLegId === leg.id));
|
|
let totalDistance = 0;
|
|
if (game.locationLat && game.locationLng) {
|
|
let prevLat = game.locationLat;
|
|
let prevLng = game.locationLng;
|
|
for (const leg of routeLegs) {
|
|
if (leg.locationLat && leg.locationLng) {
|
|
const R = 6371;
|
|
const dLat = (leg.locationLat - prevLat) * Math.PI / 180;
|
|
const dLng = (leg.locationLng - prevLng) * Math.PI / 180;
|
|
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
Math.cos(prevLat * Math.PI / 180) * Math.cos(leg.locationLat * Math.PI / 180) *
|
|
Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
totalDistance += R * c;
|
|
prevLat = leg.locationLat;
|
|
prevLng = leg.locationLng;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
gameId: game.id,
|
|
gameName: game.name,
|
|
gameStatus: game.status,
|
|
gameMaster: game.gameMaster.name,
|
|
startDate: game.startDate,
|
|
teamId: team.id,
|
|
teamName: team.name,
|
|
teamStatus: team.status,
|
|
routeId: route?.id || null,
|
|
routeName: route?.name || null,
|
|
routeColor: route?.color || null,
|
|
totalLegs: routeLegs.length,
|
|
totalDistance: Math.round(totalDistance * 100) / 100,
|
|
proofLocations: proofLocations.map(leg => ({
|
|
legNumber: leg.sequenceNumber,
|
|
description: leg.description,
|
|
locationLat: leg.locationLat,
|
|
locationLng: leg.locationLng,
|
|
hasPhotoProof: photoSubmissions.some(p => p.routeLegId === leg.id)
|
|
}))
|
|
};
|
|
});
|
|
res.json(gamesWithDetails);
|
|
}
|
|
catch (error) {
|
|
console.error('Get user games error:', error);
|
|
res.status(500).json({ error: 'Failed to get user games' });
|
|
}
|
|
});
|
|
router.delete('/me/location-data', auth_1.authenticate, async (req, res) => {
|
|
try {
|
|
await index_1.prisma.locationHistory.deleteMany({
|
|
where: { userId: req.user.id }
|
|
});
|
|
res.json({ message: 'Location data deleted' });
|
|
}
|
|
catch (error) {
|
|
console.error('Delete location data error:', error);
|
|
res.status(500).json({ error: 'Failed to delete location data' });
|
|
}
|
|
});
|
|
router.delete('/me/account', auth_1.authenticate, async (req, res) => {
|
|
try {
|
|
await index_1.prisma.user.delete({
|
|
where: { id: req.user.id }
|
|
});
|
|
res.json({ message: 'Account deleted' });
|
|
}
|
|
catch (error) {
|
|
console.error('Delete account error:', error);
|
|
res.status(500).json({ error: 'Failed to delete account' });
|
|
}
|
|
});
|
|
exports.default = router;
|