Skip to content

Commit

Permalink
release: 1.1.0 (#73)
Browse files Browse the repository at this point in the history
* chore: set jobs sort to active by default

* fix: typos

* refactor: redux dry (#67)

* fix: typos

* refactor: sort algo

* refactor: logout

* refactor: type-safe reducers [WIP]

* refactor: code clean up

* refactor: keep store clean & DRY

* chore: update TASKS

* fix: minor bugs (#68)

* chore: track amount left on payment creation

* refactor: proper keyboard actions

* chore: UI for additional note on job

* fix: handle on image picker canceled

* chore: dispose of FocusNode

* fix: snackbar loader width

* chore: update TASKS

* fix: adding multiple contact

* refactor: fetch settings before silent login

* refactor(redux): added settings

* refactor: homepage & splash

* refactor: add WillPopScope to Homepage

* chore: update TASKS

* feat: personalized measures (#69)

* chore: first look

* chore: refactor + second look

* chore: delete block

* chore: code clean up

* chore: edit measure item

* chore: code clean up

* refactor(redux): measures

* chore: implementation details

* chore(redux): clean up implementation details

* chore: code clean up

* chore: code clean up

* chore: code clean up

* fix: settings no network issue

* chore: still cleaning up

* chore: link contacts to account measures

* feat: personalize measurements w/ account

* chore: update TASKS

* chore: code clean up

* fix: minor bugs (#70)

* feat: in app review (#71)

* chore: first look

* chore: set up redux

* chore(redux): code clean up

* chore: code cleanup

* chore: code clean up

* chore: update TASKS

* release: 1.1.0 (#72)

* chore: added verified icon

* refactor: contact upload state snack

* feat: bump version to 1.1.0
  • Loading branch information
jogboms authored Jul 27, 2018
1 parent 021776c commit 308ca5e
Show file tree
Hide file tree
Showing 92 changed files with 2,725 additions and 1,461 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
"editor.insertSpaces": false,
"editor.formatOnSave": true
},
"java.configuration.updateBuildConfiguration": "interactive",
}
34 changes: 27 additions & 7 deletions TASKS.todo
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
PENDING:
☐ delete-able payment + images + jobs + contacts
☐ implement share payment + image
☐ Collect account details on account creation
☐ Generate invoice & share as SMS containing link to pay on paystack
☐ Firebase function on successful payments w/ push notification
☐ delete-able payment + images + jobs + contacts @goals
☐ implement share payment + image @goals
☐ Collect account details on account creation @goals
☐ Generate invoice & share as SMS containing link to pay on paystack @goals
☐ Firebase function on successful payments w/ push notification @goals
☐ On account create, send personal email + email to user @high
☐ personalize measurements w/ account @critical
☐ indicator for premium accounts @today
☐ empty states icons @quickie
☐ edit job measurements @high
☐ Trigger loading action for any side-effect to the store @low
☐ gradual migration to BLoC to reduce boilerplate from Redux @goals
☐ copy and paste jobs @goals
☐ migrate all firebase actions to within epics @goals

COMPLETED:
✔ indicator for premium accounts @goals @done(18-07-27 04:38)
✔ add in-app review @quickie @done(18-07-27 03:16)
✔ personalize measurements w/ account @critical @done(18-07-25 18:47)
✔ long press to delete or edit measure block snackbar message @critical @done(18-07-25 01:20)
✔ fix issue with reloading state on outdated app @critical @done(18-07-24 11:23)
✔ add WillPopScope to Homepage @high @done(18-07-24 11:22)
✔ make sure fetching settings happens before silent login @critical @done(18-07-24 08:51)
✔ adding multiple contact doesn't work @critical @done(18-07-23 14:06)
✔ snackbar loader width @today @started(18-07-23 01:05) @done(18-07-23 02:01) @lasted(56m27s)
✔ handle on image picker canceled. @critical @done(18-07-23 01:01)
✔ No UI for additional note on job @today @done(18-07-23 00:57)
✔ Add proper keyboard actions @started(18-07-23 00:15) @done(18-07-23 00:48) @lasted(33m35s)
✔ The getter 'id' was called on null on contact create @critical @done(18-07-23 00:48)
✔ track amount left on payment creation @today @started(18-07-23 00:01) @done(18-07-23 00:14) @lasted(13m32s)
✔ DRY redux @today @done(18-07-22 12:34)
✔ fix create "contacts" typo in modal @today @done(18-07-22 09:23)
✔ reference upload issue @critical @done(18-07-21 16:40)
✔ stats image count on job update image @today @done(18-07-21 15:49)
✔ check for outdated version + template @today @done(18-07-21 15:40)
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

ext.versionMajor = 1
ext.versionMinor = 0
ext.versionPatch = 3
ext.versionMinor = 1
ext.versionPatch = 0
ext.versionClassifier = "beta"
ext.isSnapshot = false
ext.minimumSdkVersion = 16
Expand Down
Binary file added assets/images/verified.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions lib/models/account.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class AccountModel extends Model {
String photoURL;
AccountModelStatus status;
bool hasPremiumEnabled;
bool hasSendRating;
int rating;
String notice;
bool hasReadNotice;

Expand All @@ -25,6 +27,8 @@ class AccountModel extends Model {
@required this.photoURL,
@required this.status,
@required this.hasPremiumEnabled,
@required this.hasSendRating,
@required this.rating,
@required this.notice,
@required this.hasReadNotice,
});
Expand All @@ -41,6 +45,8 @@ class AccountModel extends Model {
status:
AccountModelStatus.values[int.tryParse(json['status'].toString())],
hasPremiumEnabled: json['hasPremiumEnabled'],
hasSendRating: json['hasSendRating'] ?? false,
rating: json['rating'],
notice: json['notice'],
hasReadNotice: json['hasReadNotice'],
);
Expand All @@ -57,6 +63,8 @@ class AccountModel extends Model {
String photoURL,
AccountModelStatus status,
bool hasPremiumEnabled,
bool hasSendRating,
int rating,
String notice,
bool hasReadNotice,
}) {
Expand All @@ -69,6 +77,8 @@ class AccountModel extends Model {
photoURL: photoURL ?? this.photoURL,
status: status ?? this.status,
hasPremiumEnabled: hasPremiumEnabled ?? this.hasPremiumEnabled,
hasSendRating: hasSendRating ?? this.hasSendRating,
rating: rating ?? this.rating,
notice: notice ?? this.notice,
hasReadNotice: hasReadNotice ?? this.hasReadNotice,
)..reference = this.reference;
Expand All @@ -85,6 +95,8 @@ class AccountModel extends Model {
'photoURL': photoURL,
'status': status.index,
'hasPremiumEnabled': hasPremiumEnabled,
'hasSendRating': hasSendRating,
'rating': rating,
'notice': notice,
'hasReadNotice': hasReadNotice,
};
Expand Down
21 changes: 8 additions & 13 deletions lib/models/contact.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:tailor_made/models/main.dart';
import 'package:tailor_made/models/measure.dart';
import 'package:tailor_made/services/auth.dart';
import 'package:tailor_made/utils/tm_uuid.dart';

Expand All @@ -12,7 +11,7 @@ class ContactModel extends Model {
String location;
String imageUrl;
DateTime createdAt;
List<MeasureModel> measurements;
Map<String, double> measurements;
int totalJobs;
int pendingJobs;

Expand All @@ -24,24 +23,20 @@ class ContactModel extends Model {
this.location,
this.imageUrl,
DateTime createdAt,
List<MeasureModel> measurements,
Map<String, double> measurements,
this.totalJobs = 0,
this.pendingJobs = 0,
}) : id = id ?? uuid(),
createdAt = createdAt ?? DateTime.now(),
userID = userID ?? Auth.getUser.uid,
measurements = measurements != null && measurements.isNotEmpty
? measurements
: createDefaultMeasures();
measurements =
measurements != null && measurements.isNotEmpty ? measurements : {};

factory ContactModel.fromJson(Map<String, dynamic> json) {
assert(json != null);
final List<MeasureModel> measurements = [];
Map<String, double> measurements;
if (json['measurements'] != null) {
json['measurements'].forEach(
(dynamic measure) => measurements
.add(MeasureModel.fromJson(measure.cast<String, dynamic>())),
);
measurements = json['measurements'].cast<String, double>();
}
return new ContactModel(
id: json['id'],
Expand All @@ -66,7 +61,7 @@ class ContactModel extends Model {
String phone,
String location,
String imageUrl,
List<MeasureModel> measurements,
Map<String, double> measurements,
}) {
return new ContactModel(
id: this.id,
Expand All @@ -92,7 +87,7 @@ class ContactModel extends Model {
'location': location,
'imageUrl': imageUrl,
'createdAt': createdAt.toString(),
'measurements': measurements.map((measure) => measure.toMap()).toList(),
'measurements': measurements,
'totalJobs': totalJobs,
'pendingJobs': pendingJobs,
};
Expand Down
28 changes: 19 additions & 9 deletions lib/models/job.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'package:tailor_made/models/image.dart';
import 'package:tailor_made/models/main.dart';
import 'package:tailor_made/models/measure.dart';
import 'package:tailor_made/models/payment.dart';
import 'package:tailor_made/services/auth.dart';
import 'package:tailor_made/utils/tm_uuid.dart';
Expand All @@ -17,7 +16,7 @@ class JobModel extends Model {
double pendingPayment;
String notes;
List<ImageModel> images;
List<MeasureModel> measurements;
Map<String, double> measurements;
List<PaymentModel> payments;
bool isComplete;
DateTime createdAt;
Expand All @@ -32,7 +31,7 @@ class JobModel extends Model {
this.images,
this.completedPayment = 0.0,
this.pendingPayment = 0.0,
this.measurements = const [],
this.measurements = const {},
this.payments = const [],
this.isComplete = false,
DateTime createdAt,
Expand All @@ -42,12 +41,9 @@ class JobModel extends Model {

factory JobModel.fromJson(Map<String, dynamic> json) {
assert(json != null);
final List<MeasureModel> measurements = [];
Map<String, double> measurements;
if (json['measurements'] != null) {
json['measurements'].forEach(
(dynamic measure) => measurements
.add(MeasureModel.fromJson(measure.cast<String, dynamic>())),
);
measurements = json['measurements'].cast<String, double>();
}
final List<PaymentModel> payments = [];
if (json['payments'] != null) {
Expand Down Expand Up @@ -84,6 +80,20 @@ class JobModel extends Model {
return JobModel.fromJson(doc.data)..reference = doc.reference;
}

// TODO implement others
JobModel copyWith({
String contactID,
Map<String, double> measurements,
}) {
return new JobModel(
id: this.id,
userID: this.userID,
contactID: contactID ?? this.contactID,
measurements: measurements ?? this.measurements,
createdAt: this.createdAt,
)..reference = this.reference;
}

@override
Map<String, dynamic> toMap() {
return <String, dynamic>{
Expand All @@ -97,7 +107,7 @@ class JobModel extends Model {
'notes': notes,
'images': images.map((image) => image.toMap()).toList(),
'createdAt': createdAt.toString(),
'measurements': measurements.map((measure) => measure.toMap()).toList(),
'measurements': measurements,
'payments': payments.map((payment) => payment.toMap()).toList(),
'isComplete': isComplete,
};
Expand Down
4 changes: 4 additions & 0 deletions lib/models/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@ abstract class Model {
String toString() {
return json.encode(toMap());
}

dynamic operator [](String key) {
return toMap()[key];
}
}
72 changes: 43 additions & 29 deletions lib/models/measure.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'package:tailor_made/models/main.dart';
import 'package:tailor_made/utils/tm_uuid.dart';

List<MeasureModel> createDefaultMeasures() {
return [
MeasureModel(name: 'Arm Hole', type: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder', type: MeasureModelType.blouse),
MeasureModel(name: 'Bust', type: MeasureModelType.blouse),
MeasureModel(name: 'Bust Point', type: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder - Bust Point', type: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder - Under Bust', type: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder - Waist', type: MeasureModelType.blouse),
MeasureModel(name: 'Length', type: MeasureModelType.trouser),
MeasureModel(name: 'Waist', type: MeasureModelType.trouser),
MeasureModel(name: 'Crouch', type: MeasureModelType.trouser),
MeasureModel(name: 'Thigh', type: MeasureModelType.trouser),
MeasureModel(name: 'Body Rise', type: MeasureModelType.trouser),
MeasureModel(name: 'Width', type: MeasureModelType.trouser),
MeasureModel(name: 'Hip', type: MeasureModelType.trouser),
MeasureModel(name: 'Full Length', type: MeasureModelType.skirts),
MeasureModel(name: 'Short Length', type: MeasureModelType.skirts),
MeasureModel(name: 'Knee Length', type: MeasureModelType.skirts),
MeasureModel(name: 'Hip', type: MeasureModelType.skirts),
MeasureModel(name: 'Waist', type: MeasureModelType.gown),
MeasureModel(name: 'Long Length', type: MeasureModelType.gown),
MeasureModel(name: 'Short Length', type: MeasureModelType.gown),
MeasureModel(name: 'Knee Length', type: MeasureModelType.gown),
MeasureModel(name: 'Arm Hole', group: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder', group: MeasureModelType.blouse),
MeasureModel(name: 'Bust', group: MeasureModelType.blouse),
MeasureModel(name: 'Bust Point', group: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder - Bust Point', group: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder - Under Bust', group: MeasureModelType.blouse),
MeasureModel(name: 'Shoulder - Waist', group: MeasureModelType.blouse),
MeasureModel(name: 'Length', group: MeasureModelType.trouser),
MeasureModel(name: 'Waist', group: MeasureModelType.trouser),
MeasureModel(name: 'Crouch', group: MeasureModelType.trouser),
MeasureModel(name: 'Thigh', group: MeasureModelType.trouser),
MeasureModel(name: 'Body Rise', group: MeasureModelType.trouser),
MeasureModel(name: 'Width', group: MeasureModelType.trouser),
MeasureModel(name: 'Hip', group: MeasureModelType.trouser),
MeasureModel(name: 'Full Length', group: MeasureModelType.skirts),
MeasureModel(name: 'Short Length', group: MeasureModelType.skirts),
MeasureModel(name: 'Knee Length', group: MeasureModelType.skirts),
MeasureModel(name: 'Hip', group: MeasureModelType.skirts),
MeasureModel(name: 'Waist', group: MeasureModelType.gown),
MeasureModel(name: 'Long Length', group: MeasureModelType.gown),
MeasureModel(name: 'Short Length', group: MeasureModelType.gown),
MeasureModel(name: 'Knee Length', group: MeasureModelType.gown),
];
}

Expand All @@ -36,35 +38,47 @@ class MeasureModelType {
}

class MeasureModel extends Model {
String id;
String name;
// TODO only for UI purposes
double value;
String unit;
String type;
String group;
DateTime createdAt;

MeasureModel({
String id,
@required this.name,
this.value = 0.0,
this.unit = 'In',
@required this.type,
});
DateTime createdAt,
@required this.group,
}) : id = id ?? uuid(),
createdAt = createdAt ?? DateTime.now();

factory MeasureModel.fromJson(Map<String, dynamic> json) {
assert(json != null);
return new MeasureModel(
id: json['id'],
name: json['name'],
value: double.tryParse(json['value'].toString()),
unit: json['unit'],
type: json['type'],
group: json['group'],
createdAt: DateTime.tryParse(json['createdAt'].toString()),
);
}

factory MeasureModel.fromDoc(DocumentSnapshot doc) {
return MeasureModel.fromJson(doc.data)..reference = doc.reference;
}

@override
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'name': name,
'value': value,
'unit': unit,
'type': type,
'group': group,
'createdAt': createdAt.toString(),
};
}
}
Loading

0 comments on commit 308ca5e

Please sign in to comment.