diff --git a/.gitignore b/.gitignore
index 8104aa3d..1a76ca18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,7 @@ doc/api/
.atom/
.dart_tool/
.idea
-.vscode/
ios/.generated/
packages
.flutter-plugins
+.log
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..5743ee0d
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [{
+ "name": "Flutter",
+ "type": "dart",
+ "request": "launch",
+ "args": [
+ "--flavor=development"
+ ],
+ "program": "lib/main.dart"
+ }]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..79ecc5ae
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+ "editor.codeActionsOnSave": {
+ "source.organizeImports": true
+ }
+}
diff --git a/README.md b/README.md
index 41350144..a590bb86 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,24 @@
+
+
# TailorMade
-A Flutter experiment.
+A Flutter experiment for managing a Fashion designer's daily routine. Logo, Design & Concept by Me.
+
+> Android-only support
+
+## Tools
-## UI Shots (so far)
+1. Firebase Auth
+2. Firebase Cloud Firestore
+3. Firebase Cloud Functions
+4. Firebase Storage
+5. RxDart
+6. Redux
+7. Redux Epics
+
+For a full description of OSS used, see pubspec.yaml
+
+## UI Shots
@@ -64,6 +80,15 @@ A Flutter experiment.
|
+
+
+ |
+
+
+ |
+
+
+ |
diff --git a/TASKS.todo b/TASKS.todo
index 0fce0b47..c6999ed5 100644
--- a/TASKS.todo
+++ b/TASKS.todo
@@ -1,8 +1,9 @@
PENDING:
+☐ remodel w/ authID
☐ delete-able payment
☐ delete-able images
☐ implement share payment + image
-
+☐ filter + search jobs & contacts
COMPLETED:
✔ update stats db on creation @high @done(18-07-10 16:39)
diff --git a/android/.gitignore b/android/.gitignore
index 65b7315a..07242eed 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -8,3 +8,4 @@
/build
/captures
GeneratedPluginRegistrant.java
+google-services.json
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 3d1f343e..616ad25d 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,6 +37,19 @@ android {
signingConfig signingConfigs.debug
}
}
+
+ flavorDimensions "flavor-type"
+
+ productFlavors {
+ development {
+ dimension "flavor-type"
+ applicationIdSuffix ".dev"
+ versionNameSuffix "-dev"
+ }
+ production {
+ dimension "flavor-type"
+ }
+ }
}
flutter {
diff --git a/android/app/google-services.json b/android/app/google-services.json
deleted file mode 100644
index 063908f6..00000000
--- a/android/app/google-services.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "project_info": {
- "project_number": "411406804353",
- "firebase_url": "https://tailor-made-2018.firebaseio.com",
- "project_id": "tailor-made-2018",
- "storage_bucket": "tailor-made-2018.appspot.com"
- },
- "client": [
- {
- "client_info": {
- "mobilesdk_app_id": "1:411406804353:android:bb6c31c0382b00e8",
- "android_client_info": {
- "package_name": "io.github.jogboms.tailormade"
- }
- },
- "oauth_client": [
- {
- "client_id": "411406804353-m2renekg4a6e86opvlotdr1jj4lojvc8.apps.googleusercontent.com",
- "client_type": 3
- }
- ],
- "api_key": [
- {
- "current_key": "AIzaSyCMpRzd1u83akc6kvCza0rBjsxFmUkf7TI"
- }
- ],
- "services": {
- "analytics_service": {
- "status": 1
- },
- "appinvite_service": {
- "status": 1,
- "other_platform_oauth_client": []
- },
- "ads_service": {
- "status": 2
- }
- }
- }
- ],
- "configuration_version": "1"
-}
\ No newline at end of file
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/development/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-hdpi/ic_launcher.png
rename to android/app/src/development/res/mipmap-hdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/development/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-mdpi/ic_launcher.png
rename to android/app/src/development/res/mipmap-mdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/development/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
rename to android/app/src/development/res/mipmap-xhdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/development/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
rename to android/app/src/development/res/mipmap-xxhdpi/ic_launcher.png
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/development/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
rename to android/app/src/development/res/mipmap-xxxhdpi/ic_launcher.png
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml
index 304732f8..0622e1d0 100644
--- a/android/app/src/main/res/drawable/launch_background.xml
+++ b/android/app/src/main/res/drawable/launch_background.xml
@@ -1,12 +1,10 @@
-
-
+
+
+
-
-
+ -
+
+
diff --git a/android/app/src/main/res/mipmap-hdpi/logo.png b/android/app/src/main/res/mipmap-hdpi/logo.png
new file mode 100755
index 00000000..eb7120e4
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/logo.png differ
diff --git a/android/app/src/main/res/mipmap-hdpi/pattern.png b/android/app/src/main/res/mipmap-hdpi/pattern.png
new file mode 100755
index 00000000..7b6ce24e
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/pattern.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/logo.png b/android/app/src/main/res/mipmap-mdpi/logo.png
new file mode 100755
index 00000000..e86d7df7
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/logo.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/pattern.png b/android/app/src/main/res/mipmap-mdpi/pattern.png
new file mode 100755
index 00000000..25fc8c7e
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/pattern.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/logo.png b/android/app/src/main/res/mipmap-xhdpi/logo.png
new file mode 100755
index 00000000..ad08d89c
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/logo.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/pattern.png b/android/app/src/main/res/mipmap-xhdpi/pattern.png
new file mode 100755
index 00000000..a663a60e
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/pattern.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/logo.png b/android/app/src/main/res/mipmap-xxhdpi/logo.png
new file mode 100755
index 00000000..ff71de7a
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/logo.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/pattern.png b/android/app/src/main/res/mipmap-xxhdpi/pattern.png
new file mode 100755
index 00000000..77456c04
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/pattern.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/logo.png b/android/app/src/main/res/mipmap-xxxhdpi/logo.png
new file mode 100755
index 00000000..0cd9c64b
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/logo.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/pattern.png b/android/app/src/main/res/mipmap-xxxhdpi/pattern.png
new file mode 100755
index 00000000..f62771f3
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/pattern.png differ
diff --git a/android/app/src/production/res/mipmap-hdpi/ic_launcher.png b/android/app/src/production/res/mipmap-hdpi/ic_launcher.png
new file mode 100755
index 00000000..cee7958b
Binary files /dev/null and b/android/app/src/production/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/production/res/mipmap-mdpi/ic_launcher.png b/android/app/src/production/res/mipmap-mdpi/ic_launcher.png
new file mode 100755
index 00000000..4b8ba76e
Binary files /dev/null and b/android/app/src/production/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/production/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/production/res/mipmap-xhdpi/ic_launcher.png
new file mode 100755
index 00000000..583ff5e1
Binary files /dev/null and b/android/app/src/production/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/production/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/production/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100755
index 00000000..8960b9ff
Binary files /dev/null and b/android/app/src/production/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/production/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/production/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100755
index 00000000..a2c0fca8
Binary files /dev/null and b/android/app/src/production/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/assets/images/2.0x/google_logo.png b/assets/images/2.0x/google_logo.png
new file mode 100755
index 00000000..a1a565e4
Binary files /dev/null and b/assets/images/2.0x/google_logo.png differ
diff --git a/assets/images/2.0x/logo.png b/assets/images/2.0x/logo.png
new file mode 100755
index 00000000..ad08d89c
Binary files /dev/null and b/assets/images/2.0x/logo.png differ
diff --git a/assets/images/2.0x/pattern.png b/assets/images/2.0x/pattern.png
new file mode 100755
index 00000000..a663a60e
Binary files /dev/null and b/assets/images/2.0x/pattern.png differ
diff --git a/assets/images/3.0x/google_logo.png b/assets/images/3.0x/google_logo.png
new file mode 100755
index 00000000..891fdb33
Binary files /dev/null and b/assets/images/3.0x/google_logo.png differ
diff --git a/assets/images/3.0x/logo.png b/assets/images/3.0x/logo.png
new file mode 100755
index 00000000..ff71de7a
Binary files /dev/null and b/assets/images/3.0x/logo.png differ
diff --git a/assets/images/3.0x/pattern.png b/assets/images/3.0x/pattern.png
new file mode 100755
index 00000000..77456c04
Binary files /dev/null and b/assets/images/3.0x/pattern.png differ
diff --git a/assets/images/google_logo.png b/assets/images/google_logo.png
new file mode 100755
index 00000000..0569d132
Binary files /dev/null and b/assets/images/google_logo.png differ
diff --git a/assets/images/logo.png b/assets/images/logo.png
new file mode 100755
index 00000000..e86d7df7
Binary files /dev/null and b/assets/images/logo.png differ
diff --git a/assets/images/pattern.png b/assets/images/pattern.png
new file mode 100755
index 00000000..25fc8c7e
Binary files /dev/null and b/assets/images/pattern.png differ
diff --git a/functions/functions/src/fn/auth.ts b/functions/functions/src/fn/auth.ts
new file mode 100644
index 00000000..0395d7d3
--- /dev/null
+++ b/functions/functions/src/fn/auth.ts
@@ -0,0 +1,52 @@
+import { firestore as Firestore } from "firebase-admin";
+import { auth, EventContext } from "firebase-functions";
+import { ChangeState } from "../utils";
+
+export function _onAuth(onCreate: ChangeState) {
+ return async (user: auth.UserRecord, context: EventContext) => {
+ const db = Firestore();
+ const batch = db.batch();
+
+ const account = db.collection("accounts").doc(user.uid);
+ batch.set(account, {
+ storeName: user.displayName,
+ uid: user.uid,
+ email: user.email,
+ displayName: user.displayName,
+ phoneNumber: user.phoneNumber,
+ photoURL: user.photoURL
+ });
+
+ const stats = db.collection("stats").doc(user.uid);
+ batch.set(stats, {
+ contacts: {
+ total: 0
+ },
+ gallery: {
+ total: 0
+ },
+ jobs: {
+ total: 0,
+ pending: 0,
+ completed: 0
+ },
+ payments: {
+ total: 0,
+ pending: 0,
+ completed: 0
+ }
+ });
+
+ // Commit the batch
+ return batch.commit();
+ };
+}
+
+export function onAuthCreate(onCreate: ChangeState) {
+ const store = auth.user();
+
+ // return onCreate == ChangeState.Create
+ // ? store.onCreate(_onAuth(onCreate))
+ // : store.onDelete(_onAuth(onCreate));
+ return store.onCreate(_onAuth(onCreate));
+}
diff --git a/functions/functions/src/fn/stats_contacts.ts b/functions/functions/src/fn/stats_contacts.ts
index b9260523..e885744c 100644
--- a/functions/functions/src/fn/stats_contacts.ts
+++ b/functions/functions/src/fn/stats_contacts.ts
@@ -1,15 +1,16 @@
import { firestore as Firestore } from "firebase-admin";
import { EventContext, firestore } from "firebase-functions";
import { isArray } from "util";
+import { ChangeState } from "../utils";
-export function _onStatsContacts(onCreate: boolean) {
+export function _onStatsContacts(onCreate: ChangeState) {
return async (
snapshot: firestore.DocumentSnapshot,
context: EventContext
) => {
const db = Firestore();
- const stats = db.doc("stats/current");
const contact = snapshot.data();
+ const stats = db.doc(`stats/${contact.userID}`);
const statsSnap = await stats.get();
@@ -25,10 +26,10 @@ export function _onStatsContacts(onCreate: boolean) {
};
}
-export function onStatsContacts(onCreate = true) {
+export function onStatsContacts(onCreate: ChangeState) {
const store = firestore.document("contacts/{contactId}");
- return onCreate
+ return onCreate === ChangeState.Created
? store.onCreate(_onStatsContacts(onCreate))
: store.onDelete(_onStatsContacts(onCreate));
}
diff --git a/functions/functions/src/fn/stats_jobs.ts b/functions/functions/src/fn/stats_jobs.ts
index cffba8bc..6c02ee36 100644
--- a/functions/functions/src/fn/stats_jobs.ts
+++ b/functions/functions/src/fn/stats_jobs.ts
@@ -1,14 +1,35 @@
import * as admin from "firebase-admin";
import { Change, EventContext, firestore } from "firebase-functions";
+import { isArray } from "util";
+import { ChangeState } from "../utils";
-async function _onStatsJob(
+// TODO
+// Maybe not the best way to go about this
+async function _onStatsJobUpdate(
change: Change,
context: EventContext
+) {
+ const jobs = change.before.exists ? change.before : change.after;
+
+ return _onStatsJob(jobs, context);
+}
+
+async function _onStatsJob(
+ snapshot: firestore.DocumentSnapshot,
+ context: EventContext
) {
const db = admin.firestore();
- const stats = db.doc("stats/current");
+ const _data = snapshot.data();
+
+ // Get user ID from Job
+ const userID = isArray(_data) ? _data[0].userID : _data.userID;
+
+ const stats = db.doc(`stats/${userID}`);
- const jobsSnap = await db.collection("jobs").get();
+ const jobsSnap = await db
+ .collection("jobs")
+ .where("userID", "==", userID)
+ .get();
let completedJob = 0,
pendingJob = 0,
@@ -46,6 +67,14 @@ async function _onStatsJob(
});
}
-export const onStatsJob = firestore
- .document("jobs/{jobId}")
- .onWrite(_onStatsJob);
+export function onStatsJob(change: ChangeState) {
+ const store = firestore.document("jobs/{jobId}");
+
+ if (change === ChangeState.Created) {
+ return store.onCreate(_onStatsJob);
+ } else if (change === ChangeState.Updated) {
+ return store.onUpdate(_onStatsJobUpdate);
+ } else {
+ return store.onDelete(_onStatsJob);
+ }
+}
diff --git a/functions/functions/src/index.ts b/functions/functions/src/index.ts
index 3e729352..49c9f2ce 100644
--- a/functions/functions/src/index.ts
+++ b/functions/functions/src/index.ts
@@ -1,21 +1,29 @@
import { initializeApp } from "firebase-admin";
import { config } from "firebase-functions";
+import { onAuthCreate } from "./fn/auth";
import { onContactStats } from "./fn/contact_stats";
import { onJobPayments } from "./fn/job_payments";
import { onPaymentGallery } from "./fn/payment_gallery";
import { onStatsContacts } from "./fn/stats_contacts";
import { onStatsJob } from "./fn/stats_jobs";
+import { ChangeState } from "./utils";
initializeApp(config().firebase);
+export const AuthCreate = onAuthCreate(ChangeState.Created);
+
export const PaymentGallery = onPaymentGallery;
export const JobPayments = onJobPayments;
-export const StatsJobs = onStatsJob;
+export const StatsJobsCreate = onStatsJob(ChangeState.Created);
+
+export const StatsJobsUpdate = onStatsJob(ChangeState.Updated);
+
+export const StatsJobsDelete = onStatsJob(ChangeState.Deleted);
-export const StatsContactsCreate = onStatsContacts();
+export const StatsContactsCreate = onStatsContacts(ChangeState.Created);
-export const StatsContactsDelete = onStatsContacts(false);
+export const StatsContactsDelete = onStatsContacts(ChangeState.Deleted);
export const ContactStats = onContactStats;
diff --git a/functions/functions/src/utils.ts b/functions/functions/src/utils.ts
new file mode 100644
index 00000000..fdee0c24
--- /dev/null
+++ b/functions/functions/src/utils.ts
@@ -0,0 +1,5 @@
+export enum ChangeState {
+ Created,
+ Updated,
+ Deleted
+}
diff --git a/lib/main.dart b/lib/main.dart
index 793360f5..31bf05b3 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,9 +1,8 @@
-import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
-import 'package:tailor_made/pages/homepage/homepage.dart';
-import 'package:tailor_made/redux/actions/main.dart';
+import 'package:tailor_made/pages/splash/splash.dart';
import 'package:tailor_made/redux/main.dart';
import 'package:tailor_made/redux/states/main.dart';
import 'package:tailor_made/utils/tm_fonts.dart';
@@ -12,10 +11,7 @@ import 'package:tailor_made/utils/tm_strings.dart';
import 'package:tailor_made/utils/tm_theme.dart';
void main() {
- FirebaseAuth.instance.signInAnonymously().then((r) {
- print(r);
- });
-
+ SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
return runApp(new TMApp());
}
@@ -30,25 +26,16 @@ class TMApp extends StatelessWidget {
debugShowCheckedModeBanner: false,
title: TMStrings.appName,
theme: new ThemeData(
- accentColor: accentColor,
- primarySwatch: primarySwatch,
+ accentColor: kAccentColor,
+ primarySwatch: kPrimarySwatch,
fontFamily: TMFonts.raleway,
),
onGenerateRoute: (RouteSettings settings) {
return new TMNavigateRoute(
- builder: (_) => TMTheme(
- child: new StoreBuilder(
- onInit: (store) => store.dispatch(new InitDataEvents()),
- onDispose: (store) => store.dispatch(new DisposeDataEvents()),
- builder: (BuildContext context, store) {
- return HomePage();
- },
- ),
- ),
+ builder: (_) => TMTheme(child: SplashPage(isColdStart: true)),
settings: settings,
);
},
- // home: TMTheme(child: HomePage()),
),
);
}
diff --git a/lib/models/account.dart b/lib/models/account.dart
new file mode 100644
index 00000000..9de0a394
--- /dev/null
+++ b/lib/models/account.dart
@@ -0,0 +1,48 @@
+import 'package:cloud_firestore/cloud_firestore.dart';
+import 'package:flutter/foundation.dart';
+import 'package:tailor_made/models/main.dart';
+
+class AccountModel extends Model {
+ String uid;
+ String storeName;
+ String email;
+ String displayName;
+ int phoneNumber;
+ String photoURL;
+
+ AccountModel({
+ @required this.uid,
+ @required this.storeName,
+ @required this.email,
+ @required this.displayName,
+ @required this.phoneNumber,
+ @required this.photoURL,
+ });
+
+ factory AccountModel.fromJson(Map json) {
+ assert(json != null);
+ return new AccountModel(
+ uid: json['uid'],
+ storeName: json['storeName'],
+ email: json['email'],
+ displayName: json['displayName'],
+ phoneNumber: int.tryParse(json['phoneNumber'].toString()),
+ photoURL: json['photoURL'],
+ );
+ }
+
+ factory AccountModel.fromDoc(DocumentSnapshot doc) {
+ return AccountModel.fromJson(doc.data)..reference = doc.reference;
+ }
+
+ toMap() {
+ return {
+ "uid": uid,
+ "storeName": storeName,
+ "email": email,
+ "displayName": displayName,
+ "phoneNumber": phoneNumber,
+ "photoURL": photoURL,
+ };
+ }
+}
diff --git a/lib/models/contact.dart b/lib/models/contact.dart
index b763e6fa..0572a6c0 100644
--- a/lib/models/contact.dart
+++ b/lib/models/contact.dart
@@ -1,10 +1,12 @@
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';
class ContactModel extends Model {
String id;
+ String userID;
String fullname;
String phone;
String location;
@@ -16,6 +18,7 @@ class ContactModel extends Model {
ContactModel({
String id,
+ String userID,
this.fullname,
this.phone,
this.location,
@@ -26,6 +29,7 @@ class ContactModel extends Model {
this.pendingJobs = 0,
}) : id = id ?? uuid(),
createdAt = createdAt ?? DateTime.now(),
+ userID = userID ?? Auth.getUser.uid,
measurements = measurements != null && measurements.isNotEmpty ? measurements : createDefaultMeasures();
factory ContactModel.fromJson(Map json) {
@@ -38,6 +42,7 @@ class ContactModel extends Model {
}
return new ContactModel(
id: json['id'],
+ userID: json['userID'],
fullname: json['fullname'],
phone: json['phone'],
location: json['location'],
@@ -56,6 +61,7 @@ class ContactModel extends Model {
toMap() {
return {
"id": id,
+ "userID": userID,
"fullname": fullname,
"phone": phone,
"location": location,
diff --git a/lib/models/image.dart b/lib/models/image.dart
index 41fc3a0c..7edc6dc5 100644
--- a/lib/models/image.dart
+++ b/lib/models/image.dart
@@ -1,9 +1,11 @@
import 'package:flutter/foundation.dart';
import 'package:tailor_made/models/main.dart';
+import 'package:tailor_made/services/auth.dart';
import 'package:tailor_made/utils/tm_uuid.dart';
class ImageModel extends Model {
String id;
+ String userID;
String contactID;
String jobID;
String path;
@@ -11,19 +13,22 @@ class ImageModel extends Model {
DateTime createdAt;
ImageModel({
- id,
+ String id,
+ String userID,
@required this.contactID,
@required this.jobID,
@required this.path,
@required this.src,
- createdAt,
+ DateTime createdAt,
}) : id = id ?? uuid(),
+ userID = userID ?? Auth.getUser.uid,
createdAt = createdAt ?? DateTime.now();
factory ImageModel.fromJson(Map json) {
assert(json != null);
return new ImageModel(
id: json['id'],
+ userID: json['userID'],
contactID: json['contactID'],
jobID: json['jobID'],
path: json['path'],
@@ -36,6 +41,7 @@ class ImageModel extends Model {
toMap() {
return {
"id": id,
+ "userID": userID,
"contactID": contactID,
"jobID": jobID,
"path": path,
diff --git a/lib/models/job.dart b/lib/models/job.dart
index e963a56c..f482790c 100644
--- a/lib/models/job.dart
+++ b/lib/models/job.dart
@@ -4,10 +4,12 @@ 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';
class JobModel extends Model {
String id;
+ String userID;
String contactID;
String name;
double price;
@@ -21,7 +23,8 @@ class JobModel extends Model {
DateTime createdAt;
JobModel({
- id,
+ String id,
+ String userID,
@required this.contactID,
this.name,
this.price,
@@ -32,8 +35,9 @@ class JobModel extends Model {
this.measurements = const [],
this.payments = const [],
this.isComplete = false,
- createdAt,
+ DateTime createdAt,
}) : id = id ?? uuid(),
+ userID = userID ?? Auth.getUser.uid,
createdAt = createdAt ?? DateTime.now();
factory JobModel.fromJson(Map json) {
@@ -58,6 +62,7 @@ class JobModel extends Model {
}
return new JobModel(
id: json['id'],
+ userID: json['userID'],
contactID: json['contactID'],
name: json['name'],
price: double.tryParse(json['price'].toString()),
@@ -80,6 +85,7 @@ class JobModel extends Model {
toMap() {
return {
"id": id,
+ "userID": userID,
"contactID": contactID,
"name": name,
"price": price,
diff --git a/lib/models/payment.dart b/lib/models/payment.dart
index 245c318c..884c94ba 100644
--- a/lib/models/payment.dart
+++ b/lib/models/payment.dart
@@ -1,9 +1,11 @@
import 'package:flutter/foundation.dart';
import 'package:tailor_made/models/main.dart';
+import 'package:tailor_made/services/auth.dart';
import 'package:tailor_made/utils/tm_uuid.dart';
class PaymentModel extends Model {
String id;
+ String userID;
String contactID;
String jobID;
double price;
@@ -11,19 +13,22 @@ class PaymentModel extends Model {
DateTime createdAt;
PaymentModel({
- id,
+ String id,
+ String userID,
@required this.contactID,
@required this.jobID,
@required this.price,
@required this.notes,
- createdAt,
+ DateTime createdAt,
}) : id = id ?? uuid(),
+ userID = userID ?? Auth.getUser.uid,
createdAt = createdAt ?? DateTime.now();
factory PaymentModel.fromJson(Map json) {
assert(json != null);
return new PaymentModel(
id: json['id'],
+ userID: json['userID'],
contactID: json['contactID'],
jobID: json['jobID'],
price: double.tryParse(json['price'].toString()),
@@ -36,6 +41,7 @@ class PaymentModel extends Model {
toMap() {
return {
"id": id,
+ "userID": userID,
"contactID": contactID,
"jobID": jobID,
"price": price,
diff --git a/lib/models/stats.dart b/lib/models/stats.dart
index b0160f27..4d336921 100644
--- a/lib/models/stats.dart
+++ b/lib/models/stats.dart
@@ -24,6 +24,26 @@ class PaymentStatsModel {
}
}
+// KEEP
+// {
+// "contacts": {
+// "total": 0
+// },
+// "gallery": {
+// "total": 0
+// },
+// "jobs": {
+// "total": 0,
+// "pending": 0,
+// "completed": 0,
+// },
+// "payments": {
+// "total": 0,
+// "pending": 0,
+// "completed": 0,
+// },
+// }
+
class StatsModel {
DetailStatsModel jobs;
DetailStatsModel contacts;
diff --git a/lib/pages/contacts/contact.dart b/lib/pages/contacts/contact.dart
index bddf056f..03b4951d 100644
--- a/lib/pages/contacts/contact.dart
+++ b/lib/pages/contacts/contact.dart
@@ -39,12 +39,13 @@ class _ContactState extends State {
new SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
child: new SliverAppBar(
- backgroundColor: accentColor,
+ backgroundColor: kAccentColor,
automaticallyImplyLeading: false,
title: new ContactAppBar(contact: widget.contact),
pinned: true,
titleSpacing: 0.0,
centerTitle: false,
+ brightness: Brightness.dark,
expandedHeight: 0.0,
forceElevated: true,
bottom: tabTitles(),
diff --git a/lib/pages/contacts/contacts_create.dart b/lib/pages/contacts/contacts_create.dart
index dbc1bae0..30547ac4 100644
--- a/lib/pages/contacts/contacts_create.dart
+++ b/lib/pages/contacts/contacts_create.dart
@@ -44,7 +44,7 @@ class _ContactsCreatePageState extends State with SnackBarPr
IconButton(
icon: Icon(
Icons.content_cut,
- color: titleBaseColor,
+ color: kTitleBaseColor,
),
onPressed: () => TMNavigate(
context,
diff --git a/lib/pages/contacts/ui/contact_appbar.dart b/lib/pages/contacts/ui/contact_appbar.dart
index aa25f0d6..4ef25b72 100644
--- a/lib/pages/contacts/ui/contact_appbar.dart
+++ b/lib/pages/contacts/ui/contact_appbar.dart
@@ -157,30 +157,18 @@ class ContactAppBarState extends State {
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
- fontWeight: FontWeight.w500,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ Text(
+ widget.contact.location,
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ style: TextStyle(
+ fontSize: 13.0,
+ color: Colors.white,
),
),
- isAtTop || (widget.contact.pendingJobs < 1)
- ? Container()
- : Text.rich(
- TextSpan(
- children: [
- TextSpan(
- text: widget.contact.pendingJobs.toString(),
- style: TextStyle(fontWeight: FontWeight.w600),
- ),
- TextSpan(
- text: " pending",
- ),
- ],
- ),
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- fontSize: 13.0,
- color: Colors.white,
- ),
- ),
],
);
}
@@ -192,7 +180,6 @@ class ContactAppBarState extends State {
child: new Icon(icon, color: Colors.white),
onTap: onTap,
radius: 20.0,
- splashColor: accentColor.withOpacity(.25),
),
);
}
diff --git a/lib/pages/contacts/ui/contact_form.dart b/lib/pages/contacts/ui/contact_form.dart
index c15673b7..b6f7acf4 100644
--- a/lib/pages/contacts/ui/contact_form.dart
+++ b/lib/pages/contacts/ui/contact_form.dart
@@ -103,7 +103,7 @@ class ContactFormState extends State with SnackBarProvider {
),
SizedBox(height: 32.0),
RaisedButton(
- color: accentColor,
+ color: kAccentColor,
shape: StadiumBorder(),
onPressed: _handleSubmit,
child: Text(
@@ -125,12 +125,12 @@ class ContactFormState extends State with SnackBarProvider {
padding: EdgeInsets.all(4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
- border: Border.all(color: primarySwatch.withOpacity(.5), width: 2.0),
+ border: Border.all(color: kPrimarySwatch.shade200, width: 2.0),
),
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
- color: primarySwatch.withOpacity(.2),
+ color: kPrimarySwatch.shade100,
),
child: Center(
child: GestureDetector(
@@ -143,7 +143,7 @@ class ContactFormState extends State with SnackBarProvider {
contact.imageUrl != null
? CircleAvatar(
backgroundImage: NetworkImage(contact.imageUrl),
- backgroundColor: primarySwatch.withOpacity(.2),
+ backgroundColor: kPrimarySwatch.shade100,
)
: SizedBox(),
isLoading
diff --git a/lib/pages/contacts/ui/contact_measure.dart b/lib/pages/contacts/ui/contact_measure.dart
index 1aa126f6..1b23cd4b 100644
--- a/lib/pages/contacts/ui/contact_measure.dart
+++ b/lib/pages/contacts/ui/contact_measure.dart
@@ -35,7 +35,7 @@ class _ContactMeasureState extends State with SnackBarProvider {
children.add(
Padding(
child: RaisedButton(
- color: accentColor,
+ color: kAccentColor,
shape: StadiumBorder(),
child: Text(
"FINISH",
@@ -59,7 +59,7 @@ class _ContactMeasureState extends State with SnackBarProvider {
IconButton(
icon: Icon(
Icons.remove_red_eye,
- color: titleBaseColor,
+ color: kTitleBaseColor,
),
onPressed: () => TMNavigate(
context,
@@ -95,8 +95,8 @@ class _ContactMeasureState extends State with SnackBarProvider {
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- Text(title.toUpperCase(), style: ralewayLight(12.0, textBaseColor.shade800)),
- Text(trailing, style: ralewayLight(12.0, textBaseColor.shade800)),
+ Text(title.toUpperCase(), style: ralewayLight(12.0, kTextBaseColor.shade800)),
+ Text(trailing, style: ralewayLight(12.0, kTextBaseColor.shade800)),
],
),
);
diff --git a/lib/pages/contacts/ui/contacts_list_item.dart b/lib/pages/contacts/ui/contacts_list_item.dart
index 649c06d6..4d6a5684 100644
--- a/lib/pages/contacts/ui/contacts_list_item.dart
+++ b/lib/pages/contacts/ui/contacts_list_item.dart
@@ -34,7 +34,7 @@ class ContactsListItem extends StatelessWidget {
tag: contact.id,
child: new CircleAvatar(
radius: 24.0,
- backgroundColor: theme.accentColor.withOpacity(.5),
+ backgroundColor: theme.primaryColor,
backgroundImage: contact.imageUrl != null ? CachedNetworkImageProvider(contact.imageUrl) : null,
child: Stack(
children: [
@@ -45,7 +45,7 @@ class ContactsListItem extends StatelessWidget {
width: 15.5,
height: 15.5,
decoration: new BoxDecoration(
- color: accentColor,
+ color: theme.accentColor,
border: Border.all(
color: Colors.white,
style: BorderStyle.solid,
@@ -93,7 +93,7 @@ class ContactsListItem extends StatelessWidget {
onTap: onTapContact ?? () => TMNavigate(context, ContactPage(contact: contact)),
leading: avatar(),
title: title,
- subtitle: Text(pending >= 1 ? "$pending pending" : "No pending wears", style: TextStyle(fontSize: 14.0, color: textBaseColor)),
+ subtitle: Text(pending >= 1 ? "$pending pending" : "No pending wears", style: TextStyle(fontSize: 14.0, color: kTextBaseColor)),
trailing: showActions ? icons : null,
);
}
diff --git a/lib/pages/gallery/gallery.dart b/lib/pages/gallery/gallery.dart
index 0262f926..ebd0d1bb 100644
--- a/lib/pages/gallery/gallery.dart
+++ b/lib/pages/gallery/gallery.dart
@@ -50,7 +50,7 @@ class GalleryPageState extends State {
"${images.length} Photos",
style: TextStyle(
fontSize: 11.0,
- color: textBaseColor,
+ color: kTextBaseColor,
),
)
: SizedBox(),
diff --git a/lib/pages/homepage/homepage.dart b/lib/pages/homepage/homepage.dart
index 457b7d4c..60e3f08b 100644
--- a/lib/pages/homepage/homepage.dart
+++ b/lib/pages/homepage/homepage.dart
@@ -10,12 +10,15 @@ import 'package:tailor_made/pages/homepage/ui/helpers.dart';
import 'package:tailor_made/pages/homepage/ui/stats.dart';
import 'package:tailor_made/pages/homepage/ui/top_row.dart';
import 'package:tailor_made/pages/jobs/jobs_create.dart';
+import 'package:tailor_made/pages/splash/splash.dart';
import 'package:tailor_made/redux/actions/main.dart';
import 'package:tailor_made/redux/states/main.dart';
import 'package:tailor_made/redux/view_models/contacts.dart';
+import 'package:tailor_made/services/auth.dart';
import 'package:tailor_made/services/cloudstore.dart';
import 'package:tailor_made/ui/tm_loading_spinner.dart';
import 'package:tailor_made/utils/tm_colors.dart';
+import 'package:tailor_made/utils/tm_images.dart';
import 'package:tailor_made/utils/tm_navigate.dart';
import 'package:tailor_made/utils/tm_theme.dart';
@@ -56,113 +59,146 @@ class _HomePageState extends State with SingleTickerProviderStateMixin
Widget build(BuildContext context) {
final TMTheme theme = TMTheme.of(context);
- onTapCreate(List contacts) {
- return () async {
- CreateOptions result = await showDialog(
- context: context,
- builder: (BuildContext context) {
- return new SimpleDialog(
- title: const Text('Select action', style: const TextStyle(fontSize: 14.0)),
- children: [
- new SimpleDialogOption(
- onPressed: () {
- Navigator.pop(context, CreateOptions.clients);
- },
- child: TMListTile(
- color: Colors.orangeAccent,
- icon: Icons.supervisor_account,
- title: "Clients",
- ),
- ),
- new SimpleDialogOption(
- onPressed: () {
- Navigator.pop(context, CreateOptions.jobs);
- },
- child: TMListTile(
- color: Colors.greenAccent.shade400,
- icon: Icons.attach_money,
- title: "Job",
- ),
- ),
- ],
- );
- },
- );
- switch (result) {
- case CreateOptions.clients:
- TMNavigate(context, ContactsCreatePage());
- break;
- case CreateOptions.jobs:
- TMNavigate(context, JobsCreatePage(contacts: contacts));
- break;
- }
- };
- }
-
return new Scaffold(
backgroundColor: theme.scaffoldColor,
- appBar: AppBar(
- elevation: 0.0,
- backgroundColor: theme.scaffoldColor,
- brightness: Brightness.light,
- // actions: [
- // new IconButton(
- // icon: new Icon(
- // Icons.person,
- // color: theme.appBarColor,
- // ),
- // onPressed: () => TMNavigate(context, AccountsPage()),
- // )
- // ],
- ),
- body: StreamBuilder(
- stream: Cloudstore.stats.snapshots(),
- builder: (context, snapshot) {
- if (!snapshot.hasData) {
- return Center(
- child: loadingSpinner(),
- );
- }
+ body: Stack(
+ fit: StackFit.expand,
+ children: [
+ Opacity(
+ opacity: .5,
+ child: DecoratedBox(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: TMImages.pattern,
+ fit: BoxFit.cover,
+ ),
+ ),
+ ),
+ ),
+ new StoreBuilder(
+ onInit: (store) => store.dispatch(new InitDataEvents()),
+ onDispose: (store) => store.dispatch(new DisposeDataEvents()),
+ builder: (BuildContext context, store) {
+ return StreamBuilder(
+ stream: Cloudstore.stats.snapshots(),
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) {
+ return Center(
+ child: loadingSpinner(),
+ );
+ }
- final DocumentSnapshot _data = snapshot.data;
- final stats = StatsModel.fromJson(_data.data);
+ final DocumentSnapshot _data = snapshot.data;
+ final stats = StatsModel.fromJson(_data.data);
- return new SafeArea(
- top: false,
- child: new Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- HeaderWidget(),
- StatsWidget(stats: stats),
- TopRowWidget(stats: stats),
- BottomRowWidget(stats: stats),
- new StoreConnector(
- converter: (store) => ContactsViewModel(store),
- onInit: (store) => store.dispatch(new InitDataEvents()),
- onDispose: (store) => store.dispatch(new DisposeDataEvents()),
- builder: (BuildContext context, ContactsViewModel vm) {
- return new FlatButton(
- shape: RoundedRectangleBorder(),
- padding: EdgeInsets.only(top: 16.0, bottom: 16.0),
- color: accentColor,
- child: ScaleTransition(
- scale: new Tween(begin: 0.95, end: 1.025).animate(controller),
- alignment: FractionalOffset.center,
- child: new Text(
- "TAP TO CREATE",
- style: ralewayBold(14.0, TMColors.white).copyWith(letterSpacing: 1.25),
- ),
- ),
- onPressed: onTapCreate(vm.contacts),
- );
- },
+ return new SafeArea(
+ top: false,
+ child: new Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Expanded(child: HeaderWidget()),
+ StatsWidget(stats: stats),
+ TopRowWidget(stats: stats),
+ BottomRowWidget(stats: stats),
+ _buildCreateBtn(),
+ ],
+ ),
+ );
+ },
+ );
+ },
+ ),
+ Align(
+ alignment: Alignment.topRight,
+ child: SafeArea(
+ child: IconButton(
+ icon: new Icon(
+ Icons.power_settings_new,
+ color: theme.appBarColor,
),
- ],
+ // onPressed: () => TMNavigate(context, AccountsPage()),
+ onPressed: () async {
+ await Auth.signOutWithGoogle();
+ Navigator.pushReplacement(
+ context,
+ TMNavigate.fadeIn(
+ new SplashPage(isColdStart: false),
+ ),
+ );
+ },
+ ),
),
- );
- },
+ ),
+ ],
),
);
}
+
+ StoreConnector _buildCreateBtn() {
+ return new StoreConnector(
+ converter: (store) => ContactsViewModel(store),
+ onInit: (store) => store.dispatch(new InitDataEvents()),
+ onDispose: (store) => store.dispatch(new DisposeDataEvents()),
+ builder: (BuildContext context, ContactsViewModel vm) {
+ return new FlatButton(
+ shape: RoundedRectangleBorder(),
+ padding: EdgeInsets.only(top: 16.0, bottom: 16.0),
+ color: kAccentColor,
+ child: ScaleTransition(
+ scale: new Tween(begin: 0.95, end: 1.025).animate(controller),
+ alignment: FractionalOffset.center,
+ child: new Text(
+ "TAP TO CREATE",
+ style: ralewayBold(14.0, TMColors.white).copyWith(letterSpacing: 1.25),
+ ),
+ ),
+ onPressed: onTapCreate(vm.contacts),
+ );
+ },
+ );
+ }
+
+ onTapCreate(List contacts) {
+ return () async {
+ CreateOptions result = await showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return new SimpleDialog(
+ title: const Text('Select action', style: const TextStyle(fontSize: 14.0)),
+ children: [
+ new SimpleDialogOption(
+ onPressed: () {
+ Navigator.pop(context, CreateOptions.clients);
+ },
+ child: TMListTile(
+ color: Colors.orangeAccent,
+ icon: Icons.supervisor_account,
+ title: "Clients",
+ ),
+ ),
+ new SimpleDialogOption(
+ onPressed: () {
+ Navigator.pop(context, CreateOptions.jobs);
+ },
+ child: TMListTile(
+ color: Colors.greenAccent.shade400,
+ icon: Icons.attach_money,
+ title: "Job",
+ ),
+ ),
+ ],
+ );
+ },
+ );
+ switch (result) {
+ case CreateOptions.clients:
+ TMNavigate(context, ContactsCreatePage());
+ break;
+ case CreateOptions.jobs:
+ TMNavigate(context, JobsCreatePage(contacts: contacts));
+ break;
+ }
+ };
+ }
}
diff --git a/lib/pages/homepage/ui/header.dart b/lib/pages/homepage/ui/header.dart
index eba592cc..6ff2918d 100644
--- a/lib/pages/homepage/ui/header.dart
+++ b/lib/pages/homepage/ui/header.dart
@@ -1,4 +1,7 @@
import 'package:flutter/material.dart';
+import 'package:tailor_made/models/account.dart';
+import 'package:tailor_made/services/cloudstore.dart';
+import 'package:tailor_made/ui/tm_loading_spinner.dart';
import 'package:tailor_made/utils/tm_format_date.dart';
import 'package:tailor_made/utils/tm_theme.dart';
@@ -7,51 +10,62 @@ class HeaderWidget extends StatelessWidget {
Widget build(BuildContext context) {
final TMTheme theme = TMTheme.of(context);
- return new Expanded(
- child: Container(
- padding: EdgeInsets.fromLTRB(20.0, 35.0, 20.0, 40.0),
- width: double.infinity,
- decoration: new BoxDecoration(
- border: new Border(
- bottom: TMBorderSide(),
+ return new StreamBuilder(
+ stream: Cloudstore.account.snapshots(),
+ builder: (BuildContext context, snapshot) {
+ if (!snapshot.hasData) {
+ return Center(
+ child: loadingSpinner(),
+ );
+ }
+
+ final account = AccountModel.fromDoc(snapshot.data);
+
+ return Container(
+ padding: EdgeInsets.fromLTRB(20.0, 35.0, 20.0, 40.0),
+ width: double.infinity,
+ decoration: new BoxDecoration(
+ border: new Border(
+ bottom: TMBorderSide(),
+ ),
),
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- new Text(
- "Hello",
- style: new TextStyle(
- color: theme.textColor,
- fontSize: 35.0,
- fontWeight: FontWeight.w200,
- letterSpacing: 2.5,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ new Text(
+ "Hello",
+ style: new TextStyle(
+ color: theme.textColor,
+ fontSize: 32.0,
+ fontWeight: FontWeight.w200,
+ letterSpacing: 2.5,
+ ),
),
- ),
- new Text(
- "Mikun Sews",
- style: new TextStyle(
- color: theme.textColor,
- fontSize: 50.0,
- fontWeight: FontWeight.w300,
- height: 1.05,
+ new Text(
+ account.displayName.split(" ").first,
+ style: new TextStyle(
+ color: theme.textColor,
+ fontSize: 52.0,
+ fontWeight: FontWeight.w300,
+ height: 1.15,
+ ),
+ maxLines: 1,
+ overflow: TextOverflow.fade,
+ softWrap: false,
),
- maxLines: 1,
- overflow: TextOverflow.fade,
- softWrap: false,
- ),
- new Text(
- formatDate(DateTime.now(), day: "EEEE", month: "MMMM"),
- style: new TextStyle(
- fontSize: 14.0,
- fontWeight: FontWeight.w300,
- height: 1.5,
+ new Text(
+ formatDate(DateTime.now(), day: "EEEE", month: "MMMM"),
+ style: new TextStyle(
+ fontSize: 14.0,
+ fontWeight: FontWeight.w300,
+ height: 1.75,
+ ),
),
- ),
- ],
- ),
- ),
+ ],
+ ),
+ );
+ },
);
}
}
diff --git a/lib/pages/homepage/ui/stats.dart b/lib/pages/homepage/ui/stats.dart
index e69d7887..83e8c11f 100644
--- a/lib/pages/homepage/ui/stats.dart
+++ b/lib/pages/homepage/ui/stats.dart
@@ -30,7 +30,7 @@ class StatsWidget extends StatelessWidget {
),
),
Container(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 1.0,
height: 40.0,
margin: EdgeInsets.only(left: 0.0, right: 0.0),
@@ -43,7 +43,7 @@ class StatsWidget extends StatelessWidget {
),
),
Container(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 1.0,
height: 40.0,
margin: EdgeInsets.only(left: 0.0, right: 0.0),
diff --git a/lib/pages/jobs/job.dart b/lib/pages/jobs/job.dart
index 067f839f..1b599c1a 100644
--- a/lib/pages/jobs/job.dart
+++ b/lib/pages/jobs/job.dart
@@ -46,19 +46,19 @@ class JobPageState extends State with SnackBarProvider {
Widget build(BuildContext context) {
final TMTheme theme = TMTheme.of(context);
- return new Scaffold(
- key: scaffoldKey,
- backgroundColor: theme.scaffoldColor,
- body: new StreamBuilder(
- stream: job.reference.snapshots(),
- builder: (BuildContext context, snapshot) {
- if (!snapshot.hasData) {
- return Center(
- child: loadingSpinner(),
- );
- }
- job = JobModel.fromDoc(snapshot.data);
- return new NestedScrollView(
+ return new StreamBuilder(
+ stream: job.reference.snapshots(),
+ builder: (BuildContext context, snapshot) {
+ if (!snapshot.hasData) {
+ return Center(
+ child: loadingSpinner(),
+ );
+ }
+ job = JobModel.fromDoc(snapshot.data);
+ return new Scaffold(
+ key: scaffoldKey,
+ backgroundColor: theme.scaffoldColor,
+ body: new NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
@@ -88,13 +88,24 @@ class JobPageState extends State with SnackBarProvider {
GalleryGrids(job: job),
const SizedBox(height: 4.0),
PaymentGrids(job: job),
+ const SizedBox(height: 32.0),
],
),
),
),
- );
- },
- ),
+ ),
+ floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
+ floatingActionButton: FloatingActionButton.extended(
+ icon: new Icon(
+ job.isComplete ? Icons.undo : Icons.check,
+ ),
+ backgroundColor: job.isComplete ? Colors.white : kAccentColor,
+ foregroundColor: job.isComplete ? kAccentColor : Colors.white,
+ label: Text(job.isComplete ? "Undo Completed" : "Mark Completed"),
+ onPressed: onTapComplete,
+ ),
+ );
+ },
);
}
@@ -213,9 +224,7 @@ class JobPageState extends State with SnackBarProvider {
contact.fullname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
- style: ralewayRegular(16.0, textColor).copyWith(
- fontWeight: FontWeight.w500,
- ),
+ style: ralewayBold(18.0, kTitleBaseColor),
),
),
iconColor: textColor,
@@ -230,10 +239,10 @@ class JobPageState extends State with SnackBarProvider {
actions: [
IconButton(
icon: new Icon(
- job.isComplete ? Icons.check_box : Icons.check_box_outline_blank,
- color: textBaseColor.shade900,
+ Icons.check,
+ color: job.isComplete ? kPrimaryColor : kTextBaseColor.shade400,
),
- onPressed: onTapComplete,
+ onPressed: null,
)
],
);
@@ -244,7 +253,7 @@ class JobPageState extends State with SnackBarProvider {
void onTapComplete() async {
var choice = await confirmDialog(
context: context,
- title: Text("Marking this job as complete?"),
+ title: Text("Are you sure?"),
);
if (choice == null || choice == false) return;
diff --git a/lib/pages/jobs/job_list_item.dart b/lib/pages/jobs/job_list_item.dart
index 299e585f..406f60e5 100644
--- a/lib/pages/jobs/job_list_item.dart
+++ b/lib/pages/jobs/job_list_item.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
-import 'package:tailor_made/pages/jobs/job.dart';
import 'package:tailor_made/models/job.dart';
+import 'package:tailor_made/pages/jobs/job.dart';
import 'package:tailor_made/utils/tm_format_naira.dart';
import 'package:tailor_made/utils/tm_months.dart';
import 'package:tailor_made/utils/tm_navigate.dart';
@@ -57,13 +57,13 @@ class JobListItem extends StatelessWidget {
children: [
Text(job.name, style: TextStyle(fontSize: 16.0, color: theme.textColor, fontWeight: FontWeight.w600)),
new SizedBox(height: 4.0),
- Text(_price, style: TextStyle(fontSize: 14.0, color: textBaseColor)),
+ Text(_price, style: TextStyle(fontSize: 14.0, color: kTextBaseColor)),
],
),
),
new Icon(
Icons.check,
- color: job.isComplete ? theme.accentColor : textBaseColor.shade300,
+ color: job.isComplete ? theme.primaryColor : kTextBaseColor.shade300,
),
],
),
diff --git a/lib/pages/jobs/jobs_create.dart b/lib/pages/jobs/jobs_create.dart
index 9dc20e74..610880b3 100644
--- a/lib/pages/jobs/jobs_create.dart
+++ b/lib/pages/jobs/jobs_create.dart
@@ -84,8 +84,8 @@ class _JobsCreatePageState extends State with SnackBarProvider {
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- Text(title.toUpperCase(), style: ralewayLight(12.0, textBaseColor.shade800)),
- Text(trailing, style: ralewayLight(12.0, textBaseColor.shade800)),
+ Text(title.toUpperCase(), style: ralewayLight(12.0, kTextBaseColor.shade800)),
+ Text(trailing, style: ralewayLight(12.0, kTextBaseColor.shade800)),
],
),
);
@@ -110,7 +110,7 @@ class _JobsCreatePageState extends State with SnackBarProvider {
children.add(
Padding(
child: RaisedButton(
- color: accentColor,
+ color: kAccentColor,
shape: StadiumBorder(),
child: Text(
"FINISH",
@@ -191,7 +191,7 @@ class _JobsCreatePageState extends State with SnackBarProvider {
contact.fullname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
- style: ralewayRegular(18.0, theme.appBarColor),
+ style: ralewayBold(18.0, theme.appBarColor),
),
subtitle: Text("${contact.totalJobs} Jobs", style: theme.smallTextStyle),
actions: widget.contacts.isNotEmpty
@@ -249,7 +249,7 @@ class _JobsCreatePageState extends State with SnackBarProvider {
hintStyle: TextStyle(fontSize: 14.0),
border: UnderlineInputBorder(
borderSide: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 0.0,
style: BorderStyle.solid,
),
@@ -273,7 +273,7 @@ class _JobsCreatePageState extends State with SnackBarProvider {
child: Icon(
Icons.add_a_photo,
size: 24.0,
- color: textBaseColor.withOpacity(.35),
+ color: kTextBaseColor.withOpacity(.35),
),
),
),
@@ -359,7 +359,7 @@ class _JobsCreatePageState extends State with SnackBarProvider {
// border: InputBorder.none,
border: UnderlineInputBorder(
borderSide: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 1.0,
style: BorderStyle.solid,
),
@@ -384,7 +384,7 @@ class _JobsCreatePageState extends State with SnackBarProvider {
hintStyle: TextStyle(fontSize: 14.0),
border: UnderlineInputBorder(
borderSide: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 0.0,
style: BorderStyle.solid,
),
diff --git a/lib/pages/jobs/ui/gallery_grids.dart b/lib/pages/jobs/ui/gallery_grids.dart
index c67d509b..599f1b86 100644
--- a/lib/pages/jobs/ui/gallery_grids.dart
+++ b/lib/pages/jobs/ui/gallery_grids.dart
@@ -86,7 +86,7 @@ class GalleryGridsState extends State {
const SizedBox(width: 16.0),
Expanded(child: Text("GALLERY", style: ralewayRegular(12.0, Colors.black87))),
CupertinoButton(
- child: Text("SHOW ALL", style: ralewayRegular(11.0, textBaseColor)),
+ child: Text("SHOW ALL", style: ralewayRegular(11.0, kTextBaseColor)),
onPressed: () => TMNavigate(context, GalleryPage(images: widget.job.images), fullscreenDialog: true),
),
],
@@ -116,7 +116,7 @@ class GalleryGridsState extends State {
child: Icon(
Icons.add_a_photo,
size: 24.0,
- color: textBaseColor.withOpacity(.35),
+ color: kTextBaseColor.withOpacity(.35),
),
),
),
diff --git a/lib/pages/jobs/ui/measure_create_items.dart b/lib/pages/jobs/ui/measure_create_items.dart
index 133d8993..3bf43896 100644
--- a/lib/pages/jobs/ui/measure_create_items.dart
+++ b/lib/pages/jobs/ui/measure_create_items.dart
@@ -55,7 +55,7 @@ class JobMeasureBlock extends StatelessWidget {
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 1.0,
style: BorderStyle.solid,
),
@@ -73,12 +73,12 @@ class JobMeasureBlock extends StatelessWidget {
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 1.0,
style: removeBorder ? BorderStyle.none : BorderStyle.solid,
),
right: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 1.0,
style: index % 2 == 0 ? BorderStyle.solid : BorderStyle.none,
),
diff --git a/lib/pages/jobs/ui/measure_list_item.dart b/lib/pages/jobs/ui/measure_list_item.dart
index 87ab3fc2..cb8047e1 100644
--- a/lib/pages/jobs/ui/measure_list_item.dart
+++ b/lib/pages/jobs/ui/measure_list_item.dart
@@ -20,7 +20,7 @@ class MeasureListItem extends StatelessWidget {
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 1.0),
child: Text(item.type.toLowerCase(), style: ralewayRegular(10.0, Colors.white)),
decoration: BoxDecoration(
- color: accentColor,
+ color: kAccentColor,
borderRadius: BorderRadius.circular(10.0),
),
),
@@ -31,12 +31,12 @@ class MeasureListItem extends StatelessWidget {
if (item.value != null && item.value > 0) {
children.addAll([
- Text("${item.value} ", style: ralewayRegular(16.0, accentColor)),
+ Text("${item.value} ", style: ralewayRegular(16.0, kAccentColor)),
SizedBox(width: 2.0),
- Text(item.unit, style: ralewayLight(12.0, titleBaseColor)),
+ Text(item.unit, style: ralewayLight(12.0, kTitleBaseColor)),
]);
} else {
- children.add(Text("N/A", style: ralewayLight(12.0, titleBaseColor)));
+ children.add(Text("N/A", style: ralewayLight(12.0, kTitleBaseColor)));
}
return new Container(
diff --git a/lib/pages/jobs/ui/measure_lists.dart b/lib/pages/jobs/ui/measure_lists.dart
index 6d2e1dc6..0c3f6356 100644
--- a/lib/pages/jobs/ui/measure_lists.dart
+++ b/lib/pages/jobs/ui/measure_lists.dart
@@ -26,7 +26,7 @@ class MeasureLists extends StatelessWidget {
const SizedBox(width: 16.0),
Expanded(child: Text("MEASUREMENTS", style: ralewayRegular(12.0, Colors.black87))),
CupertinoButton(
- child: Text("SHOW ALL", style: ralewayRegular(11.0, textBaseColor)),
+ child: Text("SHOW ALL", style: ralewayRegular(11.0, kTextBaseColor)),
onPressed: () => TMNavigate(context, MeasuresPage(measurements: measurements), fullscreenDialog: true),
),
],
diff --git a/lib/pages/jobs/ui/payment_grid_item.dart b/lib/pages/jobs/ui/payment_grid_item.dart
index b6839b97..2fbe8c31 100644
--- a/lib/pages/jobs/ui/payment_grid_item.dart
+++ b/lib/pages/jobs/ui/payment_grid_item.dart
@@ -30,7 +30,7 @@ class PaymentGridItem extends StatelessWidget {
child: new Material(
elevation: 1.0,
borderRadius: BorderRadius.circular(5.0),
- color: primarySwatch.shade300,
+ color: kPrimaryColor,
child: new InkWell(
onTap: () => TMNavigate(context, PaymentPage(payment: payment), fullscreenDialog: true),
child: Padding(
diff --git a/lib/pages/jobs/ui/payment_grids.dart b/lib/pages/jobs/ui/payment_grids.dart
index bf58f252..9ca26f91 100644
--- a/lib/pages/jobs/ui/payment_grids.dart
+++ b/lib/pages/jobs/ui/payment_grids.dart
@@ -69,7 +69,7 @@ class PaymentGridsState extends State {
const SizedBox(width: 16.0),
Expanded(child: Text("PAYMENTS", style: ralewayRegular(12.0, Colors.black87))),
CupertinoButton(
- child: Text("SHOW ALL", style: ralewayRegular(11.0, textBaseColor)),
+ child: Text("SHOW ALL", style: ralewayRegular(11.0, kTextBaseColor)),
onPressed: () => TMNavigate(context, PaymentsPage(payments: widget.job.payments), fullscreenDialog: true),
),
],
@@ -138,7 +138,7 @@ class PaymentGridsState extends State {
child: Icon(
Icons.note_add,
size: 30.0,
- color: textBaseColor.withOpacity(.35),
+ color: kTextBaseColor.withOpacity(.35),
),
),
),
diff --git a/lib/pages/payments/payment.dart b/lib/pages/payments/payment.dart
index 99631ecc..29017dc9 100644
--- a/lib/pages/payments/payment.dart
+++ b/lib/pages/payments/payment.dart
@@ -41,21 +41,21 @@ class PaymentPage extends StatelessWidget {
IconButton(
icon: Icon(
Icons.work,
- color: titleBaseColor,
+ color: kTitleBaseColor,
),
onPressed: () => TMNavigate(context, JobPage(job: job)),
),
IconButton(
icon: Icon(
Icons.person,
- color: titleBaseColor,
+ color: kTitleBaseColor,
),
onPressed: () => TMNavigate(context, ContactPage(contact: contact)),
),
IconButton(
icon: Icon(
Icons.share,
- color: titleBaseColor,
+ color: kTitleBaseColor,
),
// TODO
onPressed: null,
diff --git a/lib/pages/payments/payment_list_item.dart b/lib/pages/payments/payment_list_item.dart
index 815903e0..d242837d 100644
--- a/lib/pages/payments/payment_list_item.dart
+++ b/lib/pages/payments/payment_list_item.dart
@@ -35,7 +35,7 @@ class PaymentListItem extends StatelessWidget {
children: [
TextSpan(
text: _date.day.toString(),
- style: ralewayMedium(16.0, accentColor),
+ style: ralewayMedium(16.0, kAccentColor),
),
TextSpan(text: "\n"),
TextSpan(
@@ -56,7 +56,7 @@ class PaymentListItem extends StatelessWidget {
width: 4.0,
height: 4.0,
decoration: BoxDecoration(
- color: accentColor,
+ color: kAccentColor,
shape: BoxShape.circle,
),
),
diff --git a/lib/pages/payments/payments.dart b/lib/pages/payments/payments.dart
index dbe42c34..3c8ce16e 100644
--- a/lib/pages/payments/payments.dart
+++ b/lib/pages/payments/payments.dart
@@ -50,7 +50,7 @@ class PaymentsPageState extends State {
"${payments.length} Tickets",
style: TextStyle(
fontSize: 11.0,
- color: textBaseColor,
+ color: kTextBaseColor,
),
)
: SizedBox(),
diff --git a/lib/pages/payments/payments_create.dart b/lib/pages/payments/payments_create.dart
index 44a4f008..b115b697 100644
--- a/lib/pages/payments/payments_create.dart
+++ b/lib/pages/payments/payments_create.dart
@@ -36,7 +36,7 @@ class _PaymentsCreatePageState extends State with SnackBarPr
children.add(
Padding(
child: RaisedButton(
- color: accentColor,
+ color: kAccentColor,
shape: StadiumBorder(),
child: Text(
"FINISH",
@@ -82,8 +82,8 @@ class _PaymentsCreatePageState extends State with SnackBarPr
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- Text(title.toUpperCase(), style: ralewayLight(12.0, textBaseColor.shade800)),
- Text(trailing, style: ralewayLight(12.0, textBaseColor.shade800)),
+ Text(title.toUpperCase(), style: ralewayLight(12.0, kTextBaseColor.shade800)),
+ Text(trailing, style: ralewayLight(12.0, kTextBaseColor.shade800)),
],
),
);
@@ -102,7 +102,7 @@ class _PaymentsCreatePageState extends State with SnackBarPr
hintStyle: TextStyle(fontSize: 14.0),
border: UnderlineInputBorder(
borderSide: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 0.0,
style: BorderStyle.solid,
),
@@ -127,7 +127,7 @@ class _PaymentsCreatePageState extends State with SnackBarPr
hintStyle: TextStyle(fontSize: 14.0),
border: UnderlineInputBorder(
borderSide: BorderSide(
- color: borderSideColor,
+ color: kBorderSideColor,
width: 0.0,
style: BorderStyle.solid,
),
diff --git a/lib/pages/splash/splash.dart b/lib/pages/splash/splash.dart
new file mode 100644
index 00000000..32fdd49c
--- /dev/null
+++ b/lib/pages/splash/splash.dart
@@ -0,0 +1,126 @@
+import 'dart:async';
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:tailor_made/pages/homepage/homepage.dart';
+import 'package:tailor_made/services/auth.dart';
+import 'package:tailor_made/ui/tm_loading_spinner.dart';
+import 'package:tailor_made/utils/tm_images.dart';
+import 'package:tailor_made/utils/tm_navigate.dart';
+import 'package:tailor_made/utils/tm_snackbar.dart';
+import 'package:tailor_made/utils/tm_strings.dart';
+import 'package:tailor_made/utils/tm_theme.dart';
+
+class SplashPage extends StatefulWidget {
+ final bool isColdStart;
+
+ SplashPage({
+ Key key,
+ @required this.isColdStart,
+ }) : super(key: key);
+
+ @override
+ State createState() => new _SplashPageState();
+}
+
+class _SplashPageState extends State with SnackBarProvider {
+ final scaffoldKey = new GlobalKey();
+ bool isLoading;
+
+ @override
+ void initState() {
+ super.initState();
+ isLoading = widget.isColdStart;
+
+ if (widget.isColdStart == true) {
+ _trySilent();
+ }
+
+ Auth.onAuthStateChanged.firstWhere((user) => user != null).then(
+ (user) {
+ Auth.setUser(user);
+ Navigator.pushReplacement(context, TMNavigate.fadeIn(new HomePage()));
+ },
+ );
+ }
+
+ _trySilent() async {
+ // Give the navigation animations, etc, some time to finish
+ await new Future.delayed(new Duration(seconds: 1)).then((_) => _onLogin());
+ }
+
+ _onLogin() async => await Auth.signInWithGoogle();
+
+ @override
+ Widget build(BuildContext context) {
+ return new Scaffold(
+ key: scaffoldKey,
+ body: Stack(
+ fit: StackFit.expand,
+ children: [
+ Opacity(
+ opacity: .5,
+ child: Container(
+ decoration: BoxDecoration(
+ image: DecorationImage(
+ image: TMImages.pattern,
+ fit: BoxFit.cover,
+ ),
+ ),
+ ),
+ ),
+ Positioned.fill(
+ top: null,
+ bottom: 32.0,
+ child: Text(
+ TMStrings.appName,
+ style: ralewayMedium(22.0, kTextBaseColor.withOpacity(.6)),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ isLoading && widget.isColdStart
+ ? SizedBox()
+ : Center(
+ child: Image(
+ image: TMImages.logo,
+ width: 148.0,
+ color: Colors.white.withOpacity(.35),
+ colorBlendMode: BlendMode.saturation,
+ ),
+ ),
+ Positioned(
+ height: 96.0,
+ bottom: 64.0,
+ left: 0.0,
+ right: 0.0,
+ child: isLoading ? loadingSpinner() : Center(child: _googleBtn()),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _googleBtn() {
+ return RaisedButton(
+ color: Colors.white,
+ onPressed: () {
+ setState(() => isLoading = true);
+ try {
+ _onLogin();
+ } catch (e) {
+ setState(() => isLoading = false);
+ showInSnackBar(e.toString());
+ }
+ },
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Image(image: TMImages.google_logo, width: 24.0),
+ const SizedBox(width: 8.0),
+ Text("Continue with Google", style: TextStyle(fontWeight: FontWeight.w700)),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/services/auth.dart b/lib/services/auth.dart
new file mode 100644
index 00000000..0482f209
--- /dev/null
+++ b/lib/services/auth.dart
@@ -0,0 +1,55 @@
+import 'dart:async';
+
+import 'package:firebase_auth/firebase_auth.dart';
+import 'package:google_sign_in/google_sign_in.dart';
+
+final GoogleSignIn _googleSignIn = new GoogleSignIn();
+final FirebaseAuth _auth = FirebaseAuth.instance;
+
+class Auth {
+ static FirebaseUser _user;
+ Auth._();
+
+ static FirebaseUser setUser(FirebaseUser user) => _user = user;
+ static FirebaseUser get getUser => _user;
+
+ static Future silently() async => await _googleSignIn.signInSilently();
+
+ static get onAuthStateChanged => _auth.onAuthStateChanged;
+
+ static Future signInWithGoogle() async {
+ // Attempt to get the currently authenticated user
+ GoogleSignInAccount currentUser = _googleSignIn.currentUser;
+ if (currentUser == null) {
+ // Attempt to sign in without user interaction
+ currentUser = await _googleSignIn.signInSilently();
+ }
+ if (currentUser == null) {
+ // Force the user to interactively sign in
+ currentUser = await _googleSignIn.signIn();
+ }
+
+ final GoogleSignInAuthentication auth = await currentUser.authentication;
+
+ // Authenticate with firebase
+ final FirebaseUser user = await _auth.signInWithGoogle(
+ idToken: auth.idToken,
+ accessToken: auth.accessToken,
+ );
+
+ assert(user != null);
+ assert(!user.isAnonymous);
+
+ setUser(user);
+ return user;
+ }
+
+ static Future signOutWithGoogle() async {
+ // Sign out with firebase
+ await _auth.signOut();
+ // Sign out with google
+ await _googleSignIn.signOut();
+ // Clear state
+ _user = null;
+ }
+}
diff --git a/lib/services/cloudstore.dart b/lib/services/cloudstore.dart
index cbdf01c6..1a632345 100644
--- a/lib/services/cloudstore.dart
+++ b/lib/services/cloudstore.dart
@@ -1,13 +1,15 @@
import 'package:cloud_firestore/cloud_firestore.dart';
+import 'package:tailor_made/services/auth.dart';
class Cloudstore {
static Firestore instance = Firestore.instance;
Cloudstore._();
- static DocumentReference stats = instance.document("stats/current");
- static CollectionReference gallery = instance.collection("gallery");
- static CollectionReference payments = instance.collection("payments");
- static CollectionReference contacts = instance.collection("contacts");
- static CollectionReference jobs = instance.collection("jobs");
+ static DocumentReference get account => instance.document("accounts/${Auth.getUser.uid}");
+ static DocumentReference get stats => instance.document("stats/${Auth.getUser.uid}");
+ static CollectionReference get gallery => instance.collection("gallery").where("userID", isEqualTo: Auth.getUser.uid).reference();
+ static CollectionReference get payments => instance.collection("payments").where("userID", isEqualTo: Auth.getUser.uid).reference();
+ static CollectionReference get contacts => instance.collection("contacts").where("userID", isEqualTo: Auth.getUser.uid).reference();
+ static CollectionReference get jobs => instance.collection("jobs").where("userID", isEqualTo: Auth.getUser.uid).reference();
}
diff --git a/lib/ui/circle_avatar.dart b/lib/ui/circle_avatar.dart
index bc695b4e..f2ca5e9d 100644
--- a/lib/ui/circle_avatar.dart
+++ b/lib/ui/circle_avatar.dart
@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
import 'package:tailor_made/utils/tm_theme.dart';
CircleAvatar circleAvatar({double radius, bool useAlt = false, String imageUrl}) {
- final iconColor = useAlt ? primarySwatch.shade300 : Colors.white;
- final backgroundColor = useAlt ? Colors.white : primarySwatch.shade300;
+ final iconColor = useAlt ? kPrimaryColor : Colors.white;
+ final backgroundColor = useAlt ? Colors.white : kPrimaryColor;
return new CircleAvatar(
radius: radius ?? null,
backgroundColor: imageUrl != null ? Colors.grey.shade400 : backgroundColor,
diff --git a/lib/ui/tm_empty_result.dart b/lib/ui/tm_empty_result.dart
index c090855f..ecdf3366 100644
--- a/lib/ui/tm_empty_result.dart
+++ b/lib/ui/tm_empty_result.dart
@@ -19,7 +19,7 @@ class TMEmptyResult extends StatelessWidget {
children: [
new Icon(
Icons.equalizer,
- color: theme.accentColor,
+ color: theme.primaryColor,
size: 36.0,
),
const SizedBox(height: 8.0),
diff --git a/lib/ui/tm_error_result.dart b/lib/ui/tm_error_result.dart
index fc8a3855..d26eeb73 100644
--- a/lib/ui/tm_error_result.dart
+++ b/lib/ui/tm_error_result.dart
@@ -19,7 +19,7 @@ class TMErrorResult extends StatelessWidget {
children: [
new Icon(
Icons.error_outline,
- color: theme.accentColor,
+ color: theme.primaryColor,
size: 50.0,
),
const SizedBox(height: 16.0),
diff --git a/lib/ui/tm_loading_spinner.dart b/lib/ui/tm_loading_spinner.dart
index 7e923830..191b7228 100644
--- a/lib/ui/tm_loading_spinner.dart
+++ b/lib/ui/tm_loading_spinner.dart
@@ -5,7 +5,7 @@ import 'package:tailor_made/utils/tm_theme.dart';
Widget loadingSpinner({Color color}) {
return Center(
child: SpinKitFadingFour(
- color: color ?? accentColor,
+ color: color ?? kAccentColor,
// color: color ?? primarySwatch,
width: 30.0,
height: 30.0,
diff --git a/lib/utils/tm_colors.dart b/lib/utils/tm_colors.dart
index c5766f72..58179e96 100644
--- a/lib/utils/tm_colors.dart
+++ b/lib/utils/tm_colors.dart
@@ -3,7 +3,8 @@ import 'package:flutter/widgets.dart';
class TMColors {
TMColors._();
-
+ static const _baseBlue = 0xFF9168ed;
+ static const _basePink = 0xFFf54295;
static const MaterialColor dark = const MaterialColor(
0xFF444444,
const {
@@ -35,12 +36,12 @@ class TMColors {
},
);
static const MaterialColor biro_blue = const MaterialColor(
- 0xFF0000d0,
+ _baseBlue,
const {
50: const Color(0xFFeee5fc),
100: const Color(0xFFd1bff6),
200: const Color(0xFFb295f1),
- 300: const Color(0xFF9168ed),
+ 300: const Color(_baseBlue),
400: const Color(0xFF7644e9),
500: const Color(0xFF5519e4),
600: const Color(0xFF4815de),
@@ -49,7 +50,22 @@ class TMColors {
900: const Color(0xFF0000ca),
},
);
- static const Color accent = const Color(0xFF0000d0);
- static const Color primary = const Color(0xFFf54295);
+ static const MaterialColor slate_pink = const MaterialColor(
+ _basePink,
+ const {
+ 50: const Color(0xFFf54290),
+ 100: const Color(0xFFf54291),
+ 200: const Color(0xFFf54293),
+ 300: const Color(0xFFf54294),
+ 400: const Color(_basePink),
+ 500: const Color(0xFFf54296),
+ 600: const Color(0xFFf54297),
+ 700: const Color(0xFFf54298),
+ 800: const Color(0xFFf54299),
+ 900: const Color(0xFFf54210),
+ },
+ );
+ static const Color accent = const Color(_basePink);
+ static const Color primary = const Color(_baseBlue);
static const Color light_grey = const Color(0xFF9B9B9B);
}
diff --git a/lib/utils/tm_images.dart b/lib/utils/tm_images.dart
new file mode 100644
index 00000000..f446abd3
--- /dev/null
+++ b/lib/utils/tm_images.dart
@@ -0,0 +1,9 @@
+import 'package:flutter/widgets.dart';
+
+class TMImages {
+ TMImages._();
+
+ static const ImageProvider google_logo = AssetImage('assets/images/google_logo.png');
+ static const ImageProvider pattern = AssetImage('assets/images/pattern.png');
+ static const ImageProvider logo = AssetImage('assets/images/logo.png');
+}
diff --git a/lib/utils/tm_theme.dart b/lib/utils/tm_theme.dart
index 62f5ac9c..5ef7f041 100644
--- a/lib/utils/tm_theme.dart
+++ b/lib/utils/tm_theme.dart
@@ -6,18 +6,21 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:tailor_made/utils/tm_colors.dart';
-const Color accentColor = TMColors.primary;
-const Color accentColorAlt = Colors.blueGrey;
-const MaterialColor primarySwatch = TMColors.biro_blue;
-final Color borderSideColor = Colors.grey.shade300;
-const MaterialColor textBaseColor = Colors.grey;
-const MaterialColor titleBaseColor = TMColors.dark;
-const MaterialColor backgroundBaseColor = TMColors.white;
+const Color kAccentColor = TMColors.accent;
+const Color kPrimaryColor = TMColors.primary;
+
+const MaterialColor kAccentSwatch = TMColors.slate_pink;
+const MaterialColor kPrimarySwatch = TMColors.biro_blue;
+
+final Color kBorderSideColor = Colors.grey.shade300;
+const MaterialColor kTextBaseColor = Colors.grey;
+const MaterialColor kTitleBaseColor = TMColors.dark;
+const MaterialColor kBackgroundBaseColor = TMColors.white;
class TMBorderSide extends BorderSide {
TMBorderSide({Color color})
: super(
- color: color != null ? color : borderSideColor,
+ color: color != null ? color : kBorderSideColor,
style: BorderStyle.solid,
width: 1.0,
);
@@ -28,11 +31,11 @@ class TMStyle extends TextStyle {
: super(inherit: false, color: color, fontFamily: 'Raleway', fontSize: size, fontWeight: weight, textBaseline: TextBaseline.alphabetic);
}
-TextStyle ralewayThin(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w100, color ?? textBaseColor);
-TextStyle ralewayLight(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w300, color ?? textBaseColor);
-TextStyle ralewayRegular(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w400, color ?? textBaseColor);
-TextStyle ralewayMedium(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w500, color ?? textBaseColor);
-TextStyle ralewayBold(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w700, color ?? textBaseColor);
+TextStyle ralewayThin(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w100, color ?? kTextBaseColor);
+TextStyle ralewayLight(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w300, color ?? kTextBaseColor);
+TextStyle ralewayRegular(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w400, color ?? kTextBaseColor);
+TextStyle ralewayMedium(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w500, color ?? kTextBaseColor);
+TextStyle ralewayBold(double fontSize, [Color color]) => new TMStyle.raleway(fontSize, FontWeight.w700, color ?? kTextBaseColor);
/// The TextStyles and Colors used for titles, labels, and descriptions. This
/// InheritedWidget is shared by all of the routes and widgets created for
@@ -42,24 +45,19 @@ class TMTheme extends InheritedWidget {
: assert(child != null),
super(key: key, child: child);
- Color get accentColor => TMColors.accent;
- Color get primaryColor => TMColors.primary;
- Color get borderSideColor => borderSideColor;
+ Color get accentColor => kAccentColor;
+ Color get primaryColor => kPrimaryColor;
+ Color get borderSideColor => kBorderSideColor;
Color get appBarBackgroundColor => scaffoldColor;
- final Color scaffoldColor = backgroundBaseColor;
- final Color scaffoldColorAlt = textBaseColor.shade100;
- final Color appBarColor = titleBaseColor;
- final Color textColor = textBaseColor.shade800;
- final Color textMutedColor = textBaseColor.shade500;
-
- // final Color scaffoldColor = Color(0xFF00251a);
- // final Color scaffoldColorAlt = Colors.blueGrey.shade700;
- // final Color appBarColor = Color(0xFF39796b);
- // final Color textColor = Color(0xFF39796b);
+ final Color scaffoldColor = kBackgroundBaseColor;
+ final Color scaffoldColorAlt = kTextBaseColor.shade100;
+ final Color appBarColor = kTitleBaseColor;
+ final Color textColor = kTextBaseColor.shade800;
+ final Color textMutedColor = kTextBaseColor.shade500;
TextStyle get appBarStyle => ralewayBold(20.0, appBarColor);
- TextStyle get titleStyle => ralewayMedium(18.0, titleBaseColor);
+ TextStyle get titleStyle => ralewayMedium(18.0, kTitleBaseColor);
TextStyle get smallTextStyle => ralewayRegular(12.0, textColor);
TextStyle get mediumTextStyle => ralewayRegular(16.0, textColor);
diff --git a/pubspec.lock b/pubspec.lock
deleted file mode 100644
index fa6b4320..00000000
--- a/pubspec.lock
+++ /dev/null
@@ -1,546 +0,0 @@
-# Generated by pub
-# See https://www.dartlang.org/tools/pub/glossary#lockfile
-packages:
- analyzer:
- dependency: transitive
- description:
- name: analyzer
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.31.2-alpha.2"
- args:
- dependency: transitive
- description:
- name: args
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.4.3"
- async:
- dependency: transitive
- description:
- name: async
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.7"
- boolean_selector:
- dependency: transitive
- description:
- name: boolean_selector
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.3"
- cached_network_image:
- dependency: "direct main"
- description:
- name: cached_network_image
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.1+1"
- carousel:
- dependency: "direct main"
- description:
- name: carousel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.0.1"
- charcode:
- dependency: transitive
- description:
- name: charcode
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.1"
- cloud_firestore:
- dependency: "direct main"
- description:
- name: cloud_firestore
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.7.3"
- cloud_functions:
- dependency: "direct main"
- description:
- name: cloud_functions
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.0.1"
- collection:
- dependency: transitive
- description:
- name: collection
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.14.6"
- convert:
- dependency: transitive
- description:
- name: convert
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.1"
- crypto:
- dependency: transitive
- description:
- name: crypto
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.5"
- csslib:
- dependency: transitive
- description:
- name: csslib
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.14.4"
- firebase_analytics:
- dependency: "direct main"
- description:
- name: firebase_analytics
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.1"
- firebase_auth:
- dependency: "direct main"
- description:
- name: firebase_auth
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.5.12"
- firebase_core:
- dependency: transitive
- description:
- name: firebase_core
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.4"
- firebase_storage:
- dependency: "direct main"
- description:
- name: firebase_storage
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.3.7"
- flutter:
- dependency: "direct main"
- description: flutter
- source: sdk
- version: "0.0.0"
- flutter_cache_manager:
- dependency: transitive
- description:
- name: flutter_cache_manager
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.1.1"
- flutter_masked_text:
- dependency: "direct main"
- description:
- name: flutter_masked_text
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.5.0"
- flutter_redux:
- dependency: "direct main"
- description:
- name: flutter_redux
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.5.2"
- flutter_spinkit:
- dependency: "direct main"
- description:
- name: flutter_spinkit
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.0"
- flutter_test:
- dependency: "direct dev"
- description: flutter
- source: sdk
- version: "0.0.0"
- front_end:
- dependency: transitive
- description:
- name: front_end
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.1.0-alpha.12"
- glob:
- dependency: transitive
- description:
- name: glob
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.5"
- html:
- dependency: transitive
- description:
- name: html
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.13.3+1"
- http:
- dependency: transitive
- description:
- name: http
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.11.3+16"
- http_multi_server:
- dependency: transitive
- description:
- name: http_multi_server
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.5"
- http_parser:
- dependency: transitive
- description:
- name: http_parser
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.1.2"
- image_picker:
- dependency: "direct main"
- description:
- name: image_picker
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.5"
- intl:
- dependency: "direct main"
- description:
- name: intl
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.15.6"
- io:
- dependency: transitive
- description:
- name: io
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.3.2+1"
- js:
- dependency: transitive
- description:
- name: js
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.6.1"
- json_rpc_2:
- dependency: transitive
- description:
- name: json_rpc_2
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.8"
- kernel:
- dependency: transitive
- description:
- name: kernel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.3.0-alpha.12"
- logging:
- dependency: transitive
- description:
- name: logging
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.11.3+1"
- matcher:
- dependency: transitive
- description:
- name: matcher
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.12.2"
- meta:
- dependency: transitive
- description:
- name: meta
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.5"
- mime:
- dependency: transitive
- description:
- name: mime
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.9.6+1"
- multi_server_socket:
- dependency: transitive
- description:
- name: multi_server_socket
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.1"
- node_preamble:
- dependency: transitive
- description:
- name: node_preamble
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.4.2"
- package_config:
- dependency: transitive
- description:
- name: package_config
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.3"
- package_resolver:
- dependency: transitive
- description:
- name: package_resolver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.3"
- path:
- dependency: transitive
- description:
- name: path
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.6.1"
- path_provider:
- dependency: transitive
- description:
- name: path_provider
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.1"
- photo_view:
- dependency: "direct main"
- description:
- name: photo_view
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.0.2"
- plugin:
- dependency: transitive
- description:
- name: plugin
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.0+2"
- pool:
- dependency: transitive
- description:
- name: pool
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.3.5"
- pub_semver:
- dependency: transitive
- description:
- name: pub_semver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.4.1"
- quiver:
- dependency: transitive
- description:
- name: quiver
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.29.0+1"
- redux:
- dependency: "direct main"
- description:
- name: redux
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.0"
- redux_epics:
- dependency: "direct main"
- description:
- name: redux_epics
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.10.0"
- redux_logging:
- dependency: "direct main"
- description:
- name: redux_logging
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.3.0"
- rxdart:
- dependency: "direct main"
- description:
- name: rxdart
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.18.1"
- shared_preferences:
- dependency: transitive
- description:
- name: shared_preferences
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.4.2"
- shelf:
- dependency: transitive
- description:
- name: shelf
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.7.3+1"
- shelf_packages_handler:
- dependency: transitive
- description:
- name: shelf_packages_handler
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.3"
- shelf_static:
- dependency: transitive
- description:
- name: shelf_static
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.7+1"
- shelf_web_socket:
- dependency: transitive
- description:
- name: shelf_web_socket
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.2+2"
- sky_engine:
- dependency: transitive
- description: flutter
- source: sdk
- version: "0.0.99"
- source_map_stack_trace:
- dependency: transitive
- description:
- name: source_map_stack_trace
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.4"
- source_maps:
- dependency: transitive
- description:
- name: source_maps
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.10.5"
- source_span:
- dependency: transitive
- description:
- name: source_span
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.4.0"
- stack_trace:
- dependency: transitive
- description:
- name: stack_trace
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.9.2"
- stream_channel:
- dependency: transitive
- description:
- name: stream_channel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.6.7+1"
- string_scanner:
- dependency: transitive
- description:
- name: string_scanner
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.2"
- synchronized:
- dependency: transitive
- description:
- name: synchronized
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.5.0+1"
- term_glyph:
- dependency: transitive
- description:
- name: term_glyph
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.0"
- test:
- dependency: transitive
- description:
- name: test
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.12.41"
- typed_data:
- dependency: transitive
- description:
- name: typed_data
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.1.5"
- url_launcher:
- dependency: "direct main"
- description:
- name: url_launcher
- url: "https://pub.dartlang.org"
- source: hosted
- version: "3.0.2"
- utf:
- dependency: transitive
- description:
- name: utf
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.9.0+4"
- uuid:
- dependency: transitive
- description:
- name: uuid
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.5.3"
- vector_math:
- dependency: transitive
- description:
- name: vector_math
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.0.6"
- vm_service_client:
- dependency: transitive
- description:
- name: vm_service_client
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.2.4+3"
- watcher:
- dependency: transitive
- description:
- name: watcher
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.9.7+8"
- web_socket_channel:
- dependency: transitive
- description:
- name: web_socket_channel
- url: "https://pub.dartlang.org"
- source: hosted
- version: "1.0.8"
- yaml:
- dependency: transitive
- description:
- name: yaml
- url: "https://pub.dartlang.org"
- source: hosted
- version: "2.1.14"
-sdks:
- dart: ">=2.0.0-dev.62.0 <=2.0.0-dev.63.0.flutter-4c9689c1d2"
- flutter: ">=0.2.4 <2.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 21d36959..19887dc2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,10 @@
name: tailor_made
description: Tailor-Made with love.
+version: 0.1.0
dependencies:
flutter:
sdk: flutter
- carousel: ^0.0.1
firebase_analytics: ^1.0.1
cloud_firestore: ^0.7.3
cloud_functions: ^0.0.1
@@ -22,6 +22,7 @@ dependencies:
photo_view: ^0.0.2
cached_network_image: "^0.4.1"
flutter_spinkit: "^1.0.0"
+ google_sign_in: "^3.0.4"
dev_dependencies:
flutter_test:
@@ -30,19 +31,19 @@ dev_dependencies:
flutter:
uses-material-design: true
-assets:
- - assets/images/
+ assets:
+ - assets/images/
-fonts:
- - family: Raleway
- fonts:
- - asset: assets/fonts/Raleway-Thin.ttf
- weight: 100
- - asset: assets/fonts/Raleway-Light.ttf
- weight: 300
- - asset: assets/fonts/Raleway-Regular.ttf
- weight: 400
- - asset: assets/fonts/Raleway-Medium.ttf
- weight: 500
- - asset: assets/fonts/Raleway-SemiBold.ttf
- weight: 600
+ fonts:
+ - family: Raleway
+ fonts:
+ - asset: assets/fonts/Raleway-Thin.ttf
+ weight: 100
+ - asset: assets/fonts/Raleway-Light.ttf
+ weight: 300
+ - asset: assets/fonts/Raleway-Regular.ttf
+ weight: 400
+ - asset: assets/fonts/Raleway-Medium.ttf
+ weight: 500
+ - asset: assets/fonts/Raleway-SemiBold.ttf
+ weight: 600
diff --git a/screenshots/ss01.png b/screenshots/ss01.png
index 7c456622..cf0bd069 100644
Binary files a/screenshots/ss01.png and b/screenshots/ss01.png differ
diff --git a/screenshots/ss02.png b/screenshots/ss02.png
index 08950517..49ceb394 100644
Binary files a/screenshots/ss02.png and b/screenshots/ss02.png differ
diff --git a/screenshots/ss03.png b/screenshots/ss03.png
index a242966e..c1b4a6e9 100644
Binary files a/screenshots/ss03.png and b/screenshots/ss03.png differ
diff --git a/screenshots/ss04.png b/screenshots/ss04.png
index a804900c..4f6ab366 100644
Binary files a/screenshots/ss04.png and b/screenshots/ss04.png differ
diff --git a/screenshots/ss05.png b/screenshots/ss05.png
index 31842a7e..db401a1f 100644
Binary files a/screenshots/ss05.png and b/screenshots/ss05.png differ
diff --git a/screenshots/ss06.png b/screenshots/ss06.png
index 22e730ce..067fb401 100644
Binary files a/screenshots/ss06.png and b/screenshots/ss06.png differ
diff --git a/screenshots/ss07.png b/screenshots/ss07.png
index a57cb154..3d2b6086 100644
Binary files a/screenshots/ss07.png and b/screenshots/ss07.png differ
diff --git a/screenshots/ss08.png b/screenshots/ss08.png
index ae10ffba..ad810a7e 100644
Binary files a/screenshots/ss08.png and b/screenshots/ss08.png differ
diff --git a/screenshots/ss09.png b/screenshots/ss09.png
index 75ad8f1e..918fba20 100644
Binary files a/screenshots/ss09.png and b/screenshots/ss09.png differ
diff --git a/screenshots/ss10.png b/screenshots/ss10.png
index 1b6c5034..2efbe74b 100644
Binary files a/screenshots/ss10.png and b/screenshots/ss10.png differ
diff --git a/screenshots/ss11.png b/screenshots/ss11.png
index 9db3a5bc..c7eeb7f7 100644
Binary files a/screenshots/ss11.png and b/screenshots/ss11.png differ
diff --git a/screenshots/ss12.png b/screenshots/ss12.png
index abe2521f..7cee1298 100644
Binary files a/screenshots/ss12.png and b/screenshots/ss12.png differ
diff --git a/screenshots/ss13.png b/screenshots/ss13.png
index eb80a582..b02d8f2d 100644
Binary files a/screenshots/ss13.png and b/screenshots/ss13.png differ
diff --git a/screenshots/ss14.png b/screenshots/ss14.png
index 0f0ab372..7dd15123 100644
Binary files a/screenshots/ss14.png and b/screenshots/ss14.png differ
diff --git a/screenshots/ss15.png b/screenshots/ss15.png
index 0abc990e..fa4e0238 100644
Binary files a/screenshots/ss15.png and b/screenshots/ss15.png differ
diff --git a/screenshots/ss16.png b/screenshots/ss16.png
index 56213b1d..09f1b234 100644
Binary files a/screenshots/ss16.png and b/screenshots/ss16.png differ
diff --git a/screenshots/ss17.png b/screenshots/ss17.png
index 9eed354b..5570a834 100644
Binary files a/screenshots/ss17.png and b/screenshots/ss17.png differ
diff --git a/screenshots/ss18.png b/screenshots/ss18.png
new file mode 100644
index 00000000..ca8d5468
Binary files /dev/null and b/screenshots/ss18.png differ
diff --git a/screenshots/ss19.png b/screenshots/ss19.png
new file mode 100644
index 00000000..528839da
Binary files /dev/null and b/screenshots/ss19.png differ
diff --git a/screenshots/ss20.png b/screenshots/ss20.png
new file mode 100644
index 00000000..1fc78312
Binary files /dev/null and b/screenshots/ss20.png differ