feat: Refactor code structure and optimize performance across multiple modules

This commit is contained in:
Achintha Isuru
2025-11-17 23:29:28 -05:00
parent 831570f2e0
commit a64cbd9edf
1508 changed files with 105319 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:injectable/injectable.dart';
import 'package:krow/core/application/clients/api/api_client.dart';
import 'package:krow/core/application/clients/api/api_exception.dart';
import 'package:krow/core/data/models/event/event_model.dart';
import 'package:krow/core/data/models/pagination_wrapper/pagination_wrapper.dart';
import 'package:krow/features/events/data/events_gql.dart';
@Injectable()
class EventsApiProvider {
final ApiClient _client;
EventsApiProvider({required ApiClient client}) : _client = client;
Future<PaginationWrapper?> fetchEvents(String status, {String? after}) async {
final QueryResult result = await _client.query(
schema: getEventsQuery,
body: {'status': status, 'first': 30, 'after': after});
if (result.hasException) {
throw parseBackendError(result.exception);
}
if (result.data == null || result.data!['client_events'] == null) {
return null;
}
return PaginationWrapper<EventModel?>.fromJson(
result.data!['client_events'], (json) {
try {
return EventModel.fromJson(json);
}catch (e) {
print(e);
return null;
}
});
}
Future<EventModel?> fetchEventById(String id) async {
final QueryResult result = await _client.query(schema: getEventById, body: {
'id': id,
});
if (result.hasException) {
throw parseBackendError(result.exception);
}
if (result.data == null || result.data!['client_event'] == null) {
return null;
}
return EventModel.fromJson(result.data!['client_event']);
}
Future<void> cancelClientEvent(String id) async {
final QueryResult result = await _client.mutate(
schema: cancelClientEventMutation,
body: {'event_id': id},
);
if (result.hasException) {
throw parseBackendError(result.exception);
}
}
Future<void> completeClientEvent(String id, {String? comment}) async {
final QueryResult result = await _client.mutate(
schema: completeClientEventMutation,
body: {'event_id': id, if(comment!=null)'comment': comment.trim()},
);
if (result.hasException) {
print(result.exception.toString());
throw parseBackendError(result.exception);
}
}
Future<void> trackClientClockin(String positionStaffId) async {
final QueryResult result = await _client.mutate(
schema: trackClientClockinMutation,
body: {'position_staff_id': positionStaffId},
);
if (result.hasException) {
throw parseBackendError(result.exception);
}
}
Future<void> trackClientClockout(String positionStaffId) async {
final QueryResult result = await _client.mutate(
schema: trackClientClockoutMutation,
body: {'position_staff_id': positionStaffId},
);
if (result.hasException) {
throw parseBackendError(result.exception);
}
}
Future<void> notShowedPositionStaff(String positionStaffId) async {
final QueryResult result = await _client.mutate(
schema: notShowedPositionStaffMutation,
body: {'position_staff_id': positionStaffId},
);
if (result.hasException) {
throw parseBackendError(result.exception);
}
}
Future<void> replacePositionStaff(
String positionStaffId, String reason) async {
final QueryResult result = await _client.mutate(
schema: replacePositionStaffMutation,
body: {'position_staff_id': positionStaffId, 'reason': reason.trim()},
);
if (result.hasException) {
throw parseBackendError(result.exception);
}
}
}

View File

