feat: legacy mobile apps created
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
class MutateKitDto {
|
||||
String id;
|
||||
String? photo;
|
||||
|
||||
MutateKitDto({
|
||||
required this.id,
|
||||
this.photo,
|
||||
});
|
||||
|
||||
Map<String, String> toJson() => {
|
||||
'id': id,
|
||||
if (photo != null) 'photo': photo!,
|
||||
};
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return toJson().toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
const String confirmStaffUniformsMutation = '''
|
||||
mutation ConfirmStaffUniforms(\$skillId: String!, \$uniforms: [ConfirmStaffUniformInput!]!) {
|
||||
confirm_staff_uniforms(skill_id: \$skillId, uniforms: \$uniforms)
|
||||
}
|
||||
''';
|
||||
|
||||
const String confirmStaffEquipmentsMutation = '''
|
||||
mutation ConfirmStaffEquipments(\$skillId: String!, \$equipments: [ConfirmStaffEquipmentInput!]!) {
|
||||
confirm_staff_equipments(skill_id: \$skillId, equipments: \$equipments)
|
||||
}
|
||||
''';
|
||||
|
||||
const String uploadImageMutation = '''
|
||||
mutation UploadImage(\$file: Upload!) {
|
||||
upload_file(file: \$file) {
|
||||
token
|
||||
url
|
||||
}
|
||||
}
|
||||
''';
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:http_parser/http_parser.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/application/clients/api/gql.dart';
|
||||
import 'package:krow/core/data/models/staff_role.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/models/mutate_kit_dto.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/staf_kit_gql.dart';
|
||||
|
||||
@injectable
|
||||
class StaffRoleKitApiProvider {
|
||||
final ApiClient _apiClient;
|
||||
|
||||
StaffRoleKitApiProvider(this._apiClient);
|
||||
|
||||
Future<List<StaffRole>> fetchStaffRoles() async {
|
||||
var result = await _apiClient.query(schema: getStaffRolesQuery);
|
||||
|
||||
if (result.hasException) {
|
||||
throw parseBackendError(result.exception);
|
||||
}
|
||||
|
||||
return result.data!['staff_roles'].map<StaffRole>((e) {
|
||||
return StaffRole.fromJson(e);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Future<void> putUniform(String skillId, List<MutateKitDto> kits) async {
|
||||
final Map<String, dynamic> variables = {
|
||||
'skillId': skillId,
|
||||
'uniforms': kits,
|
||||
};
|
||||
var result = await _apiClient.mutate(
|
||||
schema: confirmStaffUniformsMutation, body: variables);
|
||||
|
||||
if (result.hasException) {
|
||||
throw parseBackendError(result.exception);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> putEquipment(String skillId, List<MutateKitDto> kits) async {
|
||||
final Map<String, dynamic> variables = {
|
||||
'skillId': skillId,
|
||||
'equipments': kits,
|
||||
};
|
||||
var result = await _apiClient.mutate(
|
||||
schema: confirmStaffEquipmentsMutation, body: variables);
|
||||
if (result.hasException) {
|
||||
throw parseBackendError(result.exception);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> uploadImage(String imagePath) async {
|
||||
final ApiClient apiClient = ApiClient();
|
||||
|
||||
var byteData = File(imagePath).readAsBytesSync();
|
||||
|
||||
var multipartFile = MultipartFile.fromBytes(
|
||||
'photo',
|
||||
byteData,
|
||||
filename: '${DateTime.now().millisecondsSinceEpoch}.jpg',
|
||||
contentType: MediaType('image', 'jpg'),
|
||||
);
|
||||
|
||||
final Map<String, dynamic> variables = {
|
||||
'file': multipartFile,
|
||||
};
|
||||
|
||||
final result = await apiClient.mutate(
|
||||
schema: uploadImageMutation,
|
||||
body: variables,
|
||||
);
|
||||
|
||||
if (result.hasException) {
|
||||
debugPrint(result.exception.toString());
|
||||
} else {
|
||||
return result.data!['upload_file'];
|
||||
}
|
||||
return <String, dynamic>{};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:krow/core/data/models/staff_role.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
|
||||
import 'models/mutate_kit_dto.dart';
|
||||
|
||||
abstract class StaffRoleKitRepository {
|
||||
Future<List<StaffRole>> getStaffRole();
|
||||
|
||||
Future<void> putKit(
|
||||
String skillId, List<MutateKitDto> kits, RoleKitType type);
|
||||
|
||||
Future<Map<String, dynamic>> uploadImage(String imagePath);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:krow/core/application/clients/api/api_exception.dart';
|
||||
import 'package:krow/core/application/di/injectable.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/models/mutate_kit_dto.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/staff_role_kit_repository.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_event.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_state.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/role_kit_entity.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
|
||||
class RoleKitBloc extends Bloc<RoleKitEvent, RoleKitState> {
|
||||
RoleKitBloc() : super(RoleKitState()) {
|
||||
on<RoleKitEventFetch>(_onFetch);
|
||||
on<RoleKitEventSelectRole>(_onSelectRole);
|
||||
on<RoleKitEventSubmit>(_onSubmit);
|
||||
on<RoleKiEventChangeState>(_onChangeState);
|
||||
on<RoleKitEventUploadPhoto>(_onUploadPhoto);
|
||||
on<RoleKitEventDeletePhoto>(_onDeletePhoto);
|
||||
}
|
||||
|
||||
Future<void> _onFetch(
|
||||
RoleKitEventFetch event, Emitter<RoleKitState> emit) async {
|
||||
emit(state.copyWith(roleKitType: event.type, loading: true));
|
||||
var roles = await getIt<StaffRoleKitRepository>().getStaffRole();
|
||||
emit(state.copyWith(roles: roles, loading: false));
|
||||
}
|
||||
|
||||
Future<void> _onSelectRole(
|
||||
RoleKitEventSelectRole event, Emitter<RoleKitState> emit) async {
|
||||
List<RoleKitEntity> roleKitViewModels = [];
|
||||
|
||||
var confirmedKits = state.roleKitType == RoleKitType.equipment
|
||||
? event.role.confirmedEquipments
|
||||
: event.role.confirmedUniforms;
|
||||
|
||||
|
||||
|
||||
|
||||
(state.roleKitType == RoleKitType.equipment
|
||||
? event.role.skill?.equipments
|
||||
: event.role.skill?.uniforms)
|
||||
?.forEach((item) {
|
||||
var confirmed = confirmedKits
|
||||
?.where((element) => element.skillKitId == item.id)
|
||||
.firstOrNull;
|
||||
roleKitViewModels.add(RoleKitEntity(
|
||||
id: item.id,
|
||||
title: item.name ?? '',
|
||||
confirmed: confirmed != null,
|
||||
imageUrl: confirmed?.photo,
|
||||
isMandatory: (item.isRequired ?? false) || (item.photoRequired ?? false),
|
||||
needPhoto: item.photoRequired ?? false));
|
||||
});
|
||||
|
||||
emit(state.copyWith(
|
||||
selectedRole: event.role, roleKitItems: roleKitViewModels));
|
||||
}
|
||||
|
||||
void _onChangeState(
|
||||
RoleKiEventChangeState event, Emitter<RoleKitState> emit) {
|
||||
event.item.confirmed = !event.item.confirmed;
|
||||
emit(state.copyWith(showError: false));
|
||||
}
|
||||
|
||||
void _onUploadPhoto(
|
||||
RoleKitEventUploadPhoto event, Emitter<RoleKitState> emit) async {
|
||||
event.item.uploading = true;
|
||||
emit(state.copyWith(showError: false));
|
||||
try {
|
||||
var image = await ImagePicker().pickImage(source: ImageSource.gallery);
|
||||
if (image != null) {
|
||||
var imagePath = image.path;
|
||||
var result =
|
||||
await getIt<StaffRoleKitRepository>().uploadImage(imagePath);
|
||||
event.item.uploading = false;
|
||||
event.item.imageToken = result['token'];
|
||||
event.item.imageUrl = result['url'];
|
||||
event.item.localImage = imagePath;
|
||||
}
|
||||
} catch(e){
|
||||
if (e is DisplayableException) {
|
||||
emit(state.copyWith(apiError: e.message,loading: false));
|
||||
}
|
||||
}finally {
|
||||
event.item.uploading = false;
|
||||
emit(state.copyWith());
|
||||
}
|
||||
}
|
||||
|
||||
void _onSubmit(RoleKitEventSubmit event, Emitter<RoleKitState> emit) async {
|
||||
final allMandatoryItemsChecked = state.roleKitItems
|
||||
.where((element) => element.isMandatory)
|
||||
.every((element) => element.confirmed);
|
||||
final allPhotoUploaded = state.roleKitItems
|
||||
.where((element) => element.needPhoto)
|
||||
.every((element) =>
|
||||
element.imageUrl != null || element.localImage != null);
|
||||
|
||||
if (allMandatoryItemsChecked && allPhotoUploaded) {
|
||||
emit(state.copyWith(loading: true));
|
||||
|
||||
var confirmed = state.roleKitItems
|
||||
.where((e) => e.confirmed)
|
||||
.map((e) => MutateKitDto(id: e.id, photo: e.imageToken ?? e.imageUrl))
|
||||
.toList();
|
||||
try {
|
||||
await getIt<StaffRoleKitRepository>()
|
||||
.putKit(
|
||||
state.selectedRole!.skill!.id, confirmed, state.roleKitType);
|
||||
|
||||
}catch (e) {
|
||||
if (e is DisplayableException) {
|
||||
emit(state.copyWith(apiError: e.message));
|
||||
}
|
||||
return;
|
||||
} finally {
|
||||
emit(state.copyWith(loading: false));
|
||||
}
|
||||
emit(state.copyWith(success: true));
|
||||
} else {
|
||||
emit(state.copyWith(showError: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _onDeletePhoto(
|
||||
RoleKitEventDeletePhoto event, Emitter<RoleKitState> emit) {
|
||||
event.item.imageUrl = null;
|
||||
event.item.localImage = null;
|
||||
event.item.imageToken = null;
|
||||
emit(state.copyWith());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:krow/core/data/models/staff_role.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/role_kit_entity.dart';
|
||||
|
||||
sealed class RoleKitEvent {}
|
||||
|
||||
class RoleKitEventFetch extends RoleKitEvent {
|
||||
final RoleKitType type;
|
||||
|
||||
RoleKitEventFetch({required this.type});
|
||||
}
|
||||
|
||||
class RoleKitEventSubmit extends RoleKitEvent {}
|
||||
|
||||
class RoleKiEventChangeState extends RoleKitEvent {
|
||||
final RoleKitEntity item;
|
||||
|
||||
RoleKiEventChangeState(this.item);
|
||||
}
|
||||
|
||||
class RoleKitEventUploadPhoto extends RoleKitEvent {
|
||||
final RoleKitEntity item;
|
||||
final String photoPath;
|
||||
|
||||
RoleKitEventUploadPhoto({required this.item, required this.photoPath});
|
||||
}
|
||||
|
||||
class RoleKitEventDeletePhoto extends RoleKitEvent {
|
||||
final RoleKitEntity item;
|
||||
|
||||
RoleKitEventDeletePhoto(this.item);
|
||||
}
|
||||
|
||||
class RoleKitEventSelectRole extends RoleKitEvent {
|
||||
final StaffRole role;
|
||||
|
||||
RoleKitEventSelectRole({required this.role});
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:krow/core/data/models/staff_role.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/role_kit_entity.dart';
|
||||
|
||||
class RoleKitState {
|
||||
final bool showError;
|
||||
final bool loading;
|
||||
final bool success;
|
||||
final RoleKitType roleKitType;
|
||||
final List<RoleKitEntity> roleKitItems;
|
||||
final List<StaffRole> roles;
|
||||
final StaffRole? selectedRole;
|
||||
final String? apiError;
|
||||
|
||||
RoleKitState(
|
||||
{this.showError = false,
|
||||
this.roleKitItems = const [],
|
||||
this.roles = const [],
|
||||
this.loading = false,
|
||||
this.selectedRole,
|
||||
this.roleKitType = RoleKitType.uniform,
|
||||
this.success = false,
|
||||
this.apiError});
|
||||
|
||||
copyWith(
|
||||
{bool? showError,
|
||||
List<RoleKitEntity>? roleKitItems,
|
||||
RoleKitType? roleKitType,
|
||||
bool? loading,
|
||||
bool? success,
|
||||
List<StaffRole>? roles,
|
||||
StaffRole? selectedRole,
|
||||
String? apiError}) {
|
||||
return RoleKitState(
|
||||
showError: showError ?? this.showError,
|
||||
roleKitItems: roleKitItems ?? this.roleKitItems,
|
||||
loading: loading ?? false,
|
||||
success: success ?? false,
|
||||
roleKitType: roleKitType ?? this.roleKitType,
|
||||
roles: roles ?? this.roles,
|
||||
selectedRole: selectedRole ?? this.selectedRole,
|
||||
apiError: apiError,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
class RoleKitEntity {
|
||||
final String id;
|
||||
final String title;
|
||||
final bool isMandatory;
|
||||
final bool needPhoto;
|
||||
bool uploading;
|
||||
bool confirmed;
|
||||
String? imageUrl;
|
||||
String? localImage;
|
||||
|
||||
String? imageToken;
|
||||
|
||||
RoleKitEntity({
|
||||
required this.id,
|
||||
required this.title,
|
||||
this.isMandatory = false,
|
||||
this.confirmed = false,
|
||||
this.imageUrl,
|
||||
this.needPhoto = false,
|
||||
this.uploading = false,
|
||||
this.localImage,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:krow/core/data/models/staff_role.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/models/mutate_kit_dto.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/staff_role_kit_api.dart';
|
||||
import 'package:krow/features/profile/role_kit/data/staff_role_kit_repository.dart';
|
||||
|
||||
enum RoleKitType {
|
||||
uniform,
|
||||
equipment,
|
||||
}
|
||||
|
||||
@Injectable(as: StaffRoleKitRepository)
|
||||
class StaffRoleKitRepositoryImpl extends StaffRoleKitRepository {
|
||||
final StaffRoleKitApiProvider _staffRoleApi;
|
||||
|
||||
StaffRoleKitRepositoryImpl(this._staffRoleApi);
|
||||
|
||||
@override
|
||||
Future<List<StaffRole>> getStaffRole() async {
|
||||
return _staffRoleApi.fetchStaffRoles();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> putKit(
|
||||
String skillId, List<MutateKitDto> kits, RoleKitType type) async {
|
||||
if (type == RoleKitType.uniform) {
|
||||
return _staffRoleApi.putUniform(skillId, kits);
|
||||
} else {
|
||||
return _staffRoleApi.putEquipment(skillId, kits);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> uploadImage(String imagePath) async {
|
||||
return _staffRoleApi.uploadImage(imagePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_bloc.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_event.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
|
||||
@RoutePage()
|
||||
class RoleKitFlowScreen extends StatelessWidget {
|
||||
final RoleKitType roleKitType;
|
||||
|
||||
const RoleKitFlowScreen({super.key, required this.roleKitType});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) =>
|
||||
RoleKitBloc()..add(RoleKitEventFetch(type: roleKitType)),
|
||||
child: const AutoRouter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:krow/core/presentation/gen/assets.gen.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_box_decorations.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/core/presentation/widgets/scroll_layout_helper.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/check_box_card.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_button.dart';
|
||||
import 'package:krow/core/presentation/widgets/uploud_image_card.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_bloc.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_event.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_state.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/role_kit_entity.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
||||
|
||||
@RoutePage()
|
||||
class RoleKitScreen extends StatelessWidget {
|
||||
const RoleKitScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<RoleKitBloc, RoleKitState>(
|
||||
listenWhen: (oldState, newState) =>
|
||||
oldState.success != newState.success ||
|
||||
oldState.apiError != newState.apiError,
|
||||
listener: (context, state) {
|
||||
if (state.success) {
|
||||
context.router.maybePop();
|
||||
}
|
||||
if (state.apiError != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text(state.apiError ?? ''),
|
||||
));
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return ModalProgressHUD(
|
||||
inAsyncCall: state.loading,
|
||||
child: Scaffold(
|
||||
appBar: KwAppBar(
|
||||
titleText: state.roleKitType == RoleKitType.uniform
|
||||
? '${state.selectedRole?.skill?.name} ${'uniform'.tr()}'
|
||||
: '${state.selectedRole?.skill?.name} ${'equipment'.tr()}',
|
||||
),
|
||||
body: ScrollLayoutHelper(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
upperWidget: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
'${'please_indicate'.tr()} ${state.roleKitType == RoleKitType.uniform ? 'uniform'.tr().toLowerCase() : 'equipment'.tr().toLowerCase()}:',
|
||||
style: AppTextStyles.bodyTinyReg
|
||||
.copyWith(color: AppColors.blackGray),
|
||||
),
|
||||
if (state.showError) _buildErrorMessage(),
|
||||
const Gap(24),
|
||||
if (state.roleKitItems
|
||||
.where((item) => item.isMandatory)
|
||||
.isNotEmpty) ...[
|
||||
_buildSectionLabel('mandatory_items'.tr()),
|
||||
_buildItems(
|
||||
context, state.roleKitItems, true, state.showError),
|
||||
const Gap(4),
|
||||
],
|
||||
if (state.roleKitItems
|
||||
.where((item) => !item.isMandatory)
|
||||
.isNotEmpty) ...[
|
||||
_buildSectionLabel('optional_items'.tr()),
|
||||
_buildItems(
|
||||
context, state.roleKitItems, false, state.showError),
|
||||
],
|
||||
if (state.roleKitItems
|
||||
.where((item) => item.needPhoto)
|
||||
.isNotEmpty) ...[
|
||||
const Gap(32),
|
||||
_buildSectionLabel('confirm_availability'.tr()),
|
||||
_buildUploadProofItems(
|
||||
context, state.roleKitItems, state.showError),
|
||||
]
|
||||
],
|
||||
),
|
||||
lowerWidget: KwButton.primary(
|
||||
label: 'confirm'.tr(),
|
||||
onPressed: () {
|
||||
BlocProvider.of<RoleKitBloc>(context)
|
||||
.add(RoleKitEventSubmit());
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildSectionLabel(String text) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(text.toUpperCase(),
|
||||
style: AppTextStyles.captionReg.copyWith(
|
||||
color: AppColors.blackCaptionGreen,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
_buildItems(
|
||||
context, List<RoleKitEntity> items, bool required, bool showError) {
|
||||
return Column(
|
||||
children: items.where((item) => item.isMandatory == required).map((item) {
|
||||
return CheckBoxCard(
|
||||
isChecked: item.confirmed,
|
||||
title: item.title,
|
||||
errorMessage: showError && !item.confirmed && required
|
||||
? 'please_confirm_availability'.tr()
|
||||
: null,
|
||||
message: item.confirmed
|
||||
? 'availability_confirmed'.tr()
|
||||
: item.needPhoto
|
||||
? 'confirm_availability_photo'.tr()
|
||||
: null,
|
||||
onTap: () {
|
||||
BlocProvider.of<RoleKitBloc>(context)
|
||||
.add(RoleKiEventChangeState(item));
|
||||
},
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
_buildUploadProofItems(context, List<RoleKitEntity> items, bool showError) {
|
||||
return Column(
|
||||
children: items.where((item) => item.needPhoto).map((item) {
|
||||
return UploadImageCard(
|
||||
title: item.title,
|
||||
onSelectImage: () {
|
||||
BlocProvider.of<RoleKitBloc>(context)
|
||||
.add(RoleKitEventUploadPhoto(item: item, photoPath: ''));
|
||||
},
|
||||
onDeleteTap: () {
|
||||
BlocProvider.of<RoleKitBloc>(context)
|
||||
.add(RoleKitEventDeletePhoto(item));
|
||||
},
|
||||
onTap: () {},
|
||||
imageUrl: item.imageUrl,
|
||||
localImagePath: item.localImage,
|
||||
inUploading: item.uploading,
|
||||
statusColor: item.imageUrl == null
|
||||
? AppColors.statusError
|
||||
: AppColors.statusSuccess,
|
||||
message: (item.imageUrl == null)
|
||||
? showError
|
||||
? 'availability_requires_confirmation'.tr()
|
||||
: null
|
||||
: 'availability_confirmed'.tr(),
|
||||
hasError: showError,
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Container _buildErrorMessage() {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 12),
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: KwBoxDecorations.primaryLight8,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 28,
|
||||
width: 28,
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle, color: AppColors.tintRed),
|
||||
child: Center(
|
||||
child: Assets.images.icons.alertCircle.svg(),
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'item_checked_in_box'.tr(),
|
||||
style: AppTextStyles.bodyTinyMed
|
||||
.copyWith(color: AppColors.statusError),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:krow/core/data/models/staff_role.dart';
|
||||
import 'package:krow/core/presentation/gen/assets.gen.dart';
|
||||
import 'package:krow/core/application/routing/routes.gr.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_box_decorations.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
|
||||
import 'package:krow/core/presentation/widgets/scroll_layout_helper.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/staff_role_kit_repository_impl.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_bloc.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_event.dart';
|
||||
import 'package:krow/features/profile/role_kit/domain/bloc/role_kit_state.dart';
|
||||
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
||||
|
||||
@RoutePage()
|
||||
class RolesKitListScreen extends StatefulWidget {
|
||||
|
||||
const RolesKitListScreen({super.key, });
|
||||
|
||||
@override
|
||||
State<RolesKitListScreen> createState() => _RolesKitListScreenState();
|
||||
}
|
||||
|
||||
class _RolesKitListScreenState extends State<RolesKitListScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<RoleKitBloc, RoleKitState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: KwAppBar(
|
||||
titleText: state.roleKitType == RoleKitType.uniform
|
||||
? 'uniform'.tr()
|
||||
: 'equipment'.tr(),
|
||||
),
|
||||
body: ModalProgressHUD(
|
||||
inAsyncCall: state.loading,
|
||||
child: ScrollLayoutHelper(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
upperWidget: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(
|
||||
'roles'.tr().toUpperCase(),
|
||||
style: AppTextStyles.captionReg
|
||||
.copyWith(color: AppColors.blackCaptionGreen),
|
||||
),
|
||||
...state.roles.map((role) => _buildKitWidget(role,state.roleKitType)),
|
||||
const Gap(24),
|
||||
]),
|
||||
lowerWidget: const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildKitWidget(StaffRole role, RoleKitType roleKitType ) {
|
||||
return GestureDetector(
|
||||
onTap: () async{
|
||||
context.read<RoleKitBloc>().add(RoleKitEventSelectRole(role: role));
|
||||
await context.router.push(const RoleKitRoute());
|
||||
context.read<RoleKitBloc>().add(RoleKitEventFetch(type: roleKitType));
|
||||
},
|
||||
child: Container(
|
||||
height: 56,
|
||||
padding: const EdgeInsets.all(12),
|
||||
margin: const EdgeInsets.only(top: 8),
|
||||
decoration: KwBoxDecorations.primaryLight8,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
role.skill?.name ?? '',
|
||||
style: AppTextStyles.headingH3,
|
||||
),
|
||||
),
|
||||
const Gap(16),
|
||||
Assets.images.icons.caretRight.svg()
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user