feature: dashboard settings and invite activation flow consistency fixed. frontend warnings fixed
This commit is contained in:
@@ -48,8 +48,9 @@ export class AuthService {
|
||||
*/
|
||||
async validateUser(email: string, password: string): Promise<any> {
|
||||
try {
|
||||
const normalizedEmail = email.trim().toLowerCase();
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { email },
|
||||
where: { email: normalizedEmail },
|
||||
include: {
|
||||
memberships: {
|
||||
include: {
|
||||
@@ -147,6 +148,7 @@ export class AuthService {
|
||||
? {
|
||||
name: membership.organization.plan.name,
|
||||
maxUsers: membership.organization.plan.maxUsers,
|
||||
price: membership.organization.plan.price,
|
||||
}
|
||||
: undefined,
|
||||
}));
|
||||
@@ -177,7 +179,8 @@ export class AuthService {
|
||||
* @returns Created user info without password
|
||||
*/
|
||||
async register(registerDto: RegisterDto) {
|
||||
const { email, password, name, organizationName, organizationEmail, organizationType } = registerDto;
|
||||
const { password, name, organizationName, organizationEmail, organizationType } = registerDto;
|
||||
const email = registerDto.email.trim().toLowerCase();
|
||||
|
||||
// 1. Check existing user
|
||||
const existingUser = await this.prisma.user.findUnique({
|
||||
@@ -354,6 +357,7 @@ export class AuthService {
|
||||
? {
|
||||
name: membership.organization.plan.name,
|
||||
maxUsers: membership.organization.plan.maxUsers,
|
||||
price: membership.organization.plan.price,
|
||||
}
|
||||
: undefined,
|
||||
}));
|
||||
@@ -474,6 +478,7 @@ export class AuthService {
|
||||
? {
|
||||
name: membership.organization.plan.name,
|
||||
maxUsers: membership.organization.plan.maxUsers,
|
||||
price: membership.organization.plan.price,
|
||||
}
|
||||
: undefined,
|
||||
}));
|
||||
@@ -680,6 +685,7 @@ export class AuthService {
|
||||
? {
|
||||
name: membership.organization.plan.name,
|
||||
maxUsers: membership.organization.plan.maxUsers,
|
||||
price: membership.organization.plan.price,
|
||||
}
|
||||
: undefined,
|
||||
}));
|
||||
@@ -759,6 +765,7 @@ export class AuthService {
|
||||
? {
|
||||
name: membership.organization.plan.name,
|
||||
maxUsers: membership.organization.plan.maxUsers,
|
||||
price: membership.organization.plan.price,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
@@ -770,7 +777,12 @@ export class AuthService {
|
||||
memberships: Array<{
|
||||
isOwner: boolean;
|
||||
isActive: boolean;
|
||||
organization: { id: string; name: string; type: { name: string }; plan?: { name: string; maxUsers: number } | null };
|
||||
organization: {
|
||||
id: string;
|
||||
name: string;
|
||||
type: { name: string };
|
||||
plan?: { name: string; maxUsers: number; price: number } | null;
|
||||
};
|
||||
permissions?: Array<{ permission: { name: string } }>;
|
||||
}> = [],
|
||||
) {
|
||||
@@ -790,6 +802,8 @@ export class AuthService {
|
||||
seatsLow: false,
|
||||
trialEndingSoon: false,
|
||||
trialExpired: false,
|
||||
daysUntilPlanEnd: null,
|
||||
planEndsAt: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -811,6 +825,8 @@ export class AuthService {
|
||||
seatsLow: false,
|
||||
trialEndingSoon: false,
|
||||
trialExpired: false,
|
||||
daysUntilPlanEnd: null,
|
||||
planEndsAt: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -830,23 +846,16 @@ export class AuthService {
|
||||
const seatsLow =
|
||||
!unlimited && remaining >= 0 && remaining <= 2 && maxUsers > 0;
|
||||
|
||||
let trialEndingSoon = false;
|
||||
let trialExpired = false;
|
||||
let daysUntilTrialEnd: number | null = null;
|
||||
let trialEndsAt: string | null = null;
|
||||
// Current pricing model: trial lasts 30 days; paid plans last 90 days.
|
||||
const durationDays = plan.name === 'trial' ? 30 : 90;
|
||||
const end = new Date(org.createdAt);
|
||||
end.setDate(end.getDate() + durationDays);
|
||||
const planEndsAt = end.toISOString();
|
||||
const ms = end.getTime() - Date.now();
|
||||
const daysUntilPlanEnd = Math.ceil(ms / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (plan.name === 'trial') {
|
||||
const end = new Date(org.createdAt);
|
||||
end.setDate(end.getDate() + 30);
|
||||
trialEndsAt = end.toISOString();
|
||||
const ms = end.getTime() - Date.now();
|
||||
daysUntilTrialEnd = Math.ceil(ms / (1000 * 60 * 60 * 24));
|
||||
if (daysUntilTrialEnd <= 0) {
|
||||
trialExpired = true;
|
||||
} else if (daysUntilTrialEnd <= 7) {
|
||||
trialEndingSoon = true;
|
||||
}
|
||||
}
|
||||
const trialExpired = plan.name === 'trial' && daysUntilPlanEnd <= 0;
|
||||
const trialEndingSoon = plan.name === 'trial' && daysUntilPlanEnd > 0 && daysUntilPlanEnd <= 7;
|
||||
|
||||
const showWarning = seatsLow || trialEndingSoon || trialExpired;
|
||||
|
||||
@@ -859,8 +868,10 @@ export class AuthService {
|
||||
trialExpired,
|
||||
seatsUsed,
|
||||
seatsLimit: maxUsers,
|
||||
daysUntilTrialEnd,
|
||||
trialEndsAt,
|
||||
daysUntilTrialEnd: plan.name === 'trial' ? daysUntilPlanEnd : null,
|
||||
trialEndsAt: plan.name === 'trial' ? planEndsAt : null,
|
||||
daysUntilPlanEnd,
|
||||
planEndsAt,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user