Diff to HTML by rtfpessoa

Files changed (55) hide show
  1. .firebaserc +10 -7
  2. DIFF.md +6 -33
  3. FIREBASE.md +93 -15
  4. README.md +25 -2
  5. UPDATE.md +196 -0
  6. angular.json +11 -3
  7. capacitor.config.ts +1 -1
  8. firebase.json +42 -0
  9. package.json +56 -56
  10. src/app/app-routing.module.ts +2 -3
  11. src/app/app.component.html +1 -1
  12. src/app/app.component.ts +3 -2
  13. src/app/categories/categories.module.ts +0 -2
  14. src/app/components/countdown-timer/countdown-timer.component.ts +1 -1
  15. src/app/components/counter-input/counter-input.component.ts +3 -3
  16. src/app/contact-card/contact-card.module.ts +0 -2
  17. src/app/deals/details/deals-details.module.ts +0 -2
  18. src/app/deals/details/deals-details.page.ts +5 -0
  19. src/app/deals/listing/deals-listing.module.ts +0 -2
  20. src/app/fashion/details/fashion-details.module.ts +0 -2
  21. src/app/fashion/details/fashion-details.page.ts +6 -0
  22. src/app/fashion/listing/fashion-listing.module.ts +0 -3
  23. src/app/firebase/auth/firebase-auth.helper.ts +107 -0
  24. src/app/firebase/auth/firebase-auth.module.ts +5 -1
  25. src/app/firebase/auth/firebase-auth.service.ts +75 -144
  26. src/app/firebase/auth/sign-in/firebase-sign-in.page.ts +5 -5
  27. src/app/firebase/auth/sign-up/firebase-sign-up.page.ts +9 -9
  28. src/app/firebase/crud/listing/firebase-listing.page.ts +4 -4
  29. src/app/food/details/food-details.module.ts +0 -2
  30. src/app/food/listing/food-listing.module.ts +0 -2
  31. src/app/forgot-password/forgot-password.page.ts +4 -4
  32. src/app/forms/filters/forms-filters.page.ts +41 -41
  33. src/app/forms/validations/forms-validations.page.ts +20 -20
  34. src/app/getting-started/getting-started.page.ts +11 -11
  35. src/app/login/login.page.ts +5 -5
  36. src/app/notifications/notifications.module.ts +0 -2
  37. src/app/page-not-found/page-not-found.module.ts +0 -2
  38. src/app/real-estate/details/real-estate-details.module.ts +0 -2
  39. src/app/real-estate/listing/real-estate-listing.module.ts +0 -2
  40. src/app/shell/image-shell/image-shell.component.ts +4 -1
  41. src/app/showcase/showcase.module.ts +0 -1
  42. src/app/signup/signup.page.ts +9 -9
  43. src/app/travel/details/travel-details.module.ts +0 -2
  44. src/app/travel/listing/travel-listing.module.ts +0 -2
  45. src/app/user/profile/user-profile.module.ts +2 -2
  46. src/app/validators/password.validator.ts +3 -3
  47. src/app/validators/username.validator.ts +2 -2
  48. src/app/walkthrough/walkthrough.guard.ts +3 -2
  49. src/app/walkthrough/walkthrough.module.ts +1 -0
  50. src/app/walkthrough/walkthrough.page.ts +4 -7
  51. src/global.scss +5 -5
  52. src/index.html +2 -1
  53. src/theme/app-defaults.scss +4 -5
  54. src/tsconfig.app.json +0 -1
  55. tsconfig.json +3 -2
.firebaserc CHANGED
@@ -1,20 +1,23 @@
1
  {
2
  "projects": {
3
  "dev": "dev-ion4fullpwa",
4
- "prod": "ion4fullpwa",
5
- "beginners": "ion5fullapp-beginners",
6
  "basic": "basic-ionic-6-full-app"
7
  },
8
  "targets": {
9
  "basic-ionic-6-full-app": {
10
  "hosting": {
11
- "06-2022-release": [
12
  "basic-ionic-6-full-app"
13
- ],
14
- "12-2021-release": [
15
- "basic-ionic-5-full-app"
 
 
 
 
16
  ]
17
  }
18
  }
19
- }
 
20
  }
1
  {
2
  "projects": {
3
  "dev": "dev-ion4fullpwa",
 
 
4
  "basic": "basic-ionic-6-full-app"
5
  },
6
  "targets": {
7
  "basic-ionic-6-full-app": {
8
  "hosting": {
9
+ "02-2023-release": [
10
  "basic-ionic-6-full-app"
11
+ ]
12
+ }
13
+ },
14
+ "dev-ion4fullpwa": {
15
+ "hosting": {
16
+ "02-2023-release": [
17
+ "dev-ionic-6-full-app"
18
  ]
19
  }
20
  }
21
+ },
22
+ "etags": {}
23
  }
DIFF.md CHANGED
@@ -1,43 +1,22 @@
1
  ## Generate diff file
2
- *BASIC vs PRO (**no /android or /ios configs**)*
3
  ```bash
4
- git diff basic-version..pro-version --diff-filter=ADCMRT ':!package-lock.json' ':!www' ':!.gradle/*' ':!android' ':!ios' ':!*.diff' ':!*.png' ':!*.svg' > diff/basic-vs-pro_changelog.diff
5
  ```
6
 
7
- *BASIC vs PRO (**android config**)*
8
  ```bash
9
- git diff basic-version..pro-version --diff-filter=ADCMRT -- android/ > diff/basic-vs-pro_android-changelog.diff
10
  ```
11
 
12
- *BASIC vs PRO (**ios config**)*
13
  ```bash
14
- git diff basic-version..pro-version --diff-filter=ADCMRT -- ios/ > diff/basic-vs-pro_ios-changelog.diff
15
- ```
16
-
17
- *Last BASIC update (**12-2021**) vs Current BASIC update (**06-2022**)*
18
- ```bash
19
- git diff 12-2021_basic-update..basic-version --diff-filter=ADCMRT ':!package-lock.json' ':!www' ':!.gradle/*' ':!android' ':!ios' ':!*.diff' ':!*.png' ':!*.svg' > diff/last-basic-update-vs-current-basic_changelog.diff
20
- ```
21
-
22
- *Last BASIC update (**12-2021**) vs Current BASIC update (**06-2022**) (**android config**)*
23
- ```bash
24
- git diff 12-2021_basic-update..basic-version --diff-filter=ADCMRT -- android/ > diff/last-basic-update-vs-current-basic_android-changelog.diff
25
- ```
26
-
27
- *Last BASIC update (**12-2021**) vs Current BASIC update (**06-2022**) (**ios config**)*
28
- ```bash
29
- git diff 12-2021_basic-update..basic-version --diff-filter=ADCMRT -- ios/ > diff/last-basic-update-vs-current-basic_ios-changelog.diff
30
  ```
31
 
32
  ## Generate visual diff HTML file
33
  *To generate a static HTML file with the diff*
34
  ```bash
35
- diff2html --style side --file diff/previews/basic-vs-pro_changelog.html --input file -- diff/basic-vs-pro_changelog.diff
36
-
37
- diff2html --style side --file diff/previews/basic-vs-pro_android-changelog.html --input file -- diff/basic-vs-pro_android-changelog.diff
38
-
39
- diff2html --style side --file diff/previews/basic-vs-pro_ios-changelog.html --input file -- diff/basic-vs-pro_ios-changelog.diff
40
-
41
  diff2html --style side --file diff/previews/last-basic-update-vs-current-basic_changelog.html --input file -- diff/last-basic-update-vs-current-basic_changelog.diff
42
 
43
  diff2html --style side --file diff/previews/last-basic-update-vs-current-basic_android-changelog.html --input file -- diff/last-basic-update-vs-current-basic_android-changelog.diff
@@ -47,12 +26,6 @@ diff2html --style side --file diff/previews/last-basic-update-vs-current-basic_i
47
 
48
  *To open the visual diff on the browser*
49
  ```bash
50
- diff2html --style side --input file -- diff/basic-vs-pro_changelog.diff
51
-
52
- diff2html --style side --input file -- diff/basic-vs-pro_android-changelog.diff
53
-
54
- diff2html --style side --input file -- diff/basic-vs-pro_ios-changelog.diff
55
-
56
  diff2html --style side --input file -- diff/last-basic-update-vs-current-basic_changelog.diff
57
 
58
  diff2html --style side --input file -- diff/last-basic-update-vs-current-basic_android-changelog.diff
1
  ## Generate diff file
2
+ *Last BASIC update (**06-2022**) vs Current BASIC update (**02-2023**)*
3
  ```bash
4
+ git diff 06-2022_basic-update..basic-version --diff-filter=ADCMRT ':!package-lock.json' ':!www' ':!diff' ':!.gradle/*' ':!android' ':!ios' ':!*.diff' ':!*.png' ':!*.svg' > diff/last-basic-update-vs-current-basic_changelog.diff
5
  ```
6
 
7
+ *Last BASIC update (**06-2022**) vs Current BASIC update (**02-2023**) (**android config**)*
8
  ```bash
9
+ git diff 06-2022_basic-update..basic-version --diff-filter=ADCMRT -- android/ ':!*.svg' > diff/last-basic-update-vs-current-basic_android-changelog.diff
10
  ```
11
 
12
+ *Last BASIC update (**06-2022**) vs Current BASIC update (**02-2023**) (**ios config**)*
13
  ```bash
14
+ git diff 06-2022_basic-update..basic-version --diff-filter=ADCMRT -- ios/ > diff/last-basic-update-vs-current-basic_ios-changelog.diff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  ```
16
 
17
  ## Generate visual diff HTML file
18
  *To generate a static HTML file with the diff*
19
  ```bash
 
 
 
 
 
 
20
  diff2html --style side --file diff/previews/last-basic-update-vs-current-basic_changelog.html --input file -- diff/last-basic-update-vs-current-basic_changelog.diff
21
 
22
  diff2html --style side --file diff/previews/last-basic-update-vs-current-basic_android-changelog.html --input file -- diff/last-basic-update-vs-current-basic_android-changelog.diff
26
 
27
  *To open the visual diff on the browser*
28
  ```bash
 
 
 
 
 
 
29
  diff2html --style side --input file -- diff/last-basic-update-vs-current-basic_changelog.diff
30
 
31
  diff2html --style side --input file -- diff/last-basic-update-vs-current-basic_android-changelog.diff
FIREBASE.md CHANGED
@@ -1,23 +1,24 @@
1
- # Prepare assets to deploy
 
 
2
  Before deploying the app to Firebase Hosting, run `ionic build --prod`
3
 
4
- # Multiple Environments with Firebase
5
  For managing one site across different environments, we recommend multiple projects for promoting best practices of each environment having its own set of Firebase resources.
6
 
7
  For example for this repo we will have two firebase projects:
8
  - dev-ion4fullpwa
9
- - ion4fullpwa
10
 
11
- ## Check available alias
12
  Before deploying to Firebase Hosting make sure you are using the correct alias (dev, prod)
13
  `firebase use` will list all the alias available
14
  ```
15
  * dev (dev-ion4fullpwa)
16
- prod (ion4fullpwa)
17
- pro (pro-ion4fullpwa)
18
  ```
19
 
20
- ## Create alias
21
  If you don't see these alias (dev, prod), you should create them
22
  `firebase use --add`
23
  ```
@@ -25,7 +26,7 @@ If you don't see these alias (dev, prod), you should create them
25
  ? What alias do you want to use for this project? (e.g. staging) prod
26
  ```
27
 
28
- ## Select alias (switching environments)
29
  `firebase use dev`
30
 
31
  You can also use the `-P` flag to specify an alias like this:
@@ -35,15 +36,15 @@ firebase deploy --only hosting -P dev
35
 
36
  This will deploy to the `dev` alias/environment
37
 
38
- ## Serve and test your Firebase project locally
39
  For more info see: https://firebase.google.com/docs/hosting/deploying
40
  `firebase serve --only hosting`
41
 
42
  ---
43
 
44
- # [Advanced uses](https://firebase.google.com/docs/cli/targets#deploy-target-commands)
45
 
46
- ## [Create target](https://firebase.google.com/docs/cli/targets#set-up-deploy-target-hosting)
47
  - TARGET_NAME = 12-2021-release
48
  - RESOURCE_IDENTIFIER (the SITE_ID) = basic-ionic-5-full-app
49
  ``` bash
@@ -57,7 +58,7 @@ firebase target:apply hosting 06-2022-release basic-ionic-6-full-app -P basic
57
  ```
58
 
59
 
60
- ## [Configure your `firebase.json` file to use deploy targets](https://firebase.google.com/docs/cli/targets#configure_your_firebasejson_file_to_use_deploy_targets)
61
  Don't forget to configure this before deploying to the new target
62
 
63
 
@@ -67,8 +68,85 @@ firebase deploy --only hosting:06-2022-release -P basic
67
  ```
68
 
69
 
70
- ## Create channel
71
- - CHANNEL_ID = dev
 
 
 
72
  ``` bash
73
- firebase hosting:channel:deploy dev --only 06-2022-release -P basic
74
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Firebase instructions
2
+
3
+ ### Prepare assets to deploy
4
  Before deploying the app to Firebase Hosting, run `ionic build --prod`
5
 
6
+ ### Multiple Environments with Firebase
7
  For managing one site across different environments, we recommend multiple projects for promoting best practices of each environment having its own set of Firebase resources.
8
 
9
  For example for this repo we will have two firebase projects:
10
  - dev-ion4fullpwa
11
+ - basic-ionic-6-full-app
12
 
13
+ ### Check available alias
14
  Before deploying to Firebase Hosting make sure you are using the correct alias (dev, prod)
15
  `firebase use` will list all the alias available
16
  ```
17
  * dev (dev-ion4fullpwa)
18
+ basic (basic-ionic-6-full-app)
 
19
  ```
20
 
21
+ ### Create alias
22
  If you don't see these alias (dev, prod), you should create them
23
  `firebase use --add`
24
  ```
26
  ? What alias do you want to use for this project? (e.g. staging) prod
27
  ```
28
 
29
+ ### Select alias (switching environments)
30
  `firebase use dev`
31
 
32
  You can also use the `-P` flag to specify an alias like this:
36
 
37
  This will deploy to the `dev` alias/environment
38
 
39
+ ### Serve and test your Firebase project locally
40
  For more info see: https://firebase.google.com/docs/hosting/deploying
41
  `firebase serve --only hosting`
42
 
43
  ---
44
 
45
+ ## [Advanced uses](https://firebase.google.com/docs/cli/targets#deploy-target-commands)
46
 
47
+ ### [Create target](https://firebase.google.com/docs/cli/targets#set-up-deploy-target-hosting)
48
  - TARGET_NAME = 12-2021-release
49
  - RESOURCE_IDENTIFIER (the SITE_ID) = basic-ionic-5-full-app
