feat: legacy mobile apps created
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
const String getStaffScheduleSchema = '''
|
||||
query GetStaffSchedule {
|
||||
me {
|
||||
id
|
||||
schedule {
|
||||
id
|
||||
type
|
||||
start_at
|
||||
end_at
|
||||
day_of_week
|
||||
}
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const String createStaffScheduleMutationSchema = r'''
|
||||
mutation CreateStaffSchedule($input: [StaffScheduleInput!]!) {
|
||||
create_staff_schedule(input: $input) {
|
||||
id
|
||||
type
|
||||
start_at
|
||||
end_at
|
||||
day_of_week
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const String updateStaffScheduleMutationSchema = r'''
|
||||
mutation UpdateStaffSchedule($id: ID!, $input: StaffScheduleInput!) {
|
||||
update_staff_schedule(id: $id, input: $input) {
|
||||
id
|
||||
type
|
||||
start_at
|
||||
end_at
|
||||
day_of_week
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const String deleteStaffScheduleMutationSchema = r'''
|
||||
mutation DeleteStaffSchedule($ids: [ID!]!) {
|
||||
delete_staff_schedule(ids: $ids) {
|
||||
id
|
||||
type
|
||||
start_at
|
||||
end_at
|
||||
day_of_week
|
||||
}
|
||||
}
|
||||
''';
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:krow/features/profile/schedule/data/models/schedule_slot_model.dart';
|
||||
|
||||
class DayScheduleModel {
|
||||
DayScheduleModel({
|
||||
required this.date,
|
||||
required this.slots,
|
||||
this.isWeekly = false,
|
||||
});
|
||||
|
||||
final DateTime date;
|
||||
final bool isWeekly;
|
||||
List<ScheduleSlotModel> slots;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:krow/core/application/common/date_time_extension.dart';
|
||||
|
||||
class ScheduleSlotModel {
|
||||
ScheduleSlotModel({
|
||||
required this.isWeekly,
|
||||
required this.startAt,
|
||||
required this.endAt,
|
||||
this.id,
|
||||
});
|
||||
|
||||
factory ScheduleSlotModel.fromJson(Map<String, dynamic> data) {
|
||||
return ScheduleSlotModel(
|
||||
id: data['id'] as String?,
|
||||
isWeekly: data['type'] == 'weekly',
|
||||
startAt: DateTime.parse(data['start_at'] as String),
|
||||
endAt: DateTime.parse(data['end_at'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
final String? id;
|
||||
final bool isWeekly;
|
||||
final DateTime startAt;
|
||||
final DateTime endAt;
|
||||
|
||||
// TODO(Sleep): For now has to use .replaceAll('.000', '') for trim DateTime otherwise will result in error from backend.
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
// if (id != null) 'id': id,
|
||||
'type': isWeekly ? 'weekly' : 'range',
|
||||
'start_at': startAt.toString().replaceAll('.000', ''),
|
||||
'end_at': endAt.toString().replaceAll('.000', ''),
|
||||
'day_of_week': startAt.getWeekdayId(),
|
||||
};
|
||||
}
|
||||
|
||||
String getIdKey() =>
|
||||
isWeekly ? startAt.getWeekdayId() : startAt.getDayDateId();
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
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/features/profile/schedule/data/gql_schemas.dart';
|
||||
import 'package:krow/features/profile/schedule/data/models/day_schedule_model.dart';
|
||||
import 'package:krow/features/profile/schedule/data/models/schedule_slot_model.dart';
|
||||
|
||||
@injectable
|
||||
class StaffScheduleApiProvider {
|
||||
final ApiClient _apiClient;
|
||||
|
||||
StaffScheduleApiProvider(this._apiClient);
|
||||
|
||||
Map<String, DayScheduleModel> _processScheduleDataList(
|
||||
List<dynamic> scheduleData,
|
||||
) {
|
||||
final schedules = [
|
||||
for (final scheduleItem in scheduleData)
|
||||
ScheduleSlotModel.fromJson(
|
||||
scheduleItem as Map<String, dynamic>,
|
||||
),
|
||||
];
|
||||
|
||||
Map<String, DayScheduleModel> scheduleMap = {};
|
||||
|
||||
for (int i = 0; i < schedules.length; i++) {
|
||||
final scheduleKey = schedules[i].getIdKey();
|
||||
var scheduleDay = scheduleMap[scheduleKey];
|
||||
|
||||
if (scheduleDay == null) {
|
||||
scheduleDay = DayScheduleModel(
|
||||
date: schedules[i].startAt.copyWith(
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
),
|
||||
slots: [schedules[i]],
|
||||
isWeekly: schedules[i].isWeekly,
|
||||
);
|
||||
scheduleMap[scheduleKey] = scheduleDay;
|
||||
} else {
|
||||
scheduleDay.slots.add(schedules[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return scheduleMap;
|
||||
}
|
||||
|
||||
Future<Map<String, DayScheduleModel>> _handleResultReturn(
|
||||
QueryResult<Object?> result,
|
||||
String mutationKey,
|
||||
) async {
|
||||
if (result.hasException) throw Exception(result.exception.toString());
|
||||
|
||||
if (result.data == null || result.data!.isEmpty) return {};
|
||||
|
||||
final scheduleData = result.data?[mutationKey] as List<dynamic>? ?? [];
|
||||
|
||||
return _processScheduleDataList(scheduleData);
|
||||
}
|
||||
|
||||
Future<Map<String, DayScheduleModel>> getStaffSchedule() async {
|
||||
final response = await _apiClient.query(schema: getStaffScheduleSchema);
|
||||
|
||||
if (response.hasException) {
|
||||
throw Exception(response.exception.toString());
|
||||
}
|
||||
|
||||
final scheduleData = (response.data?['me']
|
||||
as Map<String, dynamic>?)?['schedule'] as List<dynamic>? ??
|
||||
[];
|
||||
|
||||
return _processScheduleDataList(scheduleData);
|
||||
}
|
||||
|
||||
Stream<Map<String, DayScheduleModel>> getStaffScheduleWithCache() async* {
|
||||
await for (var response in _apiClient.queryWithCache(
|
||||
schema: getStaffScheduleSchema,
|
||||
)) {
|
||||
if (response == null || response.data == null) continue;
|
||||
|
||||
if (response.data == null || response.data!.isEmpty) {
|
||||
if (response.source?.name == 'cache') continue;
|
||||
|
||||
if (response.hasException) {
|
||||
throw Exception(response.exception.toString());
|
||||
}
|
||||
}
|
||||
|
||||
final scheduleData = (response.data?['me']
|
||||
as Map<String, dynamic>?)?['schedule'] as List<dynamic>? ??
|
||||
[];
|
||||
|
||||
yield _processScheduleDataList(scheduleData);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, DayScheduleModel>> createStaffSchedule(
|
||||
List<ScheduleSlotModel> schedules,
|
||||
) async {
|
||||
final result = await _apiClient.mutate(
|
||||
schema: createStaffScheduleMutationSchema,
|
||||
body: {
|
||||
'input': [
|
||||
for (final schedule in schedules) schedule.toJson(),
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
return _handleResultReturn(result, 'create_staff_schedule');
|
||||
}
|
||||
|
||||
Future<Map<String, DayScheduleModel>> updateStaffSchedule(
|
||||
List<ScheduleSlotModel> schedules,
|
||||
) async {
|
||||
// var result = await _apiClient.mutate(
|
||||
// schema: updateStaffScheduleMutationSchema,
|
||||
// body: {
|
||||
// 'input': [
|
||||
// for (final schedule in schedules) schedule.toJson(),
|
||||
// ],
|
||||
// },
|
||||
// );
|
||||
|
||||
await Future.wait(
|
||||
[
|
||||
for (final schedule in schedules)
|
||||
_apiClient.mutate(
|
||||
schema: updateStaffScheduleMutationSchema,
|
||||
body: {
|
||||
'id': schedule.id,
|
||||
'input': schedule.toJson(),
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final result = await _apiClient.mutate(
|
||||
schema: updateStaffScheduleMutationSchema,
|
||||
body: {
|
||||
'id': schedules.last.id,
|
||||
'input': schedules.last.toJson(),
|
||||
},
|
||||
);
|
||||
|
||||
return _handleResultReturn(result, 'update_staff_schedule');
|
||||
}
|
||||
|
||||
Future<ScheduleSlotModel?> deleteStaffSchedule(
|
||||
List<ScheduleSlotModel> schedules,
|
||||
) async {
|
||||
final result = await _apiClient.mutate(
|
||||
schema: deleteStaffScheduleMutationSchema,
|
||||
body: {
|
||||
'ids': [
|
||||
for (final schedule in schedules) schedule.id,
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
if (result.hasException) throw Exception(result.exception.toString());
|
||||
|
||||
if (result.data == null || result.data!.isEmpty) return null;
|
||||
|
||||
//TODO: For now backend returns only one value so there is no
|
||||
// point in returning it
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<ScheduleSlotModel?> deleteStaffScheduleById(List<String> ids) async {
|
||||
final result = await _apiClient.mutate(
|
||||
schema: deleteStaffScheduleMutationSchema,
|
||||
body: {'ids': ids},
|
||||
);
|
||||
|
||||
if (result.hasException) throw Exception(result.exception.toString());
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:krow/features/profile/schedule/data/models/day_schedule_model.dart';
|
||||
import 'package:krow/features/profile/schedule/data/models/schedule_slot_model.dart';
|
||||
import 'package:krow/features/profile/schedule/data/staff_schedule_api_provider.dart';
|
||||
import 'package:krow/features/profile/schedule/domain/entities/day_shedule.dart';
|
||||
import 'package:krow/features/profile/schedule/domain/entities/schedule_slot.dart';
|
||||
import 'package:krow/features/profile/schedule/domain/staff_schedule_repository.dart';
|
||||
|
||||
@Injectable(as: StaffScheduleRepository)
|
||||
class StaffScheduleRepositoryImpl extends StaffScheduleRepository {
|
||||
StaffScheduleRepositoryImpl({
|
||||
required StaffScheduleApiProvider apiProvider,
|
||||
}) : _apiProvider = apiProvider;
|
||||
|
||||
final StaffScheduleApiProvider _apiProvider;
|
||||
|
||||
Map<String, DaySchedule> _processSchedulesMap(
|
||||
Map<String, DayScheduleModel> daySchedulesData,
|
||||
) {
|
||||
return daySchedulesData.map(
|
||||
(key, dayEntry) {
|
||||
return MapEntry(
|
||||
key,
|
||||
DaySchedule(
|
||||
date: dayEntry.date,
|
||||
isWeekly: dayEntry.isWeekly,
|
||||
slots: [
|
||||
for (final slot in dayEntry.slots)
|
||||
ScheduleSlot(
|
||||
id: slot.startAt.microsecondsSinceEpoch.toString(),
|
||||
startTime: slot.startAt,
|
||||
endTime: slot.endAt,
|
||||
remoteId: slot.id,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<ScheduleSlotModel> _expandDailySchedulesToSlots(
|
||||
List<DaySchedule> schedules,
|
||||
) {
|
||||
return [
|
||||
for (final daySchedule in schedules) ...[
|
||||
for (final slot in daySchedule.slots)
|
||||
ScheduleSlotModel(
|
||||
isWeekly: daySchedule.isWeekly,
|
||||
startAt: slot.startTime,
|
||||
endAt: slot.endTime,
|
||||
id: slot.remoteId,
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<Map<String, DaySchedule>> getStaffSchedule() async* {
|
||||
await for (final daySchedulesData
|
||||
in _apiProvider.getStaffScheduleWithCache()) {
|
||||
yield _processSchedulesMap(daySchedulesData);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, DaySchedule>> createStaffSchedule({
|
||||
required List<DaySchedule> schedules,
|
||||
}) async {
|
||||
return _processSchedulesMap(
|
||||
await _apiProvider.createStaffSchedule(
|
||||
_expandDailySchedulesToSlots(schedules),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, DaySchedule>> updateStaffSchedule({
|
||||
required List<DaySchedule> schedules,
|
||||
}) async {
|
||||
if (schedules.length == 1) {
|
||||
if (schedules.first.deletedSlots != null) {
|
||||
await _apiProvider.deleteStaffScheduleById(
|
||||
[
|
||||
for (final deletedSlot in schedules.first.deletedSlots!)
|
||||
deletedSlot.remoteId ?? '',
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// In case there were only deletion of slots for the day, and no edits
|
||||
if (schedules.first.slots.isEmpty) {
|
||||
return _processSchedulesMap(
|
||||
await _apiProvider.getStaffSchedule(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return _processSchedulesMap(
|
||||
await _apiProvider.updateStaffSchedule(
|
||||
_expandDailySchedulesToSlots(schedules),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DaySchedule?> deleteStaffSchedule({
|
||||
required List<DaySchedule> schedules,
|
||||
}) async {
|
||||
await _apiProvider.deleteStaffSchedule(
|
||||
_expandDailySchedulesToSlots(schedules),
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user