Here we created a check list using Riverpod FutureProvider. With this you will learn how to get data from the internet and then put them in a check list. You would be able to check in tick list manner.
This tutorial does not follow code generation tool and latest syntax. Many flutter programmer like to follow classic way of writting FutureProvider.
Let's create a CheckList class with enum. Here we created an enum named CheckListState
enum CheckListState { BEFORE, ING, SUCCESS, FAILL }
class CheckList {
int checkListId;
int patientId;
String startDate;
String endDate;
String content;
CheckListState state;
CheckList(
{required this.checkListId,
required this.patientId,
required this.startDate,
required this.endDate,
required this.content,
required this.state});
factory CheckList.fromJson(Map<String, dynamic> json) {
return CheckList(
checkListId: json['checklist_id'],
patientId: json['patient_id'],
startDate: json['start_date'],
endDate: json['end_date'],
content: json['content'],
state: CheckListState.values[json['state']]);
}
}
Let's here create a controller. This would help us do network call. Here our class name is ChecklistService and the main method is getChecklists(). This is the method we will call from our FutureProvider.
class ChecklistService {
final String? _baseUrl = dotenv.env['BASE_URL'];
Future<List<CheckList>> getChecklists() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final int id = prefs.getInt('id')!;
final response = await DioClient()
.get('$_baseUrl/checklist/get/today/$id', {'patient_id': id}, true);
if (response.result == Result.success) {
List<CheckList> checklist = response.response
.map((counselor) {
return CheckList.fromJson(counselor);
})
.cast<CheckList>()
.toList();
return checklist;
} else {
throw Exception('Failed to load checklists from API');
}
}
}
Here's the UI of this code using ConsumerWidget with FutureProvider. First at the top we call FutureProvider with autoDispose modifier. This is because we want to remove the provider from the memory when not needed.
final checkListProvider = FutureProvider.autoDispose<List<CheckList>>(
(ref) => ChecklistService().getChecklists());
class CheckListWidget extends ConsumerWidget {
const CheckListWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final checkList = ref.watch(checkListProvider);
return Container(
padding: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: Colors.white38,
borderRadius: BorderRadius.circular(20),
),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: checkList.when(
data: ((data) {
if (data.isEmpty) {
return [
Container(
padding: const EdgeInsets.only(left: 15),
child: const Text(
'no checkList in today',
style: TextStyle(
fontSize: 18,
color: Colors.white,
height: 1.4,
fontWeight: FontWeight.w600),
),
)
];
} else {
return data
.map(
(e) => Row(
children: [
Checkbox(
fillColor:
MaterialStateProperty.all(Palette.appColor),
value: false,
onChanged: (value) {
if (value!) {
e.state = CheckListState.SUCCESS;
} else {
e.state = CheckListState.FAILL;
}
},
),
Text(
e.content,
style: const TextStyle(
fontSize: 18,
color: Colors.black87,
height: 1.4,
fontWeight: FontWeight.w600),
),
],
),
)
.toList();
}
}),
loading: () => [const Text('Loading...')],
error: (error, stackTrace) => [
const Text(
'fail to load checkList',
style: TextStyle(
fontSize: 18,
color: Colors.black87,
height: 1.4,
fontWeight: FontWeight.w600),
),
])));
}
}