mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
feat: add web campaign links — capture, auth integration, bonus UI
- Add campaign.ts utility (capture from URL, localStorage with TTL, validation) - Pass campaign_slug in all auth API methods (telegram, widget, email, oauth) - Consume slug in auth store login methods, set pendingCampaignBonus state - Add CampaignBonusNotifier component (toast on bonus, mounted in AppShell) - Show web_link alongside bot deep_link in AdminCampaignStats - Add CampaignBonusInfo type with union bonus_type - Fix VerifyEmail: ref guard against StrictMode double-fire, setTimeout cleanup - Fix AdminCampaignStats: setTimeout refs with cleanup, i18n-aware locale - Wrap all localStorage access in try/catch (Safari private browsing safety) - Add campaignBonus translations (ru/en/fa/zh)
This commit is contained in:
@@ -3,32 +3,44 @@ import type { AuthResponse, OAuthProvider, RegisterResponse, TokenResponse, User
|
||||
|
||||
export const authApi = {
|
||||
// Telegram WebApp authentication
|
||||
loginTelegram: async (initData: string): Promise<AuthResponse> => {
|
||||
loginTelegram: async (initData: string, campaignSlug?: string | null): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>('/cabinet/auth/telegram', {
|
||||
init_data: initData,
|
||||
campaign_slug: campaignSlug || undefined,
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Telegram Login Widget authentication
|
||||
loginTelegramWidget: async (data: {
|
||||
id: number;
|
||||
first_name: string;
|
||||
last_name?: string;
|
||||
username?: string;
|
||||
photo_url?: string;
|
||||
auth_date: number;
|
||||
hash: string;
|
||||
}): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>('/cabinet/auth/telegram/widget', data);
|
||||
loginTelegramWidget: async (
|
||||
data: {
|
||||
id: number;
|
||||
first_name: string;
|
||||
last_name?: string;
|
||||
username?: string;
|
||||
photo_url?: string;
|
||||
auth_date: number;
|
||||
hash: string;
|
||||
},
|
||||
campaignSlug?: string | null,
|
||||
): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>('/cabinet/auth/telegram/widget', {
|
||||
...data,
|
||||
campaign_slug: campaignSlug || undefined,
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Email login
|
||||
loginEmail: async (email: string, password: string): Promise<AuthResponse> => {
|
||||
loginEmail: async (
|
||||
email: string,
|
||||
password: string,
|
||||
campaignSlug?: string | null,
|
||||
): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>('/cabinet/auth/email/login', {
|
||||
email,
|
||||
password,
|
||||
campaign_slug: campaignSlug || undefined,
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
@@ -62,8 +74,11 @@ export const authApi = {
|
||||
},
|
||||
|
||||
// Verify email and get auth tokens
|
||||
verifyEmail: async (token: string): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>('/cabinet/auth/email/verify', { token });
|
||||
verifyEmail: async (token: string, campaignSlug?: string | null): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>('/cabinet/auth/email/verify', {
|
||||
token,
|
||||
campaign_slug: campaignSlug || undefined,
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
@@ -146,10 +161,15 @@ export const authApi = {
|
||||
},
|
||||
|
||||
// OAuth: callback (exchange code for tokens)
|
||||
oauthCallback: async (provider: string, code: string, state: string): Promise<AuthResponse> => {
|
||||
oauthCallback: async (
|
||||
provider: string,
|
||||
code: string,
|
||||
state: string,
|
||||
campaignSlug?: string | null,
|
||||
): Promise<AuthResponse> => {
|
||||
const response = await apiClient.post<AuthResponse>(
|
||||
`/cabinet/auth/oauth/${encodeURIComponent(provider)}/callback`,
|
||||
{ code, state },
|
||||
{ code, state, campaign_slug: campaignSlug || undefined },
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
@@ -44,6 +44,7 @@ export interface CampaignDetail {
|
||||
created_at: string;
|
||||
updated_at: string | null;
|
||||
deep_link: string | null;
|
||||
web_link: string | null;
|
||||
}
|
||||
|
||||
export interface CampaignCreateRequest {
|
||||
@@ -104,6 +105,7 @@ export interface CampaignStatistics {
|
||||
conversion_rate: number;
|
||||
trial_conversion_rate: number;
|
||||
deep_link: string | null;
|
||||
web_link: string | null;
|
||||
}
|
||||
|
||||
export interface CampaignRegistrationItem {
|
||||
|
||||
Reference in New Issue
Block a user