111 lines
3.2 KiB
TypeScript
111 lines
3.2 KiB
TypeScript
import { Paginated } from './purchase';
|
|
|
|
// Nested user on an auth log row (subset of the full User model)
|
|
export interface AuthLogUser {
|
|
id: number;
|
|
uuid: string;
|
|
first_name: string | null;
|
|
last_name: string | null;
|
|
email: string | null;
|
|
mobile: string | null;
|
|
}
|
|
|
|
// One authentication event — matches backend App\Models\AuthLog
|
|
export interface AuthLog {
|
|
id: number;
|
|
user_id: number | null;
|
|
mobile: string | null;
|
|
email: string | null;
|
|
event: AuthEvent;
|
|
package_name: string | null;
|
|
source: number | null;
|
|
success: boolean;
|
|
sms_sent: boolean;
|
|
ip: string | null;
|
|
user_agent: string | null;
|
|
created_at: string;
|
|
updated_at: string;
|
|
user: AuthLogUser | null;
|
|
}
|
|
|
|
// Event keys — must stay in sync with AuthLog::EVENTS on the backend
|
|
export const AUTH_EVENTS = {
|
|
otp_sent: { label: 'ارسال کد ورود (پیامک)', sms: true },
|
|
otp_verified: { label: 'تأیید کد ورود', sms: false },
|
|
otp_failed: { label: 'کد ورود نامعتبر', sms: false },
|
|
mobile_otp_sent: { label: 'ارسال کد تأیید شماره (پیامک)', sms: true },
|
|
mobile_verified: { label: 'تأیید شماره موبایل', sms: false },
|
|
mobile_verify_failed: { label: 'تأیید شماره ناموفق', sms: false },
|
|
login: { label: 'ورود با رمز عبور', sms: false },
|
|
login_failed: { label: 'ورود ناموفق', sms: false },
|
|
register: { label: 'ثبتنام', sms: false },
|
|
google_login: { label: 'ورود با گوگل', sms: false },
|
|
} as const;
|
|
|
|
export type AuthEvent = keyof typeof AUTH_EVENTS;
|
|
|
|
export const getAuthEventLabel = (event: string): string =>
|
|
(AUTH_EVENTS as Record<string, { label: string }>)[event]?.label || event;
|
|
|
|
export interface AuthStatsDaily {
|
|
date: string;
|
|
total: number;
|
|
sms: number;
|
|
otp_sent: number;
|
|
otp_verified: number;
|
|
otp_failed: number;
|
|
}
|
|
|
|
export interface AuthStatsPackage {
|
|
package_name: string;
|
|
sms: number;
|
|
logins: number;
|
|
}
|
|
|
|
export interface AuthStats {
|
|
filters: {
|
|
date_from: string | null;
|
|
date_to: string | null;
|
|
event: string | null;
|
|
package_name: string | null;
|
|
};
|
|
totals: {
|
|
events: number;
|
|
unique_mobiles: number;
|
|
unique_users: number;
|
|
sms_sent: number;
|
|
sms_cost: number;
|
|
sms_unit_cost: number;
|
|
otp_sent: number;
|
|
otp_verified: number;
|
|
otp_failed: number;
|
|
otp_conversion_rate: number;
|
|
logins: number;
|
|
registers: number;
|
|
};
|
|
by_event: Record<string, number>;
|
|
by_package: AuthStatsPackage[];
|
|
daily: AuthStatsDaily[];
|
|
}
|
|
|
|
// Filters shared by the auth-logs and auth-stats endpoints
|
|
export interface AuthLogFilters {
|
|
event?: string;
|
|
mobile?: string;
|
|
email?: string;
|
|
package_name?: string;
|
|
success?: boolean;
|
|
sms_only?: boolean;
|
|
// Date/time window on created_at (Y-m-d dates, H:i(:s) times, Tehran-local)
|
|
date_from?: string;
|
|
date_to?: string;
|
|
time_from?: string;
|
|
time_to?: string;
|
|
// Only used by the stats endpoint, to price the SMS total
|
|
sms_unit_cost?: number;
|
|
per_page?: number;
|
|
page?: number;
|
|
}
|
|
|
|
export type PaginatedAuthLogs = Paginated<AuthLog>;
|