Files
sendico/frontend/pweb/lib/services/amplitude.dart
2025-11-13 15:06:15 +03:00

210 lines
7.8 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:amplitude_flutter/amplitude.dart';
import 'package:amplitude_flutter/configuration.dart';
import 'package:amplitude_flutter/constants.dart' as amp;
import 'package:amplitude_flutter/events/base_event.dart';
import 'package:flutter/widgets.dart';
import 'package:pshared/models/account/account.dart';
import 'package:pshared/models/payment/type.dart';
import 'package:pshared/models/recipient/status.dart';
import 'package:pshared/models/recipient/type.dart';
import 'package:pweb/widgets/sidebar/destinations.dart';
class AmplitudeService {
static late Amplitude _analytics;
static Amplitude _amp() => _analytics;
static Future<void> initialize() async {
_analytics = Amplitude(Configuration(
apiKey: '12345', //TODO define through App Contants
serverZone: amp.ServerZone.eu, //TODO define through App Contants
));
await _analytics.isBuilt;
}
static Future<void> identify(Account account) async =>
_amp().setUserId(account.id);
static Future<void> login(Account account) async =>
_logEvent(
'login',
userProperties: {
// 'email': account.email, TODO Add email into account
'locale': account.locale,
},
);
static Future<void> logout() async => _logEvent("logout");
static Future<void> pageOpened(PayoutDestination page, {String? path, String? uiSource}) async {
return _logEvent("pageOpened", eventProperties: {
"page": page,
if (path != null) "path": path,
if (uiSource != null) "uiSource": uiSource,
});
}
//TODO Add when registration is ready. User properties {user_id, registration_date, has_wallet (true/false), wallet_balance (should concider loggin it as: 0 / <100 / 100500 / 500+), preferred_method (Wallet/Card/Bank/IBAN), total_transactions, total_amount, last_payout_date, last_login_date , marketing_source}
// static Future<void> registrationStarted(String method, String country) async =>
// _logEvent("registrationStarted", eventProperties: {"method": method, "country": country});
// static Future<void> registrationCompleted(String method, String country) async =>
// _logEvent("registrationCompleted", eventProperties: {"method": method, "country": country});
static Future<void> pageNotFound(String url) async =>
_logEvent("pageNotFound", eventProperties: {"url": url});
static Future<void> localeChanged(Locale locale) async =>
_logEvent("localeChanged", eventProperties: {"locale": locale.toString()});
static Future<void> localeMatched(String locale, bool haveRequested) async => //DO we need it?
_logEvent("localeMatched", eventProperties: {
"locale": locale,
"have_requested_locale": haveRequested
});
static Future<void> recipientAddStarted() async =>
_logEvent("recipientAddStarted");
static Future<void> recipientAddCompleted(
RecipientType type,
RecipientStatus status,
Set<PaymentType> methods,
) async {
_logEvent(
"recipientAddCompleted",
eventProperties: {
"methods": methods.map((m) => m.name).toList(),
"type": type.name,
"status": status.name,
},
);
}
static Future<void> _paymentEvent(
String evt,
double amount,
double fee,
bool payerCoversFee,
PaymentType source,
PaymentType recpientPaymentMethod, {
String? message,
String? errorType,
Map<String, dynamic>? extraProps,
}) async {
final props = {
"amount": amount,
"fee": fee,
"feeCoveredBy": payerCoversFee ? 'payer' : 'recipient',
"source": source,
"recipient_method": recpientPaymentMethod,
if (message != null) "message": message,
if (errorType != null) "error_type": errorType,
if (extraProps != null) ...extraProps,
};
return _logEvent(evt, eventProperties: props);
}
static Future<void> paymentPrepared(double amount, double fee,
bool payerCoversFee, PaymentType source, PaymentType recpientPaymentMethod) async =>
_paymentEvent("paymentPrepared", amount, fee, payerCoversFee, source, recpientPaymentMethod);
//TODO Rework paymentStarted (do i need all those properties or is the event enough? Mb properties should be passed at paymentPrepared)
static Future<void> paymentStarted(double amount, double fee,
bool payerCoversFee, PaymentType source, PaymentType recpientPaymentMethod) async =>
_paymentEvent("paymentStarted", amount, fee, payerCoversFee, source, recpientPaymentMethod);
static Future<void> paymentFailed(double amount, double fee, bool payerCoversFee,
PaymentType source, PaymentType recpientPaymentMethod, String errorType, String message) async =>
_paymentEvent("paymentFailed", amount, fee, payerCoversFee, source, recpientPaymentMethod,
errorType: errorType, message: message);
static Future<void> paymentError(double amount, double fee, bool payerCoversFee,
PaymentType source,PaymentType recpientPaymentMethod, String message) async =>
_paymentEvent("paymentError", amount, fee, payerCoversFee, source, recpientPaymentMethod,
message: message);
static Future<void> paymentSuccess({
required double amount,
required double fee,
required bool payerCoversFee,
required PaymentType source,
required PaymentType recpientPaymentMethod,
required String transactionId,
String? comment,
required int durationMs,
}) async {
return _paymentEvent(
"paymentSuccess",
amount,
fee,
payerCoversFee,
source,
recpientPaymentMethod,
message: comment,
extraProps: {
"transaction_id": transactionId,
"duration_ms": durationMs, //How do i calculate duration here?
"\$revenue": amount, //How do i calculate revenue here?
"\$revenueType": "payment", //Do we need to get revenue type?
},
);
}
//TODO add when support is ready
// static Future<void> supportOpened(String fromPage, String trigger) async =>
// _logEvent("supportOpened", eventProperties: {"from_page": fromPage, "trigger": trigger});
// static Future<void> supportMessageSent(String category, bool resolved) async =>
// _logEvent("supportMessageSent", eventProperties: {"category": category, "resolved": resolved});
static Future<void> walletTopUp(double amount, PaymentType method) async =>
_logEvent("walletTopUp", eventProperties: {"amount": amount, "method": method});
//TODO Decide do we need uiElementClicked or pageOpened is enough?
static Future<void> uiElementClicked(String elementName, String page, String uiSource) async =>
_logEvent("uiElementClicked", eventProperties: {
"element_name": elementName,
"page": page,
"uiSource": uiSource
});
static final Map<String, int> _stepStartTimes = {};
//TODO Consider it as part of payment flow or registration flow or adding recipient and rework accordingly
static Future<void> stepStarted(String stepName, {String? context}) async {
_stepStartTimes[stepName] = DateTime.now().millisecondsSinceEpoch;
return _logEvent("stepStarted", eventProperties: {
"step_name": stepName,
if (context != null) "context": context,
});
}
static Future<void> stepCompleted(String stepName, bool success) async {
final now = DateTime.now().millisecondsSinceEpoch;
final start = _stepStartTimes[stepName] ?? now;
final duration = now - start;
return _logEvent("stepCompleted", eventProperties: {
"step_name": stepName,
"duration_ms": duration,
"success": success
});
}
static Future<void> _logEvent(
String eventType, {
Map<String, dynamic>? eventProperties,
Map<String, dynamic>? userProperties,
}) async {
final event = BaseEvent(
eventType,
eventProperties: eventProperties,
userProperties: userProperties,
);
_amp().track(event);
print(event.toString()); //TODO delete when everything is ready
}
}