connect with backend

This commit is contained in:
Abhishek Mali
2025-12-03 11:57:05 +05:30
parent c6b4c66c10
commit 3bf27cc29d
48 changed files with 2618 additions and 126 deletions

View File

@@ -4,25 +4,43 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../services/auth_service.dart';
class AuthProvider extends ChangeNotifier {
final AuthService _service = AuthService();
AuthService? _service;
bool _loading = false;
bool get loading => _loading;
bool initialized = false;
String? _token;
Map<String, dynamic>? _user;
String? get token => _token;
Map<String, dynamic>? get user => _user;
bool get isLoggedIn => _token != null && _token!.isNotEmpty;
// Inject context after provider initializes
void initContext(BuildContext context) {
_service = AuthService(context);
}
AuthProvider() {
_loadFromPrefs();
}
// ---------------------- NEW FIX: SAFE INIT -----------------------
Future<void> init() async {
if (!initialized) {
await _loadFromPrefs();
}
}
// ---------------------- LOAD FROM PREFS -----------------------
Future<void> _loadFromPrefs() async {
final prefs = await SharedPreferences.getInstance();
_token = prefs.getString('token');
final userJson = prefs.getString('user');
if (userJson != null) {
try {
@@ -31,22 +49,33 @@ class AuthProvider extends ChangeNotifier {
_user = null;
}
}
initialized = true;
notifyListeners();
}
Future<Map<String, dynamic>> login(String loginId, String password) async {
// -------------------------- LOGIN -----------------------------
Future<Map<String, dynamic>> login(
BuildContext context, String loginId, String password) async {
_service ??= AuthService(context);
_loading = true;
notifyListeners();
final res = await _service.login(loginId, password);
final res = await _service!.login(loginId, password);
_loading = false;
if (res['success'] == true) {
final token = res['token']?.toString();
final userMap = res['user'] is Map ? Map<String, dynamic>.from(res['user']) : null;
final userMap =
res['user'] is Map ? Map<String, dynamic>.from(res['user']) : null;
if (token != null && userMap != null) {
final prefs = await SharedPreferences.getInstance();
await prefs.setString("saved_login_id", loginId);
await prefs.setString("saved_password", password);
await _saveSession(token, userMap);
}
}
@@ -55,27 +84,64 @@ class AuthProvider extends ChangeNotifier {
return res;
}
Future<void> _saveSession(String token, Map<String, dynamic> userMap) async {
// --------------------- SAVE SESSION ---------------------------
Future<void> _saveSession(
String token, Map<String, dynamic> userMap) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', token);
await prefs.setString('user', jsonEncode(userMap));
_token = token;
_user = userMap;
notifyListeners();
}
Future<void> logout() async {
// optional: call API logout if implemented
if (_token != null) {
try {
await _service.logout(_token!);
} catch (_) {}
}
// ----------------------- LOGOUT -------------------------------
Future<void> logout(BuildContext context) async {
_service ??= AuthService(context);
try {
await _service!.logout();
} catch (_) {}
final prefs = await SharedPreferences.getInstance();
await prefs.remove('token');
await prefs.remove('user');
_token = null;
_user = null;
notifyListeners();
}
// -------------------- AUTO LOGIN ------------------------------
Future<bool> autoLoginFromSavedCredentials(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
final loginId = prefs.getString('saved_login_id');
final password = prefs.getString('saved_password');
if (loginId == null || password == null) return false;
final res = await login(context, loginId, password);
return res['success'] == true;
}
// --------------------- REFRESH TOKEN --------------------------
Future<bool> tryRefreshToken(BuildContext context) async {
final prefs = await SharedPreferences.getInstance();
final oldToken = prefs.getString('token');
if (oldToken == null) return false;
_service ??= AuthService(context);
final res = await _service!.refreshToken(oldToken);
if (res['success'] == true && res['token'] != null) {
await prefs.setString('token', res['token']);
_token = res['token'];
notifyListeners();
return true;
}
return false;
}
}

View File

@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import '../services/dashboard_service.dart';
class DashboardProvider extends ChangeNotifier {
DashboardService? _service;
bool loading = false;
int activeOrders = 0;
int inTransitOrders = 0;
int deliveredOrders = 0;
String totalValue = "0";
double totalRaw = 0;
void init(BuildContext context) {
_service = DashboardService(context);
}
Future<void> loadSummary(BuildContext context) async {
loading = true;
notifyListeners();
_service ??= DashboardService(context);
final res = await _service!.getSummary();
if (res['status'] == true) {
final s = res['summary'];
activeOrders = s['active_orders'] ?? 0;
inTransitOrders = s['in_transit_orders'] ?? 0;
deliveredOrders = s['delivered_orders'] ?? 0;
totalValue = s['total_value']?.toString() ?? "0";
totalRaw = double.tryParse(s['total_raw'].toString()) ?? 0;
}
loading = false;
notifyListeners();
}
}

View File

@@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
import '../services/dio_client.dart';
import '../services/invoice_service.dart';
class InvoiceInstallmentScreen extends StatefulWidget {
final int invoiceId;
const InvoiceInstallmentScreen({super.key, required this.invoiceId});
@override
State<InvoiceInstallmentScreen> createState() =>
_InvoiceInstallmentScreenState();
}
class _InvoiceInstallmentScreenState extends State<InvoiceInstallmentScreen> {
bool loading = true;
List installments = [];
@override
void initState() {
super.initState();
load();
}
Future<void> load() async {
final service = InvoiceService(DioClient.getInstance(context));
final res = await service.getInstallments(widget.invoiceId);
if (res['success'] == true) {
installments = res['installments'] ?? [];
}
loading = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Installments")),
body: loading
? const Center(child: CircularProgressIndicator())
: installments.isEmpty
? const Center(
child: Text("Installments not created yet",
style: TextStyle(fontSize: 18)),
)
: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: installments.length,
itemBuilder: (_, i) {
final inst = installments[i];
return Card(
child: ListTile(
title: Text(
"Amount: ₹${inst['amount']?.toString() ?? '0'}"),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Date: ${inst['installment_date'] ?? 'N/A'}"),
Text(
"Payment: ${inst['payment_method'] ?? 'N/A'}"),
Text(
"Reference: ${inst['reference_no'] ?? 'N/A'}"),
],
),
),
);
},
),
);
}
}

