Merge remote-tracking branch 'origin/312-feature-integrate-google-maps-places-autocomplete-for-hub-address-validation' into 298-bug-enhance-order-creation-flow-implement-robust-timezone-handling-in-mobile-client-app

This commit is contained in:
José Salazar
2026-01-29 14:36:43 -05:00
35 changed files with 213 additions and 252 deletions

View File

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1 version: 0.0.1
resolution: workspace resolution: workspace
environment: environment:

View File

@@ -6,7 +6,7 @@
/// Locales: 2 /// Locales: 2
/// Strings: 1038 (519 per locale) /// Strings: 1038 (519 per locale)
/// ///
/// Built on 2026-01-29 at 06:58 UTC /// Built on 2026-01-29 at 15:50 UTC
// coverage:ignore-file // coverage:ignore-file
// ignore_for_file: type=lint, unused_import // ignore_for_file: type=lint, unused_import

View File

@@ -37,4 +37,7 @@ class UiConstants {
static const double space12 = 48.0; static const double space12 = 48.0;
static const double space14 = 56.0; static const double space14 = 56.0;
static const double space16 = 64.0; static const double space16 = 64.0;
static const double space20 = 80.0;
static const double space24 = 96.0;
static const double space32 = 128.0;
} }

View File

@@ -2,16 +2,16 @@ import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import '../blocs/billing_bloc.dart'; import '../blocs/billing_bloc.dart';
import '../blocs/billing_event.dart'; import '../blocs/billing_event.dart';
import '../blocs/billing_state.dart'; import '../blocs/billing_state.dart';
import '../widgets/billing_header.dart'; import '../widgets/billing_header.dart';
import '../widgets/pending_invoices_section.dart';
import '../widgets/payment_method_card.dart';
import '../widgets/spending_breakdown_card.dart';
import '../widgets/savings_card.dart';
import '../widgets/invoice_history_section.dart'; import '../widgets/invoice_history_section.dart';
import '../widgets/export_invoices_button.dart'; import '../widgets/payment_method_card.dart';
import '../widgets/pending_invoices_section.dart';
import '../widgets/savings_card.dart';
import '../widgets/spending_breakdown_card.dart';
/// The entry point page for the client billing feature. /// The entry point page for the client billing feature.
/// ///
@@ -43,7 +43,6 @@ class BillingView extends StatelessWidget {
return BlocBuilder<BillingBloc, BillingState>( return BlocBuilder<BillingBloc, BillingState>(
builder: (BuildContext context, BillingState state) { builder: (BuildContext context, BillingState state) {
return Scaffold( return Scaffold(
backgroundColor: UiColors.bgPrimary,
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
BillingHeader( BillingHeader(
@@ -89,9 +88,7 @@ class BillingView extends StatelessWidget {
SavingsCard(savings: state.savings), SavingsCard(savings: state.savings),
const SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space6),
InvoiceHistorySection(invoices: state.invoiceHistory), InvoiceHistorySection(invoices: state.invoiceHistory),
const SizedBox(height: UiConstants.space6), const SizedBox(height: UiConstants.space24),
const ExportInvoicesButton(),
const SizedBox(height: UiConstants.space6),
], ],
), ),
); );

View File

@@ -1,7 +1,7 @@
name: billing name: billing
description: Client Billing feature package description: Client Billing feature package
publish_to: 'none' publish_to: 'none'
version: 1.0.0+1 version: 0.0.1
resolution: workspace resolution: workspace
environment: environment:

View File

@@ -24,7 +24,6 @@ class CoveragePage extends StatelessWidget {
create: (BuildContext context) => Modular.get<CoverageBloc>() create: (BuildContext context) => Modular.get<CoverageBloc>()
..add(CoverageLoadRequested(date: DateTime.now())), ..add(CoverageLoadRequested(date: DateTime.now())),
child: Scaffold( child: Scaffold(
backgroundColor: UiColors.background,
body: BlocBuilder<CoverageBloc, CoverageState>( body: BlocBuilder<CoverageBloc, CoverageState>(
builder: (BuildContext context, CoverageState state) { builder: (BuildContext context, CoverageState state) {
return Column( return Column(
@@ -121,6 +120,7 @@ class CoveragePage extends StatelessWidget {
), ),
const SizedBox(height: UiConstants.space3), const SizedBox(height: UiConstants.space3),
CoverageShiftList(shifts: state.shifts), CoverageShiftList(shifts: state.shifts),
const SizedBox(height: 100),
], ],
), ),
); );

View File

@@ -35,24 +35,23 @@ class CoverageShiftList extends StatelessWidget {
if (shifts.isEmpty) { if (shifts.isEmpty) {
return Container( return Container(
padding: const EdgeInsets.all(UiConstants.space8), padding: const EdgeInsets.all(UiConstants.space8),
width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
color: UiColors.bgPopup, color: UiColors.bgPopup,
borderRadius: UiConstants.radiusLg, borderRadius: UiConstants.radiusLg,
border: Border.all(color: UiColors.border), border: Border.all(color: UiColors.border),
), ),
child: Column( child: Column(
spacing: UiConstants.space4,
children: <Widget>[ children: <Widget>[
const Icon( const Icon(
UiIcons.users, UiIcons.users,
size: UiConstants.space12, size: UiConstants.space12,
color: UiColors.mutedForeground, color: UiColors.textSecondary,
), ),
const SizedBox(height: UiConstants.space3),
Text( Text(
'No shifts scheduled for this day', 'No shifts scheduled for this day',
style: UiTypography.body2r.copyWith( style: UiTypography.body2r.textSecondary,
color: UiColors.mutedForeground,
),
), ),
], ],
), ),
@@ -160,12 +159,15 @@ class _ShiftHeader extends StatelessWidget {
), ),
), ),
child: Row( child: Row(
spacing: UiConstants.space4,
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
spacing: UiConstants.space2,
children: <Widget>[ children: <Widget>[
Row( Row(
spacing: UiConstants.space2,
children: <Widget>[ children: <Widget>[
Container( Container(
width: UiConstants.space2, width: UiConstants.space2,
@@ -175,42 +177,43 @@ class _ShiftHeader extends StatelessWidget {
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
), ),
const SizedBox(width: UiConstants.space2),
Text( Text(
title, title,
style: UiTypography.body1b.copyWith( style: UiTypography.body1b.textPrimary,
color: UiColors.textPrimary,
),
), ),
], ],
), ),
const SizedBox(height: UiConstants.space2), Column(
Row( crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
const Icon( Row(
UiIcons.mapPin, spacing: UiConstants.space1,
size: UiConstants.space3, children: <Widget>[
color: UiColors.mutedForeground, const Icon(
UiIcons.mapPin,
size: UiConstants.space3,
color: UiColors.iconSecondary,
),
Expanded(child: Text(
location,
style: UiTypography.body3r.textSecondary,
overflow: TextOverflow.ellipsis,
)),
],
), ),
const SizedBox(width: UiConstants.space1), Row(
Text( spacing: UiConstants.space1,
location, children: <Widget>[
style: UiTypography.body3r.copyWith( const Icon(
color: UiColors.mutedForeground, UiIcons.clock,
), size: UiConstants.space3,
), color: UiColors.iconSecondary,
const SizedBox(width: UiConstants.space3), ),
const Icon( Text(
UiIcons.clock, startTime,
size: UiConstants.space3, style: UiTypography.body3r.textSecondary,
color: UiColors.mutedForeground, ),
), ],
const SizedBox(width: UiConstants.space1),
Text(
startTime,
style: UiTypography.body3r.copyWith(
color: UiColors.mutedForeground,
),
), ),
], ],
), ),

View File

@@ -1,6 +1,6 @@
name: client_coverage name: client_coverage
description: Client coverage feature for tracking daily shift coverage and worker status description: Client coverage feature for tracking daily shift coverage and worker status
version: 1.0.0 version: 0.0.1
publish_to: none publish_to: none
resolution: workspace resolution: workspace
@@ -33,4 +33,4 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^5.0.0 flutter_lints: ^6.0.0

View File

@@ -99,13 +99,6 @@ class ClientMainBottomBar extends StatelessWidget {
activeColor: activeColor, activeColor: activeColor,
inactiveColor: inactiveColor, inactiveColor: inactiveColor,
), ),
_buildNavItem(
index: 4,
icon: UiIcons.chart,
label: t.client_main.tabs.reports,
activeColor: activeColor,
inactiveColor: inactiveColor,
),
], ],
), ),
), ),

View File

@@ -1,5 +1,3 @@
library client_home;
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:krow_data_connect/krow_data_connect.dart'; import 'package:krow_data_connect/krow_data_connect.dart';
import 'src/data/repositories_impl/home_repository_impl.dart'; import 'src/data/repositories_impl/home_repository_impl.dart';

View File

@@ -26,6 +26,8 @@ class ClientHomeBloc extends Bloc<ClientHomeEvent, ClientHomeState> {
on<ClientHomeWidgetVisibilityToggled>(_onWidgetVisibilityToggled); on<ClientHomeWidgetVisibilityToggled>(_onWidgetVisibilityToggled);
on<ClientHomeWidgetReordered>(_onWidgetReordered); on<ClientHomeWidgetReordered>(_onWidgetReordered);
on<ClientHomeLayoutReset>(_onLayoutReset); on<ClientHomeLayoutReset>(_onLayoutReset);
add(ClientHomeStarted());
} }
Future<void> _onStarted( Future<void> _onStarted(

View File

@@ -24,8 +24,7 @@ class ClientHomePage extends StatelessWidget {
final TranslationsClientHomeEn i18n = t.client_home; final TranslationsClientHomeEn i18n = t.client_home;
return BlocProvider<ClientHomeBloc>( return BlocProvider<ClientHomeBloc>(
create: (BuildContext context) => create: (BuildContext context) => Modular.get<ClientHomeBloc>(),
Modular.get<ClientHomeBloc>()..add(ClientHomeStarted()),
child: Scaffold( child: Scaffold(
body: SafeArea( body: SafeArea(
child: Column( child: Column(
@@ -59,19 +58,15 @@ class ClientHomePage extends StatelessWidget {
100, 100,
), ),
onReorder: (int oldIndex, int newIndex) { onReorder: (int oldIndex, int newIndex) {
BlocProvider.of<ClientHomeBloc>(context).add( BlocProvider.of<ClientHomeBloc>(
ClientHomeWidgetReordered(oldIndex, newIndex), context,
); ).add(ClientHomeWidgetReordered(oldIndex, newIndex));
}, },
children: state.widgetOrder.map((String id) { children: state.widgetOrder.map((String id) {
return Container( return Container(
key: ValueKey(id), key: ValueKey<String>(id),
margin: const EdgeInsets.only(bottom: UiConstants.space4), margin: const EdgeInsets.only(bottom: UiConstants.space4),
child: DashboardWidgetBuilder( child: DashboardWidgetBuilder(id: id, state: state, isEditMode: true),
id: id,
state: state,
isEditMode: true,
),
); );
}).toList(), }).toList(),
); );

View File

@@ -24,21 +24,22 @@ class ActionsWidget extends StatelessWidget {
return Row( return Row(
children: <Widget>[ children: <Widget>[
Expanded( /// TODO: FEATURE_NOT_YET_IMPLEMENTED
child: _ActionCard( // Expanded(
title: i18n.rapid, // child: _ActionCard(
subtitle: i18n.rapid_subtitle, // title: i18n.rapid,
icon: UiIcons.zap, // subtitle: i18n.rapid_subtitle,
color: const Color(0xFFFEF2F2), // icon: UiIcons.zap,
borderColor: const Color(0xFFFECACA), // color: const Color(0xFFFEF2F2),
iconBgColor: const Color(0xFFFEE2E2), // borderColor: const Color(0xFFFECACA),
iconColor: const Color(0xFFDC2626), // iconBgColor: const Color(0xFFFEE2E2),
textColor: const Color(0xFF7F1D1D), // iconColor: const Color(0xFFDC2626),
subtitleColor: const Color(0xFFB91C1C), // textColor: const Color(0xFF7F1D1D),
onTap: onRapidPressed, // subtitleColor: const Color(0xFFB91C1C),
), // onTap: onRapidPressed,
), // ),
const SizedBox(width: UiConstants.space2), // ),
// const SizedBox(width: UiConstants.space2),
Expanded( Expanded(
child: _ActionCard( child: _ActionCard(
title: i18n.create_order, title: i18n.create_order,

View File

@@ -22,6 +22,7 @@ dependencies:
core_localization: core_localization:
path: ../../../core_localization path: ../../../core_localization
krow_domain: ^0.0.1 krow_domain: ^0.0.1
krow_data_connect: ^0.0.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@@ -1,7 +1,7 @@
name: view_orders name: view_orders
description: Client View Orders feature package description: Client View Orders feature package
publish_to: 'none' publish_to: 'none'
version: 1.0.0+1 version: 0.0.1
resolution: workspace resolution: workspace
environment: environment:

View File

@@ -32,4 +32,4 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^3.0.0 flutter_lints: ^6.0.0

View File

@@ -1,5 +1,3 @@
// ignore: unused_import
// import 'package:data_connect/data_connect.dart';
import '../../domain/entities/payment_summary.dart'; import '../../domain/entities/payment_summary.dart';
import '../../domain/entities/payment_transaction.dart'; import '../../domain/entities/payment_transaction.dart';
import '../../domain/repositories/payments_repository.dart'; import '../../domain/repositories/payments_repository.dart';

View File

@@ -1,22 +1,21 @@
import 'package:krow_data_connect/krow_data_connect.dart'; import '../../domain/entities/payment_summary.dart';
import 'package:krow_domain/krow_domain.dart'; import '../../domain/entities/payment_transaction.dart';
import '../../domain/repositories/payments_repository.dart'; import '../../domain/repositories/payments_repository.dart';
import '../datasources/payments_remote_datasource.dart';
/// Implementation of [PaymentsRepository]. /// Implementation of [PaymentsRepository].
///
/// This class handles the retrieval of payment data by delegating to the
/// [FinancialRepositoryMock] from the data connect package.
///
/// It resides in the data layer and depends on the domain layer for the repository interface.
class PaymentsRepositoryImpl implements PaymentsRepository { class PaymentsRepositoryImpl implements PaymentsRepository {
final FinancialRepositoryMock financialRepository; final PaymentsRemoteDataSource remoteDataSource;
/// Creates a [PaymentsRepositoryImpl] with the given [financialRepository]. PaymentsRepositoryImpl({required this.remoteDataSource});
PaymentsRepositoryImpl({required this.financialRepository});
@override @override
Future<List<StaffPayment>> getPayments() async { Future<PaymentSummary> getPaymentSummary() async {
// TODO: Get actual logged in staff ID return await remoteDataSource.fetchPaymentSummary();
return await financialRepository.getStaffPayments('staff_1'); }
@override
Future<List<PaymentTransaction>> getPaymentHistory(String period) async {
return await remoteDataSource.fetchPaymentHistory(period);
} }
} }

View File

@@ -0,0 +1,23 @@
import 'package:equatable/equatable.dart';
class PaymentSummary extends Equatable {
final double weeklyEarnings;
final double monthlyEarnings;
final double pendingEarnings;
final double totalEarnings;
const PaymentSummary({
required this.weeklyEarnings,
required this.monthlyEarnings,
required this.pendingEarnings,
required this.totalEarnings,
});
@override
List<Object?> get props => [
weeklyEarnings,
monthlyEarnings,
pendingEarnings,
totalEarnings,
];
}

View File

@@ -0,0 +1,41 @@
import 'package:equatable/equatable.dart';
class PaymentTransaction extends Equatable {
final String id;
final String title;
final String location;
final String address;
final String workedTime;
final double amount;
final String status;
final int hours;
final double rate;
final DateTime date;
const PaymentTransaction({
required this.id,
required this.title,
required this.location,
required this.address,
required this.workedTime,
required this.amount,
required this.status,
required this.hours,
required this.rate,
required this.date,
});
@override
List<Object?> get props => [
id,
title,
location,
address,
workedTime,
amount,
status,
hours,
rate,
date,
];
}

View File

@@ -1,10 +1,14 @@
import 'package:krow_domain/krow_domain.dart'; import '../entities/payment_summary.dart';
import '../entities/payment_transaction.dart';
/// Repository interface for Payments feature. /// Repository interface for Payments feature.
/// ///
/// Defines the contract for data access related to staff payments. /// Defines the contract for data access related to staff payments.
/// Implementations of this interface should reside in the data layer. /// Implementations of this interface should reside in the data layer.
abstract class PaymentsRepository { abstract class PaymentsRepository {
/// Fetches the list of payments for the current staff member. /// Fetches the payment summary (earnings).
Future<List<StaffPayment>> getPayments(); Future<PaymentSummary> getPaymentSummary();
/// Fetches the payment history for a specific period.
Future<List<PaymentTransaction>> getPaymentHistory(String period);
} }

View File

@@ -1,20 +1,19 @@
import 'package:krow_core/core.dart'; import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
import '../arguments/get_payment_history_arguments.dart'; import '../arguments/get_payment_history_arguments.dart';
import '../entities/payment_transaction.dart';
import '../repositories/payments_repository.dart'; import '../repositories/payments_repository.dart';
/// Use case to retrieve payment history filtered by a period. /// Use case to retrieve payment history filtered by a period.
/// ///
/// This use case delegates the data retrieval to [PaymentsRepository]. /// This use case delegates the data retrieval to [PaymentsRepository].
class GetPaymentHistoryUseCase extends UseCase<GetPaymentHistoryArguments, List<StaffPayment>> { class GetPaymentHistoryUseCase extends UseCase<GetPaymentHistoryArguments, List<PaymentTransaction>> {
final PaymentsRepository repository; final PaymentsRepository repository;
/// Creates a [GetPaymentHistoryUseCase]. /// Creates a [GetPaymentHistoryUseCase].
GetPaymentHistoryUseCase(this.repository); GetPaymentHistoryUseCase(this.repository);
@override @override
Future<List<StaffPayment>> call(GetPaymentHistoryArguments arguments) async { Future<List<PaymentTransaction>> call(GetPaymentHistoryArguments arguments) async {
// TODO: Implement filtering by period return await repository.getPaymentHistory(arguments.period);
return await repository.getPayments();
} }
} }

View File

@@ -1,19 +1,16 @@
import 'package:krow_core/core.dart'; import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart'; import '../entities/payment_summary.dart';
import '../repositories/payments_repository.dart'; import '../repositories/payments_repository.dart';
/// Use case to retrieve payment summary information. /// Use case to retrieve payment summary information.
/// class GetPaymentSummaryUseCase extends NoInputUseCase<PaymentSummary> {
/// It fetches the full list of payments, which ideally should be aggregated
/// by the presentation layer or a specific data source method.
class GetPaymentSummaryUseCase extends NoInputUseCase<List<StaffPayment>> {
final PaymentsRepository repository; final PaymentsRepository repository;
/// Creates a [GetPaymentSummaryUseCase]. /// Creates a [GetPaymentSummaryUseCase].
GetPaymentSummaryUseCase(this.repository); GetPaymentSummaryUseCase(this.repository);
@override @override
Future<List<StaffPayment>> call() async { Future<PaymentSummary> call() async {
return await repository.getPayments(); return await repository.getPaymentSummary();
} }
} }

View File

@@ -1,9 +1,9 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/krow_domain.dart';
import '../../../domain/arguments/get_payment_history_arguments.dart'; import '../../../domain/arguments/get_payment_history_arguments.dart';
import '../../../domain/usecases/get_payment_summary_usecase.dart'; import '../../../domain/entities/payment_summary.dart';
import '../../../domain/entities/payment_transaction.dart';
import '../../../domain/usecases/get_payment_history_usecase.dart'; import '../../../domain/usecases/get_payment_history_usecase.dart';
import '../../models/payment_stats.dart'; import '../../../domain/usecases/get_payment_summary_usecase.dart';
import 'payments_event.dart'; import 'payments_event.dart';
import 'payments_state.dart'; import 'payments_state.dart';
@@ -25,14 +25,13 @@ class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
) async { ) async {
emit(PaymentsLoading()); emit(PaymentsLoading());
try { try {
final List<StaffPayment> allPayments = await getPaymentSummary(); final PaymentSummary currentSummary = await getPaymentSummary();
final PaymentStats stats = _calculateStats(allPayments);
final List<StaffPayment> history = await getPaymentHistory( final List<PaymentTransaction> history = await getPaymentHistory(
const GetPaymentHistoryArguments('week'), const GetPaymentHistoryArguments('week'),
); );
emit(PaymentsLoaded( emit(PaymentsLoaded(
summary: stats, summary: currentSummary,
history: history, history: history,
activePeriod: 'week', activePeriod: 'week',
)); ));
@@ -48,7 +47,7 @@ class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
final PaymentsState currentState = state; final PaymentsState currentState = state;
if (currentState is PaymentsLoaded) { if (currentState is PaymentsLoaded) {
try { try {
final List<StaffPayment> newHistory = await getPaymentHistory( final List<PaymentTransaction> newHistory = await getPaymentHistory(
GetPaymentHistoryArguments(event.period), GetPaymentHistoryArguments(event.period),
); );
emit(currentState.copyWith( emit(currentState.copyWith(
@@ -60,38 +59,4 @@ class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
} }
} }
} }
PaymentStats _calculateStats(List<StaffPayment> payments) {
double total = 0;
double pending = 0;
double weekly = 0;
double monthly = 0;
final DateTime now = DateTime.now();
for (final StaffPayment p in payments) {
// Assuming all payments count towards total history
total += p.amount;
if (p.status == PaymentStatus.pending) {
pending += p.amount;
}
if (p.paidAt != null) {
if (now.difference(p.paidAt!).inDays < 7) {
weekly += p.amount;
}
if (now.month == p.paidAt!.month && now.year == p.paidAt!.year) {
monthly += p.amount;
}
}
}
return PaymentStats(
totalEarnings: total,
pendingEarnings: pending,
weeklyEarnings: weekly,
monthlyEarnings: monthly,
);
}
} }

View File

@@ -1,6 +1,6 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:krow_domain/krow_domain.dart'; import '../../../domain/entities/payment_summary.dart';
import '../../models/payment_stats.dart'; import '../../../domain/entities/payment_transaction.dart';
abstract class PaymentsState extends Equatable { abstract class PaymentsState extends Equatable {
const PaymentsState(); const PaymentsState();
@@ -14,8 +14,8 @@ class PaymentsInitial extends PaymentsState {}
class PaymentsLoading extends PaymentsState {} class PaymentsLoading extends PaymentsState {}
class PaymentsLoaded extends PaymentsState { class PaymentsLoaded extends PaymentsState {
final PaymentStats summary; final PaymentSummary summary;
final List<StaffPayment> history; final List<PaymentTransaction> history;
final String activePeriod; final String activePeriod;
const PaymentsLoaded({ const PaymentsLoaded({
@@ -25,8 +25,8 @@ class PaymentsLoaded extends PaymentsState {
}); });
PaymentsLoaded copyWith({ PaymentsLoaded copyWith({
PaymentStats? summary, PaymentSummary? summary,
List<StaffPayment>? history, List<PaymentTransaction>? history,
String? activePeriod, String? activePeriod,
}) { }) {
return PaymentsLoaded( return PaymentsLoaded(

View File

@@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import 'package:lucide_icons/lucide_icons.dart'; import 'package:lucide_icons/lucide_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:krow_domain/krow_domain.dart'; import '../../domain/entities/payment_transaction.dart';
import '../blocs/payments/payments_bloc.dart'; import '../blocs/payments/payments_bloc.dart';
import '../blocs/payments/payments_event.dart'; import '../blocs/payments/payments_event.dart';
import '../blocs/payments/payments_state.dart'; import '../blocs/payments/payments_state.dart';
@@ -177,19 +177,19 @@ class _PaymentsPageState extends State<PaymentsPage> {
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
Column( Column(
children: state.history.map((StaffPayment payment) { children: state.history.map((PaymentTransaction payment) {
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.only(bottom: 8),
child: PaymentHistoryItem( child: PaymentHistoryItem(
amount: payment.amount, amount: payment.amount,
title: 'Assignment ${payment.assignmentId}', title: payment.title,
location: 'Location', // TODO: Fetch from assignment location: payment.location,
address: '', address: payment.address,
date: payment.paidAt != null ? DateFormat('E, MMM d').format(payment.paidAt!) : 'Pending', date: DateFormat('E, MMM d').format(payment.date),
workedTime: '00:00 - 00:00', // TODO: Fetch from assignment workedTime: payment.workedTime,
hours: 0, hours: payment.hours,
rate: 0, rate: payment.rate,
status: payment.status.toString().split('.').last, status: payment.status,
), ),
); );
}).toList(), }).toList(),

View File

@@ -30,4 +30,5 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^3.0.0 flutter_lints: ^6.0.0

View File

@@ -5,7 +5,7 @@ publish_to: none
resolution: workspace resolution: workspace
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: '>=3.10.0 <4.0.0'
dependencies: dependencies:
flutter: flutter:

View File

@@ -34,4 +34,4 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^2.0.0 flutter_lints: ^6.0.0

View File

@@ -2,9 +2,10 @@ name: staff_time_card
description: Staff Time Card Feature description: Staff Time Card Feature
version: 0.0.1 version: 0.0.1
publish_to: none publish_to: none
resolution: workspace
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: '>=3.10.0 <4.0.0'
flutter: ">=3.0.0" flutter: ">=3.0.0"
dependencies: dependencies:

View File

@@ -31,4 +31,4 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^2.0.0 flutter_lints: ^6.0.0

View File

@@ -5,7 +5,7 @@ publish_to: 'none'
resolution: workspace resolution: workspace
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: '>=3.10.0 <4.0.0'
flutter: ">=3.0.0" flutter: ">=3.0.0"
dependencies: dependencies:
@@ -31,4 +31,4 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^3.0.0 flutter_lints: ^6.0.0

View File

@@ -65,13 +65,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
billing:
dependency: transitive
description:
path: "packages/features/client/billing"
relative: true
source: path
version: "1.0.0+1"
bloc: bloc:
dependency: transitive dependency: transitive
description: description:
@@ -192,13 +185,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.4.2" version: "0.4.2"
client_coverage:
dependency: transitive
description:
path: "packages/features/client/client_coverage"
relative: true
source: path
version: "1.0.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@@ -1120,13 +1106,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.1" version: "1.12.1"
staff_attire:
dependency: transitive
description:
path: "packages/features/staff/profile_sections/onboarding/attire"
relative: true
source: path
version: "0.0.1"
staff_availability: staff_availability:
dependency: transitive dependency: transitive
description: description:
@@ -1134,20 +1113,6 @@ packages:
relative: true relative: true
source: path source: path
version: "0.0.1" version: "0.0.1"
staff_bank_account:
dependency: transitive
description:
path: "packages/features/staff/profile_sections/finances/staff_bank_account"
relative: true
source: path
version: "0.0.1"
staff_certificates:
dependency: transitive
description:
path: "packages/features/staff/profile_sections/compliance/certificates"
relative: true
source: path
version: "0.0.1"
staff_clock_in: staff_clock_in:
dependency: transitive dependency: transitive
description: description:
@@ -1155,41 +1120,6 @@ packages:
relative: true relative: true
source: path source: path
version: "0.0.1" version: "0.0.1"
staff_documents:
dependency: transitive
description:
path: "packages/features/staff/profile_sections/compliance/documents"
relative: true
source: path
version: "0.0.1"
staff_payments:
dependency: transitive
description:
path: "packages/features/staff/payments"
relative: true
source: path
version: "0.0.1"
staff_shifts:
dependency: transitive
description:
path: "packages/features/staff/shifts"
relative: true
source: path
version: "0.0.1"
staff_tax_forms:
dependency: transitive
description:
path: "packages/features/staff/profile_sections/compliance/tax_forms"
relative: true
source: path
version: "0.0.1"
staff_time_card:
dependency: transitive
description:
path: "packages/features/staff/profile_sections/finances/time_card"
relative: true
source: path
version: "0.0.1"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:

View File

@@ -12,16 +12,26 @@ workspace:
- packages/features/staff/authentication - packages/features/staff/authentication
- packages/features/staff/home - packages/features/staff/home
- packages/features/staff/staff_main - packages/features/staff/staff_main
- packages/features/staff/payments
- packages/features/staff/profile - packages/features/staff/profile
- packages/features/staff/profile_sections/onboarding/emergency_contact - packages/features/staff/profile_sections/onboarding/emergency_contact
- packages/features/staff/profile_sections/onboarding/experience - packages/features/staff/profile_sections/onboarding/experience
- packages/features/staff/profile_sections/onboarding/profile_info - packages/features/staff/profile_sections/onboarding/profile_info
- packages/features/staff/profile_sections/onboarding/attire
- packages/features/staff/profile_sections/finances/staff_bank_account
- packages/features/staff/profile_sections/finances/time_card
- packages/features/staff/profile_sections/compliance/certificates
- packages/features/staff/profile_sections/compliance/documents
- packages/features/staff/profile_sections/compliance/tax_forms
- packages/features/staff/shifts
- packages/features/client/authentication - packages/features/client/authentication
- packages/features/client/billing
- packages/features/client/home - packages/features/client/home
- packages/features/client/settings - packages/features/client/settings
- packages/features/client/hubs - packages/features/client/hubs
- packages/features/client/create_order - packages/features/client/create_order
- packages/features/client/view_orders - packages/features/client/view_orders
- packages/features/client/client_coverage
- packages/features/client/client_main - packages/features/client/client_main
- apps/staff - apps/staff
- apps/client - apps/client