191 lines
5.3 KiB
Dart
191 lines
5.3 KiB
Dart
import 'package:get/get.dart';
|
|
import '../../constant/links.dart';
|
|
import '../functions/crud.dart';
|
|
|
|
class MarketingController extends GetxController {
|
|
bool isLoading = false;
|
|
List priceAnomalies = [];
|
|
List campaignsLog = [];
|
|
|
|
// --- Dynamic Dashboard Configurations ---
|
|
String selectedCountry = 'All'; // 'All', 'SY', 'JO', 'EG', 'IQ'
|
|
bool isAutopilotEnabled = true;
|
|
String systemPrompt = "أنت المحلل الذكي لتطبيق Siro لخدمات نقل الركاب. قمنا برصد قراءات أسعار المنافسين لتقديم عروض وحملات تسويقية ملائمة ومخصصة.";
|
|
|
|
// --- AI API Token & Cost Telemetry ---
|
|
int apiRequestsCount = 0;
|
|
int totalTokensUsed = 0;
|
|
double estimatedCostUSD = 0.0;
|
|
|
|
// --- Price Comparison Data ---
|
|
List hourlyPriceData = [];
|
|
List pciRegions = [];
|
|
Map siroBasePrices = {};
|
|
|
|
// --- Country Selection Handler ---
|
|
void changeCountry(String countryCode) {
|
|
selectedCountry = countryCode;
|
|
fetchAnomalies();
|
|
fetchCampaignsLog();
|
|
fetchPriceComparison();
|
|
}
|
|
|
|
// --- Autopilot Status Toggle ---
|
|
void toggleAutopilot(bool value) {
|
|
isAutopilotEnabled = value;
|
|
update();
|
|
Get.snackbar(
|
|
"Autopilot Updated".tr,
|
|
value ? "Full Autopilot mode enabled".tr : "Approval Mode enabled".tr,
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
);
|
|
}
|
|
|
|
// --- System Prompt Configuration Saver ---
|
|
void savePrompt(String newPrompt) {
|
|
systemPrompt = newPrompt;
|
|
update();
|
|
Get.snackbar(
|
|
"Configuration Saved".tr,
|
|
"Gemini system instructions updated successfully".tr,
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
);
|
|
}
|
|
|
|
Future<void> fetchAnomalies() async {
|
|
isLoading = true;
|
|
update();
|
|
try {
|
|
Map<String, dynamic> params = {};
|
|
if (selectedCountry != 'All') {
|
|
params['country_code'] = selectedCountry;
|
|
}
|
|
|
|
var res = await CRUD().post(
|
|
link: AppLink.getMarketAnomalies,
|
|
payload: params,
|
|
);
|
|
if (res is Map && res['status'] == 'success') {
|
|
priceAnomalies = res['message'] ?? [];
|
|
} else {
|
|
Get.snackbar("Error", "Failed to fetch price anomalies");
|
|
}
|
|
} catch (e) {
|
|
Get.snackbar("Error", "Network error while loading anomalies");
|
|
} finally {
|
|
isLoading = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
Future<void> fetchTelemetry() async {
|
|
try {
|
|
Map<String, dynamic> params = {};
|
|
if (selectedCountry != 'All') {
|
|
params['country_code'] = selectedCountry;
|
|
}
|
|
|
|
var res = await CRUD().post(
|
|
link: AppLink.getTelemetry,
|
|
payload: params,
|
|
);
|
|
if (res is Map && res['status'] == 'success') {
|
|
final data = res['message'];
|
|
if (data is Map) {
|
|
apiRequestsCount = data['api_requests_count'] ?? 0;
|
|
totalTokensUsed = data['total_tokens_used'] ?? 0;
|
|
estimatedCostUSD = (data['estimated_cost_usd'] ?? 0.0).toDouble();
|
|
update();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Silently fail — telemetry is non-critical
|
|
}
|
|
}
|
|
|
|
Future<void> fetchCampaignsLog() async {
|
|
isLoading = true;
|
|
update();
|
|
try {
|
|
Map<String, dynamic> params = {};
|
|
if (selectedCountry != 'All') {
|
|
params['country_code'] = selectedCountry;
|
|
}
|
|
|
|
var res = await CRUD().post(
|
|
link: AppLink.getCampaignsLog,
|
|
payload: params,
|
|
);
|
|
if (res is Map && res['status'] == 'success') {
|
|
campaignsLog = res['message'] ?? [];
|
|
} else {
|
|
Get.snackbar("Error", "Failed to fetch campaign logs");
|
|
}
|
|
} catch (e) {
|
|
Get.snackbar("Error", "Network error while loading campaign logs");
|
|
} finally {
|
|
isLoading = false;
|
|
update();
|
|
}
|
|
}
|
|
|
|
Future<void> fetchPriceComparison() async {
|
|
try {
|
|
Map<String, dynamic> params = {};
|
|
if (selectedCountry != 'All') {
|
|
params['country_code'] = selectedCountry;
|
|
}
|
|
|
|
var res = await CRUD().post(
|
|
link: AppLink.getPriceComparison,
|
|
payload: params,
|
|
);
|
|
if (res is Map && res['status'] == 'success') {
|
|
final data = res['message'];
|
|
if (data is Map) {
|
|
hourlyPriceData = data['hourly_competitor_prices'] ?? [];
|
|
pciRegions = data['pci_regions'] ?? [];
|
|
siroBasePrices = data['siro_base_prices'] is Map
|
|
? data['siro_base_prices'] as Map
|
|
: {};
|
|
update();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Silently fail
|
|
}
|
|
}
|
|
|
|
Future<void> triggerAICampaign() async {
|
|
isLoading = true;
|
|
update();
|
|
try {
|
|
Map<String, dynamic> params = {};
|
|
if (selectedCountry != 'All') {
|
|
params['country_code'] = selectedCountry;
|
|
}
|
|
|
|
var res = await CRUD().post(
|
|
link: AppLink.triggerCampaign,
|
|
payload: params,
|
|
);
|
|
if (res is Map) {
|
|
if (res['status'] == 'success') {
|
|
Get.snackbar("Success", "AI campaign triggered successfully! Promos sent.");
|
|
fetchCampaignsLog();
|
|
fetchTelemetry();
|
|
} else {
|
|
Get.snackbar("Campaign Alert", res['message'] ?? "Campaign rate limited.");
|
|
}
|
|
} else {
|
|
Get.snackbar("Error", "Failed to trigger AI campaign");
|
|
}
|
|
} catch (e) {
|
|
Get.snackbar("Error", "Network error while triggering campaign");
|
|
} finally {
|
|
isLoading = false;
|
|
update();
|
|
}
|
|
}
|
|
}
|