View File

@@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import '../services/invoice_service.dart';
import '../services/dio_client.dart';
class InvoiceProvider extends ChangeNotifier {
bool loading = false;
List invoices = [];
Future<void> loadInvoices(BuildContext context) async {
loading = true;
notifyListeners();
final service = InvoiceService(DioClient.getInstance(context));
final res = await service.getAllInvoices();
if (res['success'] == true) {
invoices = res['invoices'] ?? [];
}
loading = false;
notifyListeners();
}
}

View File

@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import '../services/mark_list_service.dart';
class MarkListProvider extends ChangeNotifier {
MarkListService? _service;
List<dynamic> marks = [];
bool loading = false;
void init(BuildContext context) {
_service = MarkListService(context);
}
Future<void> loadMarks(BuildContext context) async {
loading = true;
notifyListeners();
_service ??= MarkListService(context);
final res = await _service!.getMarks();
if (res['success'] == true) {
marks = res['data'] ?? [];
}
loading = false;
notifyListeners();
}
Future<Map<String, dynamic>> addMark(BuildContext context, String mark, String origin, String destination) async {
_service ??= MarkListService(context);
final res = await _service!.addMark({
"mark_no": mark,
"origin": origin,
"destination": destination
});
if (res['success'] == true) {
await loadMarks(context); // refresh list
}
return res;
}
}

View File

@@ -0,0 +1,26 @@
import 'package:flutter/cupertino.dart';
import '../services/order_service.dart';
class OrderProvider extends ChangeNotifier {
final OrderService service;
OrderProvider(this.service);
bool loading = false;
List orders = [];
Future<void> loadOrders() async {
loading = true;
notifyListeners();
final res = await service.getOrders();
if (res['success'] == true) {
orders = res['orders'];
}
loading = false;
notifyListeners();
}
}

View File

@@ -0,0 +1,70 @@
import 'dart:io';
import 'package:flutter/material.dart';
import '../models/user_profile.dart';
import '../services/user_profile_service.dart';
class UserProfileProvider extends ChangeNotifier {
UserProfileService? _service;
UserProfile? profile;
bool loading = false;
void init(BuildContext context) {
_service = UserProfileService(context);
}
Future<void> loadProfile(BuildContext context) async {
_service ??= UserProfileService(context);
loading = true;
notifyListeners();
final res = await _service!.getProfile();
if (res['success'] == true) {
profile = UserProfile.fromJson(res['data']);
}
loading = false;
notifyListeners();
}
Future<bool> updateProfileImage(BuildContext context, File image) async {
_service ??= UserProfileService(context);
loading = true;
notifyListeners();
final res = await _service!.updateProfileImage(image);
if (res['success'] == true) {
profile = UserProfile.fromJson(res['data']);
loading = false;
notifyListeners();
return true;
}
loading = false;
notifyListeners();
return false;
}
/// NEW: Send profile update request (admin approval required)
Future<bool> sendProfileUpdateRequest(
BuildContext context,
Map<String, dynamic> data,
) async {
_service ??= UserProfileService(context);
loading = true;
notifyListeners();
final res = await _service!.sendUpdateRequest(data);
loading = false;
notifyListeners();
return res['success'] == true;
}
}