Merge pull request #428 from Oloodi/408-feature-implement-paidunpaid-breaks---client-app-frontend-development
DataConnectorService is implemented in the client appplication
This commit is contained in:
@@ -41,7 +41,7 @@ class ClientSignUpPage extends StatelessWidget {
|
|||||||
final TranslationsClientAuthenticationSignUpPageEn i18n = t.client_authentication.sign_up_page;
|
final TranslationsClientAuthenticationSignUpPageEn i18n = t.client_authentication.sign_up_page;
|
||||||
final ClientAuthBloc authBloc = Modular.get<ClientAuthBloc>();
|
final ClientAuthBloc authBloc = Modular.get<ClientAuthBloc>();
|
||||||
|
|
||||||
return BlocProvider.value(
|
return BlocProvider<ClientAuthBloc>.value(
|
||||||
value: authBloc,
|
value: authBloc,
|
||||||
child: BlocConsumer<ClientAuthBloc, ClientAuthState>(
|
child: BlocConsumer<ClientAuthBloc, ClientAuthState>(
|
||||||
listener: (BuildContext context, ClientAuthState state) {
|
listener: (BuildContext context, ClientAuthState state) {
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ class BillingBloc extends Bloc<BillingEvent, BillingState>
|
|||||||
_getSpendingBreakdown.call(state.period),
|
_getSpendingBreakdown.call(state.period),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
final double currentBill = results[0] as double;
|
|
||||||
final double savings = results[1] as double;
|
final double savings = results[1] as double;
|
||||||
final List<Invoice> pendingInvoices = results[2] as List<Invoice>;
|
final List<Invoice> pendingInvoices = results[2] as List<Invoice>;
|
||||||
final List<Invoice> invoiceHistory = results[3] as List<Invoice>;
|
final List<Invoice> invoiceHistory = results[3] as List<Invoice>;
|
||||||
|
|||||||
@@ -10,24 +10,20 @@ import 'presentation/pages/coverage_page.dart';
|
|||||||
|
|
||||||
/// Modular module for the coverage feature.
|
/// Modular module for the coverage feature.
|
||||||
class CoverageModule extends Module {
|
class CoverageModule extends Module {
|
||||||
|
@override
|
||||||
|
List<Module> get imports => <Module>[DataConnectModule()];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repositories
|
// Repositories
|
||||||
i.addSingleton<CoverageRepository>(
|
i.addSingleton<CoverageRepository>(CoverageRepositoryImpl.new);
|
||||||
() => CoverageRepositoryImpl(dataConnect: ExampleConnector.instance),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Use Cases
|
// Use Cases
|
||||||
i.addSingleton(GetShiftsForDateUseCase.new);
|
i.addSingleton(GetShiftsForDateUseCase.new);
|
||||||
i.addSingleton(GetCoverageStatsUseCase.new);
|
i.addSingleton(GetCoverageStatsUseCase.new);
|
||||||
|
|
||||||
// BLoCs
|
// BLoCs
|
||||||
i.addSingleton<CoverageBloc>(
|
i.addSingleton<CoverageBloc>(CoverageBloc.new);
|
||||||
() => CoverageBloc(
|
|
||||||
getShiftsForDate: i.get<GetShiftsForDateUseCase>(),
|
|
||||||
getCoverageStats: i.get<GetCoverageStatsUseCase>(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -15,44 +15,36 @@ import '../../domain/repositories/coverage_repository.dart';
|
|||||||
/// - Returns domain entities from `domain/ui_entities`.
|
/// - Returns domain entities from `domain/ui_entities`.
|
||||||
class CoverageRepositoryImpl implements CoverageRepository {
|
class CoverageRepositoryImpl implements CoverageRepository {
|
||||||
/// Creates a [CoverageRepositoryImpl].
|
/// Creates a [CoverageRepositoryImpl].
|
||||||
CoverageRepositoryImpl({required dc.ExampleConnector dataConnect})
|
CoverageRepositoryImpl({required dc.DataConnectService service}) : _service = service;
|
||||||
: _dataConnect = dataConnect;
|
|
||||||
|
|
||||||
final dc.ExampleConnector _dataConnect;
|
final dc.DataConnectService _service;
|
||||||
|
|
||||||
/// Fetches shifts for a specific date.
|
/// Fetches shifts for a specific date.
|
||||||
@override
|
@override
|
||||||
Future<List<CoverageShift>> getShiftsForDate({required DateTime date}) async {
|
Future<List<CoverageShift>> getShiftsForDate({required DateTime date}) async {
|
||||||
try {
|
return _service.run(() async {
|
||||||
final String? businessId =
|
final String businessId = await _service.getBusinessId();
|
||||||
dc.ClientSessionStore.instance.session?.business?.id;
|
|
||||||
if (businessId == null || businessId.isEmpty) {
|
|
||||||
return <CoverageShift>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
final DateTime start = DateTime(date.year, date.month, date.day);
|
final DateTime start = DateTime(date.year, date.month, date.day);
|
||||||
final DateTime end =
|
final DateTime end = DateTime(date.year, date.month, date.day, 23, 59, 59, 999);
|
||||||
DateTime(date.year, date.month, date.day, 23, 59, 59, 999);
|
|
||||||
|
|
||||||
final fdc.QueryResult<
|
final fdc.QueryResult<dc.ListShiftRolesByBusinessAndDateRangeData,
|
||||||
dc.ListShiftRolesByBusinessAndDateRangeData,
|
|
||||||
dc.ListShiftRolesByBusinessAndDateRangeVariables> shiftRolesResult =
|
dc.ListShiftRolesByBusinessAndDateRangeVariables> shiftRolesResult =
|
||||||
await _dataConnect
|
await _service.connector
|
||||||
.listShiftRolesByBusinessAndDateRange(
|
.listShiftRolesByBusinessAndDateRange(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
start: _toTimestamp(start),
|
start: _service.toTimestamp(start),
|
||||||
end: _toTimestamp(end),
|
end: _service.toTimestamp(end),
|
||||||
)
|
)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
final fdc.QueryResult<
|
final fdc.QueryResult<dc.ListStaffsApplicationsByBusinessForDayData,
|
||||||
dc.ListStaffsApplicationsByBusinessForDayData,
|
|
||||||
dc.ListStaffsApplicationsByBusinessForDayVariables> applicationsResult =
|
dc.ListStaffsApplicationsByBusinessForDayVariables> applicationsResult =
|
||||||
await _dataConnect
|
await _service.connector
|
||||||
.listStaffsApplicationsByBusinessForDay(
|
.listStaffsApplicationsByBusinessForDay(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
dayStart: _toTimestamp(start),
|
dayStart: _service.toTimestamp(start),
|
||||||
dayEnd: _toTimestamp(end),
|
dayEnd: _service.toTimestamp(end),
|
||||||
)
|
)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@@ -61,18 +53,7 @@ class CoverageRepositoryImpl implements CoverageRepository {
|
|||||||
applicationsResult.data.applications,
|
applicationsResult.data.applications,
|
||||||
date,
|
date,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
});
|
||||||
final String error = e.toString().toLowerCase();
|
|
||||||
if (error.contains('network') ||
|
|
||||||
error.contains('connection') ||
|
|
||||||
error.contains('unavailable') ||
|
|
||||||
error.contains('offline') ||
|
|
||||||
error.contains('socket') ||
|
|
||||||
error.contains('failed host lookup')) {
|
|
||||||
throw NetworkException(technicalMessage: 'Coverage fetch failed: $e');
|
|
||||||
}
|
|
||||||
throw ServerException(technicalMessage: 'Coverage fetch failed: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches coverage statistics for a specific date.
|
/// Fetches coverage statistics for a specific date.
|
||||||
@@ -110,14 +91,6 @@ class CoverageRepositoryImpl implements CoverageRepository {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fdc.Timestamp _toTimestamp(DateTime dateTime) {
|
|
||||||
final DateTime utc = dateTime.toUtc();
|
|
||||||
final int seconds = utc.millisecondsSinceEpoch ~/ 1000;
|
|
||||||
final int nanoseconds =
|
|
||||||
(utc.millisecondsSinceEpoch % 1000) * 1000000;
|
|
||||||
return fdc.Timestamp(nanoseconds, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<CoverageShift> _mapCoverageShifts(
|
List<CoverageShift> _mapCoverageShifts(
|
||||||
List<dc.ListShiftRolesByBusinessAndDateRangeShiftRoles> shiftRoles,
|
List<dc.ListShiftRolesByBusinessAndDateRangeShiftRoles> shiftRoles,
|
||||||
List<dc.ListStaffsApplicationsByBusinessForDayApplications> applications,
|
List<dc.ListStaffsApplicationsByBusinessForDayApplications> applications,
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import '../../domain/repositories/client_create_order_repository_interface.dart'
|
|||||||
|
|
||||||
/// Implementation of [ClientCreateOrderRepositoryInterface].
|
/// Implementation of [ClientCreateOrderRepositoryInterface].
|
||||||
///
|
///
|
||||||
/// This implementation coordinates data access for order creation by delegating
|
/// This implementation coordinates data access for order creation by [DataConnectService] from the shared
|
||||||
/// to the [OrderRepositoryMock] and [ExampleConnector] from the shared
|
|
||||||
/// Data Connect package.
|
/// Data Connect package.
|
||||||
///
|
///
|
||||||
/// It follows the KROW Clean Architecture by keeping the data layer focused
|
/// It follows the KROW Clean Architecture by keeping the data layer focused
|
||||||
|
|||||||
@@ -23,11 +23,7 @@ class ClientHomeModule extends Module {
|
|||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repositories
|
// Repositories
|
||||||
i.addLazySingleton<HomeRepositoryInterface>(
|
i.addLazySingleton<HomeRepositoryInterface>(HomeRepositoryImpl.new);
|
||||||
() => HomeRepositoryImpl(
|
|
||||||
ExampleConnector.instance,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// UseCases
|
// UseCases
|
||||||
i.addLazySingleton(GetDashboardDataUseCase.new);
|
i.addLazySingleton(GetDashboardDataUseCase.new);
|
||||||
@@ -35,13 +31,7 @@ class ClientHomeModule extends Module {
|
|||||||
i.addLazySingleton(GetUserSessionDataUseCase.new);
|
i.addLazySingleton(GetUserSessionDataUseCase.new);
|
||||||
|
|
||||||
// BLoCs
|
// BLoCs
|
||||||
i.add<ClientHomeBloc>(
|
i.add<ClientHomeBloc>(ClientHomeBloc.new);
|
||||||
() => ClientHomeBloc(
|
|
||||||
getDashboardDataUseCase: i.get<GetDashboardDataUseCase>(),
|
|
||||||
getRecentReordersUseCase: i.get<GetRecentReordersUseCase>(),
|
|
||||||
getUserSessionDataUseCase: i.get<GetUserSessionDataUseCase>(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -8,25 +8,14 @@ import '../../domain/repositories/home_repository_interface.dart';
|
|||||||
/// This implementation resides in the data layer and acts as a bridge between the
|
/// This implementation resides in the data layer and acts as a bridge between the
|
||||||
/// domain layer and the data source (in this case, a mock from data_connect).
|
/// domain layer and the data source (in this case, a mock from data_connect).
|
||||||
class HomeRepositoryImpl implements HomeRepositoryInterface {
|
class HomeRepositoryImpl implements HomeRepositoryInterface {
|
||||||
|
|
||||||
/// Creates a [HomeRepositoryImpl].
|
/// Creates a [HomeRepositoryImpl].
|
||||||
HomeRepositoryImpl(this._dataConnect);
|
HomeRepositoryImpl(this._service);
|
||||||
final dc.ExampleConnector _dataConnect;
|
final dc.DataConnectService _service;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<HomeDashboardData> getDashboardData() async {
|
Future<HomeDashboardData> getDashboardData() async {
|
||||||
try {
|
return _service.run(() async {
|
||||||
final String? businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
final String businessId = await _service.getBusinessId();
|
||||||
if (businessId == null || businessId.isEmpty) {
|
|
||||||
return const HomeDashboardData(
|
|
||||||
weeklySpending: 0,
|
|
||||||
next7DaysSpending: 0,
|
|
||||||
weeklyShifts: 0,
|
|
||||||
next7DaysScheduled: 0,
|
|
||||||
totalNeeded: 0,
|
|
||||||
totalFilled: 0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final DateTime now = DateTime.now();
|
final DateTime now = DateTime.now();
|
||||||
final int daysFromMonday = now.weekday - DateTime.monday;
|
final int daysFromMonday = now.weekday - DateTime.monday;
|
||||||
@@ -35,14 +24,13 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
|
|||||||
final DateTime weekRangeStart = DateTime(monday.year, monday.month, monday.day);
|
final DateTime weekRangeStart = DateTime(monday.year, monday.month, monday.day);
|
||||||
final DateTime weekRangeEnd =
|
final DateTime weekRangeEnd =
|
||||||
DateTime(monday.year, monday.month, monday.day + 13, 23, 59, 59, 999);
|
DateTime(monday.year, monday.month, monday.day + 13, 23, 59, 59, 999);
|
||||||
final fdc.QueryResult<
|
final fdc.QueryResult<dc.GetCompletedShiftsByBusinessIdData,
|
||||||
dc.GetCompletedShiftsByBusinessIdData,
|
|
||||||
dc.GetCompletedShiftsByBusinessIdVariables> completedResult =
|
dc.GetCompletedShiftsByBusinessIdVariables> completedResult =
|
||||||
await _dataConnect
|
await _service.connector
|
||||||
.getCompletedShiftsByBusinessId(
|
.getCompletedShiftsByBusinessId(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
dateFrom: _toTimestamp(weekRangeStart),
|
dateFrom: _service.toTimestamp(weekRangeStart),
|
||||||
dateTo: _toTimestamp(weekRangeEnd),
|
dateTo: _service.toTimestamp(weekRangeEnd),
|
||||||
)
|
)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@@ -50,8 +38,7 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
|
|||||||
double next7DaysSpending = 0.0;
|
double next7DaysSpending = 0.0;
|
||||||
int weeklyShifts = 0;
|
int weeklyShifts = 0;
|
||||||
int next7DaysScheduled = 0;
|
int next7DaysScheduled = 0;
|
||||||
for (final dc.GetCompletedShiftsByBusinessIdShifts shift
|
for (final dc.GetCompletedShiftsByBusinessIdShifts shift in completedResult.data.shifts) {
|
||||||
in completedResult.data.shifts) {
|
|
||||||
final DateTime? shiftDate = shift.date?.toDateTime();
|
final DateTime? shiftDate = shift.date?.toDateTime();
|
||||||
if (shiftDate == null) {
|
if (shiftDate == null) {
|
||||||
continue;
|
continue;
|
||||||
@@ -73,14 +60,13 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
|
|||||||
final DateTime start = DateTime(now.year, now.month, now.day);
|
final DateTime start = DateTime(now.year, now.month, now.day);
|
||||||
final DateTime end = DateTime(now.year, now.month, now.day, 23, 59, 59, 999);
|
final DateTime end = DateTime(now.year, now.month, now.day, 23, 59, 59, 999);
|
||||||
|
|
||||||
final fdc.QueryResult<
|
final fdc.QueryResult<dc.ListShiftRolesByBusinessAndDateRangeData,
|
||||||
dc.ListShiftRolesByBusinessAndDateRangeData,
|
|
||||||
dc.ListShiftRolesByBusinessAndDateRangeVariables> result =
|
dc.ListShiftRolesByBusinessAndDateRangeVariables> result =
|
||||||
await _dataConnect
|
await _service.connector
|
||||||
.listShiftRolesByBusinessAndDateRange(
|
.listShiftRolesByBusinessAndDateRange(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
start: _toTimestamp(start),
|
start: _service.toTimestamp(start),
|
||||||
end: _toTimestamp(end),
|
end: _service.toTimestamp(end),
|
||||||
)
|
)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
@@ -100,18 +86,7 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
|
|||||||
totalNeeded: totalNeeded,
|
totalNeeded: totalNeeded,
|
||||||
totalFilled: totalFilled,
|
totalFilled: totalFilled,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
});
|
||||||
final String error = e.toString().toLowerCase();
|
|
||||||
if (error.contains('network') ||
|
|
||||||
error.contains('connection') ||
|
|
||||||
error.contains('unavailable') ||
|
|
||||||
error.contains('offline') ||
|
|
||||||
error.contains('socket') ||
|
|
||||||
error.contains('failed host lookup')) {
|
|
||||||
throw NetworkException(technicalMessage: 'Home dashboard fetch failed: $e');
|
|
||||||
}
|
|
||||||
throw ServerException(technicalMessage: 'Home dashboard fetch failed: $e');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -125,34 +100,29 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<ReorderItem>> getRecentReorders() async {
|
Future<List<ReorderItem>> getRecentReorders() async {
|
||||||
try {
|
return _service.run(() async {
|
||||||
final String? businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
final String businessId = await _service.getBusinessId();
|
||||||
if (businessId == null || businessId.isEmpty) {
|
|
||||||
return const <ReorderItem>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
final DateTime now = DateTime.now();
|
final DateTime now = DateTime.now();
|
||||||
final DateTime start = now.subtract(const Duration(days: 30));
|
final DateTime start = now.subtract(const Duration(days: 30));
|
||||||
final fdc.Timestamp startTimestamp = _toTimestamp(start);
|
final fdc.Timestamp startTimestamp = _service.toTimestamp(start);
|
||||||
final fdc.Timestamp endTimestamp = _toTimestamp(now);
|
final fdc.Timestamp endTimestamp = _service.toTimestamp(now);
|
||||||
|
|
||||||
final fdc.QueryResult<
|
final fdc.QueryResult<dc.ListShiftRolesByBusinessDateRangeCompletedOrdersData,
|
||||||
dc.ListShiftRolesByBusinessDateRangeCompletedOrdersData,
|
|
||||||
dc.ListShiftRolesByBusinessDateRangeCompletedOrdersVariables> result =
|
dc.ListShiftRolesByBusinessDateRangeCompletedOrdersVariables> result =
|
||||||
await _dataConnect.listShiftRolesByBusinessDateRangeCompletedOrders(
|
await _service.connector
|
||||||
|
.listShiftRolesByBusinessDateRangeCompletedOrders(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
start: startTimestamp,
|
start: startTimestamp,
|
||||||
end: endTimestamp,
|
end: endTimestamp,
|
||||||
).execute();
|
)
|
||||||
|
.execute();
|
||||||
|
|
||||||
return result.data.shiftRoles.map((
|
return result.data.shiftRoles
|
||||||
|
.map((
|
||||||
dc.ListShiftRolesByBusinessDateRangeCompletedOrdersShiftRoles shiftRole,
|
dc.ListShiftRolesByBusinessDateRangeCompletedOrdersShiftRoles shiftRole,
|
||||||
) {
|
) {
|
||||||
|
final String location = shiftRole.shift.location ?? shiftRole.shift.locationAddress ?? '';
|
||||||
final String location =
|
|
||||||
shiftRole.shift.location ??
|
|
||||||
shiftRole.shift.locationAddress ??
|
|
||||||
'';
|
|
||||||
final String type = shiftRole.shift.order.orderType.stringValue;
|
final String type = shiftRole.shift.order.orderType.stringValue;
|
||||||
return ReorderItem(
|
return ReorderItem(
|
||||||
orderId: shiftRole.shift.order.id,
|
orderId: shiftRole.shift.order.id,
|
||||||
@@ -163,26 +133,8 @@ class HomeRepositoryImpl implements HomeRepositoryInterface {
|
|||||||
workers: shiftRole.count,
|
workers: shiftRole.count,
|
||||||
type: type,
|
type: type,
|
||||||
);
|
);
|
||||||
}).toList();
|
})
|
||||||
} catch (e) {
|
.toList();
|
||||||
final String error = e.toString().toLowerCase();
|
});
|
||||||
if (error.contains('network') ||
|
|
||||||
error.contains('connection') ||
|
|
||||||
error.contains('unavailable') ||
|
|
||||||
error.contains('offline') ||
|
|
||||||
error.contains('socket') ||
|
|
||||||
error.contains('failed host lookup')) {
|
|
||||||
throw NetworkException(technicalMessage: 'Home reorders fetch failed: $e');
|
|
||||||
}
|
|
||||||
throw ServerException(technicalMessage: 'Home reorders fetch failed: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fdc.Timestamp _toTimestamp(DateTime date) {
|
|
||||||
final DateTime utc = date.toUtc();
|
|
||||||
final int millis = utc.millisecondsSinceEpoch;
|
|
||||||
final int seconds = millis ~/ 1000;
|
|
||||||
final int nanos = (millis % 1000) * 1000000;
|
|
||||||
return fdc.Timestamp(nanos, seconds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ class CoverageDashboard extends StatelessWidget {
|
|||||||
int totalConfirmed = 0;
|
int totalConfirmed = 0;
|
||||||
double todayCost = 0;
|
double todayCost = 0;
|
||||||
|
|
||||||
for (final s in shifts) {
|
for (final dynamic s in shifts) {
|
||||||
final int needed = s['workersNeeded'] as int? ?? 0;
|
final int needed = (s as Map<String, dynamic>)['workersNeeded'] as int? ?? 0;
|
||||||
final int confirmed = s['filled'] as int? ?? 0;
|
final int confirmed = s['filled'] as int? ?? 0;
|
||||||
final double rate = s['hourlyRate'] as double? ?? 0.0;
|
final double rate = s['hourlyRate'] as double? ?? 0.0;
|
||||||
final double hours = s['hours'] as double? ?? 0.0;
|
final double hours = s['hours'] as double? ?? 0.0;
|
||||||
@@ -39,10 +39,10 @@ class CoverageDashboard extends StatelessWidget {
|
|||||||
final int unfilledPositions = totalNeeded - totalConfirmed;
|
final int unfilledPositions = totalNeeded - totalConfirmed;
|
||||||
|
|
||||||
final int checkedInCount = applications
|
final int checkedInCount = applications
|
||||||
.where((a) => (a as Map)['checkInTime'] != null)
|
.where((dynamic a) => (a as Map<String, dynamic>)['checkInTime'] != null)
|
||||||
.length;
|
.length;
|
||||||
final int lateWorkersCount = applications
|
final int lateWorkersCount = applications
|
||||||
.where((a) => (a as Map)['status'] == 'LATE')
|
.where((dynamic a) => (a as Map<String, dynamic>)['status'] == 'LATE')
|
||||||
.length;
|
.length;
|
||||||
|
|
||||||
final bool isCoverageGood = coveragePercent >= 90;
|
final bool isCoverageGood = coveragePercent >= 90;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ library;
|
|||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:krow_core/core.dart';
|
import 'package:krow_core/core.dart';
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
|
||||||
import 'src/data/repositories_impl/hub_repository_impl.dart';
|
import 'src/data/repositories_impl/hub_repository_impl.dart';
|
||||||
import 'src/domain/repositories/hub_repository_interface.dart';
|
import 'src/domain/repositories/hub_repository_interface.dart';
|
||||||
import 'src/domain/usecases/assign_nfc_tag_usecase.dart';
|
import 'src/domain/usecases/assign_nfc_tag_usecase.dart';
|
||||||
@@ -23,12 +22,7 @@ class ClientHubsModule extends Module {
|
|||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repositories
|
// Repositories
|
||||||
i.addLazySingleton<HubRepositoryInterface>(
|
i.addLazySingleton<HubRepositoryInterface>(HubRepositoryImpl.new);
|
||||||
() => HubRepositoryImpl(
|
|
||||||
firebaseAuth: firebase.FirebaseAuth.instance,
|
|
||||||
dataConnect: ExampleConnector.instance,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// UseCases
|
// UseCases
|
||||||
i.addLazySingleton(GetHubsUseCase.new);
|
i.addLazySingleton(GetHubsUseCase.new);
|
||||||
@@ -37,14 +31,7 @@ class ClientHubsModule extends Module {
|
|||||||
i.addLazySingleton(AssignNfcTagUseCase.new);
|
i.addLazySingleton(AssignNfcTagUseCase.new);
|
||||||
|
|
||||||
// BLoCs
|
// BLoCs
|
||||||
i.add<ClientHubsBloc>(
|
i.add<ClientHubsBloc>(ClientHubsBloc.new);
|
||||||
() => ClientHubsBloc(
|
|
||||||
getHubsUseCase: i.get<GetHubsUseCase>(),
|
|
||||||
createHubUseCase: i.get<CreateHubUseCase>(),
|
|
||||||
deleteHubUseCase: i.get<DeleteHubUseCase>(),
|
|
||||||
assignNfcTagUseCase: i.get<AssignNfcTagUseCase>(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -9,30 +9,26 @@ import 'package:krow_domain/krow_domain.dart' as domain;
|
|||||||
import 'package:krow_domain/krow_domain.dart'
|
import 'package:krow_domain/krow_domain.dart'
|
||||||
show
|
show
|
||||||
HubHasOrdersException,
|
HubHasOrdersException,
|
||||||
HubCreationFailedException,
|
|
||||||
BusinessNotFoundException,
|
BusinessNotFoundException,
|
||||||
NotAuthenticatedException;
|
NotAuthenticatedException;
|
||||||
|
|
||||||
import '../../domain/repositories/hub_repository_interface.dart';
|
import '../../domain/repositories/hub_repository_interface.dart';
|
||||||
|
|
||||||
/// Implementation of [HubRepositoryInterface] backed by Data Connect.
|
/// Implementation of [HubRepositoryInterface] backed by Data Connect.
|
||||||
class HubRepositoryImpl
|
class HubRepositoryImpl implements HubRepositoryInterface {
|
||||||
with dc.DataErrorHandler
|
|
||||||
implements HubRepositoryInterface {
|
|
||||||
HubRepositoryImpl({
|
HubRepositoryImpl({
|
||||||
required firebase.FirebaseAuth firebaseAuth,
|
required dc.DataConnectService service,
|
||||||
required dc.ExampleConnector dataConnect,
|
}) : _service = service;
|
||||||
}) : _firebaseAuth = firebaseAuth,
|
|
||||||
_dataConnect = dataConnect;
|
|
||||||
|
|
||||||
final firebase.FirebaseAuth _firebaseAuth;
|
final dc.DataConnectService _service;
|
||||||
final dc.ExampleConnector _dataConnect;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<domain.Hub>> getHubs() async {
|
Future<List<domain.Hub>> getHubs() async {
|
||||||
|
return _service.run(() async {
|
||||||
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
|
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
|
||||||
final String teamId = await _getOrCreateTeamId(business);
|
final String teamId = await _getOrCreateTeamId(business);
|
||||||
return _fetchHubsForTeam(teamId: teamId, businessId: business.id);
|
return _fetchHubsForTeam(teamId: teamId, businessId: business.id);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -48,6 +44,7 @@ class HubRepositoryImpl
|
|||||||
String? country,
|
String? country,
|
||||||
String? zipCode,
|
String? zipCode,
|
||||||
}) async {
|
}) async {
|
||||||
|
return _service.run(() async {
|
||||||
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
|
final dc.GetBusinessesByUserIdBusinesses business = await _getBusinessForCurrentUser();
|
||||||
final String teamId = await _getOrCreateTeamId(business);
|
final String teamId = await _getOrCreateTeamId(business);
|
||||||
final _PlaceAddress? placeAddress =
|
final _PlaceAddress? placeAddress =
|
||||||
@@ -59,7 +56,7 @@ class HubRepositoryImpl
|
|||||||
final String? zipCodeValue = zipCode ?? placeAddress?.zipCode;
|
final String? zipCodeValue = zipCode ?? placeAddress?.zipCode;
|
||||||
|
|
||||||
final OperationResult<dc.CreateTeamHubData, dc.CreateTeamHubVariables>
|
final OperationResult<dc.CreateTeamHubData, dc.CreateTeamHubVariables>
|
||||||
result = await executeProtected(() => _dataConnect
|
result = await _service.connector
|
||||||
.createTeamHub(
|
.createTeamHub(
|
||||||
teamId: teamId,
|
teamId: teamId,
|
||||||
hubName: name,
|
hubName: name,
|
||||||
@@ -73,7 +70,7 @@ class HubRepositoryImpl
|
|||||||
.street(streetValue)
|
.street(streetValue)
|
||||||
.country(countryValue)
|
.country(countryValue)
|
||||||
.zipCode(zipCodeValue)
|
.zipCode(zipCodeValue)
|
||||||
.execute());
|
.execute();
|
||||||
final String createdId = result.data.teamHub_insert.id;
|
final String createdId = result.data.teamHub_insert.id;
|
||||||
|
|
||||||
final List<domain.Hub> hubs = await _fetchHubsForTeam(
|
final List<domain.Hub> hubs = await _fetchHubsForTeam(
|
||||||
@@ -96,26 +93,22 @@ class HubRepositoryImpl
|
|||||||
nfcTagId: null,
|
nfcTagId: null,
|
||||||
status: domain.HubStatus.active,
|
status: domain.HubStatus.active,
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> deleteHub(String id) async {
|
Future<void> deleteHub(String id) async {
|
||||||
final String? businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
return _service.run(() async {
|
||||||
if (businessId == null || businessId.isEmpty) {
|
final String businessId = await _service.getBusinessId();
|
||||||
await _firebaseAuth.signOut();
|
|
||||||
throw const BusinessNotFoundException(
|
|
||||||
technicalMessage: 'Business ID missing from session',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final QueryResult<dc.ListOrdersByBusinessAndTeamHubData,
|
final QueryResult<dc.ListOrdersByBusinessAndTeamHubData,
|
||||||
dc.ListOrdersByBusinessAndTeamHubVariables> result =
|
dc.ListOrdersByBusinessAndTeamHubVariables> result =
|
||||||
await executeProtected(() => _dataConnect
|
await _service.connector
|
||||||
.listOrdersByBusinessAndTeamHub(
|
.listOrdersByBusinessAndTeamHub(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
teamHubId: id,
|
teamHubId: id,
|
||||||
)
|
)
|
||||||
.execute());
|
.execute();
|
||||||
|
|
||||||
if (result.data.orders.isNotEmpty) {
|
if (result.data.orders.isNotEmpty) {
|
||||||
throw HubHasOrdersException(
|
throw HubHasOrdersException(
|
||||||
@@ -123,7 +116,8 @@ class HubRepositoryImpl
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await executeProtected(() => _dataConnect.deleteTeamHub(id: id).execute());
|
await _service.connector.deleteTeamHub(id: id).execute();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -141,7 +135,7 @@ class HubRepositoryImpl
|
|||||||
return dc.GetBusinessesByUserIdBusinesses(
|
return dc.GetBusinessesByUserIdBusinesses(
|
||||||
id: cachedBusiness.id,
|
id: cachedBusiness.id,
|
||||||
businessName: cachedBusiness.businessName,
|
businessName: cachedBusiness.businessName,
|
||||||
userId: _firebaseAuth.currentUser?.uid ?? '',
|
userId: _service.auth.currentUser?.uid ?? '',
|
||||||
rateGroup: const dc.Known<dc.BusinessRateGroup>(dc.BusinessRateGroup.STANDARD),
|
rateGroup: const dc.Known<dc.BusinessRateGroup>(dc.BusinessRateGroup.STANDARD),
|
||||||
status: const dc.Known<dc.BusinessStatus>(dc.BusinessStatus.ACTIVE),
|
status: const dc.Known<dc.BusinessStatus>(dc.BusinessStatus.ACTIVE),
|
||||||
contactName: cachedBusiness.contactName,
|
contactName: cachedBusiness.contactName,
|
||||||
@@ -159,7 +153,7 @@ class HubRepositoryImpl
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final firebase.User? user = _firebaseAuth.currentUser;
|
final firebase.User? user = _service.auth.currentUser;
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw const NotAuthenticatedException(
|
throw const NotAuthenticatedException(
|
||||||
technicalMessage: 'No Firebase user in currentUser',
|
technicalMessage: 'No Firebase user in currentUser',
|
||||||
@@ -168,11 +162,11 @@ class HubRepositoryImpl
|
|||||||
|
|
||||||
final QueryResult<dc.GetBusinessesByUserIdData,
|
final QueryResult<dc.GetBusinessesByUserIdData,
|
||||||
dc.GetBusinessesByUserIdVariables> result =
|
dc.GetBusinessesByUserIdVariables> result =
|
||||||
await executeProtected(() => _dataConnect.getBusinessesByUserId(
|
await _service.connector.getBusinessesByUserId(
|
||||||
userId: user.uid,
|
userId: user.uid,
|
||||||
).execute());
|
).execute();
|
||||||
if (result.data.businesses.isEmpty) {
|
if (result.data.businesses.isEmpty) {
|
||||||
await _firebaseAuth.signOut();
|
await _service.auth.signOut();
|
||||||
throw BusinessNotFoundException(
|
throw BusinessNotFoundException(
|
||||||
technicalMessage: 'No business found for user ${user.uid}',
|
technicalMessage: 'No business found for user ${user.uid}',
|
||||||
);
|
);
|
||||||
@@ -203,14 +197,14 @@ class HubRepositoryImpl
|
|||||||
dc.GetBusinessesByUserIdBusinesses business,
|
dc.GetBusinessesByUserIdBusinesses business,
|
||||||
) async {
|
) async {
|
||||||
final QueryResult<dc.GetTeamsByOwnerIdData, dc.GetTeamsByOwnerIdVariables>
|
final QueryResult<dc.GetTeamsByOwnerIdData, dc.GetTeamsByOwnerIdVariables>
|
||||||
teamsResult = await executeProtected(() => _dataConnect.getTeamsByOwnerId(
|
teamsResult = await _service.connector.getTeamsByOwnerId(
|
||||||
ownerId: business.id,
|
ownerId: business.id,
|
||||||
).execute());
|
).execute();
|
||||||
if (teamsResult.data.teams.isNotEmpty) {
|
if (teamsResult.data.teams.isNotEmpty) {
|
||||||
return teamsResult.data.teams.first.id;
|
return teamsResult.data.teams.first.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
final dc.CreateTeamVariablesBuilder createTeamBuilder = _dataConnect.createTeam(
|
final dc.CreateTeamVariablesBuilder createTeamBuilder = _service.connector.createTeam(
|
||||||
teamName: '${business.businessName} Team',
|
teamName: '${business.businessName} Team',
|
||||||
ownerId: business.id,
|
ownerId: business.id,
|
||||||
ownerName: business.contactName ?? '',
|
ownerName: business.contactName ?? '',
|
||||||
@@ -222,7 +216,7 @@ class HubRepositoryImpl
|
|||||||
|
|
||||||
final OperationResult<dc.CreateTeamData, dc.CreateTeamVariables>
|
final OperationResult<dc.CreateTeamData, dc.CreateTeamVariables>
|
||||||
createTeamResult =
|
createTeamResult =
|
||||||
await executeProtected(() => createTeamBuilder.execute());
|
await createTeamBuilder.execute();
|
||||||
final String teamId = createTeamResult.data.team_insert.id;
|
final String teamId = createTeamResult.data.team_insert.id;
|
||||||
|
|
||||||
return teamId;
|
return teamId;
|
||||||
@@ -234,9 +228,9 @@ class HubRepositoryImpl
|
|||||||
}) async {
|
}) async {
|
||||||
final QueryResult<dc.GetTeamHubsByTeamIdData,
|
final QueryResult<dc.GetTeamHubsByTeamIdData,
|
||||||
dc.GetTeamHubsByTeamIdVariables> hubsResult =
|
dc.GetTeamHubsByTeamIdVariables> hubsResult =
|
||||||
await executeProtected(() => _dataConnect.getTeamHubsByTeamId(
|
await _service.connector.getTeamHubsByTeamId(
|
||||||
teamId: teamId,
|
teamId: teamId,
|
||||||
).execute());
|
).execute();
|
||||||
|
|
||||||
return hubsResult.data.teamHubs
|
return hubsResult.data.teamHubs
|
||||||
.map(
|
.map(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
|
||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:krow_core/core.dart';
|
import 'package:krow_core/core.dart';
|
||||||
|
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||||
import 'src/data/repositories_impl/settings_repository_impl.dart';
|
import 'src/data/repositories_impl/settings_repository_impl.dart';
|
||||||
import 'src/domain/repositories/settings_repository_interface.dart';
|
import 'src/domain/repositories/settings_repository_interface.dart';
|
||||||
import 'src/domain/usecases/sign_out_usecase.dart';
|
import 'src/domain/usecases/sign_out_usecase.dart';
|
||||||
@@ -9,20 +9,19 @@ import 'src/presentation/pages/client_settings_page.dart';
|
|||||||
|
|
||||||
/// A [Module] for the client settings feature.
|
/// A [Module] for the client settings feature.
|
||||||
class ClientSettingsModule extends Module {
|
class ClientSettingsModule extends Module {
|
||||||
|
@override
|
||||||
|
List<Module> get imports => <Module>[DataConnectModule()];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repositories
|
// Repositories
|
||||||
i.addLazySingleton<SettingsRepositoryInterface>(
|
i.addLazySingleton<SettingsRepositoryInterface>(SettingsRepositoryImpl.new);
|
||||||
() => SettingsRepositoryImpl(firebaseAuth: FirebaseAuth.instance),
|
|
||||||
);
|
|
||||||
|
|
||||||
// UseCases
|
// UseCases
|
||||||
i.addLazySingleton(SignOutUseCase.new);
|
i.addLazySingleton(SignOutUseCase.new);
|
||||||
|
|
||||||
// BLoCs
|
// BLoCs
|
||||||
i.add<ClientSettingsBloc>(
|
i.add<ClientSettingsBloc>(ClientSettingsBloc.new);
|
||||||
() => ClientSettingsBloc(signOutUseCase: i.get<SignOutUseCase>()),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||||
|
|
||||||
import '../../domain/repositories/settings_repository_interface.dart';
|
import '../../domain/repositories/settings_repository_interface.dart';
|
||||||
|
|
||||||
/// Implementation of [SettingsRepositoryInterface].
|
/// Implementation of [SettingsRepositoryInterface].
|
||||||
///
|
///
|
||||||
/// This implementation delegates authentication operations to [FirebaseAuth].
|
/// This implementation delegates authentication operations to [DataConnectService].
|
||||||
class SettingsRepositoryImpl implements SettingsRepositoryInterface {
|
class SettingsRepositoryImpl implements SettingsRepositoryInterface {
|
||||||
/// Creates a [SettingsRepositoryImpl] with the required [_firebaseAuth].
|
/// Creates a [SettingsRepositoryImpl] with the required [_service].
|
||||||
const SettingsRepositoryImpl({required this.firebaseAuth});
|
const SettingsRepositoryImpl({required dc.DataConnectService service}) : _service = service;
|
||||||
|
|
||||||
/// The Firebase Auth instance.
|
/// The Data Connect service.
|
||||||
final FirebaseAuth firebaseAuth;
|
final dc.DataConnectService _service;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> signOut() async {
|
Future<void> signOut() async {
|
||||||
try {
|
return _service.run(() async {
|
||||||
await firebaseAuth.signOut();
|
await _service.auth.signOut();
|
||||||
} catch (e) {
|
});
|
||||||
throw Exception('Error signing out: ${e.toString()}');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
|
||||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||||
@@ -6,53 +5,42 @@ import 'package:krow_domain/krow_domain.dart' as domain;
|
|||||||
import '../../domain/repositories/i_view_orders_repository.dart';
|
import '../../domain/repositories/i_view_orders_repository.dart';
|
||||||
|
|
||||||
/// Implementation of [IViewOrdersRepository] using Data Connect.
|
/// Implementation of [IViewOrdersRepository] using Data Connect.
|
||||||
class ViewOrdersRepositoryImpl
|
class ViewOrdersRepositoryImpl implements IViewOrdersRepository {
|
||||||
with dc.DataErrorHandler
|
final dc.DataConnectService _service;
|
||||||
implements IViewOrdersRepository {
|
|
||||||
final firebase.FirebaseAuth _firebaseAuth;
|
|
||||||
final dc.ExampleConnector _dataConnect;
|
|
||||||
|
|
||||||
ViewOrdersRepositoryImpl({
|
ViewOrdersRepositoryImpl({
|
||||||
required firebase.FirebaseAuth firebaseAuth,
|
required dc.DataConnectService service,
|
||||||
required dc.ExampleConnector dataConnect,
|
}) : _service = service;
|
||||||
}) : _firebaseAuth = firebaseAuth,
|
|
||||||
_dataConnect = dataConnect;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<domain.OrderItem>> getOrdersForRange({
|
Future<List<domain.OrderItem>> getOrdersForRange({
|
||||||
required DateTime start,
|
required DateTime start,
|
||||||
required DateTime end,
|
required DateTime end,
|
||||||
}) async {
|
}) async {
|
||||||
final String? businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
return _service.run(() async {
|
||||||
if (businessId == null || businessId.isEmpty) {
|
final String businessId = await _service.getBusinessId();
|
||||||
await _firebaseAuth.signOut();
|
|
||||||
throw Exception('Business is missing. Please sign in again.');
|
|
||||||
}
|
|
||||||
|
|
||||||
final fdc.Timestamp startTimestamp = _toTimestamp(_startOfDay(start));
|
final fdc.Timestamp startTimestamp = _service.toTimestamp(_startOfDay(start));
|
||||||
final fdc.Timestamp endTimestamp = _toTimestamp(_endOfDay(end));
|
final fdc.Timestamp endTimestamp = _service.toTimestamp(_endOfDay(end));
|
||||||
final fdc.QueryResult<dc.ListShiftRolesByBusinessAndDateRangeData,
|
final fdc.QueryResult<dc.ListShiftRolesByBusinessAndDateRangeData,
|
||||||
dc.ListShiftRolesByBusinessAndDateRangeVariables> result =
|
dc.ListShiftRolesByBusinessAndDateRangeVariables> result =
|
||||||
await executeProtected(() => _dataConnect
|
await _service.connector
|
||||||
.listShiftRolesByBusinessAndDateRange(
|
.listShiftRolesByBusinessAndDateRange(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
start: startTimestamp,
|
start: startTimestamp,
|
||||||
end: endTimestamp,
|
end: endTimestamp,
|
||||||
)
|
)
|
||||||
.execute());
|
.execute();
|
||||||
print(
|
print(
|
||||||
'ViewOrders range start=${start.toIso8601String()} end=${end.toIso8601String()} shiftRoles=${result.data.shiftRoles.length}',
|
'ViewOrders range start=${start.toIso8601String()} end=${end.toIso8601String()} shiftRoles=${result.data.shiftRoles.length}',
|
||||||
);
|
);
|
||||||
|
|
||||||
final String businessName =
|
final String businessName =
|
||||||
dc.ClientSessionStore.instance.session?.business?.businessName ??
|
dc.ClientSessionStore.instance.session?.business?.businessName ?? 'Your Company';
|
||||||
'Your Company';
|
|
||||||
|
|
||||||
return result.data.shiftRoles.map((dc.ListShiftRolesByBusinessAndDateRangeShiftRoles shiftRole) {
|
return result.data.shiftRoles.map((dc.ListShiftRolesByBusinessAndDateRangeShiftRoles shiftRole) {
|
||||||
final DateTime? shiftDate = shiftRole.shift.date?.toDateTime().toLocal();
|
final DateTime? shiftDate = shiftRole.shift.date?.toDateTime().toLocal();
|
||||||
final String dateStr = shiftDate == null
|
final String dateStr = shiftDate == null ? '' : DateFormat('yyyy-MM-dd').format(shiftDate);
|
||||||
? ''
|
|
||||||
: DateFormat('yyyy-MM-dd').format(shiftDate);
|
|
||||||
final String startTime = _formatTime(shiftRole.startTime);
|
final String startTime = _formatTime(shiftRole.startTime);
|
||||||
final String endTime = _formatTime(shiftRole.endTime);
|
final String endTime = _formatTime(shiftRole.endTime);
|
||||||
final int filled = shiftRole.assigned ?? 0;
|
final int filled = shiftRole.assigned ?? 0;
|
||||||
@@ -69,8 +57,7 @@ class ViewOrdersRepositoryImpl
|
|||||||
'end=${shiftRole.endTime?.toJson()} hours=$hours totalValue=$totalValue',
|
'end=${shiftRole.endTime?.toJson()} hours=$hours totalValue=$totalValue',
|
||||||
);
|
);
|
||||||
|
|
||||||
final String eventName =
|
final String eventName = shiftRole.shift.order.eventName ?? shiftRole.shift.title;
|
||||||
shiftRole.shift.order.eventName ?? shiftRole.shift.title;
|
|
||||||
|
|
||||||
return domain.OrderItem(
|
return domain.OrderItem(
|
||||||
id: _shiftRoleKey(shiftRole.shiftId, shiftRole.roleId),
|
id: _shiftRoleKey(shiftRole.shiftId, shiftRole.roleId),
|
||||||
@@ -91,36 +78,35 @@ class ViewOrdersRepositoryImpl
|
|||||||
confirmedApps: const <Map<String, dynamic>>[],
|
confirmedApps: const <Map<String, dynamic>>[],
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, List<Map<String, dynamic>>>> getAcceptedApplicationsForDay(
|
Future<Map<String, List<Map<String, dynamic>>>> getAcceptedApplicationsForDay(
|
||||||
DateTime day,
|
DateTime day,
|
||||||
) async {
|
) async {
|
||||||
final String? businessId = dc.ClientSessionStore.instance.session?.business?.id;
|
return _service.run(() async {
|
||||||
if (businessId == null || businessId.isEmpty) {
|
final String businessId = await _service.getBusinessId();
|
||||||
await _firebaseAuth.signOut();
|
|
||||||
throw Exception('Business is missing. Please sign in again.');
|
|
||||||
}
|
|
||||||
|
|
||||||
final fdc.Timestamp dayStart = _toTimestamp(_startOfDay(day));
|
final fdc.Timestamp dayStart = _service.toTimestamp(_startOfDay(day));
|
||||||
final fdc.Timestamp dayEnd = _toTimestamp(_endOfDay(day));
|
final fdc.Timestamp dayEnd = _service.toTimestamp(_endOfDay(day));
|
||||||
final fdc.QueryResult<dc.ListAcceptedApplicationsByBusinessForDayData,
|
final fdc.QueryResult<dc.ListAcceptedApplicationsByBusinessForDayData,
|
||||||
dc.ListAcceptedApplicationsByBusinessForDayVariables> result =
|
dc.ListAcceptedApplicationsByBusinessForDayVariables> result =
|
||||||
await executeProtected(() => _dataConnect
|
await _service.connector
|
||||||
.listAcceptedApplicationsByBusinessForDay(
|
.listAcceptedApplicationsByBusinessForDay(
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
dayStart: dayStart,
|
dayStart: dayStart,
|
||||||
dayEnd: dayEnd,
|
dayEnd: dayEnd,
|
||||||
)
|
)
|
||||||
.execute());
|
.execute();
|
||||||
|
|
||||||
print(
|
print(
|
||||||
'ViewOrders day=${day.toIso8601String()} applications=${result.data.applications.length}',
|
'ViewOrders day=${day.toIso8601String()} applications=${result.data.applications.length}',
|
||||||
);
|
);
|
||||||
|
|
||||||
final Map<String, List<Map<String, dynamic>>> grouped = <String, List<Map<String, dynamic>>>{};
|
final Map<String, List<Map<String, dynamic>>> grouped = <String, List<Map<String, dynamic>>>{};
|
||||||
for (final dc.ListAcceptedApplicationsByBusinessForDayApplications application in result.data.applications) {
|
for (final dc.ListAcceptedApplicationsByBusinessForDayApplications application
|
||||||
|
in result.data.applications) {
|
||||||
print(
|
print(
|
||||||
'ViewOrders app: shiftId=${application.shiftId} roleId=${application.roleId} '
|
'ViewOrders app: shiftId=${application.shiftId} roleId=${application.roleId} '
|
||||||
'checkIn=${application.checkInTime?.toJson()} checkOut=${application.checkOutTime?.toJson()}',
|
'checkIn=${application.checkInTime?.toJson()} checkOut=${application.checkOutTime?.toJson()}',
|
||||||
@@ -138,19 +124,13 @@ class ViewOrdersRepositoryImpl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return grouped;
|
return grouped;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
String _shiftRoleKey(String shiftId, String roleId) {
|
String _shiftRoleKey(String shiftId, String roleId) {
|
||||||
return '$shiftId:$roleId';
|
return '$shiftId:$roleId';
|
||||||
}
|
}
|
||||||
|
|
||||||
fdc.Timestamp _toTimestamp(DateTime dateTime) {
|
|
||||||
final DateTime utc = dateTime.toUtc();
|
|
||||||
final int seconds = utc.millisecondsSinceEpoch ~/ 1000;
|
|
||||||
final int nanoseconds = (utc.microsecondsSinceEpoch % 1000000) * 1000;
|
|
||||||
return fdc.Timestamp(nanoseconds, seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime _startOfDay(DateTime dateTime) {
|
DateTime _startOfDay(DateTime dateTime) {
|
||||||
return DateTime(dateTime.year, dateTime.month, dateTime.day);
|
return DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,23 +80,6 @@ class _ViewOrderCardState extends State<ViewOrderCard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats the date string for display.
|
|
||||||
String _formatDate({required String dateStr}) {
|
|
||||||
try {
|
|
||||||
final DateTime date = DateTime.parse(dateStr);
|
|
||||||
final DateTime now = DateTime.now();
|
|
||||||
final DateTime today = DateTime(now.year, now.month, now.day);
|
|
||||||
final DateTime tomorrow = today.add(const Duration(days: 1));
|
|
||||||
final DateTime checkDate = DateTime(date.year, date.month, date.day);
|
|
||||||
|
|
||||||
if (checkDate == today) return t.client_view_orders.card.today;
|
|
||||||
if (checkDate == tomorrow) return t.client_view_orders.card.tomorrow;
|
|
||||||
return DateFormat('EEE, MMM d').format(date);
|
|
||||||
} catch (_) {
|
|
||||||
return dateStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Formats the time string for display.
|
/// Formats the time string for display.
|
||||||
String _formatTime({required String timeStr}) {
|
String _formatTime({required String timeStr}) {
|
||||||
if (timeStr.isEmpty) return '';
|
if (timeStr.isEmpty) return '';
|
||||||
@@ -829,10 +812,7 @@ class _OrderEditSheetState extends State<_OrderEditSheet> {
|
|||||||
final String dateText = orderDate == null
|
final String dateText = orderDate == null
|
||||||
? widget.order.date
|
? widget.order.date
|
||||||
: DateFormat('yyyy-MM-dd').format(orderDate);
|
: DateFormat('yyyy-MM-dd').format(orderDate);
|
||||||
final String location = firstShift.order.teamHub?.hubName ??
|
final String location = firstShift.order.teamHub.hubName;
|
||||||
firstShift.locationAddress ??
|
|
||||||
firstShift.location ??
|
|
||||||
widget.order.locationAddress;
|
|
||||||
|
|
||||||
_dateController.text = dateText;
|
_dateController.text = dateText;
|
||||||
_globalLocationController.text = location;
|
_globalLocationController.text = location;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
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 'package:firebase_auth/firebase_auth.dart' as firebase;
|
|
||||||
|
|
||||||
import 'data/repositories/view_orders_repository_impl.dart';
|
import 'data/repositories/view_orders_repository_impl.dart';
|
||||||
import 'domain/repositories/i_view_orders_repository.dart';
|
import 'domain/repositories/i_view_orders_repository.dart';
|
||||||
@@ -21,24 +20,14 @@ class ViewOrdersModule extends Module {
|
|||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
// Repositories
|
// Repositories
|
||||||
i.add<IViewOrdersRepository>(
|
i.add<IViewOrdersRepository>(ViewOrdersRepositoryImpl.new);
|
||||||
() => ViewOrdersRepositoryImpl(
|
|
||||||
firebaseAuth: firebase.FirebaseAuth.instance,
|
|
||||||
dataConnect: ExampleConnector.instance,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// UseCases
|
// UseCases
|
||||||
i.add(GetOrdersUseCase.new);
|
i.add(GetOrdersUseCase.new);
|
||||||
i.add(GetAcceptedApplicationsForDayUseCase.new);
|
i.add(GetAcceptedApplicationsForDayUseCase.new);
|
||||||
|
|
||||||
// BLoCs
|
// BLoCs
|
||||||
i.add(
|
i.add(ViewOrdersCubit.new);
|
||||||
() => ViewOrdersCubit(
|
|
||||||
getOrdersUseCase: i.get<GetOrdersUseCase>(),
|
|
||||||
getAcceptedAppsUseCase: i.get<GetAcceptedApplicationsForDayUseCase>(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
Reference in New Issue
Block a user