@@ -0,0 +1,272 @@
String getEventsQuery = '''
query GetEvents (\$status: EventStatus!, \$first: Int!, \$after: String) {
client_events(status: \$status, first: \$first, after: \$after) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
total
count
currentPage
lastPage
}
edges {
...node
cursor
}
}
}
$nodeFragment
''';
var getEventById = '''
query GetEventById(\$id: ID!) {
client_event(id: \$id) {
$_eventFields
}
}
$fragments
''';
var nodeFragment = '''
fragment node on EventEdge {
node {
$_eventsListFields
}
}
''';
const String cancelClientEventMutation = r'''
mutation cancel_client_event($event_id: ID!) {
cancel_client_event(event_id: $event_id) {
id
}
}
''';
const String completeClientEventMutation = r'''
mutation complete_client_event($event_id: ID!, $comment: String) {
complete_client_event(event_id: $event_id, comment: $comment) {
id
}
}
''';
const String trackClientClockinMutation = r'''
mutation track_client_clockin($position_staff_id: ID!) {
track_client_clockin(position_staff_id: $position_staff_id) {
id
}
}
''';
const String trackClientClockoutMutation = r'''
mutation track_client_clockout($position_staff_id: ID!) {
track_client_clockout(position_staff_id: $position_staff_id) {
id
}
}
''';
const String notShowedPositionStaffMutation = r'''
mutation not_showed_position_staff($position_staff_id: ID!) {
not_showed_position_staff(position_staff_id: $position_staff_id) {
id
}
}
''';
const String replacePositionStaffMutation = r'''
mutation replace_position_staff($position_staff_id: ID!, $reason: String!) {
replace_position_staff(position_staff_id: $position_staff_id, reason: $reason) {
id
}
}
''';
String _eventsListFields = '''
id
business {
id
name
registration
avatar
}
hub {
id
name
address
}
name
status
date
start_time
end_time
purchase_order
contract_type
schedule_type
''';
String _eventFields = '''
id
business {
id
name
registration
avatar
...addons
}
hub {
id
name
address
}
name
status
date
start_time
end_time
purchase_order
contract_type
schedule_type
additional_info
addons {
id
name
}
tags {
id
name
slug
}
...shifts
''';
String fragments = '''fragment addons on Business {
addons {
id
name
}
}
fragment shifts on Event {
shifts {
id
name
address
...full_address
contacts {
id
first_name
last_name
title
...auth_info
}
positions {
id
count
start_time
end_time
rate
break
...business_skill
...staff
department {
id
name
}
}
}
}
fragment auth_info on BusinessMember {
auth_info {
email
phone
}
}
fragment business_skill on EventShiftPosition {
business_skill {
id
skill {
id
name
slug
price
}
price
is_active
}
}
fragment full_address on EventShift {
full_address {
street_number
zip_code
latitude
longitude
formatted_address
street
region
city
country
}
}
fragment staff on EventShiftPosition {
staff {
id
first_name
last_name
middle_name
email
phone
avatar
pivot {
id
status
start_at
end_at
clock_in
clock_out
...staff_position
...cancel_reason
rating {
id
rating
}
}
}
}
fragment cancel_reason on EventShiftPositionStaff {
cancel_reason {
type
reason
details
}
}
fragment staff_position on EventShiftPositionStaff {
position {
id
count
start_time
end_time
rate
break
business_skill {
id
price
skill{
name
}
}
}
}''';

View File

@@ -0,0 +1,137 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:injectable/injectable.dart';
import 'package:krow/core/entity/event_entity.dart';
import 'package:krow/features/events/data/events_api_provider.dart';
import 'package:krow/features/events/domain/events_repository.dart';
@Singleton(as: EventsRepository)
class EventsRepositoryImpl extends EventsRepository {
final EventsApiProvider _apiProvider;
StreamController<EventStatus>? _statusController;
EventsRepositoryImpl({required EventsApiProvider apiProvider})
: _apiProvider = apiProvider;
@override
Stream<EventStatus> get statusStream {
_statusController ??= StreamController<EventStatus>.broadcast();
return _statusController!.stream;
}
@override
Future<List<EventEntity>> getEvents(
{String? lastItemId, required EventStatus statusFilter}) async {
try {
var paginationWrapper = await _apiProvider.fetchEvents(
statusFilterToGqlString(statusFilter),
after: lastItemId);
return paginationWrapper?.edges
.map((e) => EventEntity.fromEventDto(
e.node,
cursor: paginationWrapper.pageInfo.hasNextPage
? e.cursor
: null,
))
.toList() ??
[];
} catch (e) {
rethrow;
}
}
@override
void dispose() {
_statusController?.close();
}
statusFilterToGqlString(EventStatus statusFilter) {
return statusFilter.name;
}
@override
Future<void> cancelClientEvent(String id, EventStatus? status) async {
try {
await _apiProvider.cancelClientEvent(id);
if (!(_statusController?.isClosed ?? true)) {
if (status != null) _statusController?.add(status);
}
} catch (exception) {
debugPrint(exception.toString());
rethrow;
}
}
@override
Future<void> completeClientEvent(String id, {String? comment}) async {
try {
await _apiProvider.completeClientEvent(id, comment: comment);
if (!(_statusController?.isClosed ?? true)) {
_statusController?.add(EventStatus.finished);
_statusController?.add(EventStatus.completed);
}
} catch (exception) {
debugPrint(exception.toString());
rethrow;
}
}
@override
Future<void> trackClientClockin(String positionStaffId) async {
try {
await _apiProvider.trackClientClockin(positionStaffId);
} catch (exception) {
debugPrint(exception.toString());
rethrow;
}
}
@override
Future<void> trackClientClockout(String positionStaffId) async {
try {
await _apiProvider.trackClientClockout(positionStaffId);
} catch (exception) {
debugPrint(exception.toString());
rethrow;
}
}
@override
Future<void> notShowedPositionStaff(String positionStaffId) async {
try {
await _apiProvider.notShowedPositionStaff(positionStaffId);
} catch (exception) {
debugPrint(exception.toString());
rethrow;
}
}
@override
Future<void> replacePositionStaff(
String positionStaffId, String reason) async {
try {
await _apiProvider.replacePositionStaff(positionStaffId, reason);
} catch (exception) {
debugPrint(exception.toString());
rethrow;
}
}
@override
void refreshEvents(EventStatus status) {
if (!(_statusController?.isClosed ?? true)) {
_statusController?.add(status);
}
}
@override
Future<EventEntity?> getEventById(String id) async {
return await _apiProvider.fetchEventById(id).then((event) {
if (event != null) {
return EventEntity.fromEventDto(event);
}
return null;
});
}
}