836 lines
32 KiB
Dart
836 lines
32 KiB
Dart
import 'dart:io';
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:onufitness/constants/api_enum_constant.dart';
|
|
import 'package:onufitness/constants/color_constant.dart';
|
|
import 'package:onufitness/constants/text_constant.dart';
|
|
import 'package:onufitness/screens/rise/controllers/create_challenge_controller.dart';
|
|
import 'package:onufitness/screens/rise/controllers/rise_controller.dart';
|
|
import 'package:onufitness/screens/echoboard/widget/exclusive_connection_tile.dart';
|
|
import 'package:onufitness/services/local_storage_services/shared_services.dart';
|
|
import 'package:onufitness/utils/custom_sneakbar.dart';
|
|
import 'package:onufitness/widgets/Dropdowns/custom_lebel_dropdown.dart';
|
|
import 'package:onufitness/widgets/appbars/custom_appbar.dart';
|
|
import 'package:onufitness/widgets/TextFields/custom_textfield_with_inside_container_label_text.dart';
|
|
import 'package:onufitness/widgets/bottomsheet/common_upload_option_bottomsheet.dart';
|
|
import 'package:onufitness/widgets/pickers/lebel_text_date_picker.dart';
|
|
import 'package:onufitness/widgets/pickers/lebel_text_file_picker.dart';
|
|
|
|
class CreateChallengeScreen extends StatefulWidget {
|
|
const CreateChallengeScreen({super.key});
|
|
|
|
@override
|
|
State<CreateChallengeScreen> createState() => _CreateChallengeScreenState();
|
|
}
|
|
|
|
class _CreateChallengeScreenState extends State<CreateChallengeScreen> {
|
|
final ScrollController _membersScrollController = ScrollController();
|
|
CreateChallengeController createChallengeController = Get.put(
|
|
CreateChallengeController(),
|
|
);
|
|
final riseController = Get.find<RiseController>();
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_membersScrollController.addListener(_onMembersScroll);
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
createChallengeController.fetchExclusiveConnections(refresh: true);
|
|
|
|
createChallengeController.fetchMetricsList();
|
|
createChallengeController.fetchFitnessGoals();
|
|
});
|
|
}
|
|
|
|
void _onMembersScroll() {
|
|
if (_membersScrollController.position.pixels >=
|
|
_membersScrollController.position.maxScrollExtent - 200) {
|
|
if (createChallengeController.hasMoreDataConnection.value &&
|
|
!createChallengeController.isConnectionPaginationLoading.value) {
|
|
createChallengeController.fetchExclusiveConnections();
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> _onRefresh() async {
|
|
await createChallengeController.fetchExclusiveConnections(refresh: true);
|
|
createChallengeController.selectedConnections.clear();
|
|
createChallengeController.selectedConnections.refresh();
|
|
createChallengeController.selectedIds.clear();
|
|
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
createChallengeController.clearAll();
|
|
createChallengeController.selectedConnections.clear();
|
|
createChallengeController.selectedConnections.refresh();
|
|
createChallengeController.selectedIds.clear();
|
|
super.dispose();
|
|
}
|
|
|
|
bool hasValidWordLength(String text) {
|
|
final wordCount = text.trim().split(RegExp(r'\s+')).length;
|
|
return wordCount <= 100;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.white,
|
|
appBar: CustomAppBar(
|
|
title: 'Create a Challenge',
|
|
textColor: appbarTextColor,
|
|
titleFontSize: appBarHeardingText,
|
|
backgroundColor: Colors.white,
|
|
leading: IconButton(
|
|
icon: Icon(Icons.arrow_back_ios, color: Colors.black),
|
|
onPressed: () => Get.back(),
|
|
),
|
|
),
|
|
body: SingleChildScrollView(
|
|
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 10.h),
|
|
|
|
StatefulBuilder(
|
|
builder: (context, setState) {
|
|
return CustomTextFieldContainerInsideLabel(
|
|
controller: createChallengeController.titleController,
|
|
borderColor: lightGreyColor,
|
|
label: 'Challenge Title *',
|
|
fillColor: textFieldFillColor,
|
|
lebelTextPadding: 12.h,
|
|
topContentPadding: 20.h,
|
|
height:
|
|
createChallengeController.titleController.text.isEmpty
|
|
? 40.h
|
|
: null,
|
|
lebelTextFontWeight: FontWeight.w500,
|
|
);
|
|
},
|
|
),
|
|
|
|
SizedBox(height: 15),
|
|
Obx(() {
|
|
return createChallengeController.isFitnessGoalsLoading.value
|
|
? const Center(child: CircularProgressIndicator())
|
|
: EnhancedLebelTextDropdown(
|
|
title: "Fitness Goals *",
|
|
items: createChallengeController.localFitnessGoalsList,
|
|
selectedItem:
|
|
createChallengeController.selectedFitnessGoal.isEmpty
|
|
? null
|
|
: createChallengeController
|
|
.selectedFitnessGoal
|
|
.value,
|
|
onChanged: (String? newValue) {
|
|
if (newValue != null) {
|
|
createChallengeController.selectedFitnessGoal.value =
|
|
newValue;
|
|
var selectedObj = createChallengeController
|
|
.apiFitnessGoalsList
|
|
.firstWhere(
|
|
(element) => element.fitnessGoalTitle == newValue,
|
|
);
|
|
createChallengeController.selectedFitnessGoalId.value =
|
|
selectedObj.fitnessGoalId!;
|
|
}
|
|
},
|
|
borderColor: lightGreyColor,
|
|
);
|
|
}),
|
|
|
|
SizedBox(height: 15.h),
|
|
|
|
Obx(
|
|
() => EnhancedDatePicker(
|
|
label: "Start date *",
|
|
selectedDate:
|
|
createChallengeController.startDate.value?.toString() ?? "",
|
|
onDatePicked: createChallengeController.pickStartDate,
|
|
borderColor: lightGreyColor,
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 15.h),
|
|
|
|
Obx(
|
|
() => EnhancedDatePicker(
|
|
label: "End date *",
|
|
selectedDate:
|
|
createChallengeController.endDate.value?.toString() ?? "",
|
|
onDatePicked: createChallengeController.pickEndDate,
|
|
borderColor: lightGreyColor,
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 15.h),
|
|
CustomTextFieldContainerInsideLabel(
|
|
borderColor: lightGreyColor,
|
|
label: 'Description *',
|
|
fillColor: textFieldFillColor,
|
|
controller: createChallengeController.descriptionController,
|
|
maxLine: 4,
|
|
lebelTextPadding: 12.h,
|
|
topContentPadding: 30.h,
|
|
lebelTextFontWeight: FontWeight.w500,
|
|
),
|
|
SizedBox(height: 15.h),
|
|
|
|
// Upload Demo Video
|
|
Obx(
|
|
() => EnhancedFilePickerTile(
|
|
hintText: "Upload Demo Video",
|
|
fileName:
|
|
createChallengeController.demoVideoName.value.isEmpty
|
|
? null
|
|
: createChallengeController.demoVideoName.value,
|
|
icon: Icons.file_upload_outlined,
|
|
onTap: () {
|
|
CommonUploadBottomSheet.show(
|
|
context: context,
|
|
title: "Upload Video From",
|
|
allowedFileTypes: ['mp4', 'm4v'],
|
|
maxFileSizeMB: 50.0,
|
|
showCamera: false,
|
|
showGallery: true,
|
|
showDocument: true,
|
|
onFileSelected: (
|
|
String filePath,
|
|
String fileName,
|
|
String fileExtension,
|
|
) {
|
|
// Convert String path to PlatformFile
|
|
createChallengeController
|
|
.demoVideoFile
|
|
.value = PlatformFile(
|
|
path: filePath,
|
|
name: fileName,
|
|
size: File(filePath).lengthSync(),
|
|
bytes: null,
|
|
);
|
|
createChallengeController.demoVideoName.value = fileName;
|
|
},
|
|
onError: (String errorMessage) {
|
|
// Show error message
|
|
customSnackbar(title: "Error", message: errorMessage);
|
|
},
|
|
);
|
|
},
|
|
|
|
onClear: () => createChallengeController.clearDemoVideo(),
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 16.h),
|
|
|
|
// Upload Banner Image
|
|
Obx(
|
|
() => EnhancedFilePickerTile(
|
|
hintText: "Upload Banner Image",
|
|
fileName:
|
|
createChallengeController.bannerImageName.value.isEmpty
|
|
? null
|
|
: createChallengeController.bannerImageName.value,
|
|
icon: Icons.image_outlined,
|
|
|
|
onTap: () {
|
|
CommonUploadBottomSheet.show(
|
|
context: context,
|
|
title: "Upload Image from",
|
|
allowedFileTypes: ['jpg', 'jpeg', 'png'],
|
|
maxFileSizeMB: 5.0,
|
|
showCamera: true,
|
|
showGallery: true,
|
|
showDocument: true,
|
|
onFileSelected: (
|
|
String filePath,
|
|
String fileName,
|
|
String fileExtension,
|
|
) {
|
|
// Convert String path to PlatformFile
|
|
createChallengeController
|
|
.bannerImageFile
|
|
.value = PlatformFile(
|
|
path: filePath,
|
|
name: fileName,
|
|
size: File(filePath).lengthSync(),
|
|
bytes: null,
|
|
);
|
|
createChallengeController.bannerImageName.value =
|
|
fileName;
|
|
},
|
|
onError: (String errorMessage) {
|
|
// Show error message
|
|
customSnackbar(title: "Error", message: errorMessage);
|
|
},
|
|
);
|
|
},
|
|
onClear: () => createChallengeController.clearBannerImage(),
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 16.h),
|
|
Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.all(16.w),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
color: Colors.grey[100],
|
|
border: Border.all(color: Colors.grey.shade300),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Challenge task",
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
SizedBox(height: 12.h),
|
|
|
|
SizedBox(height: 12.h),
|
|
CustomTextFieldContainerInsideLabel(
|
|
controller: createChallengeController.taskTitleController,
|
|
borderColor: lightGreyColor,
|
|
label: "Title *",
|
|
fillColor: Colors.white,
|
|
lebelTextPadding: 12.h,
|
|
topContentPadding: 20.h,
|
|
),
|
|
SizedBox(height: 12.h),
|
|
|
|
// Updated Metric Dropdown
|
|
Obx(() {
|
|
return createChallengeController.isMetricsLoading.value
|
|
? const Center(child: CircularProgressIndicator())
|
|
: EnhancedLebelTextDropdown(
|
|
title: "Metric *",
|
|
items: createChallengeController.localMetricsList,
|
|
selectedItem:
|
|
createChallengeController.selectedMetric.isEmpty
|
|
? null
|
|
: createChallengeController
|
|
.selectedMetric
|
|
.value,
|
|
onChanged: (String? newValue) {
|
|
if (newValue != null) {
|
|
createChallengeController.selectedMetric.value =
|
|
newValue;
|
|
// Find the selected metric object to get its ID and units
|
|
var selectedMetricObj = createChallengeController
|
|
.apiMetricsList
|
|
.firstWhere(
|
|
(element) => element.metricName == newValue,
|
|
);
|
|
createChallengeController.selectedMetricId.value =
|
|
selectedMetricObj.metricId!;
|
|
|
|
// Update units list based on selected metric
|
|
|
|
createChallengeController
|
|
.updateUnitsForSelectedMetric(
|
|
selectedMetricObj.metricUnits ?? [],
|
|
);
|
|
|
|
// Clear selected unit when metric changes
|
|
createChallengeController.selectedUnit.value = '';
|
|
}
|
|
},
|
|
borderColor: lightGreyColor,
|
|
filledColor: Colors.white,
|
|
);
|
|
}),
|
|
|
|
SizedBox(height: 12.h),
|
|
|
|
CustomTextFieldContainerInsideLabel(
|
|
controller: createChallengeController.targetValueController,
|
|
borderColor: lightGreyColor,
|
|
label: 'Target Value *',
|
|
fillColor: Colors.white,
|
|
lebelTextPadding: 12.h,
|
|
keyboardType: TextInputType.numberWithOptions(),
|
|
topContentPadding: 20.h,
|
|
),
|
|
SizedBox(height: 12.h),
|
|
|
|
// Updated Unit Dropdown
|
|
Obx(() {
|
|
return EnhancedLebelTextDropdown(
|
|
title: "Unit *",
|
|
items: createChallengeController.localUnitsList.toList(),
|
|
selectedItem:
|
|
createChallengeController.selectedUnit.isEmpty
|
|
? null
|
|
: createChallengeController.selectedUnit.value,
|
|
onChanged: (String? newValue) {
|
|
if (newValue != null) {
|
|
createChallengeController.selectedUnit.value =
|
|
newValue;
|
|
}
|
|
},
|
|
borderColor: lightGreyColor,
|
|
filledColor: Colors.white,
|
|
);
|
|
}),
|
|
],
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 24.h),
|
|
|
|
// Challenge Visibility Section
|
|
challengeVisibilitySection(),
|
|
|
|
SizedBox(height: 24.h),
|
|
|
|
Obx(() {
|
|
if (createChallengeController.challengeVisibilityId.value == 3) {
|
|
return Column(
|
|
children: [membersSelectionSection(), SizedBox(height: 32.h)],
|
|
);
|
|
}
|
|
return SizedBox(height: 32.h);
|
|
}),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: ElevatedButton(
|
|
onPressed: () => Get.back(),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.black,
|
|
foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
padding: EdgeInsets.symmetric(vertical: 14.h),
|
|
),
|
|
child: Text(
|
|
'Cancel',
|
|
style: TextStyle(
|
|
fontSize: regularSizeText,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(width: 16.w),
|
|
Expanded(
|
|
child: Obx(
|
|
() => ElevatedButton(
|
|
onPressed: () async {
|
|
if (!createChallengeController
|
|
.isCreatingChallengeLoading
|
|
.value) {
|
|
await createChallengeController
|
|
.createChallenge()
|
|
.then((value) async {
|
|
if (value) {
|
|
await riseController.fetchOngoingChallenges(
|
|
isRefresh: true,
|
|
);
|
|
await riseController.fetchUpcomingChallenges(
|
|
isRefresh: true,
|
|
);
|
|
await riseController.fetchCreatedChallenges(
|
|
isRefresh: true,
|
|
);
|
|
await riseController.fetchJoinedChallenges(
|
|
isRefresh: true,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor:
|
|
createChallengeController
|
|
.isCreatingChallengeLoading
|
|
.value
|
|
? lightGreyColor
|
|
: Color(primaryColor),
|
|
foregroundColor: Colors.black,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
padding: EdgeInsets.symmetric(vertical: 14.h),
|
|
),
|
|
child:
|
|
createChallengeController
|
|
.isCreatingChallengeLoading
|
|
.value
|
|
? SizedBox(
|
|
height: 20.h,
|
|
width: 20.w,
|
|
child: CircularProgressIndicator(
|
|
color: Colors.white,
|
|
strokeWidth: 2.0,
|
|
),
|
|
)
|
|
: Text(
|
|
'Create',
|
|
style: TextStyle(
|
|
fontSize: regularSizeText,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 60.h),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget challengeVisibilitySection() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (SharedServices.getLoginDetails()?.data?.userRole ==
|
|
ApiEnum.coachUserRole)
|
|
Obx(
|
|
() => Row(
|
|
children: [
|
|
Checkbox(
|
|
value: createChallengeController.isAutoJoin.value,
|
|
onChanged: (bool? value) {
|
|
createChallengeController.isAutoJoin.value = value ?? true;
|
|
},
|
|
activeColor: Color(primaryColor),
|
|
checkColor: Colors.white,
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
'Auto-join challenge (You will automatically join this challenge)',
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w500,
|
|
color: Colors.black87,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
if (SharedServices.getLoginDetails()?.data?.userRole ==
|
|
ApiEnum.coachUserRole)
|
|
SizedBox(height: 15.h),
|
|
Text(
|
|
'Challenge Visibility',
|
|
style: TextStyle(
|
|
fontSize: regularSizeText,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
SizedBox(height: 10.h),
|
|
Obx(() {
|
|
return Column(
|
|
children: [
|
|
RadioListTile<int>(
|
|
title: Text(
|
|
'Public',
|
|
style: TextStyle(
|
|
fontSize: 15.sp,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
subtitle: Text(
|
|
'Anyone can join this challenge',
|
|
style: TextStyle(fontSize: 13.sp, color: greyTextColor1),
|
|
),
|
|
value: ApiEnum.publicPostVisibilityID,
|
|
groupValue:
|
|
createChallengeController.challengeVisibilityId.value,
|
|
activeColor: Color(primaryColor),
|
|
onChanged: (int? value) {
|
|
if (value != null) {
|
|
createChallengeController.challengeVisibilityId.value =
|
|
value;
|
|
// Clear selected connections when switching to public
|
|
if (value == 1) {
|
|
createChallengeController.selectedConnections.clear();
|
|
createChallengeController.selectedIds.clear();
|
|
}
|
|
}
|
|
},
|
|
contentPadding: EdgeInsets.zero,
|
|
),
|
|
RadioListTile<int>(
|
|
title: Text(
|
|
'Exclusive',
|
|
style: TextStyle(
|
|
fontSize: 15.sp,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
subtitle: Text(
|
|
'Only selected members can join',
|
|
style: TextStyle(fontSize: 13.sp, color: greyTextColor1),
|
|
),
|
|
value: ApiEnum.exclusivePostVisibilityID,
|
|
groupValue:
|
|
createChallengeController.challengeVisibilityId.value,
|
|
activeColor: Color(primaryColor),
|
|
onChanged: (int? value) {
|
|
if (value != null) {
|
|
createChallengeController.challengeVisibilityId.value =
|
|
value;
|
|
}
|
|
},
|
|
contentPadding: EdgeInsets.zero,
|
|
),
|
|
],
|
|
);
|
|
}),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget membersSelectionSection() {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Select Members and Groups',
|
|
style: TextStyle(
|
|
fontSize: regularSizeText,
|
|
fontWeight: FontWeight.w600,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
SizedBox(height: 5.h),
|
|
Text(
|
|
'Select members and groups to add to your challenge.',
|
|
style: TextStyle(fontSize: verySmallSizeText, color: greyTextColor1),
|
|
),
|
|
SizedBox(height: 20.h),
|
|
|
|
// Search Field
|
|
TextField(
|
|
controller: createChallengeController.connectionSearchController,
|
|
decoration: InputDecoration(
|
|
hintText: 'Search for members',
|
|
hintStyle: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
color: greyBorderColor,
|
|
),
|
|
prefixIcon: Padding(
|
|
padding: EdgeInsets.only(left: 20.w),
|
|
child: Icon(Icons.search),
|
|
),
|
|
suffixIcon: IconButton(
|
|
icon: Padding(
|
|
padding: EdgeInsets.only(right: 10.w),
|
|
child: Icon(Icons.close),
|
|
),
|
|
onPressed: () => createChallengeController.clearSearch(),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
borderSide: BorderSide(color: lightGreyColor),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
borderSide: BorderSide(color: lightGreyColor),
|
|
),
|
|
filled: true,
|
|
fillColor: textFieldFillColor,
|
|
),
|
|
onChanged: (newValue) {
|
|
createChallengeController.connectionSearchValue.value = newValue;
|
|
},
|
|
onSubmitted: (_) {
|
|
createChallengeController.fetchExclusiveConnections(refresh: true);
|
|
},
|
|
),
|
|
SizedBox(height: 20.h),
|
|
Container(
|
|
height: 400.h,
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: Colors.grey[300]!),
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
child: Obx(
|
|
() =>
|
|
createChallengeController.isConnectionsFetchLoading.value &&
|
|
createChallengeController
|
|
.exclusiveConnections
|
|
.data
|
|
?.items ==
|
|
null
|
|
? Center(
|
|
child: CircularProgressIndicator(color: Colors.black),
|
|
)
|
|
: createChallengeController
|
|
.exclusiveConnections
|
|
.data
|
|
?.items ==
|
|
null ||
|
|
createChallengeController
|
|
.exclusiveConnections
|
|
.data!
|
|
.items!
|
|
.isEmpty
|
|
? Center(
|
|
child: RefreshIndicator(
|
|
onRefresh: _onRefresh,
|
|
child: ListView(
|
|
physics: AlwaysScrollableScrollPhysics(),
|
|
children: [
|
|
SizedBox(height: 150.h),
|
|
Center(child: Text('No members found')),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
: RefreshIndicator(
|
|
backgroundColor: Colors.white,
|
|
color: Colors.black,
|
|
onRefresh: _onRefresh,
|
|
child: ListView.builder(
|
|
controller: _membersScrollController,
|
|
physics: AlwaysScrollableScrollPhysics(),
|
|
padding: EdgeInsets.all(8.w),
|
|
itemCount:
|
|
createChallengeController
|
|
.exclusiveConnections
|
|
.data!
|
|
.items!
|
|
.length +
|
|
(createChallengeController
|
|
.isConnectionPaginationLoading
|
|
.value
|
|
? 1
|
|
: 0),
|
|
itemBuilder: (_, i) {
|
|
if (i ==
|
|
createChallengeController
|
|
.exclusiveConnections
|
|
.data!
|
|
.items!
|
|
.length) {
|
|
return Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 16.h),
|
|
child: Center(
|
|
child: CircularProgressIndicator(
|
|
backgroundColor: Colors.white,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
final connection =
|
|
createChallengeController
|
|
.exclusiveConnections
|
|
.data!
|
|
.items![i];
|
|
final String itemId =
|
|
connection.tribeId != null
|
|
? 'tribe_${connection.tribeId}'
|
|
: 'user_${connection.connectedUserId}';
|
|
|
|
return Obx(() {
|
|
final bool isSelected = createChallengeController
|
|
.selectedIds
|
|
.contains(itemId);
|
|
|
|
return ExclusiveConnectionTile(
|
|
name:
|
|
connection.tribeId != null
|
|
? connection.tribeName ?? 'Unknown Tribe'
|
|
: connection.fullName ?? 'Unknown User',
|
|
type:
|
|
connection.tribeId != null ? 'group' : 'user',
|
|
members: connection.totalMemberCount,
|
|
imageUrl:
|
|
connection.tribeId != null
|
|
? connection.adminProfilePicture ?? ''
|
|
: connection.profilePicture ?? '',
|
|
isSelected: isSelected,
|
|
onTap: () {
|
|
createChallengeController
|
|
.exclusiveConnectionToggleSelection(
|
|
tribeId: connection.tribeId,
|
|
connectedUserId:
|
|
connection.connectedUserId,
|
|
);
|
|
},
|
|
);
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
Widget filePickerTile({
|
|
required String label,
|
|
String? fileName,
|
|
required IconData icon,
|
|
required VoidCallback onTap,
|
|
VoidCallback? onClear,
|
|
bool isRequired = false,
|
|
}) {
|
|
return InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h),
|
|
decoration: BoxDecoration(
|
|
color: textFieldFillColor,
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
border: Border.all(color: lightGreyColor),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(icon, color: Colors.grey),
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: Text(
|
|
fileName ?? "$label${isRequired ? ' *' : ''}",
|
|
style: TextStyle(
|
|
fontSize: 15.sp,
|
|
color: fileName == null ? Colors.black54 : Colors.black,
|
|
fontWeight:
|
|
fileName == null ? FontWeight.normal : FontWeight.w500,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
if (fileName != null && fileName.isNotEmpty && onClear != null)
|
|
GestureDetector(
|
|
onTap: () {
|
|
onClear();
|
|
},
|
|
child: Padding(
|
|
padding: EdgeInsets.only(left: 8.w),
|
|
child: Icon(Icons.close, color: Colors.grey),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|