feat: prompt vehicle selection on login after auto-downgrade (#60) #62

Merged
egullickson merged 5 commits from issue-60-vehicle-selection-prompt into main 2026-01-24 17:56:24 +00:00
Showing only changes of commit 68948484a4 - Show all commits

View File

@@ -28,8 +28,13 @@ export class VehiclesController {
async getUserVehicles(request: FastifyRequest, reply: FastifyReply) {
try {
const userId = (request as any).user.sub;
const vehicles = await this.vehiclesService.getUserVehicles(userId);
// Use tier-aware method to filter out locked vehicles after downgrade
const vehiclesWithStatus = await this.vehiclesService.getUserVehiclesWithTierStatus(userId);
// Only return active vehicles (filter out locked ones)
const vehicles = vehiclesWithStatus
.filter(v => v.tierStatus === 'active')
.map(({ tierStatus, ...vehicle }) => vehicle);
return reply.code(200).send(vehicles);
} catch (error) {
logger.error('Error getting user vehicles', { error, userId: (request as any).user?.sub });
@@ -107,20 +112,34 @@ export class VehiclesController {
try {
const userId = (request as any).user.sub;
const { id } = request.params;
// Check tier status - block access to locked vehicles
const vehiclesWithStatus = await this.vehiclesService.getUserVehiclesWithTierStatus(userId);
const vehicleStatus = vehiclesWithStatus.find(v => v.id === id);
if (vehicleStatus && vehicleStatus.tierStatus === 'locked') {
return reply.code(403).send({
error: 'TIER_REQUIRED',
requiredTier: 'pro',
feature: 'vehicle.access',
featureName: 'Vehicle Access',
upgradePrompt: 'Upgrade to Pro to access all your vehicles',
message: 'This vehicle is not available on your current subscription tier'
});
}
const vehicle = await this.vehiclesService.getVehicle(id, userId);
return reply.code(200).send(vehicle);
} catch (error: any) {
logger.error('Error getting vehicle', { error, vehicleId: request.params.id, userId: (request as any).user?.sub });
if (error.message === 'Vehicle not found' || error.message === 'Unauthorized') {
return reply.code(404).send({
error: 'Not Found',
message: 'Vehicle not found'
});
}
return reply.code(500).send({
error: 'Internal server error',
message: 'Failed to get vehicle'