feat: add staff time card feature with localization and repository implementation

- Implemented Spanish translations for time card related strings.
- Created TimeCardRepository to fetch time card data based on shifts.
- Added use cases for retrieving time cards and payment history.
- Developed BLoC for managing time card state and events.
- Designed UI components for displaying time card summary and shift history.
- Integrated time card navigation within the staff main module.
- Updated pubspec.yaml files to include new dependencies and modules.
This commit is contained in:
Achintha Isuru
2026-01-25 21:16:50 -05:00
parent 6ad2cf4c2d
commit 0622002014
33 changed files with 972 additions and 74 deletions

View File

@@ -2,9 +2,16 @@ import 'package:krow_data_connect/krow_data_connect.dart';
import 'package:krow_domain/krow_domain.dart';
import '../../domain/repositories/payments_repository.dart';
/// 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 {
final FinancialRepositoryMock financialRepository;
/// Creates a [PaymentsRepositoryImpl] with the given [financialRepository].
PaymentsRepositoryImpl({required this.financialRepository});
@override

View File

@@ -0,0 +1,12 @@
import 'package:krow_core/core.dart';
/// Arguments for getting payment history.
class GetPaymentHistoryArguments extends UseCaseArgument {
/// The period to filter by (e.g., "monthly", "weekly").
final String period;
const GetPaymentHistoryArguments(this.period);
@override
List<Object?> get props => [period];
}

View File

@@ -1,23 +0,0 @@
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

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

View File

@@ -1,6 +1,10 @@
import 'package:krow_domain/krow_domain.dart';
/// Repository interface for Payments feature.
///
/// Defines the contract for data access related to staff payments.
/// Implementations of this interface should reside in the data layer.
abstract class PaymentsRepository {
/// Fetches the list of payments.
/// Fetches the list of payments for the current staff member.
Future<List<StaffPayment>> getPayments();
}

View File

@@ -1,14 +1,19 @@
import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
import '../arguments/get_payment_history_arguments.dart';
import '../repositories/payments_repository.dart';
class GetPaymentHistoryUseCase extends UseCase<String, List<StaffPayment>> {
/// Use case to retrieve payment history filtered by a period.
///
/// 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);
@override
Future<List<StaffPayment>> call(String period) async {
Future<List<StaffPayment>> call(GetPaymentHistoryArguments arguments) async {
// TODO: Implement filtering by period
return await repository.getPayments();
}

View File

@@ -2,9 +2,14 @@ import 'package:krow_core/core.dart';
import 'package:krow_domain/krow_domain.dart';
import '../repositories/payments_repository.dart';
/// Use case to retrieve payment summary information.
///
/// 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;
/// Creates a [GetPaymentSummaryUseCase].
GetPaymentSummaryUseCase(this.repository);
@override

View File

@@ -1,5 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow_domain/krow_domain.dart';
import '../../../domain/arguments/get_payment_history_arguments.dart';
import '../../../domain/usecases/get_payment_summary_usecase.dart';
import '../../../domain/usecases/get_payment_history_usecase.dart';
import '../../models/payment_stats.dart';
@@ -27,7 +28,9 @@ class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
final List<StaffPayment> allPayments = await getPaymentSummary();
final PaymentStats stats = _calculateStats(allPayments);
final List<StaffPayment> history = await getPaymentHistory('week');
final List<StaffPayment> history = await getPaymentHistory(
const GetPaymentHistoryArguments('week'),
);
emit(PaymentsLoaded(
summary: stats,
history: history,
@@ -44,10 +47,10 @@ class PaymentsBloc extends Bloc<PaymentsEvent, PaymentsState> {
) async {
final PaymentsState currentState = state;
if (currentState is PaymentsLoaded) {
if (currentState.activePeriod == event.period) return;
try {
final List<StaffPayment> newHistory = await getPaymentHistory(event.period);
final List<StaffPayment> newHistory = await getPaymentHistory(
GetPaymentHistoryArguments(event.period),
);
emit(currentState.copyWith(
history: newHistory,
activePeriod: event.period,