50
  ``` bash
58
  ```
59
 
60
 
61
+ ### [Configure your `firebase.json` file to use deploy targets](https://firebase.google.com/docs/cli/targets#configure_your_firebasejson_file_to_use_deploy_targets)
62
  Don't forget to configure this before deploying to the new target
63
 
64
 
68
  ```
69
 
70
 
71
+ ### Create preview channel
72
+ > Preview channels don't have Firebase auth configured automatically `Unable to add channel domain to Firebase Auth`
73
+ - CHANNEL_ID = 6-0-0
74
+ - TARGET_NAME = 02-2023-release
75
+ - PROJECT_ALIAS = basic
76
  ``` bash
77
+ firebase hosting:channel:deploy 6-0-0 --only 02-2023-release -P basic
78
  ```
79
+
80
+
81
+ ---
82
+
83
+ # Update release process
84
+
85
+ ## DEV
86
+ First test the changes on the dev site (dev-ionic-6-full-app)
87
+
88
+
89
+ ### 1 - Create new target
90
+ > This updates the `.firebaserc` file
91
+
92
+ - TARGET_NAME = 02-2023-release
93
+ - RESOURCE_IDENTIFIER (the SITE_ID) = dev-ionic-6-full-app
94
+ - PROJECT_ALIAS = dev
95
+ ``` bash
96
+ firebase target:apply hosting 02-2023-release dev-ionic-6-full-app -P dev
97
+ ```
98
+
99
+
100
+ ### 2 - Update firebase.json
101
+ > Manually update the file and add the new target (`02-2023-release`) config (just copy and paste from the previous one)
102
+
103
+
104
+ ### [OPTIONAL] - Create preview channel for the latest update you want to test live
105
+ > Preview channels don't have Firebase auth configured automatically `Unable to add channel domain to Firebase Auth`
106
+ - CHANNEL_ID = 6-0-0
107
+ - TARGET_NAME = 02-2023-release
108
+ - PROJECT_ALIAS = dev
109
+ ``` bash
110
+ firebase hosting:channel:deploy 6-0-0 --only 02-2023-release -P dev
111
+ ```
112
+
113
+
114
+ ### 3 - Deploy and test new version of the site
115
+ > Deploy the new version of the site
116
+ - TARGET_NAME = 02-2023-release
117
+ - PROJECT_ALIAS = dev
118
+ ``` bash
119
+ firebase deploy --only hosting:02-2023-release -P dev
120
+ ```
121
+
122
+ > Go to the preview channel and test it
123
+ [https://dev-ionic-6-full-app.web.app]
124
+
125
+
126
+ ---
127
+
128
+ ## LIVE (prod)
129
+ After you test the new version of the site, you can deploy to the production site (basic-ionic-6-full-app)
130
+
131
+
132
+ ### 1 - Create new target
133
+ > This updates the `.firebaserc` file
134
+
135
+ - TARGET_NAME = 02-2023-release
136
+ - RESOURCE_IDENTIFIER (the SITE_ID) = basic-ionic-6-full-app
137
+ - PROJECT_ALIAS = basic
138
+ ``` bash
139
+ firebase target:apply hosting 02-2023-release basic-ionic-6-full-app -P basic
140
+ ```
141
+
142
+
143
+ ### 2 - Deploy and test new version of the site
144
+ > Deploy the new version of the site
145
+ - TARGET_NAME = 02-2023-release
146
+ - PROJECT_ALIAS = basic
147
+ ``` bash
148
+ firebase deploy --only hosting:02-2023-release -P basic
149
+ ```
150
+
151
+ > Go to the preview channel and test it
152
+ [https://basic-ionic-6-full-app.web.app]
README.md CHANGED
@@ -16,7 +16,6 @@ Run `ionic build` or `ionic build --prod` to build the project
16
  Run `ionic serve` to start a live-reload dev server
17
 
18
  ### To test the app as a Native App
19
-
20
  This project uses [Capacitor](https://capacitor.ionicframework.com/docs/) (spiritual successor to Cordova).
21
 
22
  [Read this post](https://ionicthemes.com/tutorials/about/native-cross-platform-web-apps-with-ionic-capacitor) to get an introduction about Capacitor and learn the main differences between Capacitor and Cordova.
@@ -29,14 +28,38 @@ The Capacitor workflow involves a few consistent tasks:
29
  - [Open your Native IDE](https://capacitor.ionicframework.com/docs/basics/workflow/#3-open-your-native-ide)
30
  - [Periodic Maintenance](https://capacitor.ionicframework.com/docs/basics/workflow/#4-periodic-maintenance)
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  #### iOS Platform
33
- This app has an ios folder which contains the iOS native app.
34
  Read how to [build this app for iOS](https://capacitor.ionicframework.com/docs/basics/building-your-app#ios).
35
 
36
  #### Android Platform
37
  This app has an android folder which contains the Android native app.
38
  Read how to [build this app for Android](https://capacitor.ionicframework.com/docs/basics/building-your-app#android).
39
 
 
 
40
 
41
  ## Support
42
  Drop us a line to contact@ionicthemes.com
16
  Run `ionic serve` to start a live-reload dev server
17
 
18
  ### To test the app as a Native App
 
19
  This project uses [Capacitor](https://capacitor.ionicframework.com/docs/) (spiritual successor to Cordova).
20
 
21
  [Read this post](https://ionicthemes.com/tutorials/about/native-cross-platform-web-apps-with-ionic-capacitor) to get an introduction about Capacitor and learn the main differences between Capacitor and Cordova.
28
  - [Open your Native IDE](https://capacitor.ionicframework.com/docs/basics/workflow/#3-open-your-native-ide)
29
  - [Periodic Maintenance](https://capacitor.ionicframework.com/docs/basics/workflow/#4-periodic-maintenance)
30
 
31
+ #### Building your web code​
32
+ > Once you are ready to test your web app on a mobile device, you'll need to build your web app for distribution.
33
+
34
+ Run `ionic build`
35
+
36
+ #### Syncing your web code to your Capacitor project​
37
+ > Once your web code has been built for distribution, you will need to push your web code to the web native Capacitor application.
38
+
39
+ Run `npx cap sync`
40
+
41
+ > Running `npx cap sync` will copy over your already built web bundle to both your Android and iOS projects as well as update the native dependencies that Capacitor uses.
42
+
43
+ #### Testing your Capacitor app
44
+ > Once you've synced over your web bundle to your native project, it is time to test your application on a mobile device.
45
+
46
+ Run `npx cap run ios` and `npx cap run android`
47
+
48
+ ##### Open your Native IDE​
49
+ > If you'd like more control over your native project you can quickly open the native IDEs using the Capacitor CLI.
50
+
51
+ Run `npx cap open ios` and `npx cap open android`
52
+
53
  #### iOS Platform
54
+ This app has an iOS folder which contains the iOS native app.
55
  Read how to [build this app for iOS](https://capacitor.ionicframework.com/docs/basics/building-your-app#ios).
56
 
57
  #### Android Platform
58
  This app has an android folder which contains the Android native app.
59
  Read how to [build this app for Android](https://capacitor.ionicframework.com/docs/basics/building-your-app#android).
60
 
61
+ ### Want to use Cordova?
62
+ The BASIC version of the template uses Capacitor instead of Cordova, however, if you are not yet ready to use it, in the following link we show you how to remove Capacitor and add Cordova to this project: https://ionic-4-full-starter-app-docs.ionicthemes.com/capacitor#steps-to-remove-capacitor-and-add-cordova
63
 
64
  ## Support
65
  Drop us a line to contact@ionicthemes.com
UPDATE.md ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Update process
2
+
3
+ ## Capacitor 4
4
+
5
+ ### Update from Capacitor 3 to Capacitor 4
6
+ > Install the latest version of the Capacitor CLI to your project
7
+ ``` bash
8
+ npm i -D @capacitor/cli@latest
9
+ ```
10
+
11
+ >Use the CLI to handle the migration for you
12
+ ``` bash
13
+ npx cap migrate
14
+ ```
15
+
16
+ The migration should be smooth, and all the steps required both for iOS and Android are handled by the CLI. However, you can check both iOS and Android specific migration steps here:
17
+ - [iOS update](https://capacitorjs.com/docs/updating/4-0#ios)
18
+ - [Android update](https://capacitorjs.com/docs/updating/4-0#android)
19
+
20
+
21
+ ---
22
+
23
+
24
+ ### Update Capacitor plugins
25
+ > All Capacitor official plugins were updated when running the migration tool.
26
+ > The Capacitor community plugins need to be updated manually
27
+ ``` bash
28
+ npm install --save @capacitor-firebase/authentication@1.3.0
29
+ ```
30
+
31
+ > Make sure you run this command after updating the Capacitor plugins
32
+ ``` bash
33
+ npx cap sync
34
+ ```
35
+
36
+
37
+ ---
38
+
39
+
40
+ ## Ionic 6.5.0
41
+
42
+ ### Update to Ionic 6.5.0
43
+ ``` bash
44
+ ng update @ionic/angular@latest --create-commits
45
+ ```
46
+
47
+ ### Update Ionic dev dependencies
48
+ ``` bash
49
+ ng update @ionic/angular-toolkit @ionic/cli --create-commits
50
+ ```
51
+
52
+
53
+ --
54
+
55
+
56
+ ## Angular 15
57
+
58
+ > Make sure the Angular CLI is up-to-date
59
+ ``` bash
60
+ npm install -g @angular/cli
61
+ ```
62
+
63
+ ### Update from Angular 13 to Angular 14
64
+ > We should update first to Angular 14 and then to Angular 15
65
+ ``` bash
66
+ ng update @angular-eslint/schematics@14 @angular/core@14 @angular/cli@14 --create-commits
67
+ ```
68
+
69
+ ### Update from Angular 14 to Angular 15
70
+ > Then we can update Angular 15
71
+ ``` bash
72
+ ng update @angular/fire @angular-eslint/schematics@15 @angular/core@15 @angular/cli@15 --create-commits
73
+ ```
74
+
75
+
76
+ ## Other dependencies
77
+ > First check outdated dependencies by running this command
78
+ ``` bash
79
+ npm outdated --depth=0 --long
80
+ ```
81
+
82
+ ### Update dependencies
83
+ ``` bash
84
+ npm install --save firebase
85
+ npm install --save core-js
86
+ npm install --save dayjs
87
+ npm install --save google-libphonenumber
88
+ npm install --save rxjs@7.8.0
89
+ npm install --save swiper
90
+ npm install --save tslib
91
+ npm install --save zone.js
92
+ ```
93
+
94
+ ### Update dev dependencies
95
+ ``` bash
96
+ npm install --save-dev @commitlint/cli @commitlint/config-angular
97
+ npm install --save-dev @types/node
98
+ npm install --save-dev @webcomponents/webcomponentsjs
99
+ npm install --save-dev ts-node
100
+ ```
101
+
102
+
103
+ # 2023-02-01 Updated dependencies list
104
+ > Check by running this command:
105
+ ``` bash
106
+ npm list --depth=0
107
+ ```
108
+
109
+ - @angular-devkit/architect@0.1501.2
110
+ - @angular-devkit/build-angular@15.1.2
111
+ - @angular-devkit/core@15.1.2
112
+ - @angular-devkit/schematics@15.1.2
113
+ - @angular-eslint/builder@15.2.0
114
+ - @angular-eslint/eslint-plugin@15.2.0
115
+ - @angular-eslint/eslint-plugin-template@15.2.0
116
+ - @angular-eslint/schematics@15.2.0
117
+ - @angular-eslint/template-parser@15.2.0
118
+ - @angular/animations@15.1.1
119
+ - @angular/cli@15.1.2
120
+ - @angular/common@15.1.1
121
+ - @angular/compiler@15.1.1
122
+ - @angular/compiler-cli@15.1.1
123
+ - @angular/core@15.1.1
124
+ - @angular/fire@7.5.0
125
+ - @angular/forms@15.1.1
126
+ - @angular/language-service@15.1.1
127
+ - @angular/platform-browser@15.1.1
128
+ - @angular/platform-browser-dynamic@15.1.1
129
+ - @angular/router@15.1.1
130
+ - @angular/service-worker@15.1.1
131
+ - @capacitor-firebase/authentication@1.3.0
132
+ - @capacitor/android@4.6.2
133
+ - @capacitor/app@4.1.1
134
+ - @capacitor/cli@4.6.2
135
+ - @capacitor/core@4.6.2
136
+ - @capacitor/geolocation@4.1.0
137
+ - @capacitor/haptics@4.1.0
138
+ - @capacitor/ios@4.6.2
139
+ - @capacitor/keyboard@4.1.1
140
+ - @capacitor/preferences@4.0.2
141
+ - @capacitor/share@4.1.0
142
+ - @capacitor/splash-screen@4.1.3
143
+ - @capacitor/status-bar@4.1.1
144
+ - @commitlint/cli@17.4.2
145
+ - @commitlint/config-angular@17.4.2
146
+ - @ionic/angular@6.5.0
147
+ - @ionic/angular-toolkit@7.0.0
148
+ - @ionic/cli@6.20.8
149
+ - @types/core-js@2.5.5
150
+ - @types/node@17.0.45
151
+ - @typescript-eslint/eslint-plugin@5.49.0
152
+ - @typescript-eslint/parser@5.49.0
153
+ - @webcomponents/webcomponentsjs@2.7.0
154
+ - angular-pipes@10.0.0
155
+ - cordova-res@0.15.4
156
+ - core-js@2.6.12
157
+ - dayjs@1.11.7
158
+ - eslint@8.32.0
159
+ - firebase@9.16.0
160
+ - google-libphonenumber@3.2.31
161
+ - husky@4.3.8
162
+ - rxjs@7.8.0
163
+ - swiper@8.4.6
164
+ - ts-node@8.10.2
165
+ - tslib@2.4.1
166
+ - typescript@4.8.4
167
+ - zone.js@0.11.8
168
+
169
+
170
+ ---
171
+
172
+
173
+ # Tags
174
+ To create an annotated tag, enter the following:
175
+ ``` bash
176
+ git tag -a 11-2022_elite-release -m 'the initial ELITE release'
177
+ ```
178
+ Then run:
179
+ ``` bash
180
+ git push origin --tags
181
+ ```
182
+
183
+
184
+ ---
185
+
186
+
187
+ # Miscellaneous
188
+ > When updating an existing project you may want to get a specific file from another branch
189
+
190
+ ### Cherry-pick files from another git branch
191
+ > Get just one file from another branch
192
+ ``` bash
193
+ git checkout pro-version -- src/global.scss
194
+ git checkout pro-version -- src/app/firebase/auth/firebase-auth.helper.ts
195
+ git checkout pro-version -- src/app/firebase/auth/firebase-auth.module.ts
196
+ ```
angular.json CHANGED
@@ -1,7 +1,6 @@
1
  {
2
  "$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
3
  "version": 1,
4
- "defaultProject": "app",
5
  "newProjectRoot": "projects",
6
  "projects": {
7
  "app": {
@@ -127,7 +126,10 @@
127
  }
128
  },
129
  "cli": {
130
- "defaultCollection": "@angular-eslint/schematics"
 
 
 
131
  },
132
  "schematics": {
133
  "@ionic/angular-toolkit:component": {
@@ -135,6 +137,12 @@
135
  },
136
  "@ionic/angular-toolkit:page": {
137
  "styleext": "scss"
 
 
 
 
 
 
138
  }
139
  }
140
- }
1
  {
2
  "$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
3
  "version": 1,
 
4
  "newProjectRoot": "projects",
5
  "projects": {
6
  "app": {
126
  }
127
  },
128
  "cli": {
129
+ "schematicCollections": [
130
+ "@ionic/angular-toolkit",
131
+ "@angular-eslint/schematics"
132
+ ]
133
  },
134
  "schematics": {
135
  "@ionic/angular-toolkit:component": {
137
  },
138
  "@ionic/angular-toolkit:page": {
139
  "styleext": "scss"
140
+ },
141
+ "@angular-eslint/schematics:application": {
142
+ "setParserOptionsProject": true
143
+ },
144
+ "@angular-eslint/schematics:library": {
145
+ "setParserOptionsProject": true
146
  }
147
  }
148
+ }
capacitor.config.ts CHANGED
@@ -7,7 +7,7 @@ const config: CapacitorConfig = {
7
  bundledWebRuntime: false,
8
  plugins: {
9
  SplashScreen: {
10
- launchAutoHide: false,
11
  },
12
  FirebaseAuthentication: {
13
  skipNativeAuth: false,
7
  bundledWebRuntime: false,
8
  plugins: {
9
  SplashScreen: {
10
+ launchAutoHide: false
11
  },
12
  FirebaseAuthentication: {
13
  skipNativeAuth: false,
firebase.json CHANGED
@@ -1,5 +1,47 @@
1
  {
2
  "hosting": [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  {
4
  "target": "06-2022-release",
5
  "public": "www",
1
  {
2
  "hosting": [
3
+ {
4
+ "target": "02-2023-release",
5
+ "public": "www",
6
+ "ignore": [
7
+ "firebase.json",
8
+ "**/.*",
9
+ "**/node_modules/**"
10
+ ],
11
+ "rewrites": [ {
12
+ "source": "**",
13
+ "destination": "/index.html"
14
+ } ],
15
+ "headers": [
16
+ {
17
+ "source": "**",
18
+ "headers": [
19
+ {
20
+ "key": "Cache-Control",
21
+ "value": "no-cache, no-store, must-revalidate"
22
+ }
23
+ ]
24
+ },
25
+ {
26
+ "source": "**/*.@(jpg|jpeg|gif|png|svg|webp|js|css|eot|otf|ttf|ttc|woff|font.css)",
27
+ "headers": [
28
+ {
29
+ "key": "Cache-Control",
30
+ "value": "no-cache"
31
+ }
32
+ ]
33
+ },
34
+ {
35
+ "source": "ngsw-worker.js",
36
+ "headers": [
37
+ {
38
+ "key": "Cache-Control",
39
+ "value": "no-cache"
40
+ }
41
+ ]
42
+ }
43
+ ]
44
+ },
45
  {
46
  "target": "06-2022-release",
47
  "public": "www",
package.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "IonicFullApp-BASIC",
3
  "description": "The most advanced and complete Mobile & PWA Ionic starter app template",
4
- "version": "5.0.0",
5
  "author": "IonicThemes",
6
  "contributors": [
7
  "Dayana <dayana@ionicthemes.com>",
@@ -16,66 +16,66 @@
16
  "lint": "ng lint"
17
  },
18
  "dependencies": {
19
- "@angular/animations": "^13.1.1",
20
- "@angular/common": "^13.1.1",
21
- "@angular/core": "^13.1.1",
22
- "@angular/fire": "^7.4.1",
23
- "@angular/forms": "^13.1.1",
24
- "@angular/platform-browser": "^13.1.1",
25
- "@angular/platform-browser-dynamic": "^13.1.1",
26
- "@angular/router": "^13.1.1",
27
- "@angular/service-worker": "^13.1.1",
28
- "@capacitor-firebase/authentication": "^0.3.1",
29
- "@capacitor/android": "^3.5.1",
30
- "@capacitor/app": "^1.1.1",
31
- "@capacitor/core": "^3.5.1",
32
- "@capacitor/geolocation": "^1.3.1",
33
- "@capacitor/haptics": "^1.1.4",
34
- "@capacitor/ios": "^3.5.1",
35
- "@capacitor/keyboard": "^1.2.2",
36
- "@capacitor/share": "^1.1.2",
37
- "@capacitor/splash-screen": "^1.2.2",
38
- "@capacitor/status-bar": "^1.0.8",
39
- "@capacitor/storage": "^1.2.5",
40
- "@ionic/angular": "^6.1.9",
41
  "@types/core-js": "^2.5.5",
42
  "angular-pipes": "^10.0.0",
43
- "core-js": "^2.6.11",
44
- "dayjs": "^1.11.3",
45
- "firebase": "^9.8.3",
46
- "google-libphonenumber": "^3.2.28",
47
- "rxjs": "~6.6.6",
48
- "swiper": "^8.2.2",
49
- "tslib": "^2.0.0",
50
- "zone.js": "~0.11.4"
51
  },
52
  "devDependencies": {
53
- "@angular-devkit/architect": "^0.1301.2",
54
- "@angular-devkit/build-angular": "^13.1.2",
55
- "@angular-devkit/core": "^13.1.2",
56
- "@angular-devkit/schematics": "^13.1.2",
57
- "@angular-eslint/builder": "13.0.1",
58
- "@angular-eslint/eslint-plugin": "13.0.1",
59
- "@angular-eslint/eslint-plugin-template": "13.0.1",
60
- "@angular-eslint/schematics": "13.0.1",
61
- "@angular-eslint/template-parser": "13.0.1",
62
- "@angular/cli": "^13.1.2",
63
- "@angular/compiler": "^13.1.1",
64
- "@angular/compiler-cli": "^13.1.1",
65
- "@angular/language-service": "~13.1.1",
66
- "@capacitor/cli": "^3.5.1",
67
- "@commitlint/cli": "^17.0.2",
68
- "@commitlint/config-angular": "^17.0.0",
69
- "@ionic/angular-toolkit": "^6.1.0",
70
- "@ionic/cli": "6.19.1",
71
- "@types/node": "^17.0.2",
72
- "@typescript-eslint/eslint-plugin": "^5.27.1",
73
- "@typescript-eslint/parser": "^5.27.1",
74
- "@webcomponents/webcomponentsjs": "^2.6.0",
75
  "cordova-res": "0.15.4",
76
- "eslint": "^8.17.0",
77
  "husky": "^4.3.0",
78
- "ts-node": "^8.10.1",
79
- "typescript": "~4.5.4"
80
  }
81
  }
1
  {
2
  "name": "IonicFullApp-BASIC",
3
  "description": "The most advanced and complete Mobile & PWA Ionic starter app template",
4
+ "version": "6.0.0",
5
  "author": "IonicThemes",
6
  "contributors": [
7
  "Dayana <dayana@ionicthemes.com>",
16
  "lint": "ng lint"
17
  },
18
  "dependencies": {
19
+ "@angular/animations": "^15.1.1",
20
+ "@angular/common": "^15.1.1",
21
+ "@angular/core": "^15.1.1",
22
+ "@angular/fire": "^7.5.0",
23
+ "@angular/forms": "^15.1.1",
24
+ "@angular/platform-browser": "^15.1.1",
25
+ "@angular/platform-browser-dynamic": "^15.1.1",
26
+ "@angular/router": "^15.1.1",
27
+ "@angular/service-worker": "^15.1.1",
28
+ "@capacitor-firebase/authentication": "^1.3.0",
29
+ "@capacitor/android": "^4.0.0",
30
+ "@capacitor/app": "^4.0.0",
31
+ "@capacitor/core": "^4.0.0",
32
+ "@capacitor/geolocation": "^4.0.0",
33
+ "@capacitor/haptics": "^4.0.0",
34
+ "@capacitor/ios": "^4.0.0",
35
+ "@capacitor/keyboard": "^4.0.0",
36
+ "@capacitor/preferences": "^4.0.2",
37
+ "@capacitor/share": "^4.0.0",
38
+ "@capacitor/splash-screen": "^4.0.0",
39
+ "@capacitor/status-bar": "^4.0.0",
40
+ "@ionic/angular": "^6.5.0",
41
  "@types/core-js": "^2.5.5",
42
  "angular-pipes": "^10.0.0",
43
+ "core-js": "^2.6.12",
44
+ "dayjs": "^1.11.7",
45
+ "firebase": "^9.16.0",
46
+ "google-libphonenumber": "^3.2.31",
47
+ "rxjs": "^7.8.0",
48
+ "swiper": "^8.4.6",
49
+ "tslib": "^2.4.1",
50
+ "zone.js": "^0.11.8"
51
  },
52
  "devDependencies": {
53
+ "@angular-devkit/architect": "^0.1501.2",
54
+ "@angular-devkit/build-angular": "^15.1.2",
55
+ "@angular-devkit/core": "^15.1.2",
56
+ "@angular-devkit/schematics": "^15.1.2",
57
+ "@angular-eslint/builder": "15.2.0",
58
+ "@angular-eslint/eslint-plugin": "15.2.0",
59
+ "@angular-eslint/eslint-plugin-template": "15.2.0",
60
+ "@angular-eslint/schematics": "15.2.0",
61
+ "@angular-eslint/template-parser": "15.2.0",
62
+ "@angular/cli": "^15.1.2",
63
+ "@angular/compiler": "^15.1.1",
64
+ "@angular/compiler-cli": "^15.1.1",
65
+ "@angular/language-service": "^15.1.1",
66
+ "@capacitor/cli": "^4.0.0",
67
+ "@commitlint/cli": "^17.4.2",
68
+ "@commitlint/config-angular": "^17.4.2",
69
+ "@ionic/angular-toolkit": "^7.0.0",
70
+ "@ionic/cli": "6.20.8",
71
+ "@types/node": "^17.0.45",
72
+ "@typescript-eslint/eslint-plugin": "^5.43.0",
73
+ "@typescript-eslint/parser": "^5.43.0",
74
+ "@webcomponents/webcomponentsjs": "^2.7.0",
75
  "cordova-res": "0.15.4",
76
+ "eslint": "^8.28.0",
77
  "husky": "^4.3.0",
78
+ "ts-node": "^8.10.2",
79
+ "typescript": "~4.8.4"
80
  }
81
  }
src/app/app-routing.module.ts CHANGED
@@ -77,10 +77,9 @@ const routes: Routes = [
77
  @NgModule({
78
  imports: [
79
  RouterModule.forRoot(routes, {
80
- initialNavigation: 'enabled',
81
  scrollPositionRestoration: 'enabled',
82
- anchorScrolling: 'enabled',
83
- relativeLinkResolution: 'legacy'
84
  })
85
  ],
86
  exports: [RouterModule]
77
  @NgModule({
78
  imports: [
79
  RouterModule.forRoot(routes, {
80
+ initialNavigation: 'enabledBlocking',
81
  scrollPositionRestoration: 'enabled',
82
+ anchorScrolling: 'enabled'
 
83
  })
84
  ],
85
  exports: [RouterModule]
src/app/app.component.html CHANGED
@@ -116,7 +116,7 @@
116
  </ion-list>
117
  </ion-content>
118
  </ion-menu>
119
- <!-- Main app content get's rendered in this router-outlet -->
120
  <ion-router-outlet id="menu-content"></ion-router-outlet>
121
  </ion-split-pane>
122
  </ion-app>
116
  </ion-list>
117
  </ion-content>
118
  </ion-menu>
119
+ <!-- Main app content gets rendered in this router-outlet -->
120
  <ion-router-outlet id="menu-content"></ion-router-outlet>
121
  </ion-split-pane>
122
  </ion-app>
src/app/app.component.ts CHANGED
@@ -1,7 +1,8 @@
1
  import { Component } from '@angular/core';
2
  import { Router } from '@angular/router';
 
3
  import { SplashScreen } from '@capacitor/splash-screen';
4
- import { Storage } from '@capacitor/storage';
5
 
6
  @Component({
7
  selector: 'app-root',
@@ -73,7 +74,7 @@ export class AppComponent {
73
 
74
  public openTutorial(): void {
75
  // save key to mark the walkthrough as NOT visited because the user wants to check it out
76
- Storage.set({
77
  key: 'visitedWalkthrough',
78
  value: 'false'
79
  });
1
  import { Component } from '@angular/core';
2
  import { Router } from '@angular/router';
3
+
4
  import { SplashScreen } from '@capacitor/splash-screen';
5
+ import { Preferences } from '@capacitor/preferences';
6
 
7
  @Component({
8
  selector: 'app-root',
74
 
75
  public openTutorial(): void {
76
  // save key to mark the walkthrough as NOT visited because the user wants to check it out
77
+ Preferences.set({
78
  key: 'visitedWalkthrough',
79
  value: 'false'
80
  });
src/app/categories/categories.module.ts CHANGED
@@ -2,7 +2,6 @@ import { IonicModule } from '@ionic/angular';
2
  import { RouterModule, Routes } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
 
7
  import { ComponentsModule } from '../components/components.module';
8
 
@@ -19,7 +18,6 @@ const categoriesRoutes: Routes = [
19
  imports: [
20
  IonicModule,
21
  CommonModule,
22
- FormsModule,
23
  RouterModule.forChild(categoriesRoutes),
24
  ComponentsModule
25
  ],
2
  import { RouterModule, Routes } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
 
5
 
6
  import { ComponentsModule } from '../components/components.module';
7
 
18
  imports: [
19
  IonicModule,
20
  CommonModule,
 
21
  RouterModule.forChild(categoriesRoutes),
22
  ComponentsModule
23
  ],
src/app/components/countdown-timer/countdown-timer.component.ts CHANGED
@@ -87,7 +87,7 @@ export class CountdownTimerComponent implements OnInit, OnDestroy {
87
  }
88
 
89
  constructor(
90
- @Inject(PLATFORM_ID) private platformId: object,
91
  ) { }
92
 
93
  ngOnInit(): void {
87
  }
88
 
89
  constructor(
90
+ @Inject(PLATFORM_ID) private platformId: object
91
  ) { }
92
 
93
  ngOnInit(): void {
src/app/components/counter-input/counter-input.component.ts CHANGED
@@ -1,8 +1,8 @@
1
  import { Component, forwardRef, Input, OnChanges, ViewEncapsulation } from '@angular/core';
2
- import { FormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
3
 
4
  export function counterRangeValidator(minValue, maxValue) {
5
- return (c: FormControl) => {
6
  const err = {
7
  rangeError: {
8
  given: c.value,
@@ -71,7 +71,7 @@ export class CounterInputComponent implements ControlValueAccessor, OnChanges {
71
  this.counterValue--;
72
  }
73
 
74
- validate(c: FormControl) {
75
  return this.validateFn(c);
76
  }
77
  }
1
  import { Component, forwardRef, Input, OnChanges, ViewEncapsulation } from '@angular/core';
2
+ import { UntypedFormControl, ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
3
 
4
  export function counterRangeValidator(minValue, maxValue) {
5
+ return (c: UntypedFormControl) => {
6
  const err = {
7
  rangeError: {
8
  given: c.value,
71
  this.counterValue--;
72
  }
73
 
74
+ validate(c: UntypedFormControl) {
75
  return this.validateFn(c);
76
  }
77
  }
src/app/contact-card/contact-card.module.ts CHANGED
@@ -2,7 +2,6 @@ import { IonicModule } from '@ionic/angular';
2
  import { RouterModule } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
 
7
  import { ContactCardPage } from './contact-card.page';
8
  import { ComponentsModule } from '../components/components.module';
@@ -11,7 +10,6 @@ import { ComponentsModule } from '../components/components.module';
11
  imports: [
12
  IonicModule,
13
  CommonModule,
14
- FormsModule,
15
  ComponentsModule,
16
  RouterModule.forChild([{ path: '', component: ContactCardPage }])
17
  ],
2
  import { RouterModule } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
 
5
 
6
  import { ContactCardPage } from './contact-card.page';
7
  import { ComponentsModule } from '../components/components.module';
10
  imports: [
11
  IonicModule,
12
  CommonModule,
 
13
  ComponentsModule,
14
  RouterModule.forChild([{ path: '', component: ContactCardPage }])
15
  ],
src/app/deals/details/deals-details.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -27,7 +26,6 @@ const routes: Routes = [
27
  @NgModule({
28
  imports: [
29
  CommonModule,
30
- FormsModule,
31
  IonicModule,
32
  RouterModule.forChild(routes),
33
  ComponentsModule,
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
26
  @NgModule({
27
  imports: [
28
  CommonModule,
 
29
  IonicModule,
30
  RouterModule.forChild(routes),
31
  ComponentsModule,
src/app/deals/details/deals-details.page.ts CHANGED
@@ -1,5 +1,10 @@
1
  import { Component, OnInit } from '@angular/core';
2
  import { ActivatedRoute } from '@angular/router';
 
 
 
 
 
3
 
4
  @Component({
5
  selector: 'app-deals-details',
1
  import { Component, OnInit } from '@angular/core';
2
  import { ActivatedRoute } from '@angular/router';
3
+ import { IonicSwiper } from "@ionic/angular";
4
+
5
+ import SwiperCore, { Pagination } from "swiper";
6
+
7
+ SwiperCore.use([Pagination, IonicSwiper]);
8
 
9
  @Component({
10
  selector: 'app-deals-details',
src/app/deals/listing/deals-listing.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -25,7 +24,6 @@ const routes: Routes = [
25
  @NgModule({
26
  imports: [
27
  CommonModule,
28
- FormsModule,
29
  IonicModule,
30
  RouterModule.forChild(routes),
31
  ComponentsModule,
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
24
  @NgModule({
25
  imports: [
26
  CommonModule,
 
27
  IonicModule,
28
  RouterModule.forChild(routes),
29
  ComponentsModule,
src/app/fashion/details/fashion-details.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -26,7 +25,6 @@ const routes: Routes = [
26
  @NgModule({
27
  imports: [
28
  CommonModule,
29
- FormsModule,
30
  IonicModule,
31
  RouterModule.forChild(routes),
32
  ComponentsModule,
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
25
  @NgModule({
26
  imports: [
27
  CommonModule,
 
28
  IonicModule,
29
  RouterModule.forChild(routes),
30
  ComponentsModule,
src/app/fashion/details/fashion-details.page.ts CHANGED
@@ -1,8 +1,14 @@
1
  import { Component, OnInit } from '@angular/core';
2
  import { ActivatedRoute } from '@angular/router';
3
  import { AlertController } from '@ionic/angular';
 
 
 
4
  import { Subscription } from 'rxjs';
5
 
 
 
 
6
  @Component({
7
  selector: 'app-fashion-details',
8
  templateUrl: './fashion-details.page.html',
1
  import { Component, OnInit } from '@angular/core';
2
  import { ActivatedRoute } from '@angular/router';
3
  import { AlertController } from '@ionic/angular';
4
+ import { IonicSwiper } from "@ionic/angular";
5
+ import SwiperCore, { Pagination } from "swiper";
6
+
7
  import { Subscription } from 'rxjs';
8
 
9
+ SwiperCore.use([Pagination, IonicSwiper]);
10
+
11
+
12
  @Component({
13
  selector: 'app-fashion-details',
14
  templateUrl: './fashion-details.page.html',
src/app/fashion/listing/fashion-listing.module.ts CHANGED
@@ -1,10 +1,8 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
7
-
8
  import { ComponentsModule } from '../../components/components.module';
9
 
10
  import { FashionService } from '../fashion.service';
@@ -24,7 +22,6 @@ const routes: Routes = [
24
  @NgModule({
25
  imports: [
26
  CommonModule,
27
- FormsModule,
28
  IonicModule,
29
  RouterModule.forChild(routes),
30
  ComponentsModule
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
 
6
  import { ComponentsModule } from '../../components/components.module';
7
 
8
  import { FashionService } from '../fashion.service';
22
  @NgModule({
23
  imports: [
24
  CommonModule,
 
25
  IonicModule,
26
  RouterModule.forChild(routes),
27
  ComponentsModule
src/app/firebase/auth/firebase-auth.helper.ts ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Injectable } from '@angular/core';
2
+
3
+ import { FacebookAuthProvider, getAdditionalUserInfo, GoogleAuthProvider, OAuthProvider, TwitterAuthProvider } from '@angular/fire/auth';
4
+ import {
5
+ AuthCredential as FirebaseAuthCredential,
6
+ AuthProvider as FirebaseAuthProvider,
7
+ CustomParameters as FirebaseCustomParameters,
8
+ OAuthCredential,
9
+ User as FirebaseUser,
10
+ UserCredential as FirebaseUserCredential
11
+ } from '@angular/fire/auth';
12
+
13
+ import { AuthCredential, SignInResult, User, AdditionalUserInfo, SignInOptions } from '@capacitor-firebase/authentication';
14
+
15
+
16
+ // * Aux methods inspired on the @capacitor-firebase/authentication library
17
+ @Injectable()
18
+ export class FirebaseAuthHelper {
19
+
20
+ public applySignInOptions(options: SignInOptions, provider: OAuthProvider | GoogleAuthProvider | FacebookAuthProvider | TwitterAuthProvider) {
21
+ if (options.customParameters) {
22
+ const customParameters: FirebaseCustomParameters = {};
23
+ options.customParameters.map(parameter => {
24
+ customParameters[parameter.key] = parameter.value;
25
+ });
26
+ provider.setCustomParameters(customParameters);
27
+ }
28
+ if (options.scopes) {
29
+ for (const scope of options.scopes) {
30
+ provider.addScope(scope);
31
+ }
32
+ }
33
+ }
34
+
35
+ // ? (see: https://github.com/capawesome-team/capacitor-firebase/blob/9024eef856dbd25b2b6459e4b6bcee104ca89755/packages/authentication/src/web.ts#L594)
36
+ public createSignInResult(userCredential: FirebaseUserCredential | null, authCredential: FirebaseAuthCredential | null): SignInResult {
37
+ const userResult = this.createUserResult(userCredential?.user || null);
38
+ const credentialResult = this.createCredentialResult(authCredential);
39
+ const additionalUserInfoResult = this.createAdditionalUserInfoResult(userCredential);
40
+ const result: SignInResult = {
41
+ user: userResult,
42
+ credential: credentialResult,
43
+ additionalUserInfo: additionalUserInfoResult
44
+ };
45
+ return result;
46
+ }
47
+
48
+ // ? (see: https://github.com/capawesome-team/capacitor-firebase/blob/9024eef856dbd25b2b6459e4b6bcee104ca89755/packages/authentication/src/web.ts#L627)
49
+ public createUserResult(user: FirebaseUser | null): User | null {
50
+ if (!user) {
51
+ return null;
52
+ }
53
+ const result: User = {
54
+ displayName: user.displayName,
55
+ email: user.email,
56
+ emailVerified: user.emailVerified,
57
+ isAnonymous: user.isAnonymous,
58
+ phoneNumber: user.phoneNumber,
59
+ photoUrl: user.providerData[0].photoURL,
60
+ providerId: user.providerData[0].providerId,
61
+ tenantId: user.tenantId,
62
+ uid: user.uid
63
+ };
64
+ return result;
65
+ }
66
+
67
+ // ? (see: https://github.com/capawesome-team/capacitor-firebase/blob/9024eef856dbd25b2b6459e4b6bcee104ca89755/packages/authentication/src/web.ts#L610)
68
+ private createCredentialResult(credential: FirebaseAuthCredential | null): AuthCredential | null {
69
+ if (!credential) {
70
+ return null;
71
+ }
72
+ const result: AuthCredential = {
73
+ providerId: credential.providerId
74
+ };
75
+ if (credential instanceof OAuthCredential) {
76
+ result.accessToken = credential.accessToken;
77
+ result.idToken = credential.idToken;
78
+ result.secret = credential.secret;
79
+ }
80
+ return result;
81
+ }
82
+
83
+ // ? (see: https://github.com/capawesome-team/capacitor-firebase/blob/9024eef856dbd25b2b6459e4b6bcee104ca89755/packages/authentication/src/web.ts#L645)
84
+ private createAdditionalUserInfoResult(credential: FirebaseUserCredential | null): AdditionalUserInfo | null {
85
+ if (!credential) {
86
+ return null;
87
+ }
88
+ const additionalUserInfo = getAdditionalUserInfo(credential);
89
+ if (!additionalUserInfo) {
90
+ return null;
91
+ }
92
+ const { isNewUser, profile, providerId, username } = additionalUserInfo;
93
+ const result: AdditionalUserInfo = {
94
+ isNewUser
95
+ };
96
+ if (providerId !== null) {
97
+ result.providerId = providerId;
98
+ }
99
+ if (profile !== null) {
100
+ result.profile = profile as { [key: string]: unknown };
101
+ }
102
+ if (username !== null && username !== undefined) {
103
+ result.username = username;
104
+ }
105
+ return result;
106
+ }
107
+ }
src/app/firebase/auth/firebase-auth.module.ts CHANGED
@@ -11,6 +11,7 @@ import { provideAuth, getAuth, initializeAuth, indexedDBLocalPersistence } from
11
  import { ComponentsModule } from '../../components/components.module';
12
  import { environment } from '../../../environments/environment';
13
  import { FirebaseAuthService } from './firebase-auth.service';
 
14
 
15
 
16
  const routes: Routes = [
@@ -59,6 +60,9 @@ const routes: Routes = [
59
  }
60
  })
61
  ],
62
- providers: [FirebaseAuthService]
 
 
 
63
  })
64
  export class FirebaseAuthModule {}
11
  import { ComponentsModule } from '../../components/components.module';
12
  import { environment } from '../../../environments/environment';
13
  import { FirebaseAuthService } from './firebase-auth.service';
14
+ import { FirebaseAuthHelper } from './firebase-auth.helper';
15
 
16
 
17
  const routes: Routes = [
60
  }
61
  })
62
  ],
63
+ providers: [
64
+ FirebaseAuthService,
65
+ FirebaseAuthHelper
66
+ ]
67
  })
68
  export class FirebaseAuthModule {}
src/app/firebase/auth/firebase-auth.service.ts CHANGED
@@ -9,14 +9,14 @@ import { filter, map } from 'rxjs/operators';
9
  import { AuthProvider, FacebookAuthProvider, GoogleAuthProvider, TwitterAuthProvider, OAuthProvider, OAuthCredential, UserCredential, createUserWithEmailAndPassword, getAuth, getRedirectResult, signInWithCredential, signInWithEmailAndPassword, signInWithPopup, signInWithRedirect, signOut } from '@angular/fire/auth';
10
 
11
  import type {
12
- AuthCredential as FirebaseAuthCredential,
13
- User as FirebaseUser,
14
  } from '@angular/fire/auth';
15
 
16
- import { AuthCredential, AuthStateChange, FirebaseAuthentication, SignInResult, User } from '@capacitor-firebase/authentication';
17
 
18
  import { FirebaseProfileModel } from './profile/firebase-profile.model';
19
  import { SignInProvider } from './firebase-auth-definitions';
 
20
 
21
 
22
  @Injectable({
@@ -33,6 +33,7 @@ export class FirebaseAuthService implements OnDestroy {
33
  public route: ActivatedRoute,
34
  public platform: Platform,
35
  private ngZone: NgZone,
 
36
  public loadingController: LoadingController,
37
  public location: Location,
38
  @Inject(PLATFORM_ID) private platformId: object
@@ -88,7 +89,7 @@ export class FirebaseAuthService implements OnDestroy {
88
  break;
89
  }
90
 
91
- const signInResult = this.createSignInResult(result.user, credential);
92
 
93
  this.dismissLoading();
94
 
@@ -130,6 +131,36 @@ export class FirebaseAuthService implements OnDestroy {
130
  this.dismissLoading();
131
  }
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  public async signOut(): Promise<string> {
134
  const signOutPromise = new Promise<string>((resolve, reject) => {
135
  // * 1. Sign out on the native layer
@@ -154,15 +185,15 @@ export class FirebaseAuthService implements OnDestroy {
154
  return signOutPromise;
155
  }
156
 
157
- private async socialSignIn(provider: AuthProvider, scopes?: Array<string>): Promise<SignInResult> {
158
  this.presentLoading(provider.providerId);
159
 
160
  let authResult: SignInResult = null;
161
 
162
  if (this.platform.is('capacitor')) {
163
- authResult = await this.nativeAuth(provider, scopes);
164
  } else {
165
- authResult = await this.webAuth(provider);
166
  }
167
 
168
  this.dismissLoading();
@@ -174,66 +205,12 @@ export class FirebaseAuthService implements OnDestroy {
174
  }
175
  }
176
 
177
- private prepareForAuthWithProvidersRedirection(authProviderId: string): void {
178
- // ? Before invoking auth provider redirect flow, add a flag to the path.
179
- // ? The presence of the flag in the path indicates we should wait for the auth redirect to complete
180
- this.location.replaceState(this.location.path(), 'auth-redirect=' + authProviderId, this.location.getState());
181
- }
182
-
183
- private clearAuthWithProvidersRedirection(): void {
184
- // ? Remove auth-redirect param from url
185
- this.location.replaceState(this.router.url.split('?')[0], '');
186
- this.dismissLoading();
187
- }
188
-
189
- private async presentLoading(authProviderId?: string): Promise<void> {
190
- const authProviderCapitalized = authProviderId[0].toUpperCase() + authProviderId.slice(1);
191
-
192
- this.loadingController.create({
193
- message: authProviderId ? 'Signing in with ' + authProviderCapitalized : 'Signing in ...',
194
- duration: 4000
195
- }).then((loader) => {
196
- this.authLoader = loader;
197
- this.authLoader.present();
198
- });
199
- }
200
-
201
- private async dismissLoading(): Promise<void> {
202
- if (this.authLoader) {
203
- await this.authLoader.dismiss();
204
- }
205
- }
206
-
207
- private async webAuth(provider: AuthProvider, scopes?: Array<string>): Promise<SignInResult> {
208
- // ? Scopes for Firebase JS SDK auth
209
- if (scopes) {
210
- let providerWithScopes: any;
211
-
212
- switch (provider.providerId) {
213
- case SignInProvider.apple:
214
- providerWithScopes = (provider as OAuthProvider);
215
- break;
216
- case SignInProvider.facebook:
217
- providerWithScopes = (provider as FacebookAuthProvider);
218
- break;
219
- case SignInProvider.google:
220
- providerWithScopes = (provider as GoogleAuthProvider);
221
- break;
222
- case SignInProvider.twitter:
223
- providerWithScopes = (provider as TwitterAuthProvider);
224
- break;
225
- }
226
-
227
- scopes.forEach(scope => {
228
- providerWithScopes.addScope(scope);
229
- });
230
-
231
- provider = providerWithScopes;
232
- }
233
-
234
  const auth = getAuth();
235
  let webAuthUserCredential: UserCredential = null;
236
 
 
 
237
  if (this.platform.is('desktop')) {
238
  webAuthUserCredential = await signInWithPopup(auth, provider);
239
  } else {
@@ -263,33 +240,28 @@ export class FirebaseAuthService implements OnDestroy {
263
  break;
264
  }
265
 
266
- return this.createSignInResult(webAuthUserCredential.user, webCredential);
267
  } else {
268
  return Promise.reject('null webAuthUserCredential');
269
  }
270
  }
271
 
272
- private async nativeAuth(provider: AuthProvider, scopes?: Array<string>): Promise<SignInResult> {
273
  let nativeAuthResult: SignInResult = null;
274
 
275
- // ? Scopes for Firebase native SDK (iOS and Android)
276
- // TODO: Scopes for Firebase native SDK auth is a work in progress yet
277
- // (see: https://github.com/robingenz/capacitor-firebase/issues/32)
278
-
279
-
280
  // * 1. Sign in on the native layer
281
  switch (provider.providerId) {
282
  case SignInProvider.apple:
283
- nativeAuthResult = await FirebaseAuthentication.signInWithApple();
284
  break;
285
  case SignInProvider.facebook:
286
- nativeAuthResult = await FirebaseAuthentication.signInWithFacebook();
287
  break;
288
  case SignInProvider.google:
289
- nativeAuthResult = await FirebaseAuthentication.signInWithGoogle();
290
  break;
291
  case SignInProvider.twitter:
292
- nativeAuthResult = await FirebaseAuthentication.signInWithTwitter();
293
  break;
294
  }
295
 
@@ -312,11 +284,17 @@ export class FirebaseAuthService implements OnDestroy {
312
  );
313
  break;
314
  case SignInProvider.google:
315
- nativeCredential = GoogleAuthProvider.credential(nativeAuthResult.credential?.idToken, nativeAuthResult.credential?.accessToken);
 
 
 
316
  break;
317
  case SignInProvider.twitter:
318
  try {
319
- nativeCredential = TwitterAuthProvider.credential(nativeAuthResult.credential?.accessToken, nativeAuthResult.credential?.secret);
 
 
 
320
  break;
321
  } catch (error) {
322
  console.error(error);
@@ -326,7 +304,7 @@ export class FirebaseAuthService implements OnDestroy {
326
  // * 2. Sign in on the web layer using the access token we got from the native sign in
327
  const webAuthResult = await signInWithCredential(auth, nativeCredential);
328
 
329
- return this.createSignInResult(webAuthResult.user, nativeCredential);
330
  } else {
331
  return Promise.reject('null nativeAuthResult');
332
  }
@@ -334,34 +312,42 @@ export class FirebaseAuthService implements OnDestroy {
334
 
335
  public async signInWithFacebook(): Promise<SignInResult> {
336
  const provider = new FacebookAuthProvider();
337
- const scopes = ['email'];
 
 
338
 
339
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
340
- return this.socialSignIn(provider, scopes);
341
  }
342
 
343
  public async signInWithGoogle(): Promise<SignInResult> {
344
  const provider = new GoogleAuthProvider();
345
- const scopes = ['profile', 'email'];
 
 
346
 
347
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
348
- return this.socialSignIn(provider, scopes);
349
  }
350
 
351
  public async signInWithTwitter(): Promise<SignInResult> {
352
  const provider = new TwitterAuthProvider();
353
- const scopes = ['name', 'email'];
 
 
354
 
355
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
356
- return this.socialSignIn(provider, scopes);
357
  }
358
 
359
  public async signInWithApple(): Promise<SignInResult> {
360
  const provider = new OAuthProvider('apple.com');
361
- const scopes = ['name', 'email'];
 
 
362
 
363
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
364
- return this.socialSignIn(provider, scopes);
365
  }
366
 
367
  public async signInWithEmail(email: string, password: string): Promise<SignInResult> {
@@ -373,7 +359,7 @@ export class FirebaseAuthService implements OnDestroy {
373
 
374
  this.dismissLoading();
375
 
376
- return this.createSignInResultFromUserCredential(credential);
377
  }
378
 
379
  public async signUpWithEmail(email: string, password: string): Promise<SignInResult> {
@@ -385,7 +371,7 @@ export class FirebaseAuthService implements OnDestroy {
385
 
386
  this.dismissLoading();
387
 
388
- return this.createSignInResultFromUserCredential(credential);
389
  }
390
 
391
  public get redirectResult$(): Observable<any> {
@@ -402,7 +388,7 @@ export class FirebaseAuthService implements OnDestroy {
402
  .pipe(
403
  filter((user: FirebaseUser) => user != null),
404
  map((user: FirebaseUser) => {
405
- const userResult = this.createUserResult(user);
406
  return this.setUserModelForProfile(userResult);
407
  })
408
  );
@@ -439,59 +425,4 @@ export class FirebaseAuthService implements OnDestroy {
439
  return photoURL;
440
  }
441
  }
442
-
443
- // * Aux methods inspired on the @capacitor-firebase/authentication library
444
-
445
- // (see: https://github.com/robingenz/capacitor-firebase/blob/a51927ff3acce94cedcd7bfc218952bb106db904/packages/authentication/src/web.ts#L297)
446
- private createSignInResultFromUserCredential(credential: UserCredential): SignInResult {
447
- const userResult = this.createUserResult(credential.user);
448
- const result: SignInResult = {
449
- user: userResult,
450
- credential: null,
451
- };
452
- return result;
453
- }
454
-
455
- private createSignInResult(user: FirebaseUser, credential: FirebaseAuthCredential | null): SignInResult {
456
- const userResult = this.createUserResult(user);
457
- const credentialResult = this.createCredentialResult(credential);
458
- const result: SignInResult = {
459
- user: userResult,
460
- credential: credentialResult,
461
- };
462
- return result;
463
- }
464
-
465
- private createUserResult(user: FirebaseUser | null): User | null {
466
- if (!user) {
467
- return null;
468
- }
469
- const result: User = {
470
- displayName: user.displayName,
471
- email: user.email,
472
- emailVerified: user.emailVerified,
473
- isAnonymous: user.isAnonymous,
474
- phoneNumber: user.phoneNumber,
475
- photoUrl: user.photoURL,
476
- providerId: user.providerId,
477
- tenantId: user.tenantId,
478
- uid: user.uid,
479
- };
480
- return result;
481
- }
482
-
483
- private createCredentialResult(credential: FirebaseAuthCredential | null): AuthCredential | null {
484
- if (!credential) {
485
- return null;
486
- }
487
- const result: AuthCredential = {
488
- providerId: credential.providerId,
489
- };
490
- if (credential instanceof OAuthCredential) {
491
- result.accessToken = credential.accessToken;
492
- result.idToken = credential.idToken;
493
- result.secret = credential.secret;
494
- }
495
- return result;
496
- }
497
  }
9
  import { AuthProvider, FacebookAuthProvider, GoogleAuthProvider, TwitterAuthProvider, OAuthProvider, OAuthCredential, UserCredential, createUserWithEmailAndPassword, getAuth, getRedirectResult, signInWithCredential, signInWithEmailAndPassword, signInWithPopup, signInWithRedirect, signOut } from '@angular/fire/auth';
10
 
11
  import type {
12
+ User as FirebaseUser
 
13
  } from '@angular/fire/auth';
14
 
15
+ import { AuthStateChange, FirebaseAuthentication, SignInResult, SignInWithOAuthOptions, User } from '@capacitor-firebase/authentication';
16
 
17
  import { FirebaseProfileModel } from './profile/firebase-profile.model';
18
  import { SignInProvider } from './firebase-auth-definitions';
19
+ import { FirebaseAuthHelper } from './firebase-auth.helper';
20
 
21
 
22
  @Injectable({
33
  public route: ActivatedRoute,
34
  public platform: Platform,
35
  private ngZone: NgZone,
36
+ private firebaseAuthHelper: FirebaseAuthHelper,
37
  public loadingController: LoadingController,
38
  public location: Location,
39
  @Inject(PLATFORM_ID) private platformId: object
89
  break;
90
  }
91
 
92
+ const signInResult = firebaseAuthHelper.createSignInResult(result, credential);
93
 
94
  this.dismissLoading();
95
 
131
  this.dismissLoading();
132
  }
133
 
134
+ private prepareForAuthWithProvidersRedirection(authProviderId: string): void {
135
+ // ? Before invoking auth provider redirect flow, add a flag to the path.
136
+ // ? The presence of the flag in the path indicates we should wait for the auth redirect to complete
137
+ this.location.replaceState(this.location.path(), 'auth-redirect=' + authProviderId, this.location.getState());
138
+ }
139
+
140
+ private clearAuthWithProvidersRedirection(): void {
141
+ // ? Remove auth-redirect param from url
142
+ this.location.replaceState(this.router.url.split('?')[0], '');
143
+ this.dismissLoading();
144
+ }
145
+
146
+ private async presentLoading(authProviderId?: string): Promise<void> {
147
+ const authProviderCapitalized = authProviderId[0].toUpperCase() + authProviderId.slice(1);
148
+
149
+ this.loadingController.create({
150
+ message: authProviderId ? 'Signing in with ' + authProviderCapitalized : 'Signing in ...',
151
+ duration: 4000
152
+ }).then((loader) => {
153
+ this.authLoader = loader;
154
+ this.authLoader.present();
155
+ });
156
+ }
157
+
158
+ private async dismissLoading(): Promise<void> {
159
+ if (this.authLoader) {
160
+ await this.authLoader.dismiss();
161
+ }
162
+ }
163
+
164
  public async signOut(): Promise<string> {
165
  const signOutPromise = new Promise<string>((resolve, reject) => {
166
  // * 1. Sign out on the native layer
185
  return signOutPromise;
186
  }
187
 
188
+ private async socialSignIn(provider: (OAuthProvider | GoogleAuthProvider | FacebookAuthProvider | TwitterAuthProvider), authOptions?: SignInWithOAuthOptions): Promise<SignInResult> {
189
  this.presentLoading(provider.providerId);
190
 
191
  let authResult: SignInResult = null;
192
 
193
  if (this.platform.is('capacitor')) {
194
+ authResult = await this.nativeAuth(provider, authOptions);
195
  } else {
196
+ authResult = await this.webAuth(provider, authOptions);
197
  }
198
 
199
  this.dismissLoading();
205
  }
206
  }
207
 
208
+ private async webAuth(provider: (OAuthProvider | GoogleAuthProvider | FacebookAuthProvider | TwitterAuthProvider), authOptions?: SignInWithOAuthOptions): Promise<SignInResult> {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  const auth = getAuth();
210
  let webAuthUserCredential: UserCredential = null;
211
 
212
+ this.firebaseAuthHelper.applySignInOptions(authOptions || {}, provider);
213
+
214
  if (this.platform.is('desktop')) {
215
  webAuthUserCredential = await signInWithPopup(auth, provider);
216
  } else {
240
  break;
241
  }
242
 
243
+ return this.firebaseAuthHelper.createSignInResult(webAuthUserCredential, webCredential);
244
  } else {
245
  return Promise.reject('null webAuthUserCredential');
246
  }
247
  }
248
 
249
+ private async nativeAuth(provider: AuthProvider, authOptions?: SignInWithOAuthOptions): Promise<SignInResult> {
250
  let nativeAuthResult: SignInResult = null;
251
 
 
 
 
 
 
252
  // * 1. Sign in on the native layer
253
  switch (provider.providerId) {
254
  case SignInProvider.apple:
255
+ nativeAuthResult = await FirebaseAuthentication.signInWithApple(authOptions);
256
  break;
257
  case SignInProvider.facebook:
258
+ nativeAuthResult = await FirebaseAuthentication.signInWithFacebook(authOptions);
259
  break;
260
  case SignInProvider.google:
261
+ nativeAuthResult = await FirebaseAuthentication.signInWithGoogle(authOptions);
262
  break;
263
  case SignInProvider.twitter:
264
+ nativeAuthResult = await FirebaseAuthentication.signInWithTwitter(authOptions);
265
  break;
266
  }
267
 
284
  );
285
  break;
286
  case SignInProvider.google:
287
+ nativeCredential = GoogleAuthProvider.credential(
288
+ nativeAuthResult.credential?.idToken,
289
+ nativeAuthResult.credential?.accessToken
290
+ );
291
  break;
292
  case SignInProvider.twitter:
293
  try {
294
+ nativeCredential = TwitterAuthProvider.credential(
295
+ nativeAuthResult.credential?.accessToken,
296
+ nativeAuthResult.credential?.secret
297
+ );
298
  break;
299
  } catch (error) {
300
  console.error(error);
304
  // * 2. Sign in on the web layer using the access token we got from the native sign in
305
  const webAuthResult = await signInWithCredential(auth, nativeCredential);
306
 
307
+ return this.firebaseAuthHelper.createSignInResult(webAuthResult, nativeCredential);
308
  } else {
309
  return Promise.reject('null nativeAuthResult');
310
  }
312
 
313
  public async signInWithFacebook(): Promise<SignInResult> {
314
  const provider = new FacebookAuthProvider();
315
+ const authOptions: SignInWithOAuthOptions = {
316
+ scopes: ['email', 'public_profile']
317
+ };
318
 
319
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
320
+ return this.socialSignIn(provider, authOptions);
321
  }
322
 
323
  public async signInWithGoogle(): Promise<SignInResult> {
324
  const provider = new GoogleAuthProvider();
325
+ const authOptions: SignInWithOAuthOptions = {
326
+ scopes: ['email', 'profile']
327
+ };
328
 
329
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
330
+ return this.socialSignIn(provider, authOptions);
331
  }
332
 
333
  public async signInWithTwitter(): Promise<SignInResult> {
334
  const provider = new TwitterAuthProvider();
335
+ const authOptions: SignInWithOAuthOptions = {
336
+ scopes: ['email', 'name']
337
+ };
338
 
339
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
340
+ return this.socialSignIn(provider, authOptions);
341
  }
342
 
343
  public async signInWithApple(): Promise<SignInResult> {
344
  const provider = new OAuthProvider('apple.com');
345
+ const authOptions: SignInWithOAuthOptions = {
346
+ scopes: ['email', 'name']
347
+ };
348
 
349
  // ? When we use the redirect authentication flow, the code below the socialSignIn() invocation does not get executed as we leave the current page
350
+ return this.socialSignIn(provider, authOptions);
351
  }
352
 
353
  public async signInWithEmail(email: string, password: string): Promise<SignInResult> {
359
 
360
  this.dismissLoading();
361
 
362
+ return this.firebaseAuthHelper.createSignInResult(credential, null);
363
  }
364
 
365
  public async signUpWithEmail(email: string, password: string): Promise<SignInResult> {
371
 
372
  this.dismissLoading();
373
 
374
+ return this.firebaseAuthHelper.createSignInResult(credential, null);
375
  }
376
 
377
  public get redirectResult$(): Observable<any> {
388
  .pipe(
389
  filter((user: FirebaseUser) => user != null),
390
  map((user: FirebaseUser) => {
391
+ const userResult = this.firebaseAuthHelper.createUserResult(user);
392
  return this.setUserModelForProfile(userResult);
393
  })
394
  );
425
  return photoURL;
426
  }
427
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  }
src/app/firebase/auth/sign-in/firebase-sign-in.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component, NgZone } from '@angular/core';
2
- import { Validators, FormGroup, FormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { AuthStateChange, SignInResult } from '@capacitor-firebase/authentication';
5
 
@@ -15,7 +15,7 @@ import { FirebaseAuthService } from '../firebase-auth.service';
15
  ]
16
  })
17
  export class FirebaseSignInPage {
18
- loginForm: FormGroup;
19
  submitError: string;
20
  authRedirectResult: Subscription;
21
 
@@ -35,12 +35,12 @@ export class FirebaseSignInPage {
35
  public firebaseAuthService: FirebaseAuthService,
36
  private ngZone: NgZone
37
  ) {
38
- this.loginForm = new FormGroup({
39
- 'email': new FormControl('', Validators.compose([
40
  Validators.required,
41
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
42
  ])),
43
- 'password': new FormControl('', Validators.compose([
44
  Validators.minLength(6),
45
  Validators.required
46
  ]))
1
  import { Component, NgZone } from '@angular/core';
2
+ import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { AuthStateChange, SignInResult } from '@capacitor-firebase/authentication';
5
 
15
  ]
16
  })
17
  export class FirebaseSignInPage {
18
+ loginForm: UntypedFormGroup;
19
  submitError: string;
20
  authRedirectResult: Subscription;
21
 
35
  public firebaseAuthService: FirebaseAuthService,
36
  private ngZone: NgZone
37
  ) {
38
+ this.loginForm = new UntypedFormGroup({
39
+ 'email': new UntypedFormControl('', Validators.compose([
40
  Validators.required,
41
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
42
  ])),
43
+ 'password': new UntypedFormControl('', Validators.compose([
44
  Validators.minLength(6),
45
  Validators.required
46
  ]))
src/app/firebase/auth/sign-up/firebase-sign-up.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component, OnInit, NgZone } from '@angular/core';
2
- import { Validators, FormGroup, FormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { MenuController } from '@ionic/angular';
5
 
@@ -18,8 +18,8 @@ import { FirebaseAuthService } from '../firebase-auth.service';
18
  ]
19
  })
20
  export class FirebaseSignUpPage implements OnInit {
21
- signupForm: FormGroup;
22
- matching_passwords_group: FormGroup;
23
  submitError: string;
24
  authRedirectResult: Subscription;
25
 
@@ -46,18 +46,18 @@ export class FirebaseSignUpPage implements OnInit {
46
  public firebaseAuthService: FirebaseAuthService,
47
  private ngZone: NgZone
48
  ) {
49
- this.matching_passwords_group = new FormGroup({
50
- 'password': new FormControl('', Validators.compose([
51
  Validators.minLength(6),
52
  Validators.required
53
  ])),
54
- 'confirm_password': new FormControl('', Validators.required)
55
- }, (formGroup: FormGroup) => {
56
  return PasswordValidator.areNotEqual(formGroup);
57
  });
58
 
59
- this.signupForm = new FormGroup({
60
- 'email': new FormControl('', Validators.compose([
61
  Validators.required,
62
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
63
  ])),
1
  import { Component, OnInit, NgZone } from '@angular/core';
2
+ import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { MenuController } from '@ionic/angular';
5
 
18
  ]
19
  })
20
  export class FirebaseSignUpPage implements OnInit {
21
+ signupForm: UntypedFormGroup;
22
+ matching_passwords_group: UntypedFormGroup;
23
  submitError: string;
24
  authRedirectResult: Subscription;
25
 
46
  public firebaseAuthService: FirebaseAuthService,
47
  private ngZone: NgZone
48
  ) {
49
+ this.matching_passwords_group = new UntypedFormGroup({
50
+ 'password': new UntypedFormControl('', Validators.compose([
51
  Validators.minLength(6),
52
  Validators.required
53
  ])),
54
+ 'confirm_password': new UntypedFormControl('', Validators.required)
55
+ }, (formGroup: UntypedFormGroup) => {
56
  return PasswordValidator.areNotEqual(formGroup);
57
  });
58
 
59
+ this.signupForm = new UntypedFormGroup({
60
+ 'email': new UntypedFormControl('', Validators.compose([
61
  Validators.required,
62
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
63
  ])),
src/app/firebase/crud/listing/firebase-listing.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component, OnInit } from '@angular/core';
2
- import { FormGroup, FormControl } from '@angular/forms';
3
  import { ActivatedRoute } from '@angular/router';
4
 
5
  import { Observable, ReplaySubject } from 'rxjs';
@@ -17,7 +17,7 @@ import { FirebaseCrudService } from '../firebase-crud.service';
17
  ],
18
  })
19
  export class FirebaseListingPage implements OnInit {
20
- rangeForm: FormGroup;
21
  searchQuery: string;
22
  showAgeFilter = false;
23
 
@@ -34,8 +34,8 @@ export class FirebaseListingPage implements OnInit {
34
  ngOnInit() {
35
  this.searchQuery = '';
36
 
37
- this.rangeForm = new FormGroup({
38
- dual: new FormControl({lower: 1, upper: 100})
39
  });
40
 
41
  this.route.data.subscribe((resolvedRouteData) => {
1
  import { Component, OnInit } from '@angular/core';
2
+ import { UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
  import { ActivatedRoute } from '@angular/router';
4
 
5
  import { Observable, ReplaySubject } from 'rxjs';
17
  ],
18
  })
19
  export class FirebaseListingPage implements OnInit {
20
+ rangeForm: UntypedFormGroup;
21
  searchQuery: string;
22
  showAgeFilter = false;
23
 
34
  ngOnInit() {
35
  this.searchQuery = '';
36
 
37
+ this.rangeForm = new UntypedFormGroup({
38
+ dual: new UntypedFormControl({lower: 1, upper: 100})
39
  });
40
 
41
  this.route.data.subscribe((resolvedRouteData) => {
src/app/food/details/food-details.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -25,7 +24,6 @@ const routes: Routes = [
25
  @NgModule({
26
  imports: [
27
  CommonModule,
28
- FormsModule,
29
  IonicModule,
30
  RouterModule.forChild(routes),
31
  ComponentsModule,
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
24
  @NgModule({
25
  imports: [
26
  CommonModule,
 
27
  IonicModule,
28
  RouterModule.forChild(routes),
29
  ComponentsModule,
src/app/food/listing/food-listing.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -25,7 +24,6 @@ const routes: Routes = [
25
  @NgModule({
26
  imports: [
27
  CommonModule,
28
- FormsModule,
29
  IonicModule,
30
  RouterModule.forChild(routes),
31
  ComponentsModule,
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
24
  @NgModule({
25
  imports: [
26
  CommonModule,
 
27
  IonicModule,
28
  RouterModule.forChild(routes),
29
  ComponentsModule,
src/app/forgot-password/forgot-password.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component } from '@angular/core';
2
- import { Validators, FormGroup, FormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { MenuController } from '@ionic/angular';
5
 
@@ -11,7 +11,7 @@ import { MenuController } from '@ionic/angular';
11
  ]
12
  })
13
  export class ForgotPasswordPage {
14
- forgotPasswordForm: FormGroup;
15
 
16
  validation_messages = {
17
  'email': [
@@ -24,8 +24,8 @@ export class ForgotPasswordPage {
24
  public router: Router,
25
  public menu: MenuController
26
  ) {
27
- this.forgotPasswordForm = new FormGroup({
28
- 'email': new FormControl('test@test.com', Validators.compose([
29
  Validators.required,
30
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
31
  ]))
1
  import { Component } from '@angular/core';
2
+ import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { MenuController } from '@ionic/angular';
5
 
11
  ]
12
  })
13
  export class ForgotPasswordPage {
14
+ forgotPasswordForm: UntypedFormGroup;
15
 
16
  validation_messages = {
17
  'email': [
24
  public router: Router,
25
  public menu: MenuController
26
  ) {
27
+ this.forgotPasswordForm = new UntypedFormGroup({
28
+ 'email': new UntypedFormControl('test@test.com', Validators.compose([
29
  Validators.required,
30
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
31
  ]))
src/app/forms/filters/forms-filters.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component} from '@angular/core';
2
- import { FormGroup, FormControl } from '@angular/forms';
3
 
4
  import { counterRangeValidator } from '../../components/counter-input/counter-input.component';
5
 
@@ -13,65 +13,65 @@ import { counterRangeValidator } from '../../components/counter-input/counter-in
13
  })
14
  export class FormsFiltersPage {
15
  rangeForm: any;
16
- checkboxForm: FormGroup;
17
- radioForm: FormGroup;
18
- checkboxTagsForm: FormGroup;
19
- radioTagsForm: FormGroup;
20
- switchersForm: FormGroup;
21
  counterForm: any;
22
- ratingForm: FormGroup;
23
- radioColorForm: FormGroup;
24
 
25
  constructor() {
26
- this.rangeForm = new FormGroup({
27
- single: new FormControl(25),
28
- dual: new FormControl({lower: 12, upper: 23})
29
  });
30
 
31
- this.checkboxForm = new FormGroup({
32
- person_1: new FormControl(true),
33
- person_2: new FormControl(false),
34
- person_3: new FormControl(false),
35
- person_4: new FormControl(true),
36
- person_5: new FormControl(false)
37
  });
38
 
39
- this.radioForm = new FormGroup({
40
- selected_option: new FormControl('apple')
41
  });
42
 
43
- this.checkboxTagsForm = new FormGroup({
44
- tag_1: new FormControl(true),
45
- tag_2: new FormControl(false),
46
- tag_3: new FormControl(true),
47
- tag_4: new FormControl(true),
48
- tag_5: new FormControl(false),
49
- tag_6: new FormControl(false),
50
- tag_7: new FormControl({value: true, disabled: true}),
51
- tag_8: new FormControl(false)
52
  });
53
 
54
- this.radioTagsForm = new FormGroup({
55
- selected_option: new FormControl('any')
56
  });
57
 
58
- this.switchersForm = new FormGroup({
59
- notifications: new FormControl(true),
60
- email_notifications: new FormControl(false)
61
  });
62
 
63
- this.counterForm = new FormGroup({
64
- counter: new FormControl(5, counterRangeValidator(1, 7)),
65
- counter2: new FormControl(2, counterRangeValidator(1, 5))
66
  });
67
 
68
- this.ratingForm = new FormGroup({
69
- rate: new FormControl(2.5),
70
- rate2: new FormControl(1.5)
71
  });
72
 
73
- this.radioColorForm = new FormGroup({
74
- selected_color: new FormControl('#fc9961')
75
  });
76
  }
77
 
1
  import { Component} from '@angular/core';
2
+ import { UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
 
4
  import { counterRangeValidator } from '../../components/counter-input/counter-input.component';
5
 
13
  })
14
  export class FormsFiltersPage {
15
  rangeForm: any;
16
+ checkboxForm: UntypedFormGroup;
17
+ radioForm: UntypedFormGroup;
18
+ checkboxTagsForm: UntypedFormGroup;
19
+ radioTagsForm: UntypedFormGroup;
20
+ switchersForm: UntypedFormGroup;
21
  counterForm: any;
22
+ ratingForm: UntypedFormGroup;
23
+ radioColorForm: UntypedFormGroup;
24
 
25
  constructor() {
26
+ this.rangeForm = new UntypedFormGroup({
27
+ single: new UntypedFormControl(25),
28
+ dual: new UntypedFormControl({lower: 12, upper: 23})
29
  });
30
 
31
+ this.checkboxForm = new UntypedFormGroup({
32
+ person_1: new UntypedFormControl(true),
33
+ person_2: new UntypedFormControl(false),
34
+ person_3: new UntypedFormControl(false),
35
+ person_4: new UntypedFormControl(true),
36
+ person_5: new UntypedFormControl(false)
37
  });
38
 
39
+ this.radioForm = new UntypedFormGroup({
40
+ selected_option: new UntypedFormControl('apple')
41
  });
42
 
43
+ this.checkboxTagsForm = new UntypedFormGroup({
44
+ tag_1: new UntypedFormControl(true),
45
+ tag_2: new UntypedFormControl(false),
46
+ tag_3: new UntypedFormControl(true),
47
+ tag_4: new UntypedFormControl(true),
48
+ tag_5: new UntypedFormControl(false),
49
+ tag_6: new UntypedFormControl(false),
50
+ tag_7: new UntypedFormControl({value: true, disabled: true}),
51
+ tag_8: new UntypedFormControl(false)
52
  });
53
 
54
+ this.radioTagsForm = new UntypedFormGroup({
55
+ selected_option: new UntypedFormControl('any')
56
  });
57
 
58
+ this.switchersForm = new UntypedFormGroup({
59
+ notifications: new UntypedFormControl(true),
60
+ email_notifications: new UntypedFormControl(false)
61
  });
62
 
63
+ this.counterForm = new UntypedFormGroup({
64
+ counter: new UntypedFormControl(5, counterRangeValidator(1, 7)),
65
+ counter2: new UntypedFormControl(2, counterRangeValidator(1, 5))
66
  });
67
 
68
+ this.ratingForm = new UntypedFormGroup({
69
+ rate: new UntypedFormControl(2.5),
70
+ rate2: new UntypedFormControl(1.5)
71
  });
72
 
73
+ this.radioColorForm = new UntypedFormGroup({
74
+ selected_color: new UntypedFormControl('#fc9961')
75
  });
76
  }
77
 
src/app/forms/validations/forms-validations.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component, OnInit } from '@angular/core';
2
- import { Validators, FormGroup, FormControl } from '@angular/forms';
3
 
4
  import { UsernameValidator } from '../../validators/username.validator';
5
  import { PasswordValidator } from '../../validators/password.validator';
@@ -17,9 +17,9 @@ import { CountryPhone } from './country-phone.model';
17
  })
18
  export class FormsValidationsPage implements OnInit {
19
 
20
- validationsForm: FormGroup;
21
- matching_passwords_group: FormGroup;
22
- country_phone_group: FormGroup;
23
  countries: Array<CountryPhone>;
24
  genders: Array<string>;
25
 
@@ -86,48 +86,48 @@ export class FormsValidationsPage implements OnInit {
86
  'Other'
87
  ];
88
 
89
- this.matching_passwords_group = new FormGroup({
90
- password: new FormControl('', Validators.compose([
91
  Validators.minLength(5),
92
  Validators.required,
93
  Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')
94
  ])),
95
- confirm_password: new FormControl('', Validators.required)
96
- }, (formGroup: FormGroup) => {
97
  return PasswordValidator.areNotEqual(formGroup);
98
  });
99
 
100
- const country = new FormControl(this.countries[0], Validators.required);
101
 
102
- const phone = new FormControl('', Validators.compose([
103
  Validators.required,
104
  PhoneValidator.invalidCountryPhone(country)
105
  ]));
106
- this.country_phone_group = new FormGroup({
107
  country: country,
108
  phone: phone
109
  });
110
 
111
- this.validationsForm = new FormGroup({
112
- 'username': new FormControl('', Validators.compose([
113
  UsernameValidator.usernameNotAvailable,
114
  Validators.maxLength(25),
115
  Validators.minLength(5),
116
  Validators.pattern('^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$'),
117
  Validators.required
118
  ])),
119
- 'name': new FormControl('', Validators.required),
120
- 'lastname': new FormControl('', Validators.required),
121
- 'email': new FormControl('', Validators.compose([
122
  Validators.required,
123
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
124
  ])),
125
- 'gender': new FormControl(this.genders[0], Validators.required),
126
  'country_phone': this.country_phone_group,
127
  'matching_passwords': this.matching_passwords_group,
128
- 'guests': new FormControl(6, counterRangeValidator(1, 12)),
129
- 'bedrooms': new FormControl(3, counterRangeValidator(1, 5)),
130
- 'terms': new FormControl(true, Validators.pattern('true'))
131
  });
132
  }
133
 
1
  import { Component, OnInit } from '@angular/core';
2
+ import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
 
4
  import { UsernameValidator } from '../../validators/username.validator';
5
  import { PasswordValidator } from '../../validators/password.validator';
17
  })
18
  export class FormsValidationsPage implements OnInit {
19
 
20
+ validationsForm: UntypedFormGroup;
21
+ matching_passwords_group: UntypedFormGroup;
22
+ country_phone_group: UntypedFormGroup;
23
  countries: Array<CountryPhone>;
24
  genders: Array<string>;
25
 
86
  'Other'
87
  ];
88
 
89
+ this.matching_passwords_group = new UntypedFormGroup({
90
+ password: new UntypedFormControl('', Validators.compose([
91
  Validators.minLength(5),
92
  Validators.required,
93
  Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')
94
  ])),
95
+ confirm_password: new UntypedFormControl('', Validators.required)
96
+ }, (formGroup: UntypedFormGroup) => {
97
  return PasswordValidator.areNotEqual(formGroup);
98
  });
99
 
100
+ const country = new UntypedFormControl(this.countries[0], Validators.required);
101
 
102
+ const phone = new UntypedFormControl('', Validators.compose([
103
  Validators.required,
104
  PhoneValidator.invalidCountryPhone(country)
105
  ]));
106
+ this.country_phone_group = new UntypedFormGroup({
107
  country: country,
108
  phone: phone
109
  });
110
 
111
+ this.validationsForm = new UntypedFormGroup({
112
+ 'username': new UntypedFormControl('', Validators.compose([
113
  UsernameValidator.usernameNotAvailable,
114
  Validators.maxLength(25),
115
  Validators.minLength(5),
116
  Validators.pattern('^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$'),
117
  Validators.required
118
  ])),
119
+ 'name': new UntypedFormControl('', Validators.required),
120
+ 'lastname': new UntypedFormControl('', Validators.required),
121
+ 'email': new UntypedFormControl('', Validators.compose([
122
  Validators.required,
123
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
124
  ])),
125
+ 'gender': new UntypedFormControl(this.genders[0], Validators.required),
126
  'country_phone': this.country_phone_group,
127
  'matching_passwords': this.matching_passwords_group,
128
+ 'guests': new UntypedFormControl(6, counterRangeValidator(1, 12)),
129
+ 'bedrooms': new UntypedFormControl(3, counterRangeValidator(1, 5)),
130
+ 'terms': new UntypedFormControl(true, Validators.pattern('true'))
131
  });
132
  }
133
 
src/app/getting-started/getting-started.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component, HostBinding, NgZone } from '@angular/core';
2
- import { FormGroup, FormControl } from '@angular/forms';
3
 
4
  import { MenuController } from '@ionic/angular';
5
  import { IonicSwiper } from "@ionic/angular";
@@ -21,21 +21,21 @@ export class GettingStartedPage {
21
  @HostBinding('class.last-slide-active') isLastSlide = false;
22
 
23
  swiperRef: SwiperCore;
24
- gettingStartedForm: FormGroup;
25
 
26
  constructor(
27
  public menu: MenuController,
28
  private ngZone: NgZone
29
  ) {
30
- this.gettingStartedForm = new FormGroup({
31
- browsingCategory: new FormControl('men'),
32
- followingInterests: new FormGroup({
33
- tops: new FormControl(true),
34
- dresses: new FormControl(),
35
- jeans: new FormControl(),
36
- jackets: new FormControl(true),
37
- shoes: new FormControl(),
38
- glasses: new FormControl()
39
  })
40
  });
41
  }
1
  import { Component, HostBinding, NgZone } from '@angular/core';
2
+ import { UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
 
4
  import { MenuController } from '@ionic/angular';
5
  import { IonicSwiper } from "@ionic/angular";
21
  @HostBinding('class.last-slide-active') isLastSlide = false;
22
 
23
  swiperRef: SwiperCore;
24
+ gettingStartedForm: UntypedFormGroup;
25
 
26
  constructor(
27
  public menu: MenuController,
28
  private ngZone: NgZone
29
  ) {
30
+ this.gettingStartedForm = new UntypedFormGroup({
31
+ browsingCategory: new UntypedFormControl('men'),
32
+ followingInterests: new UntypedFormGroup({
33
+ tops: new UntypedFormControl(true),
34
+ dresses: new UntypedFormControl(),
35
+ jeans: new UntypedFormControl(),
36
+ jackets: new UntypedFormControl(true),
37
+ shoes: new UntypedFormControl(),
38
+ glasses: new UntypedFormControl()
39
  })
40
  });
41
  }
src/app/login/login.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component } from '@angular/core';
2
- import { Validators, FormGroup, FormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { MenuController } from '@ionic/angular';
5
 
@@ -11,7 +11,7 @@ import { MenuController } from '@ionic/angular';
11
  ]
12
  })
13
  export class LoginPage {
14
- loginForm: FormGroup;
15
 
16
  validation_messages = {
17
  'email': [
@@ -28,12 +28,12 @@ export class LoginPage {
28
  public router: Router,
29
  public menu: MenuController
30
  ) {
31
- this.loginForm = new FormGroup({
32
- 'email': new FormControl('test@test.com', Validators.compose([
33
  Validators.required,
34
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
35
  ])),
36
- 'password': new FormControl('', Validators.compose([
37
  Validators.minLength(5),
38
  Validators.required
39
  ]))
1
  import { Component } from '@angular/core';
2
+ import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { MenuController } from '@ionic/angular';
5
 
11
  ]
12
  })
13
  export class LoginPage {
14
+ loginForm: UntypedFormGroup;
15
 
16
  validation_messages = {
17
  'email': [
28
  public router: Router,
29
  public menu: MenuController
30
  ) {
31
+ this.loginForm = new UntypedFormGroup({
32
+ 'email': new UntypedFormControl('test@test.com', Validators.compose([
33
  Validators.required,
34
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
35
  ])),
36
+ 'password': new UntypedFormControl('', Validators.compose([
37
  Validators.minLength(5),
38
  Validators.required
39
  ]))
src/app/notifications/notifications.module.ts CHANGED
@@ -2,7 +2,6 @@ import { IonicModule } from '@ionic/angular';
2
  import { RouterModule } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
 
7
  import { ComponentsModule } from '../components/components.module';
8
 
@@ -14,7 +13,6 @@ import { NotificationsService } from '../notifications/notifications.service';
14
  imports: [
15
  IonicModule,
16
  CommonModule,
17
- FormsModule,
18
  ComponentsModule,
19
  RouterModule.forChild([
20
  {
2
  import { RouterModule } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
 
5
 
6
  import { ComponentsModule } from '../components/components.module';
7
 
13
  imports: [
14
  IonicModule,
15
  CommonModule,
 
16
  ComponentsModule,
17
  RouterModule.forChild([
18
  {
src/app/page-not-found/page-not-found.module.ts CHANGED
@@ -2,7 +2,6 @@ import { IonicModule } from '@ionic/angular';
2
  import { RouterModule } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
 
7
  import { ComponentsModule } from '../components/components.module';
8
  import { PageNotFoundPage } from './page-not-found.page';
@@ -12,7 +11,6 @@ import { PageNotFoundPage } from './page-not-found.page';
12
  IonicModule,
13
  CommonModule,
14
  ComponentsModule,
15
- FormsModule,
16
  RouterModule.forChild([
17
  {
18
  path: '',
2
  import { RouterModule } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
 
5
 
6
  import { ComponentsModule } from '../components/components.module';
7
  import { PageNotFoundPage } from './page-not-found.page';
11
  IonicModule,
12
  CommonModule,
13
  ComponentsModule,
 
14
  RouterModule.forChild([
15
  {
16
  path: '',
src/app/real-estate/details/real-estate-details.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -24,7 +23,6 @@ const routes: Routes = [
24
  @NgModule({
25
  imports: [
26
  CommonModule,
27
- FormsModule,
28
  IonicModule,
29
  RouterModule.forChild(routes),
30
  ComponentsModule
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
23
  @NgModule({
24
  imports: [
25
  CommonModule,
 
26
  IonicModule,
27
  RouterModule.forChild(routes),
28
  ComponentsModule
src/app/real-estate/listing/real-estate-listing.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -24,7 +23,6 @@ const routes: Routes = [
24
  @NgModule({
25
  imports: [
26
  CommonModule,
27
- FormsModule,
28
  IonicModule,
29
  RouterModule.forChild(routes),
30
  ComponentsModule
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
23
  @NgModule({
24
  imports: [
25
  CommonModule,
 
26
  IonicModule,
27
  RouterModule.forChild(routes),
28
  ComponentsModule
src/app/shell/image-shell/image-shell.component.ts CHANGED
@@ -24,6 +24,8 @@ export class ImageShellComponent {
24
  @HostBinding('class.img-loaded') imageLoaded = false;
25
  @HostBinding('class.img-error') imageError = false;
26
 
 
 
27
  @HostBinding('style.backgroundImage') backgroundImage: string;
28
 
29
  @HostBinding('attr.display')
@@ -69,11 +71,12 @@ export class ImageShellComponent {
69
  @Inject(PLATFORM_ID) private platformId: string
70
  ) {}
71
 
72
- _imageLoaded() {
73
  this.imageLoaded = true;
74
 
75
  // If it's a cover image then set the background-image property accordingly
76
  if (this._display === 'cover') {
 
77
  this.backgroundImage = 'url(' + this._src + ')';
78
  }
79
  }
24
  @HostBinding('class.img-loaded') imageLoaded = false;
25
  @HostBinding('class.img-error') imageError = false;
26
 
27
+ @HostBinding('attr.data-error') errorMessage = 'Could not load image';
28
+
29
  @HostBinding('style.backgroundImage') backgroundImage: string;
30
 
31
  @HostBinding('attr.display')
71
  @Inject(PLATFORM_ID) private platformId: string
72
  ) {}
73
 
74
+ _imageLoaded(): void {
75
  this.imageLoaded = true;
76
 
77
  // If it's a cover image then set the background-image property accordingly
78
  if (this._display === 'cover') {
79
+ // Now that the image is loaded, set the background image
80
  this.backgroundImage = 'url(' + this._src + ')';
81
  }
82
  }
src/app/showcase/showcase.module.ts CHANGED
@@ -2,7 +2,6 @@ import { IonicModule } from '@ionic/angular';
2
  import { RouterModule, Routes } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
  import { ComponentsModule } from '../components/components.module';
7
 
8
  const showcaseRoutes: Routes = [
2
  import { RouterModule, Routes } from '@angular/router';
3
  import { NgModule } from '@angular/core';
4
  import { CommonModule } from '@angular/common';
 
5
  import { ComponentsModule } from '../components/components.module';
6
 
7
  const showcaseRoutes: Routes = [
src/app/signup/signup.page.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { Component } from '@angular/core';
2
- import { Validators, FormGroup, FormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { ModalController, MenuController, IonRouterOutlet } from '@ionic/angular';
5
 
@@ -15,8 +15,8 @@ import { PasswordValidator } from '../validators/password.validator';
15
  ]
16
  })
17
  export class SignupPage {
18
- signupForm: FormGroup;
19
- matching_passwords_group: FormGroup;
20
 
21
  validation_messages = {
22
  'email': [
@@ -41,18 +41,18 @@ export class SignupPage {
41
  public menu: MenuController,
42
  private routerOutlet: IonRouterOutlet
43
  ) {
44
- this.matching_passwords_group = new FormGroup({
45
- 'password': new FormControl('', Validators.compose([
46
  Validators.minLength(5),
47
  Validators.required
48
  ])),
49
- 'confirm_password': new FormControl('', Validators.required)
50
- }, (formGroup: FormGroup) => {
51
  return PasswordValidator.areNotEqual(formGroup);
52
  });
53
 
54
- this.signupForm = new FormGroup({
55
- 'email': new FormControl('test@test.com', Validators.compose([
56
  Validators.required,
57
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
58
  ])),
1
  import { Component } from '@angular/core';
2
+ import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
3
  import { Router } from '@angular/router';
4
  import { ModalController, MenuController, IonRouterOutlet } from '@ionic/angular';
5
 
15
  ]
16
  })
17
  export class SignupPage {
18
+ signupForm: UntypedFormGroup;
19
+ matching_passwords_group: UntypedFormGroup;
20
 
21
  validation_messages = {
22
  'email': [
41
  public menu: MenuController,
42
  private routerOutlet: IonRouterOutlet
43
  ) {
44
+ this.matching_passwords_group = new UntypedFormGroup({
45
+ 'password': new UntypedFormControl('', Validators.compose([
46
  Validators.minLength(5),
47
  Validators.required
48
  ])),
49
+ 'confirm_password': new UntypedFormControl('', Validators.required)
50
+ }, (formGroup: UntypedFormGroup) => {
51
  return PasswordValidator.areNotEqual(formGroup);
52
  });
53
 
54
+ this.signupForm = new UntypedFormGroup({
55
+ 'email': new UntypedFormControl('test@test.com', Validators.compose([
56
  Validators.required,
57
  Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
58
  ])),
src/app/travel/details/travel-details.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -24,7 +23,6 @@ const routes: Routes = [
24
  @NgModule({
25
  imports: [
26
  CommonModule,
27
- FormsModule,
28
  IonicModule,
29
  RouterModule.forChild(routes),
30
  ComponentsModule
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
23
  @NgModule({
24
  imports: [
25
  CommonModule,
 
26
  IonicModule,
27
  RouterModule.forChild(routes),
28
  ComponentsModule
src/app/travel/listing/travel-listing.module.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
@@ -24,7 +23,6 @@ const routes: Routes = [
24
  @NgModule({
25
  imports: [
26
  CommonModule,
27
- FormsModule,
28
  IonicModule,
29
  RouterModule.forChild(routes),
30
  ComponentsModule
1
  import { NgModule } from '@angular/core';
2
  import { CommonModule } from '@angular/common';
 
3
  import { Routes, RouterModule } from '@angular/router';
4
 
5
  import { IonicModule } from '@ionic/angular';
23
  @NgModule({
24
  imports: [
25
  CommonModule,
 
26
  IonicModule,
27
  RouterModule.forChild(routes),
28
  ComponentsModule
src/app/user/profile/user-profile.module.ts CHANGED
@@ -5,11 +5,11 @@ import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
7
 
8
- import { ComponentsModule } from '../../components/components.module';
9
-
10
  import { UserService } from '../user.service';
11
  import { UserProfilePage } from './user-profile.page';
12
  import { UserProfileResolver } from './user-profile.resolver';
 
 
13
 
14
  const routes: Routes = [
15
  {
5
 
6
  import { IonicModule } from '@ionic/angular';
7
 
 
 
8
  import { UserService } from '../user.service';
9
  import { UserProfilePage } from './user-profile.page';
10
  import { UserProfileResolver } from './user-profile.resolver';
11
+ import { ComponentsModule } from '../../components/components.module';
12
+
13
 
14
  const routes: Routes = [
15
  {
src/app/validators/password.validator.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { FormControl, FormGroup } from '@angular/forms';
2
 
3
  export class PasswordValidator {
4
 
5
  // If our validation fails, we return an object with a key for the error name and a value of true.
6
  // Otherwise, if the validation passes, we simply return null because there is no error.
7
 
8
- static areNotEqual(formGroup: FormGroup) {
9
  let firstControlValue: any;
10
  let valid = true;
11
 
12
  for (const key in formGroup.controls) {
13
  if (formGroup.controls.hasOwnProperty(key)) {
14
- const control: FormControl = <FormControl>formGroup.controls[key];
15
 
16
  if (firstControlValue === undefined) {
17
  firstControlValue = control.value;
1
+ import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
2
 
3
  export class PasswordValidator {
4
 
5
  // If our validation fails, we return an object with a key for the error name and a value of true.
6
  // Otherwise, if the validation passes, we simply return null because there is no error.
7
 
8
+ static areNotEqual(formGroup: UntypedFormGroup) {
9
  let firstControlValue: any;
10
  let valid = true;
11
 
12
  for (const key in formGroup.controls) {
13
  if (formGroup.controls.hasOwnProperty(key)) {
14
+ const control: UntypedFormControl = <UntypedFormControl>formGroup.controls[key];
15
 
16
  if (firstControlValue === undefined) {
17
  firstControlValue = control.value;
src/app/validators/username.validator.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { FormControl } from '@angular/forms';
2
 
3
  export class UsernameValidator {
4
 
5
- static usernameNotAvailable(fc: FormControl) {
6
 
7
  // this is a dummy validator to check if the username is valid or not.
8
  // In a real app you should check against your DB if the username is already in use.
1
+ import { UntypedFormControl } from '@angular/forms';
2
 
3
  export class UsernameValidator {
4
 
5
+ static usernameNotAvailable(fc: UntypedFormControl) {
6
 
7
  // this is a dummy validator to check if the username is valid or not.
8
  // In a real app you should check against your DB if the username is already in use.
src/app/walkthrough/walkthrough.guard.ts CHANGED
@@ -1,13 +1,14 @@
1
  import { Injectable } from '@angular/core';
2
  import { CanActivate, Router } from '@angular/router';
3
- import { Storage } from '@capacitor/storage';
 
4
 
5
  @Injectable()
6
  export class WalkthroughGuard implements CanActivate {
7
  constructor(private router: Router) {}
8
 
9
  async canActivate(): Promise<boolean> {
10
- const { value } = await Storage.get({ key: 'visitedWalkthrough' });
11
 
12
  if (value === 'true') {
13
  // this is a returning user, don't show him the walkthrough
1
  import { Injectable } from '@angular/core';
2
  import { CanActivate, Router } from '@angular/router';
3
+
4
+ import { Preferences } from '@capacitor/preferences';
5
 
6
  @Injectable()
7
  export class WalkthroughGuard implements CanActivate {
8
  constructor(private router: Router) {}
9
 
10
  async canActivate(): Promise<boolean> {
11
+ const { value } = await Preferences.get({ key: 'visitedWalkthrough' });
12
 
13
  if (value === 'true') {
14
  // this is a returning user, don't show him the walkthrough
src/app/walkthrough/walkthrough.module.ts CHANGED
@@ -4,6 +4,7 @@ import { FormsModule } from '@angular/forms';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
 
7
  import { SwiperModule } from 'swiper/angular';
8
 
9
  import { ComponentsModule } from '../components/components.module';
4
  import { Routes, RouterModule } from '@angular/router';
5
 
6
  import { IonicModule } from '@ionic/angular';
7
+
8
  import { SwiperModule } from 'swiper/angular';
9
 
10
  import { ComponentsModule } from '../components/components.module';
src/app/walkthrough/walkthrough.page.ts CHANGED
@@ -1,9 +1,8 @@
1
  import { Component, AfterViewInit, ViewChild, HostBinding, OnInit, NgZone } from '@angular/core';
2
 
3
- import { Storage } from '@capacitor/storage';
4
 
5
- import { MenuController } from '@ionic/angular';
6
- import { IonicSwiper } from '@ionic/angular';
7
 
8
  import SwiperCore, { Pagination } from 'swiper';
9
  import { SwiperComponent } from 'swiper/angular';
@@ -34,8 +33,8 @@ export class WalkthroughPage implements AfterViewInit, OnInit {
34
  ) { }
35
 
36
  ngOnInit(): void {
37
- // save key to mark the walkthrough as visited so the next time the user vistis the app, he would be redirected to log in
38
- Storage.set({
39
  key: 'visitedWalkthrough',
40
  value: 'true'
41
  });
@@ -53,7 +52,6 @@ export class WalkthroughPage implements AfterViewInit, OnInit {
53
 
54
  ngAfterViewInit(): void {
55
  // Accessing slides in server platform throw errors
56
- // if (isPlatformBrowser(this.platformId)) {
57
  this.swiperRef = this.swiper.swiperRef;
58
 
59
  this.swiperRef.on('slidesLengthChange', () => {
@@ -71,7 +69,6 @@ export class WalkthroughPage implements AfterViewInit, OnInit {
71
  this.markSlides(this.swiperRef);
72
  });
73
  });
74
- // }
75
  }
76
 
77
  public setSwiperInstance(swiper: SwiperCore): void {
1
  import { Component, AfterViewInit, ViewChild, HostBinding, OnInit, NgZone } from '@angular/core';
2
 
3
+ import { Preferences } from '@capacitor/preferences';
4
 
5
+ import { MenuController, IonicSwiper } from '@ionic/angular';
 
6
 
7
  import SwiperCore, { Pagination } from 'swiper';
8
  import { SwiperComponent } from 'swiper/angular';
33
  ) { }
34
 
35
  ngOnInit(): void {
36
+ // save key to mark the walkthrough as visited so the next time the user visits the app, he would be redirected to log in
37
+ Preferences.set({
38
  key: 'visitedWalkthrough',
39
  value: 'true'
40
  });
52
 
53
  ngAfterViewInit(): void {
54
  // Accessing slides in server platform throw errors
 
55
  this.swiperRef = this.swiper.swiperRef;
56
 
57
  this.swiperRef.on('slidesLengthChange', () => {
69
  this.markSlides(this.swiperRef);
70
  });
71
  });
 
72
  }
73
 
74
  public setSwiperInstance(swiper: SwiperCore): void {
src/global.scss CHANGED
@@ -1,5 +1,5 @@
1
  // http://ionicframework.com/docs/theming/
2
- @import url('https://fonts.googleapis.com/css?family=Rubik:300,400,500,700');
3
 
4
  @import "~@ionic/angular/css/core.css";
5
  @import "~@ionic/angular/css/normalize.css";
@@ -12,10 +12,10 @@
12
  @import "~@ionic/angular/css/text-transformation.css";
13
  @import "~@ionic/angular/css/flex-utils.css";
14
 
15
- @import "~swiper/scss";
16
- @import "~swiper/scss/autoplay";
17
- @import "~swiper/scss/pagination";
18
- @import "~@ionic/angular/css/ionic-swiper";
19
 
20
  // EXTRA GLOBAL STYLES
21
  // Add custom Ionic Colors
1
  // http://ionicframework.com/docs/theming/
2
+ @import url("https://fonts.googleapis.com/css?family=Rubik:300,400,500,700");
3
 
4
  @import "~@ionic/angular/css/core.css";
5
  @import "~@ionic/angular/css/normalize.css";
12
  @import "~@ionic/angular/css/text-transformation.css";
13
  @import "~@ionic/angular/css/flex-utils.css";
14
 
15
+ @import "swiper/scss";
16
+ @import "swiper/scss/autoplay";
17
+ @import "swiper/scss/pagination";
18
+ @import "@ionic/angular/css/ionic-swiper";
19
 
20
  // EXTRA GLOBAL STYLES
21
  // Add custom Ionic Colors
src/index.html CHANGED
@@ -17,8 +17,9 @@
17
  <meta name="keywords" content="">
18
  <!-- favicon -->
19
  <!-- If you have a multi size .ico file -->
20
- <link rel="shortcut icon" sizes="64x64 48x48 32x32 24x24 16x16" href="assets/icon/favicon.ico">
21
  <!-- If you don't -->
 
22
  <link rel="icon" type="image/png" sizes="64x64" href="assets/icon/favicon-64x64.png">
23
  <link rel="icon" type="image/png" sizes="48x48" href="assets/icon/favicon-48x48.png">
24
  <link rel="icon" type="image/png" sizes="32x32" href="assets/icon/favicon-32x32.png">
17
  <meta name="keywords" content="">
18
  <!-- favicon -->
19
  <!-- If you have a multi size .ico file -->
20
+ <link rel="shortcut icon" sizes="128x128 64x64 48x48 32x32 24x24 16x16" href="assets/icon/favicon.ico">
21
  <!-- If you don't -->
22
+ <link rel="icon" type="image/png" sizes="128x128" href="assets/icon/favicon-128x128.png">
23
  <link rel="icon" type="image/png" sizes="64x64" href="assets/icon/favicon-64x64.png">
24
  <link rel="icon" type="image/png" sizes="48x48" href="assets/icon/favicon-48x48.png">
25
  <link rel="icon" type="image/png" sizes="32x32" href="assets/icon/favicon-32x32.png">
src/theme/app-defaults.scss CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  ion-title {
2
  // Adding !important to force precedence in SSR
3
  font-weight: 400 !important;
@@ -13,8 +17,3 @@ ion-title {
13
  margin-inline-start: .5rem;
14
  }
15
  }
16
-
17
- // temporary fix for https://github.com/ionic-team/ionic-framework/issues/18641
18
- ion-picker {
19
- touch-action: none;
20
- }
1
+ html {
2
+ line-height: 1.5;
3
+ }
4
+
5
  ion-title {
6
  // Adding !important to force precedence in SSR
7
  font-weight: 400 !important;
17
  margin-inline-start: .5rem;
18
  }
19
  }
 
 
 
 
 
src/tsconfig.app.json CHANGED
@@ -13,6 +13,5 @@
13
  "src/**/*.d.ts"
14
  ],
15
  "angularCompilerOptions": {
16
- "enableIvy": true
17
  }
18
  }
13
  "src/**/*.d.ts"
14
  ],
15
  "angularCompilerOptions": {
 
16
  }
17
  }
tsconfig.json CHANGED
@@ -12,7 +12,7 @@
12
  "allowSyntheticDefaultImports": true,
13
  "emitDecoratorMetadata": true,
14
  "experimentalDecorators": true,
15
- "target": "es2015",
16
  "skipLibCheck": true,
17
  "typeRoots": [
18
  "node_modules/@types"
@@ -20,6 +20,7 @@
20
  "lib": [
21
  "es2018",
22
  "dom"
23
- ]
 
24
  }
25
  }
12
  "allowSyntheticDefaultImports": true,
13
  "emitDecoratorMetadata": true,
14
  "experimentalDecorators": true,
15
+ "target": "ES2022",
16
  "skipLibCheck": true,
17
  "typeRoots": [
18
  "node_modules/@types"
20
  "lib": [
21
  "es2018",
22
  "dom"
23
+ ],
24
+ "useDefineForClassFields": false
25
  }
26
  }