доразметка событий на гпт4.1
This commit is contained in:
parent
181d89e733
commit
3c925708ab
@ -77,7 +77,7 @@ const AppContent: React.FC = () => {
|
||||
else if (hasSeenOnboarding && !hasAcceptedTerms && !location.pathname.includes('/onboarding/terms')) {
|
||||
navigate('/onboarding/terms');
|
||||
}
|
||||
}, [navigate, location.pathname]);
|
||||
}, []);
|
||||
|
||||
// Отслеживаем изменение маршрута для аналитики
|
||||
useEffect(() => {
|
||||
|
||||
@ -46,6 +46,7 @@ const BlockRenderer: React.FC<BlockRendererProps> = ({ block, onAction, extraPro
|
||||
);
|
||||
return () => URL.revokeObjectURL(tempUrl);
|
||||
}}
|
||||
onAction={onAction}
|
||||
/>;
|
||||
case 'divider':
|
||||
return <DividerBlock block={block as DividerBlockType} />;
|
||||
|
||||
@ -6,9 +6,10 @@ import { getTranslation } from '../../constants/translations';
|
||||
interface UploadPhotoBlockProps {
|
||||
onPhotoSelect?: (file: File) => void;
|
||||
previewUrl?: string;
|
||||
onAction?: (actionType: string, actionValue: string, blockId?: string, buttonId?: string) => void;
|
||||
}
|
||||
|
||||
const UploadPhotoBlock: React.FC<UploadPhotoBlockProps> = ({ onPhotoSelect, previewUrl }) => {
|
||||
const UploadPhotoBlock: React.FC<UploadPhotoBlockProps> = ({ onPhotoSelect, previewUrl, onAction }) => {
|
||||
const navigate = useNavigate();
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
@ -19,6 +20,11 @@ const UploadPhotoBlock: React.FC<UploadPhotoBlockProps> = ({ onPhotoSelect, prev
|
||||
localStorage.removeItem('stickerPreviewUrl');
|
||||
localStorage.removeItem('stickerImageData');
|
||||
|
||||
// Отправляем событие аналитики, если передан onAction
|
||||
if (typeof onAction === 'function') {
|
||||
onAction('uploadPhoto', '', undefined, undefined);
|
||||
}
|
||||
|
||||
onPhotoSelect?.(file);
|
||||
navigate('/crop-photo', { state: { file } });
|
||||
}
|
||||
|
||||
@ -8,6 +8,9 @@ import { getCurrentUserId } from '../../constants/user';
|
||||
interface GenerationButtonProps {
|
||||
onStartGeneration: () => void;
|
||||
isGenerating: boolean;
|
||||
presetName?: string;
|
||||
memeId?: string;
|
||||
emotionType?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -15,7 +18,10 @@ interface GenerationButtonProps {
|
||||
*/
|
||||
const GenerationButton: React.FC<GenerationButtonProps> = ({
|
||||
onStartGeneration,
|
||||
isGenerating
|
||||
isGenerating,
|
||||
presetName,
|
||||
memeId,
|
||||
emotionType
|
||||
}) => {
|
||||
// Находим блок кнопки генерации в конфигурации
|
||||
const generateButton = homeScreenConfig.homeScreen.blocks.find(block => block.type === 'generateButton');
|
||||
@ -28,11 +34,20 @@ const GenerationButton: React.FC<GenerationButtonProps> = ({
|
||||
const handleAction = (actionType: string, actionValue: string) => {
|
||||
if (actionType === 'function' && actionValue === 'startGeneration' && !isGenerating) {
|
||||
// Отслеживаем событие нажатия на кнопку генерации
|
||||
// Аналитика: пресет или мем
|
||||
if (emotionType === 'memes' && memeId) {
|
||||
customAnalyticsService.trackEvent({
|
||||
telegram_id: getCurrentUserId(),
|
||||
event_category: 'generation',
|
||||
event_name: 'generate_button_click'
|
||||
event_category: 'generation_meme',
|
||||
event_name: memeId
|
||||
});
|
||||
} else if (presetName) {
|
||||
customAnalyticsService.trackEvent({
|
||||
telegram_id: getCurrentUserId(),
|
||||
event_category: 'generation_preset',
|
||||
event_name: presetName
|
||||
});
|
||||
}
|
||||
|
||||
onStartGeneration();
|
||||
}
|
||||
|
||||
@ -37,6 +37,17 @@ const PresetSelector: React.FC<PresetSelectorProps> = ({
|
||||
// Обработчик выбора пресета
|
||||
const handleAction = (actionType: string, actionValue: string, blockId?: string, buttonId?: string) => {
|
||||
if (actionType === 'selectPreset') {
|
||||
// Отправляем событие выбора пресета
|
||||
import('../../services/customAnalyticsService').then(({ default: customAnalyticsService }) => {
|
||||
import('../../constants/user').then(({ getCurrentUserId }) => {
|
||||
customAnalyticsService.trackEvent({
|
||||
telegram_id: getCurrentUserId(),
|
||||
event_category: 'generation',
|
||||
event_name: 'preset_select',
|
||||
unit: actionValue
|
||||
});
|
||||
});
|
||||
});
|
||||
onPresetSelect(actionValue, buttonId);
|
||||
} else if (actionType === 'function' && actionValue === 'toggleInput') {
|
||||
onToggleInput();
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import TokenPacksModal from './TokenPacksModal';
|
||||
import { paymentService } from '../../services/paymentService';
|
||||
import { tokenPacks } from '../../constants/tokenPacks';
|
||||
import { useBalance } from '../../contexts/BalanceContext';
|
||||
import { updateBalanceWithRetries } from '../../utils/balanceUtils';
|
||||
import customAnalyticsService from '../../services/customAnalyticsService';
|
||||
import { getCurrentUserId } from '../../constants/user';
|
||||
|
||||
interface TokenPacksModalContainerProps {
|
||||
isVisible: boolean;
|
||||
@ -24,6 +26,7 @@ const TokenPacksModalContainer: React.FC<TokenPacksModalContainerProps> = ({
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { updateBalance } = useBalance();
|
||||
const attemptedRef = useRef(false);
|
||||
|
||||
/**
|
||||
* Обработчик покупки пакета токенов
|
||||
@ -32,6 +35,14 @@ const TokenPacksModalContainer: React.FC<TokenPacksModalContainerProps> = ({
|
||||
const pack = tokenPacks.find(p => p.id === packId);
|
||||
if (!pack) return;
|
||||
|
||||
// Аналитика: попытка оплаты
|
||||
customAnalyticsService.trackEvent({
|
||||
telegram_id: getCurrentUserId(),
|
||||
event_category: 'payment',
|
||||
event_name: 'purchase_attempt'
|
||||
});
|
||||
attemptedRef.current = true;
|
||||
|
||||
onClose();
|
||||
|
||||
paymentService.showBuyTokensPopup(pack, async (userData) => {
|
||||
@ -45,18 +56,34 @@ const TokenPacksModalContainer: React.FC<TokenPacksModalContainerProps> = ({
|
||||
});
|
||||
}, [onClose, updateBalance, onSuccess]);
|
||||
|
||||
/**
|
||||
* Обработчик отмены/закрытия модалки
|
||||
*/
|
||||
const handleClose = useCallback(() => {
|
||||
if (!attemptedRef.current) {
|
||||
// Аналитика: отмена оплаты
|
||||
customAnalyticsService.trackEvent({
|
||||
telegram_id: getCurrentUserId(),
|
||||
event_category: 'payment',
|
||||
event_name: 'purchase_cancel'
|
||||
});
|
||||
}
|
||||
onClose();
|
||||
attemptedRef.current = false;
|
||||
}, [onClose]);
|
||||
|
||||
/**
|
||||
* Обработчик нажатия на кнопку "Показать все пакеты"
|
||||
*/
|
||||
const handleShowAllPacks = useCallback(() => {
|
||||
onClose();
|
||||
handleClose();
|
||||
navigate('/profile');
|
||||
}, [onClose, navigate]);
|
||||
}, [handleClose, navigate]);
|
||||
|
||||
return (
|
||||
<TokenPacksModal
|
||||
isVisible={isVisible}
|
||||
onClose={onClose}
|
||||
onClose={handleClose}
|
||||
onShowAllPacks={handleShowAllPacks}
|
||||
missingTokens={missingTokens}
|
||||
onBuyPack={handleBuyPack}
|
||||
|
||||
@ -265,6 +265,17 @@ const CropPhoto: React.FC = () => {
|
||||
// Убираем префикс data:image/jpeg;base64, оставляем только данные
|
||||
const imageData = previewUrl.split(',')[1];
|
||||
|
||||
// Отправляем событие применения обрезки
|
||||
import('../services/customAnalyticsService').then(({ default: customAnalyticsService }) => {
|
||||
import('../constants/user').then(({ getCurrentUserId }) => {
|
||||
customAnalyticsService.trackEvent({
|
||||
telegram_id: getCurrentUserId(),
|
||||
event_category: 'photo',
|
||||
event_name: 'crop_photo_apply'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Сохраняем данные в localStorage для навигации между страницами
|
||||
localStorage.setItem('stickerPreviewUrl', previewUrl);
|
||||
localStorage.setItem('stickerImageData', imageData);
|
||||
|
||||
@ -252,6 +252,9 @@ const Home: React.FC = () => {
|
||||
<GenerationButton
|
||||
onStartGeneration={startGeneration}
|
||||
isGenerating={isGenerating}
|
||||
presetName={selectedPresetId}
|
||||
memeId={selectedMemeId}
|
||||
emotionType={selectedEmotionType}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user