Commit b35acfea authored by Sai Srinivas's avatar Sai Srinivas
Browse files

local fix

parents ebb11608 2a087139
......@@ -757,14 +757,17 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
notifyListeners();
}
onChangeCompanyName(value) {
companynameError = "";
// onChangeCompanyName(value) {
// companynameError = "";
// notifyListeners();
// }
onChangeContactPersonName(value) {
nameError = "";
notifyListeners();
}
onChangeAlternatemobile(value) {
AlternatemobileError = "";
notifyListeners();
......@@ -775,22 +778,22 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
notifyListeners();
}
Future<void> onChangeContactPersonName(BuildContext context, String value) async {
nameError = "";
Future<void> onChangeCompanyName(BuildContext context, String value) async {
companynameError = "";
if (value.isEmpty) {
nameError = "Name cannot be empty";
companynameError = "Company Name cannot be empty";
} else if (value.length < 3) {
nameError = "Name must be at least 3 characters";
companynameError = "Company Name must be at least 3 characters";
} else {
final exists = await checkAccountFieldExistence(
context,
type: "name",
type: "company",
typeValue: value,
);
if (!exists) {
nameError = "Name already exists";
companynameError = "Company Name already exists";
} else {
nameError = null;
companynameError = null;
}
}
notifyListeners();
......@@ -997,7 +1000,7 @@ class Addnewleadsandprospectsprovider extends ChangeNotifier {
isValid = false;
}
if(nameError == "Name already exists"){
if(companynameError == "Company Name already exists"){
isValid = false;
}
......
......@@ -34,16 +34,26 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
List<Teams> get teamsList => _teamsList;
List<Segments> get segmentsList => _segmentsList;
Teams? get selectedTeams => _selectedTeams;
Segments? get selectedSegments => _selectedSegments;
// IMPORTANT: Return null if the selected object is not present in the current list.
// This prevents DropdownButton2 from receiving a value that is not part of items.
Teams? get selectedTeams {
if (_selectedTeams == null) return null;
if (!_teamsList.contains(_selectedTeams)) return null;
return _selectedTeams;
}
Segments? get selectedSegments {
if (_selectedSegments == null) return null;
if (!_segmentsList.contains(_selectedSegments)) return null;
return _selectedSegments;
}
AccountDetails get accountsDetails => _accountDetails;
String? get selectedTeamId => _selectedTeamId;
String? get selectedTeamValue => _selectedTeamValue;
String? get selectedSegmentId => _selectedSegmentId;
String? get selectedSegmentValue => _selectedSegmentValue;
set isLoading(bool value) {
......@@ -68,15 +78,25 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
set selectedTeams(Teams? value) {
_selectedTeams = value;
_selectedTeamId = value!.id!;
_selectedTeamValue = value.name;
if (value != null) {
_selectedTeamId = value.id;
_selectedTeamValue = value.name;
} else {
_selectedTeamId = null;
_selectedTeamValue = null;
}
notifyListeners();
}
set selectedSegments(Segments? value) {
_selectedSegments = value;
_selectedSegmentId = value!.id!;
_selectedSegmentValue = value.name;
if (value != null) {
_selectedSegmentId = value.id;
_selectedSegmentValue = value.name;
} else {
_selectedSegmentId = null;
_selectedSegmentValue = null;
}
notifyListeners();
}
......@@ -101,10 +121,10 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
}
Future<void> crmLeadDetailsEditAccountAPIFunction(
context,
leadID,
mode,
) async {
context,
leadID,
mode,
) async {
try {
var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsEditAccountViewAPI(
......@@ -117,8 +137,21 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
notifyListeners();
if (data != null) {
if (data.error == "0") {
_teamsList = data.teams!;
_accountDetails = data.accountDetails!;
_teamsList = data.teams ?? [];
_accountDetails = data.accountDetails ?? AccountDetails();
// If current selected team/segment are not in the new lists, clear them
if (_selectedTeams != null && !_teamsList.contains(_selectedTeams)) {
_selectedTeams = null;
_selectedTeamId = null;
_selectedTeamValue = null;
}
if (_selectedSegments != null && !_segmentsList.contains(_selectedSegments)) {
_selectedSegments = null;
_selectedSegmentId = null;
_selectedSegmentValue = null;
}
_isLoading = false;
notifyListeners();
} else {
......@@ -136,10 +169,10 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
}
Future<void> crmLeadListSegmentOnTeamAPIFunction(
context,
mode,
teamID,
) async {
context,
mode,
teamID,
) async {
try {
var prov = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmLeadListSegmentOnTeamAPI(
......@@ -149,23 +182,43 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
);
if (data != null) {
if (data.error == "0") {
_segmentsList = data.segments!;
_segmentsList = data.segments ?? [];
// clear selectedSegments if it's not part of new list
if (_selectedSegments != null && !_segmentsList.contains(_selectedSegments)) {
_selectedSegments = null;
_selectedSegmentId = null;
_selectedSegmentValue = null;
}
notifyListeners();
}
}
} catch (e) {}
}
// Fixed: check string emptiness properly (IDs are strings in your model)
bool get isFormValid {
final nameOk = editCompanyNameController.text.trim().isNotEmpty;
final teamOk = _selectedTeamId != null && _selectedTeamId!.isNotEmpty;
final segmentOk = _selectedSegmentId != null && _selectedSegmentId!.isNotEmpty;
return nameOk && teamOk && segmentOk;
}
Future<void> crmLeadDetailsEditAccountSubmitAPIFunction(
context,
accountId,
segmentId,
teamId,
) async {
context,
accountId,
segmentId,
teamId,
) async {
try {
if (!validateForm(context)) {
return;
}
_isLoading = true;
notifyListeners();
var HomeProv = Provider.of<HomescreenNotifier>(context, listen: false);
final data = await ApiCalling.crmLeadDetailsEditAccountSubmitAPI(
HomeProv.empId,
......@@ -175,8 +228,7 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
teamId,
editCompanyNameController.text,
);
_isLoading = true;
notifyListeners();
if (data != null) {
if (data.error == "0") {
Navigator.pop(context, true);
......@@ -200,19 +252,24 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
bool validateForm(BuildContext context) {
// Reset all errors
_companyNameError = null;
_selectedTeamError = null;
_selectedSegmentError = null;
bool isValid = true;
if (_selectedTeams == null || _selectedTeamId!.isEmpty) {
_selectedTeamError = "Please select an account";
// Team checks
if (_selectedTeams == null || _selectedTeamId == null || _selectedTeamId!.isEmpty) {
_selectedTeamError = "Please select a team";
isValid = false;
}
if (_selectedSegments == null || _selectedSegmentId!.isEmpty) {
_selectedSegmentError = "Please select an account";
// Segment checks
if (_selectedSegments == null || _selectedSegmentId == null || _selectedSegmentId!.isEmpty) {
_selectedSegmentError = "Please select a segment";
isValid = false;
}
// Company name check
if (editCompanyNameController.text.trim().isEmpty) {
_companyNameError = "Please enter Company name";
isValid = false;
......@@ -223,7 +280,12 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
}
onChangedCompanyName(value) {
_companyNameError = "";
// Clear the company name error when user types
if (value != null && value.toString().trim().isNotEmpty) {
_companyNameError = null;
} else {
_companyNameError = "Name is required";
}
notifyListeners();
}
......@@ -236,11 +298,13 @@ class Editcrmaccountdetailsprovider extends ChangeNotifier {
_selectedSegmentId = null;
_selectedTeamValue = null;
_selectedSegmentValue = null;
_selectedTeamError = null;
_selectedSegmentError = null;
_companyNameError = null;
}
void checkDropDownValues() {
if (!_segmentsList.contains(_selectedSegments) &&
_selectedSegments != null) {
if (!_segmentsList.contains(_selectedSegments) && _selectedSegments != null) {
_selectedTeamId = null;
_selectedTeamValue = null;
}
......
......@@ -184,6 +184,12 @@ class Loginnotifier extends ChangeNotifier {
SharedpreferencesService().saveString("UserName", data.name!);
SharedpreferencesService().saveString("UserEmail", data.emailId!);
SharedpreferencesService().saveString("Session_id", data.sessionId!);
SharedpreferencesService().saveString("user", data.userId!);
SharedpreferencesService().saveString("session", data.sessionId!);
print("USER ID : ${data.userId}");
print("SESSISON ID: ${data.sessionId}");
var roles = data.permissions!.toString();
SharedpreferencesService().saveString("roles", roles);
......
// lib/services/background_location_service.dart
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:geolocator/geolocator.dart';
import 'package:provider/provider.dart';
import '../Notifiers/HomeScreenNotifier.dart';
import '../services/api_calling.dart';
import 'SharedpreferencesService.dart';
@pragma('vm:entry-point')
void startCallback() {
FlutterForegroundTask.setTaskHandler(LocationTaskHandler());
}
class LocationTaskHandler extends TaskHandler {
StreamSubscription<Position>? _stream;
String? _empId;
String? _sessionId;
@override
Future<void> onStart(DateTime timestamp, TaskStarter starter) async {
// Load user data
_empId = await SharedpreferencesService().getString("user");
_sessionId = await SharedpreferencesService().getString("session");
// var prov = Provider.of<HomescreenNotifier>(context, listen: false);
// _empId = prov.empId;
// _sessionId = prov.session;
print("DATA : ${_empId}");
print("DATA : ${_sessionId}");
if (_empId == null || _sessionId == null) {
FlutterForegroundTask.updateService(
notificationTitle: "GEN ERP",
notificationText: "Please login first",
);
return;
}
// Start real-time location stream (when moving)
_stream = Geolocator.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 20, // Only send if moved 20 meters
),
).listen((position) {
_sendLocationToApi(position);
});
// Send first location immediately
_sendCurrentLocationOnce();
FlutterForegroundTask.updateService(
notificationTitle: "GEN ERP",
notificationText: "Live tracking active",
);
}
Future<void> _sendCurrentLocationOnce() async {
try {
final position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
timeLimit: const Duration(seconds: 15),
);
await _sendLocationToApi(position);
} catch (e) {
if (kDebugMode) print("Initial location failed: $e");
}
}
Future<void> _sendLocationToApi(Position position) async {
final location = "${position.latitude},${position.longitude}";
_empId = await SharedpreferencesService().getString("user");
_sessionId = await SharedpreferencesService().getString("session");
print("DATA111 : ${_empId}");
print("DATA111 : ${_sessionId}");
try {
final result = await ApiCalling.trackLiveLocationEmpolyeeAPI(
_empId!,
_sessionId!,
location,
);
if (result != null && result.error == "0") {
FlutterForegroundTask.updateService(
notificationTitle: "GEN ERP",
notificationText: "Location sent • ${DateTime.now().toString().substring(11, 19)}",
);
} else {
FlutterForegroundTask.updateService(
notificationText: "Sync failed • Retrying...",
);
}
} catch (e) {
FlutterForegroundTask.updateService(
notificationText: "No network • Retrying...",
);
}
// Save last sent time
final time = DateTime.now().toString().substring(11, 19);
SharedpreferencesService().saveString("lastLocationTime", time);
}
// This runs every 6 minutes (fallback when not moving)
@override
void onRepeatEvent(DateTime timestamp) {
_sendCurrentLocationOnce();
}
@override
Future<void> onDestroy(DateTime timestamp, bool isTimeout) async {
_stream?.cancel();
}
}
// Main Service Controller
class BackgroundLocationServiceNew {
static Future<void> init() async {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: 'gen_erp_location_channel',
channelName: 'GEN ERP Tracking',
channelDescription: 'Sends location every 6 minutes',
channelImportance: NotificationChannelImportance.HIGH,
priority: NotificationPriority.HIGH,
showBadge: true,
visibility: NotificationVisibility.VISIBILITY_SECRET
),
iosNotificationOptions: const IOSNotificationOptions(),
foregroundTaskOptions: ForegroundTaskOptions(
eventAction: ForegroundTaskEventAction.repeat(360000), // Every 6 minutes
autoRunOnBoot: false, // Prevents crash on boot
allowWakeLock: true,
allowWifiLock: true,
),
);
}
static Future<bool> get isRunning => FlutterForegroundTask.isRunningService;
static Future<void> start() async {
if (await isRunning) {
await FlutterForegroundTask.restartService();
} else {
await FlutterForegroundTask.startService(
notificationTitle: 'GEN ERP',
notificationText: 'Starting location tracking...',
callback: startCallback,
);
}
}
static Future<void> stop() async {
await FlutterForegroundTask.stopService();
}
}
\ No newline at end of file
......@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_ringtone_player/flutter_ringtone_player.dart';
import 'package:generp/Models/hrmModels/leaveApplicationLIstResponse.dart';
import 'package:generp/Notifiers/QrProvider.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/screens/AttendanceScreen.dart';
import 'package:generp/screens/HomeScreen.dart';
......@@ -426,7 +427,9 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => AdvanceListProvider()),
ChangeNotifierProvider(create: (_) => CasualLeaveHistoryProvider()),
ChangeNotifierProvider(create: (_) => ContactProvider()),
ChangeNotifierProvider(create: (_) => QrProvider()),
ChangeNotifierProvider(create: (_) => CrmNearByGeneratorsProvider()),
ChangeNotifierProvider(create: (_) => EditCommonAccountProvider()),
],
child: Builder(
builder: (BuildContext context) {
......
......@@ -117,8 +117,18 @@ class _AccountslistState extends State<Accountslist> {
return (connection == "Online")
? Platform.isAndroid
? WillPopScope(
onWillPop: () => onBackPressed(context),
child: SafeArea(
onWillPop: () async {
onBackPressed(context);
_refreshList(context);
final provider = Provider.of<Accountslistprovider>(context, listen: false);
provider.resetValues();
provider.commonAccountListAPIFunction(context);
// Return true or false depending on whether you want to allow the pop
return true; // allow the back navigation
// return false; // prevent back navigation
},
child: SafeArea(
top: false,
bottom: true,
child: _scaffold(context),
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment