Files
rentall-app/backend/routes/users.js
2025-08-20 14:56:16 -04:00

225 lines
6.1 KiB
JavaScript

const express = require('express');
const { User, UserAddress } = require('../models'); // Import from models/index.js to get models with associations
const { authenticateToken } = require('../middleware/auth');
const { uploadProfileImage } = require('../middleware/upload');
const fs = require('fs').promises;
const path = require('path');
const router = express.Router();
router.get('/profile', authenticateToken, async (req, res) => {
try {
const user = await User.findByPk(req.user.id, {
attributes: { exclude: ['password'] }
});
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Address routes (must come before /:id route)
router.get('/addresses', authenticateToken, async (req, res) => {
try {
const addresses = await UserAddress.findAll({
where: { userId: req.user.id },
order: [['isPrimary', 'DESC'], ['createdAt', 'ASC']]
});
res.json(addresses);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
router.post('/addresses', authenticateToken, async (req, res) => {
try {
const address = await UserAddress.create({
...req.body,
userId: req.user.id
});
res.status(201).json(address);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
router.put('/addresses/:id', authenticateToken, async (req, res) => {
try {
const address = await UserAddress.findByPk(req.params.id);
if (!address) {
return res.status(404).json({ error: 'Address not found' });
}
if (address.userId !== req.user.id) {
return res.status(403).json({ error: 'Unauthorized' });
}
await address.update(req.body);
res.json(address);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
router.delete('/addresses/:id', authenticateToken, async (req, res) => {
try {
const address = await UserAddress.findByPk(req.params.id);
if (!address) {
return res.status(404).json({ error: 'Address not found' });
}
if (address.userId !== req.user.id) {
return res.status(403).json({ error: 'Unauthorized' });
}
await address.destroy();
res.status(204).send();
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// User availability routes (must come before /:id route)
router.get('/availability', authenticateToken, async (req, res) => {
try {
const user = await User.findByPk(req.user.id, {
attributes: ['defaultAvailableAfter', 'defaultAvailableBefore', 'defaultSpecifyTimesPerDay', 'defaultWeeklyTimes']
});
res.json({
generalAvailableAfter: user.defaultAvailableAfter,
generalAvailableBefore: user.defaultAvailableBefore,
specifyTimesPerDay: user.defaultSpecifyTimesPerDay,
weeklyTimes: user.defaultWeeklyTimes
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
router.put('/availability', authenticateToken, async (req, res) => {
try {
const { generalAvailableAfter, generalAvailableBefore, specifyTimesPerDay, weeklyTimes } = req.body;
await User.update({
defaultAvailableAfter: generalAvailableAfter,
defaultAvailableBefore: generalAvailableBefore,
defaultSpecifyTimesPerDay: specifyTimesPerDay,
defaultWeeklyTimes: weeklyTimes
}, {
where: { id: req.user.id }
});
res.json({ message: 'Availability updated successfully' });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
router.get('/:id', async (req, res) => {
try {
const user = await User.findByPk(req.params.id, {
attributes: { exclude: ['password', 'email', 'phone', 'address'] }
});
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
router.put('/profile', authenticateToken, async (req, res) => {
try {
const {
firstName,
lastName,
email,
phone,
address1,
address2,
city,
state,
zipCode,
country
} = req.body;
// Build update object, excluding empty email
const updateData = {
firstName,
lastName,
phone,
address1,
address2,
city,
state,
zipCode,
country
};
// Only include email if it's not empty
if (email && email.trim() !== '') {
updateData.email = email;
}
await req.user.update(updateData);
const updatedUser = await User.findByPk(req.user.id, {
attributes: { exclude: ['password'] }
});
res.json(updatedUser);
} catch (error) {
console.error('Profile update error:', error);
res.status(500).json({
error: error.message,
details: error.errors ? error.errors.map(e => ({ field: e.path, message: e.message })) : undefined
});
}
});
// Upload profile image endpoint
router.post('/profile/image', authenticateToken, (req, res) => {
uploadProfileImage(req, res, async (err) => {
if (err) {
console.error('Upload error:', err);
return res.status(400).json({ error: err.message });
}
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
try {
// Delete old profile image if exists
const user = await User.findByPk(req.user.id);
if (user.profileImage) {
const oldImagePath = path.join(__dirname, '../uploads/profiles', user.profileImage);
try {
await fs.unlink(oldImagePath);
} catch (unlinkErr) {
console.error('Error deleting old image:', unlinkErr);
}
}
// Update user with new image filename
await user.update({
profileImage: req.file.filename
});
res.json({
message: 'Profile image uploaded successfully',
filename: req.file.filename,
imageUrl: `/uploads/profiles/${req.file.filename}`
});
} catch (error) {
console.error('Database update error:', error);
res.status(500).json({ error: 'Failed to update profile image' });
}
});
});
module.exports = router;