refactor: centralize data connect error handling and resolve build issues across applications
This commit addresses several critical issues across the mobile monorepo:
1. Centralized Error Handling: Integrated DataErrorHandler mixin into all repository implementations, ensuring consistent mapping of Data Connect exceptions to domain AppExceptions.
2. Build Stabilization: Fixed numerous type mismatches, parameter signature errors in widgets (e.g., google_places_flutter itemBuilder), and naming conflicts (StaffSession, FirebaseAuth).
3. Code Quality: Applied 'dart fix' across all modified packages and manually cleared debug print statements and UI clutter.
4. Mono-repo alignment: Standardized Data Connect usage and aliasing ('dc.') for better maintainability.
Signed-off-by: Suriya <suriya@tenext.in>
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
import 'package:krow_data_connect/src/session/staff_session_store.dart';
|
||||
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
|
||||
import 'package:krow_core/core.dart';
|
||||
import '../../domain/repositories/payments_repository.dart';
|
||||
|
||||
class PaymentsRepositoryImpl implements PaymentsRepository {
|
||||
final dc.ExampleConnector _dataConnect;
|
||||
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||
|
||||
PaymentsRepositoryImpl() : _dataConnect = dc.ExampleConnector.instance;
|
||||
final dc.ExampleConnector _dataConnect;
|
||||
final firebase_auth.FirebaseAuth _auth = firebase_auth.FirebaseAuth.instance;
|
||||
|
||||
String? _cachedStaffId;
|
||||
|
||||
Future<String> _getStaffId() async {
|
||||
// 1. Check Session Store
|
||||
final StaffSession? session = StaffSessionStore.instance.session;
|
||||
final dc.StaffSession? session = dc.StaffSessionStore.instance.session;
|
||||
if (session?.staff?.id != null) {
|
||||
return session!.staff!.id;
|
||||
}
|
||||
@@ -25,13 +25,13 @@ class PaymentsRepositoryImpl implements PaymentsRepository {
|
||||
if (_cachedStaffId != null) return _cachedStaffId!;
|
||||
|
||||
// 3. Fetch from Data Connect using Firebase UID
|
||||
final user = _auth.currentUser;
|
||||
final firebase_auth.User? user = _auth.currentUser;
|
||||
if (user == null) {
|
||||
throw Exception('User is not authenticated');
|
||||
}
|
||||
|
||||
try {
|
||||
final response = await _dataConnect.getStaffByUserId(userId: user.uid).execute();
|
||||
final QueryResult<dc.GetStaffByUserIdData, dc.GetStaffByUserIdVariables> response = await _dataConnect.getStaffByUserId(userId: user.uid).execute();
|
||||
if (response.data.staffs.isNotEmpty) {
|
||||
_cachedStaffId = response.data.staffs.first.id;
|
||||
return _cachedStaffId!;
|
||||
@@ -66,9 +66,7 @@ class PaymentsRepositoryImpl implements PaymentsRepository {
|
||||
} catch (_) {}
|
||||
|
||||
try {
|
||||
if (dt == null) {
|
||||
dt = DateTime.tryParse(t.toString());
|
||||
}
|
||||
dt ??= DateTime.tryParse(t.toString());
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ import 'package:krow_core/core.dart';
|
||||
|
||||
/// Arguments for getting payment history.
|
||||
class GetPaymentHistoryArguments extends UseCaseArgument {
|
||||
|
||||
const GetPaymentHistoryArguments(this.period);
|
||||
/// The period to filter by (e.g., "monthly", "weekly").
|
||||
final String period;
|
||||
|
||||
const GetPaymentHistoryArguments(this.period);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [period];
|
||||
List<Object?> get props => <Object?>[period];
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import '../repositories/payments_repository.dart';
|
||||
///
|
||||
/// This use case delegates the data retrieval to [PaymentsRepository].
|
||||
class GetPaymentHistoryUseCase extends UseCase<GetPaymentHistoryArguments, List<StaffPayment>> {
|
||||
final PaymentsRepository repository;
|
||||
|
||||
/// Creates a [GetPaymentHistoryUseCase].
|
||||
GetPaymentHistoryUseCase(this.repository);
|
||||
final PaymentsRepository repository;
|
||||
|
||||
@override
|
||||
Future<List<StaffPayment>> call(GetPaymentHistoryArguments arguments) async {
|
||||
|
||||
@@ -4,10 +4,10 @@ import '../repositories/payments_repository.dart';
|
||||
|
||||
/// Use case to retrieve payment summary information.
|
||||
class GetPaymentSummaryUseCase extends NoInputUseCase<PaymentSummary> {
|
||||
final PaymentsRepository repository;
|
||||
|
||||
/// Creates a [GetPaymentSummaryUseCase].
|
||||
GetPaymentSummaryUseCase(this.repository);
|
||||
final PaymentsRepository repository;
|
||||
|
||||
@override
|
||||
Future<PaymentSummary> call() async {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||
import 'domain/repositories/payments_repository.dart';
|
||||
import 'domain/usecases/get_payment_summary_usecase.dart';
|
||||
import 'domain/usecases/get_payment_history_usecase.dart';
|
||||
@@ -26,7 +26,7 @@ class StaffPaymentsModule extends Module {
|
||||
void routes(RouteManager r) {
|
||||
r.child(
|
||||
StaffPaths.childRoute(StaffPaths.payments, StaffPaths.payments),
|
||||
child: (context) => const PaymentsPage(),
|
||||
child: (BuildContext context) => const PaymentsPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import 'payments_event.dart';
|
||||
import 'payments_state.dart';
|
||||
|
||||
class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
|
||||
final GetPaymentSummaryUseCase getPaymentSummary;
|
||||
final GetPaymentHistoryUseCase getPaymentHistory;
|
||||
|
||||
PaymentsBloc({
|
||||
required this.getPaymentSummary,
|
||||
@@ -17,6 +15,8 @@ class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
|
||||
on<LoadPaymentsEvent>(_onLoadPayments);
|
||||
on<ChangePeriodEvent>(_onChangePeriod);
|
||||
}
|
||||
final GetPaymentSummaryUseCase getPaymentSummary;
|
||||
final GetPaymentHistoryUseCase getPaymentHistory;
|
||||
|
||||
Future<void> _onLoadPayments(
|
||||
LoadPaymentsEvent event,
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class PaymentsEvent extends Equatable {
|
||||
const PaymentsEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
List<Object?> get props => <Object?>[];
|
||||
}
|
||||
|
||||
class LoadPaymentsEvent extends PaymentsEvent {}
|
||||
|
||||
class ChangePeriodEvent extends PaymentsEvent {
|
||||
final String period;
|
||||
|
||||
const ChangePeriodEvent(this.period);
|
||||
final String period;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [period];
|
||||
List<Object?> get props => <Object?>[period];
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ abstract class PaymentsState extends Equatable {
|
||||
const PaymentsState();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
List<Object?> get props => <Object?>[];
|
||||
}
|
||||
|
||||
class PaymentsInitial extends PaymentsState {}
|
||||
@@ -13,15 +13,15 @@ class PaymentsInitial extends PaymentsState {}
|
||||
class PaymentsLoading extends PaymentsState {}
|
||||
|
||||
class PaymentsLoaded extends PaymentsState {
|
||||
final PaymentSummary summary;
|
||||
final List<StaffPayment> history;
|
||||
final String activePeriod;
|
||||
|
||||
const PaymentsLoaded({
|
||||
required this.summary,
|
||||
required this.history,
|
||||
this.activePeriod = 'week',
|
||||
});
|
||||
final PaymentSummary summary;
|
||||
final List<StaffPayment> history;
|
||||
final String activePeriod;
|
||||
|
||||
PaymentsLoaded copyWith({
|
||||
PaymentSummary? summary,
|
||||
@@ -36,14 +36,14 @@ class PaymentsLoaded extends PaymentsState {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [summary, history, activePeriod];
|
||||
List<Object?> get props => <Object?>[summary, history, activePeriod];
|
||||
}
|
||||
|
||||
class PaymentsError extends PaymentsState {
|
||||
final String message;
|
||||
|
||||
const PaymentsError(this.message);
|
||||
final String message;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [message];
|
||||
List<Object?> get props => <Object?>[message];
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class PaymentStats extends Equatable {
|
||||
final double weeklyEarnings;
|
||||
final double monthlyEarnings;
|
||||
final double pendingEarnings;
|
||||
final double totalEarnings;
|
||||
|
||||
const PaymentStats({
|
||||
this.weeklyEarnings = 0.0,
|
||||
@@ -12,9 +8,13 @@ class PaymentStats extends Equatable {
|
||||
this.pendingEarnings = 0.0,
|
||||
this.totalEarnings = 0.0,
|
||||
});
|
||||
final double weeklyEarnings;
|
||||
final double monthlyEarnings;
|
||||
final double pendingEarnings;
|
||||
final double totalEarnings;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
List<Object?> get props => <Object?>[
|
||||
weeklyEarnings,
|
||||
monthlyEarnings,
|
||||
pendingEarnings,
|
||||
|
||||
@@ -177,7 +177,7 @@ class _PaymentsPageState extends State<PaymentsPage> {
|
||||
|
||||
// Recent Payments
|
||||
if (state.history.isNotEmpty) Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
"Recent Payments",
|
||||
style: TextStyle(
|
||||
|
||||
@@ -4,21 +4,21 @@ import 'package:intl/intl.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
class EarningsGraph extends StatelessWidget {
|
||||
final List<StaffPayment> payments;
|
||||
final String period;
|
||||
|
||||
const EarningsGraph({
|
||||
super.key,
|
||||
required this.payments,
|
||||
required this.period,
|
||||
});
|
||||
final List<StaffPayment> payments;
|
||||
final String period;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Basic data processing for the graph
|
||||
// We'll aggregate payments by date
|
||||
final validPayments = payments.where((p) => p.paidAt != null).toList()
|
||||
..sort((a, b) => a.paidAt!.compareTo(b.paidAt!));
|
||||
final List<StaffPayment> validPayments = payments.where((StaffPayment p) => p.paidAt != null).toList()
|
||||
..sort((StaffPayment a, StaffPayment b) => a.paidAt!.compareTo(b.paidAt!));
|
||||
|
||||
// If no data, show empty state or simple placeholder
|
||||
if (validPayments.isEmpty) {
|
||||
@@ -32,9 +32,9 @@ class EarningsGraph extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
final spots = _generateSpots(validPayments);
|
||||
final maxX = spots.isNotEmpty ? spots.last.x : 0.0;
|
||||
final maxY = spots.isNotEmpty ? spots.map((s) => s.y).reduce((a, b) => a > b ? a : b) : 0.0;
|
||||
final List<FlSpot> spots = _generateSpots(validPayments);
|
||||
final double maxX = spots.isNotEmpty ? spots.last.x : 0.0;
|
||||
final double maxY = spots.isNotEmpty ? spots.map((FlSpot s) => s.y).reduce((double a, double b) => a > b ? a : b) : 0.0;
|
||||
|
||||
return Container(
|
||||
height: 220,
|
||||
@@ -42,7 +42,7 @@ class EarningsGraph extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
offset: const Offset(0, 4),
|
||||
@@ -52,7 +52,7 @@ class EarningsGraph extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
"Earnings Trend",
|
||||
style: TextStyle(
|
||||
@@ -70,10 +70,10 @@ class EarningsGraph extends StatelessWidget {
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
getTitlesWidget: (value, meta) {
|
||||
getTitlesWidget: (double value, TitleMeta meta) {
|
||||
// Simple logic to show a few dates
|
||||
if (value % 2 != 0) return const SizedBox();
|
||||
final index = value.toInt();
|
||||
final int index = value.toInt();
|
||||
if (index >= 0 && index < validPayments.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
@@ -92,7 +92,7 @@ class EarningsGraph extends StatelessWidget {
|
||||
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
),
|
||||
borderData: FlBorderData(show: false),
|
||||
lineBarsData: [
|
||||
lineBarsData: <LineChartBarData>[
|
||||
LineChartBarData(
|
||||
spots: spots,
|
||||
isCurved: true,
|
||||
@@ -121,7 +121,7 @@ class EarningsGraph extends StatelessWidget {
|
||||
List<FlSpot> _generateSpots(List<StaffPayment> data) {
|
||||
// Generate spots based on index in the list for simplicity in this demo
|
||||
// Real implementation would map to actual dates on X-axis
|
||||
return List.generate(data.length, (index) {
|
||||
return List.generate(data.length, (int index) {
|
||||
return FlSpot(index.toDouble(), data[index].amount);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,15 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
|
||||
class PaymentHistoryItem extends StatelessWidget {
|
||||
final double amount;
|
||||
final String title;
|
||||
final String location;
|
||||
final String address;
|
||||
final String date;
|
||||
final String workedTime;
|
||||
final int hours;
|
||||
final double rate;
|
||||
final String status;
|
||||
|
||||
const PaymentHistoryItem({
|
||||
super.key,
|
||||
@@ -24,6 +15,15 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
required this.rate,
|
||||
required this.status,
|
||||
});
|
||||
final double amount;
|
||||
final String title;
|
||||
final String location;
|
||||
final String address;
|
||||
final String date;
|
||||
final String workedTime;
|
||||
final int hours;
|
||||
final double rate;
|
||||
final String status;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -32,7 +32,7 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 2,
|
||||
@@ -42,10 +42,10 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Status Badge
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 6,
|
||||
height: 6,
|
||||
@@ -70,7 +70,7 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Icon
|
||||
Container(
|
||||
width: 44,
|
||||
@@ -90,15 +90,15 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
// Content
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
@@ -119,7 +119,7 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"\$${amount.toStringAsFixed(0)}",
|
||||
style: const TextStyle(
|
||||
@@ -143,7 +143,7 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
|
||||
// Date and Time
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
LucideIcons.calendar,
|
||||
size: 12,
|
||||
@@ -177,7 +177,7 @@ class PaymentHistoryItem extends StatelessWidget {
|
||||
|
||||
// Address
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
LucideIcons.mapPin,
|
||||
size: 12,
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
|
||||
class PaymentStatsCard extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final Color iconColor;
|
||||
final String label;
|
||||
final String amount;
|
||||
|
||||
const PaymentStatsCard({
|
||||
super.key,
|
||||
@@ -14,6 +9,10 @@ class PaymentStatsCard extends StatelessWidget {
|
||||
required this.label,
|
||||
required this.amount,
|
||||
});
|
||||
final IconData icon;
|
||||
final Color iconColor;
|
||||
final String label;
|
||||
final String amount;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -22,7 +21,7 @@ class PaymentStatsCard extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 2,
|
||||
@@ -32,9 +31,9 @@ class PaymentStatsCard extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Icon(icon, size: 16, color: iconColor),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
|
||||
@@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
|
||||
class PendingPayCard extends StatelessWidget {
|
||||
final double amount;
|
||||
final VoidCallback onCashOut;
|
||||
|
||||
const PendingPayCard({
|
||||
super.key,
|
||||
required this.amount,
|
||||
required this.onCashOut,
|
||||
});
|
||||
final double amount;
|
||||
final VoidCallback onCashOut;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -17,12 +17,12 @@ class PendingPayCard extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: [Color(0xFFEFF6FF), Color(0xFFEFF6FF)], // blue-50 to blue-50
|
||||
colors: <Color>[Color(0xFFEFF6FF), Color(0xFFEFF6FF)], // blue-50 to blue-50
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 2,
|
||||
@@ -32,9 +32,9 @@ class PendingPayCard extends StatelessWidget {
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
@@ -51,7 +51,7 @@ class PendingPayCard extends StatelessWidget {
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
"Pending",
|
||||
style: TextStyle(
|
||||
|
||||
@@ -11,7 +11,8 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
firebase_data_connect:
|
||||
firebase_data_connect: ^0.2.2+2
|
||||
firebase_auth: ^6.1.4
|
||||
flutter_modular: ^6.3.2
|
||||
lucide_icons: ^0.257.0
|
||||
intl: ^0.20.0
|
||||
@@ -29,6 +30,8 @@ dependencies:
|
||||
krow_data_connect:
|
||||
path: ../../../data_connect
|
||||
|
||||
flutter_bloc: any
|
||||
equatable: any
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
Reference in New Issue
Block a user