Skip to content

Commit

Permalink
#61 - task(firestore service): add service interface for firestore API
Browse files Browse the repository at this point in the history
Sadly the converter solution was a dead end, due to dart not being able to invoke interface methods via generic types.

However, a similar solution is utilizing a middleware service for each requested entity, that fetched the required json data from the firestore and calls the corresponding toJson/fromJson method to map json data to entity model.
  • Loading branch information
sdresselmann committed Apr 27, 2024
1 parent 0ec3e7c commit ac8a8e9
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 50 deletions.
12 changes: 11 additions & 1 deletion lib/core/interfaces/json_serializable.dart
@@ -1 +1,11 @@
abstract class JsonSerializable {}
import 'package:lifting_progress_tracker/firebase/firestore_json.dart';

abstract class JsonSerializable<T> {
// Usage of named constructors can't be enforced, however the usage of
// both methods is heavily encouraged.
JsonSerializable.fromJson();

FirestoreJson toJson() {
return {};
}
}
15 changes: 4 additions & 11 deletions lib/firebase/services/firestore_service.dart
@@ -1,7 +1,7 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:get_it/get_it.dart';
import 'package:lifting_progress_tracker/firebase/firestore_json.dart';
import 'package:lifting_progress_tracker/firebase/services/firebase_service.dart';
import 'package:lifting_progress_tracker/training_plan/models/training_plan_list.dart';
import 'package:logging/logging.dart';

class FirestoreService {
Expand Down Expand Up @@ -43,19 +43,12 @@ class FirestoreService {
.set(documentData);
}

Future<TrainingPlanList> get(
Future<FirestoreJson> get(
String collectionName,
String documentId,
) async {
final DocumentSnapshot<TrainingPlanList> documentSnapshot = await _firestore
.collection(collectionName)
.doc(documentId)
.withConverter(
fromFirestore: (snapshot, _) =>
TrainingPlanList.fromJson(snapshot.data()!),
toFirestore: (trainingPlanList, _) => trainingPlanList.toJson(),
)
.get();
final DocumentSnapshot<FirestoreJson> documentSnapshot =
await _firestore.collection(collectionName).doc(documentId).get();

if (!documentSnapshot.exists) {
_logger.severe(
Expand Down
31 changes: 5 additions & 26 deletions lib/pages/home.dart
Expand Up @@ -3,49 +3,28 @@ import 'package:get_it/get_it.dart';
import 'package:lifting_progress_tracker/core/models/app_user.dart';
import 'package:lifting_progress_tracker/core/services/user_service.dart';
import 'package:lifting_progress_tracker/core/widgets/error_message.dart';
import 'package:lifting_progress_tracker/firebase/services/firestore_service.dart';
import 'package:lifting_progress_tracker/pages/starting/widgets/welcome_message.dart';
import 'package:logging/logging.dart';

class HomePage extends StatelessWidget {
final Logger _logger = Logger("StartingPage");

final UserService _userService = GetIt.I.get<UserService>();

@override
Widget build(BuildContext context) {
final UserService userService = GetIt.I.get<UserService>();
final FirestoreService firestoreService = GetIt.I.get<FirestoreService>();

return Scaffold(
body: Center(
child: FutureBuilder(
future: userService.user$,
future: _userService.user$,
builder: (BuildContext context, AsyncSnapshot<AppUser> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}

if (snapshot.connectionState == ConnectionState.done) {
return Column(
children: [
WelcomeMessage(
username: snapshot.data?.email ?? "",
),
ElevatedButton(
onPressed: () => {
firestoreService.get(
"plan-entries",
snapshot.data?.uid ?? "",
),
// .then(
// (value) {
// final plans = value;
// print(plans);
// },
// ),
},
child: const Text("press to fetch!"),
),
],
return WelcomeMessage(
username: snapshot.data?.email ?? "",
);
}

Expand Down
12 changes: 9 additions & 3 deletions lib/training_plan/models/training_plan.dart
@@ -1,16 +1,22 @@
import 'package:lifting_progress_tracker/core/interfaces/json_serializable.dart';
import 'package:lifting_progress_tracker/firebase/firestore_json.dart';
import 'package:lifting_progress_tracker/training_plan/models/training_plan_entry.dart';

class TrainingPlan {
class TrainingPlan implements JsonSerializable<TrainingPlan> {
Map<String, TrainingPlanEntry> planEntries;

TrainingPlan({required this.planEntries});

TrainingPlan.fromJson(FirestoreJson json)
: planEntries = json.map(
(key, value) => MapEntry(
key,
TrainingPlanEntry.fromJson(value as FirestoreJson),
),
);

@override
FirestoreJson toJson() {
return {
"planEntries": planEntries,
};
}
}
10 changes: 3 additions & 7 deletions lib/training_plan/models/training_plan_entry.dart
@@ -1,21 +1,17 @@
import 'package:lifting_progress_tracker/core/interfaces/json_serializable.dart';
import 'package:lifting_progress_tracker/firebase/firestore_json.dart';

class TrainingPlanEntry {
class TrainingPlanEntry implements JsonSerializable<TrainingPlanEntry> {
String repeats;
String exerciseName;
String weight;

TrainingPlanEntry({
required this.repeats,
required this.exerciseName,
required this.weight,
});

TrainingPlanEntry.fromJson(FirestoreJson json)
: repeats = json["repeats"] as String,
exerciseName = json["exerciseName"] as String,
weight = json["weight"] as String;

@override
FirestoreJson toJson() {
return {
"repeats": repeats,
Expand Down
6 changes: 4 additions & 2 deletions lib/training_plan/models/training_plan_list.dart
@@ -1,10 +1,11 @@
import 'package:lifting_progress_tracker/core/interfaces/json_serializable.dart';
import 'package:lifting_progress_tracker/firebase/firestore_json.dart';
import 'package:lifting_progress_tracker/training_plan/models/training_plan.dart';

class TrainingPlanList {
class TrainingPlanList implements JsonSerializable<TrainingPlanList> {
Map<String, TrainingPlan> trainingPlanList;

TrainingPlanList({required this.trainingPlanList});
TrainingPlanList(this.trainingPlanList);

TrainingPlanList.fromJson(FirestoreJson json)
: trainingPlanList = json.map(
Expand All @@ -14,6 +15,7 @@ class TrainingPlanList {
),
);

@override
FirestoreJson toJson() {
return {
"trainingPlanList": trainingPlanList,
Expand Down
16 changes: 16 additions & 0 deletions lib/training_plan/training_plan_service.ts.dart
@@ -0,0 +1,16 @@
import 'package:get_it/get_it.dart';
import 'package:lifting_progress_tracker/firebase/services/firestore_service.dart';
import 'package:lifting_progress_tracker/training_plan/models/training_plan_list.dart';

class TrainingPlanService {
final FirestoreService _firestoreService = GetIt.I.get<FirestoreService>();

Future<TrainingPlanList> getPlanList(
String collectionName,
String documentId,
) async {
return TrainingPlanList.fromJson(
await _firestoreService.get(collectionName, documentId),
);
}
}

0 comments on commit ac8a8e9

Please sign in to comment.