-
-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mobile: Prepare demo app POC with hardcoded data #960
base: main
Are you sure you want to change the base?
Changes from all commits
337eef1
58e608e
b429b77
59768c8
2884044
8388659
99ebeeb
eb83043
7a6840d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,149 @@ | ||||||||||
import "package:firebase_auth/firebase_auth.dart"; | ||||||||||
|
||||||||||
class DemoUser implements User { | ||||||||||
@override | ||||||||||
String? get displayName => "demo user"; | ||||||||||
|
||||||||||
@override | ||||||||||
String? get email => null; | ||||||||||
|
||||||||||
@override | ||||||||||
bool get emailVerified => true; | ||||||||||
|
||||||||||
@override | ||||||||||
Future<String?> getIdToken([bool forceRefresh = false]) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> delete() { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<IdTokenResult> getIdTokenResult([bool forceRefresh = false]) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
bool get isAnonymous => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
Future<UserCredential> linkWithCredential(AuthCredential credential) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<ConfirmationResult> linkWithPhoneNumber(String phoneNumber, [RecaptchaVerifier? verifier]) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<UserCredential> linkWithPopup(AuthProvider provider) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<UserCredential> linkWithProvider(AuthProvider provider) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> linkWithRedirect(AuthProvider provider) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
UserMetadata get metadata => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
MultiFactor get multiFactor => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
String? get phoneNumber => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
String? get photoURL => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
List<UserInfo> get providerData => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
Future<UserCredential> reauthenticateWithCredential(AuthCredential credential) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<UserCredential> reauthenticateWithPopup(AuthProvider provider) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<UserCredential> reauthenticateWithProvider(AuthProvider provider) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> reauthenticateWithRedirect(AuthProvider provider) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
String? get refreshToken => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> reload() { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> sendEmailVerification([ActionCodeSettings? actionCodeSettings]) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
String? get tenantId => throw UnimplementedError(); | ||||||||||
|
||||||||||
@override | ||||||||||
String get uid => throw UnimplementedError(); | ||||||||||
Comment on lines
+107
to
+108
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implement required uid property The - String get uid => throw UnimplementedError();
+ String get uid => "demo-user-id"; 📝 Committable suggestion
Suggested change
|
||||||||||
|
||||||||||
@override | ||||||||||
Future<User> unlink(String providerId) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> updateDisplayName(String? displayName) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> updateEmail(String newEmail) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> updatePassword(String newPassword) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> updatePhoneNumber(PhoneAuthCredential phoneCredential) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> updatePhotoURL(String? photoURL) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> updateProfile({String? displayName, String? photoURL}) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
|
||||||||||
@override | ||||||||||
Future<void> verifyBeforeUpdateEmail(String newEmail, [ActionCodeSettings? actionCodeSettings]) { | ||||||||||
throw UnimplementedError(); | ||||||||||
} | ||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import "package:cloud_firestore/cloud_firestore.dart"; | ||
|
||
// We are using DocumentReference in repository / data source. That's why we need to get | ||
// no-op implementation for it for demo data source. | ||
|
||
// ignore: subtype_of_sealed_class | ||
class NoOpDocumentReference implements DocumentReference<Map<String, dynamic>> { | ||
const NoOpDocumentReference(); | ||
|
||
@override | ||
CollectionReference<Map<String, dynamic>> collection(String collectionPath) { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
Future<void> delete() { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
FirebaseFirestore get firestore => throw UnimplementedError(); | ||
|
||
@override | ||
Future<DocumentSnapshot<Map<String, dynamic>>> get([GetOptions? options]) { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
String get id => throw UnimplementedError(); | ||
|
||
@override | ||
CollectionReference<Map<String, dynamic>> get parent => throw UnimplementedError(); | ||
|
||
@override | ||
String get path => throw UnimplementedError(); | ||
|
||
@override | ||
Future<void> set(Map<String, dynamic> data, [SetOptions? options]) { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
Stream<DocumentSnapshot<Map<String, dynamic>>> snapshots( | ||
{bool includeMetadataChanges = false, ListenSource source = ListenSource.defaultSource,}) { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
Future<void> update(Map<Object, Object?> data) { | ||
throw UnimplementedError(); | ||
} | ||
|
||
@override | ||
DocumentReference<R> withConverter<R>( | ||
{required FromFirestore<R> fromFirestore, required ToFirestore<R> toFirestore,}) { | ||
throw UnimplementedError(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,16 @@ | ||||||||||||||||||||||||||||||
import "package:app/data/datasource/organization_data_source.dart"; | ||||||||||||||||||||||||||||||
import "package:app/data/models/models.dart"; | ||||||||||||||||||||||||||||||
import "package:cloud_firestore/cloud_firestore.dart"; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
class OrganizationDemoDataSource implements OrganizationDataSource { | ||||||||||||||||||||||||||||||
final Organization _organization = _generateOrganization(); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
static Organization _generateOrganization() { | ||||||||||||||||||||||||||||||
return const Organization(name: "Demo organization", contactName: "Demo manager", contactNumber: "+232 123456789"); | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
@override | ||||||||||||||||||||||||||||||
Future<Organization?> fetchOrganization(DocumentReference<Object?> organizationRef) async { | ||||||||||||||||||||||||||||||
return _organization; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Comment on lines
+13
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error simulation capabilities The demo implementation should simulate real-world scenarios, including error cases. @override
Future<Organization?> fetchOrganization(DocumentReference<Object?> organizationRef) async {
+ // Simulate network delay
+ await Future.delayed(const Duration(milliseconds: 500));
+
+ // Simulate errors for specific refs (optional)
+ if (organizationRef.id == 'error_case') {
+ throw FirebaseException(plugin: 'demo', message: 'Simulated error');
+ }
+
return _organization;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import "dart:math"; | ||
|
||
import "package:app/data/datasource/payment_data_source.dart"; | ||
import "package:app/data/models/models.dart"; | ||
import "package:cloud_firestore/cloud_firestore.dart"; | ||
|
||
const String paymentCollection = "payments"; | ||
|
||
class PaymentDemoDataSource implements PaymentDataSource { | ||
List<SocialIncomePayment> payments = initData(); | ||
|
||
static List<SocialIncomePayment> initData() { | ||
final List<SocialIncomePayment> payments = <SocialIncomePayment>[]; | ||
|
||
final nowDate = DateTime.now(); | ||
final random = Random(); | ||
|
||
final confirmedPaymentsCount = random.nextInt(12) + 1; | ||
final notConfirmedPaymentsCount = random.nextInt(2) + 1; | ||
|
||
for (int i = 0; i < confirmedPaymentsCount; i++) { | ||
final currentDateTime = DateTime( | ||
nowDate.year, | ||
nowDate.month - confirmedPaymentsCount - notConfirmedPaymentsCount + i, | ||
15, | ||
); | ||
payments.add( | ||
SocialIncomePayment( | ||
id: "${currentDateTime.year}-${currentDateTime.month}", | ||
paymentAt: Timestamp.fromDate(currentDateTime), | ||
currency: "SLE", | ||
amount: 700, | ||
status: PaymentStatus.confirmed, | ||
), | ||
); | ||
} | ||
|
||
for (int i = 0; i < notConfirmedPaymentsCount; i++) { | ||
final currentDateTime = DateTime( | ||
nowDate.year, | ||
nowDate.month - notConfirmedPaymentsCount + i, | ||
15, | ||
); | ||
payments.add( | ||
SocialIncomePayment( | ||
id: "${currentDateTime.year}-${currentDateTime.month}", | ||
paymentAt: Timestamp.fromDate(currentDateTime), | ||
currency: "SLE", | ||
amount: 700, | ||
status: PaymentStatus.paid, | ||
), | ||
); | ||
} | ||
|
||
payments.sort((a, b) => a.id.compareTo(b.id)); | ||
|
||
return payments; | ||
} | ||
|
||
@override | ||
Future<List<SocialIncomePayment>> fetchPayments({ | ||
required String recipientId, | ||
}) async { | ||
return payments; | ||
} | ||
|
||
/// This updates the payment status to confirmed | ||
/// and also sets lastUpdatedAt and lastUpdatedBy to the | ||
/// current time and recipient | ||
@override | ||
Future<void> confirmPayment({ | ||
required Recipient recipient, | ||
required SocialIncomePayment payment, | ||
}) async { | ||
final updatedPayment = payment.copyWith( | ||
status: PaymentStatus.confirmed, | ||
updatedBy: recipient.userId, | ||
); | ||
|
||
final indexWhere = payments.indexWhere((element) => element.id == updatedPayment.id); | ||
payments[indexWhere] = updatedPayment; | ||
Comment on lines
+80
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add bounds checking for payment updates The array access could throw if payment ID is not found. Add error handling: final indexWhere = payments.indexWhere((element) => element.id == updatedPayment.id);
+ if (indexWhere == -1) {
+ throw Exception('Payment not found: ${updatedPayment.id}');
+ }
payments[indexWhere] = updatedPayment; Also applies to: 96-97 |
||
} | ||
|
||
@override | ||
Future<void> contestPayment({ | ||
required Recipient recipient, | ||
required SocialIncomePayment payment, | ||
required String contestReason, | ||
}) async { | ||
final updatedPayment = payment.copyWith( | ||
status: PaymentStatus.contested, | ||
comments: contestReason, | ||
updatedBy: recipient.userId, | ||
); | ||
|
||
final indexWhere = payments.indexWhere((element) => element.id == updatedPayment.id); | ||
payments[indexWhere] = updatedPayment; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can always just write
final organization = await ....;
instead of
final Organization? organization = await ....;
Type will be assigned automatically. Just FYI :D