diff --git a/asset/equipment/equipment_ankle_weight.jpg b/asset/equipment/equipment_ankle_weight.jpg new file mode 100644 index 0000000..c9f16cb Binary files /dev/null and b/asset/equipment/equipment_ankle_weight.jpg differ diff --git a/asset/equipment/equipment_baar.jpg b/asset/equipment/equipment_baar.jpg new file mode 100644 index 0000000..e718db3 Binary files /dev/null and b/asset/equipment/equipment_baar.jpg differ diff --git a/asset/image/equipment_bands.jpg b/asset/equipment/equipment_bands.jpg similarity index 100% rename from asset/image/equipment_bands.jpg rename to asset/equipment/equipment_bands.jpg diff --git a/asset/image/equipment_barbells.jpg b/asset/equipment/equipment_barbells.jpg similarity index 100% rename from asset/image/equipment_barbells.jpg rename to asset/equipment/equipment_barbells.jpg diff --git a/asset/image/equipment_cables.jpg b/asset/equipment/equipment_cables.jpg similarity index 100% rename from asset/image/equipment_cables.jpg rename to asset/equipment/equipment_cables.jpg diff --git a/asset/image/equipment_dumbbells.jpg b/asset/equipment/equipment_dumbbells.jpg similarity index 100% rename from asset/image/equipment_dumbbells.jpg rename to asset/equipment/equipment_dumbbells.jpg diff --git a/asset/image/equipment_exerciseball.jpg b/asset/equipment/equipment_exerciseball.jpg similarity index 100% rename from asset/image/equipment_exerciseball.jpg rename to asset/equipment/equipment_exerciseball.jpg diff --git a/asset/image/equipment_ez-baar_.jpg b/asset/equipment/equipment_ez-baar_.jpg similarity index 100% rename from asset/image/equipment_ez-baar_.jpg rename to asset/equipment/equipment_ez-baar_.jpg diff --git a/asset/image/equipment_gym_place.jpg b/asset/equipment/equipment_gym_place.jpg similarity index 100% rename from asset/image/equipment_gym_place.jpg rename to asset/equipment/equipment_gym_place.jpg diff --git a/asset/image/equipment_home.jpg b/asset/equipment/equipment_home.jpg similarity index 100% rename from asset/image/equipment_home.jpg rename to asset/equipment/equipment_home.jpg diff --git a/asset/image/equipment_home_place.jpg b/asset/equipment/equipment_home_place.jpg similarity index 100% rename from asset/image/equipment_home_place.jpg rename to asset/equipment/equipment_home_place.jpg diff --git a/asset/image/equipment_instabils.jpg b/asset/equipment/equipment_instabils.jpg similarity index 100% rename from asset/image/equipment_instabils.jpg rename to asset/equipment/equipment_instabils.jpg diff --git a/asset/image/equipment_kettlebells.jpg b/asset/equipment/equipment_kettlebells.jpg similarity index 100% rename from asset/image/equipment_kettlebells.jpg rename to asset/equipment/equipment_kettlebells.jpg diff --git a/asset/image/equipment_machine.jpg b/asset/equipment/equipment_machine.jpg similarity index 100% rename from asset/image/equipment_machine.jpg rename to asset/equipment/equipment_machine.jpg diff --git a/asset/image/equipment_medicine.jpg b/asset/equipment/equipment_medicine.jpg similarity index 100% rename from asset/image/equipment_medicine.jpg rename to asset/equipment/equipment_medicine.jpg diff --git a/asset/image/equipment_none.jpg b/asset/equipment/equipment_none.jpg similarity index 100% rename from asset/image/equipment_none.jpg rename to asset/equipment/equipment_none.jpg diff --git a/asset/image/equipment_others.jpg b/asset/equipment/equipment_others.jpg similarity index 100% rename from asset/image/equipment_others.jpg rename to asset/equipment/equipment_others.jpg diff --git a/asset/image/equipment_roll.jpg b/asset/equipment/equipment_roll.jpg similarity index 100% rename from asset/image/equipment_roll.jpg rename to asset/equipment/equipment_roll.jpg diff --git a/asset/image/equipment_rope.jpg b/asset/equipment/equipment_rope.jpg similarity index 100% rename from asset/image/equipment_rope.jpg rename to asset/equipment/equipment_rope.jpg diff --git a/asset/image/equipment_specialshome.jpg b/asset/equipment/equipment_specialshome.jpg similarity index 100% rename from asset/image/equipment_specialshome.jpg rename to asset/equipment/equipment_specialshome.jpg diff --git a/asset/image/equipment_strap.jpg b/asset/equipment/equipment_strap.jpg similarity index 100% rename from asset/image/equipment_strap.jpg rename to asset/equipment/equipment_strap.jpg diff --git a/asset/image/equipment_street.jpg b/asset/equipment/equipment_street.jpg similarity index 100% rename from asset/image/equipment_street.jpg rename to asset/equipment/equipment_street.jpg diff --git a/asset/equipment/equipment_street_place.jpg b/asset/equipment/equipment_street_place.jpg new file mode 100644 index 0000000..d1758d1 Binary files /dev/null and b/asset/equipment/equipment_street_place.jpg differ diff --git a/asset/equipment/equipment_vest_weight.jpg b/asset/equipment/equipment_vest_weight.jpg new file mode 100644 index 0000000..49576f2 Binary files /dev/null and b/asset/equipment/equipment_vest_weight.jpg differ diff --git a/asset/image/equipment_weightplates.jpg b/asset/equipment/equipment_weightplates.jpg similarity index 100% rename from asset/image/equipment_weightplates.jpg rename to asset/equipment/equipment_weightplates.jpg diff --git a/asset/image/Gain_muscle.jpg b/asset/image/Gain_muscle.jpg new file mode 100644 index 0000000..c3d2e04 Binary files /dev/null and b/asset/image/Gain_muscle.jpg differ diff --git a/asset/image/Gain_muscle.png b/asset/image/Gain_muscle.png deleted file mode 100644 index 9111e70..0000000 Binary files a/asset/image/Gain_muscle.png and /dev/null differ diff --git a/asset/image/WT01_loading_layers.png b/asset/image/WT01_loading_layers.png deleted file mode 100644 index 0e9d6bf..0000000 Binary files a/asset/image/WT01_loading_layers.png and /dev/null differ diff --git a/asset/image/WT_Results_for_female.jpg b/asset/image/WT_Results_for_female.jpg new file mode 100644 index 0000000..a244a6a Binary files /dev/null and b/asset/image/WT_Results_for_female.jpg differ diff --git a/asset/image/WT_Results_for_female.png b/asset/image/WT_Results_for_female.png deleted file mode 100644 index afbbccb..0000000 Binary files a/asset/image/WT_Results_for_female.png and /dev/null differ diff --git a/asset/image/WT_Results_for_men.jpg b/asset/image/WT_Results_for_men.jpg new file mode 100644 index 0000000..2b731e1 Binary files /dev/null and b/asset/image/WT_Results_for_men.jpg differ diff --git a/asset/image/WT_Results_for_men.png b/asset/image/WT_Results_for_men.png deleted file mode 100644 index 6ce93c8..0000000 Binary files a/asset/image/WT_Results_for_men.png and /dev/null differ diff --git a/asset/image/WT_Results_for_runners.jpg b/asset/image/WT_Results_for_runners.jpg new file mode 100644 index 0000000..24b9f0e Binary files /dev/null and b/asset/image/WT_Results_for_runners.jpg differ diff --git a/asset/image/WT_Results_for_runners.png b/asset/image/WT_Results_for_runners.png deleted file mode 100644 index a9be810..0000000 Binary files a/asset/image/WT_Results_for_runners.png and /dev/null differ diff --git a/asset/image/WT_black_G_background.jpg b/asset/image/WT_black_G_background.jpg new file mode 100644 index 0000000..d37fa73 Binary files /dev/null and b/asset/image/WT_black_G_background.jpg differ diff --git a/asset/image/WT_black_G_background.png b/asset/image/WT_black_G_background.png deleted file mode 100644 index 29184b2..0000000 Binary files a/asset/image/WT_black_G_background.png and /dev/null differ diff --git a/asset/image/WT_black_background.jpg b/asset/image/WT_black_background.jpg new file mode 100644 index 0000000..af5bbf0 Binary files /dev/null and b/asset/image/WT_black_background.jpg differ diff --git a/asset/image/WT_black_background.png b/asset/image/WT_black_background.png deleted file mode 100644 index 6bdc65b..0000000 Binary files a/asset/image/WT_black_background.png and /dev/null differ diff --git a/asset/image/WT_light_background.jpg b/asset/image/WT_light_background.jpg new file mode 100644 index 0000000..acb56c8 Binary files /dev/null and b/asset/image/WT_light_background.jpg differ diff --git a/asset/image/WT_light_background.png b/asset/image/WT_light_background.png deleted file mode 100644 index 836a7b7..0000000 Binary files a/asset/image/WT_light_background.png and /dev/null differ diff --git a/asset/image/WT_loading_layers.jpg b/asset/image/WT_loading_layers.jpg new file mode 100644 index 0000000..028c4f3 Binary files /dev/null and b/asset/image/WT_loading_layers.jpg differ diff --git a/asset/image/WT_login.jpg b/asset/image/WT_login.jpg new file mode 100644 index 0000000..c4c1bff Binary files /dev/null and b/asset/image/WT_login.jpg differ diff --git a/asset/image/WT_login.png b/asset/image/WT_login.png deleted file mode 100644 index ab6e431..0000000 Binary files a/asset/image/WT_login.png and /dev/null differ diff --git a/asset/image/WT_menu_backround.jpg b/asset/image/WT_menu_backround.jpg new file mode 100644 index 0000000..65231a8 Binary files /dev/null and b/asset/image/WT_menu_backround.jpg differ diff --git a/asset/image/WT_menu_backround.png b/asset/image/WT_menu_backround.png deleted file mode 100644 index 92b944d..0000000 Binary files a/asset/image/WT_menu_backround.png and /dev/null differ diff --git a/asset/image/WT_menu_dark.jpg b/asset/image/WT_menu_dark.jpg new file mode 100644 index 0000000..874699e Binary files /dev/null and b/asset/image/WT_menu_dark.jpg differ diff --git a/asset/image/WT_menu_dark.png b/asset/image/WT_menu_dark.png deleted file mode 100644 index 6f74804..0000000 Binary files a/asset/image/WT_menu_dark.png and /dev/null differ diff --git a/asset/image/WT_menu_welcome.png b/asset/image/WT_menu_welcome.png deleted file mode 100644 index 5463667..0000000 Binary files a/asset/image/WT_menu_welcome.png and /dev/null differ diff --git a/asset/image/WT_plainblack_background.jpg b/asset/image/WT_plainblack_background.jpg new file mode 100644 index 0000000..f80f602 Binary files /dev/null and b/asset/image/WT_plainblack_background.jpg differ diff --git a/asset/image/WT_plainblack_background.png b/asset/image/WT_plainblack_background.png deleted file mode 100644 index 0f5db20..0000000 Binary files a/asset/image/WT_plainblack_background.png and /dev/null differ diff --git a/asset/image/WT_sales_background.jpg b/asset/image/WT_sales_background.jpg new file mode 100644 index 0000000..2cd570b Binary files /dev/null and b/asset/image/WT_sales_background.jpg differ diff --git a/asset/image/WT_sales_background.png b/asset/image/WT_sales_background.png deleted file mode 100644 index 82b97fe..0000000 Binary files a/asset/image/WT_sales_background.png and /dev/null differ diff --git a/asset/image/WT_sales_background_3x5.jpg b/asset/image/WT_sales_background_3x5.jpg new file mode 100644 index 0000000..3c0a9e0 Binary files /dev/null and b/asset/image/WT_sales_background_3x5.jpg differ diff --git a/asset/image/WT_sales_background_3x5.png b/asset/image/WT_sales_background_3x5.png deleted file mode 100644 index 15c5961..0000000 Binary files a/asset/image/WT_sales_background_3x5.png and /dev/null differ diff --git a/asset/image/WT_weight_loss.jpg b/asset/image/WT_weight_loss.jpg new file mode 100644 index 0000000..b22aaba Binary files /dev/null and b/asset/image/WT_weight_loss.jpg differ diff --git a/asset/image/WT_weight_loss.png b/asset/image/WT_weight_loss.png deleted file mode 100644 index 3e751d4..0000000 Binary files a/asset/image/WT_weight_loss.png and /dev/null differ diff --git a/asset/image/WT_welcome.jpg b/asset/image/WT_welcome.jpg new file mode 100644 index 0000000..165a9b1 Binary files /dev/null and b/asset/image/WT_welcome.jpg differ diff --git a/asset/image/WT_welcome.png b/asset/image/WT_welcome.png deleted file mode 100644 index 5463667..0000000 Binary files a/asset/image/WT_welcome.png and /dev/null differ diff --git a/asset/image/add_test.png b/asset/image/add_test.png new file mode 100644 index 0000000..a279300 Binary files /dev/null and b/asset/image/add_test.png differ diff --git a/asset/image/ankle_weight.png b/asset/image/ankle_weight.png deleted file mode 100644 index 215861f..0000000 Binary files a/asset/image/ankle_weight.png and /dev/null differ diff --git a/asset/image/dots.gif b/asset/image/dots.gif deleted file mode 100644 index bce1400..0000000 Binary files a/asset/image/dots.gif and /dev/null differ diff --git a/asset/image/equipment_baar.jpg b/asset/image/equipment_baar.jpg deleted file mode 100644 index 61a3d71..0000000 Binary files a/asset/image/equipment_baar.jpg and /dev/null differ diff --git a/asset/image/equipment_street_place.jpg b/asset/image/equipment_street_place.jpg deleted file mode 100644 index fe83c5c..0000000 Binary files a/asset/image/equipment_street_place.jpg and /dev/null differ diff --git a/asset/image/lock.png b/asset/image/lock.png index edf3147..a2ba57c 100644 Binary files a/asset/image/lock.png and b/asset/image/lock.png differ diff --git a/asset/image/vest_weight.png b/asset/image/vest_weight.png deleted file mode 100644 index 3811b6d..0000000 Binary files a/asset/image/vest_weight.png and /dev/null differ diff --git a/asset/menu/1.1.aerob.jpg b/asset/menu/1.1.aerob.jpg index cf104e6..6b8f620 100644 Binary files a/asset/menu/1.1.aerob.jpg and b/asset/menu/1.1.aerob.jpg differ diff --git a/asset/menu/1.2.anaerob.jpg b/asset/menu/1.2.anaerob.jpg index 6ce88db..934280a 100644 Binary files a/asset/menu/1.2.anaerob.jpg and b/asset/menu/1.2.anaerob.jpg differ diff --git a/asset/menu/1.cardio.jpg b/asset/menu/1.cardio.jpg index 65ae155..93a5ae3 100644 Binary files a/asset/menu/1.cardio.jpg and b/asset/menu/1.cardio.jpg differ diff --git a/asset/menu/2.1.1.1RM.jpg b/asset/menu/2.1.1.1RM.jpg index 0bfd122..e7f4700 100644 Binary files a/asset/menu/2.1.1.1RM.jpg and b/asset/menu/2.1.1.1RM.jpg differ diff --git a/asset/menu/2.1.6.core.jpg b/asset/menu/2.1.6.core.jpg index 544cd84..8140ba5 100644 Binary files a/asset/menu/2.1.6.core.jpg and b/asset/menu/2.1.6.core.jpg differ diff --git a/asset/menu/2.1.endurance.jpg b/asset/menu/2.1.endurance.jpg index ce3da61..0ddfc51 100644 Binary files a/asset/menu/2.1.endurance.jpg and b/asset/menu/2.1.endurance.jpg differ diff --git a/asset/menu/2.2.1.1.chest.jpg b/asset/menu/2.2.1.1.chest.jpg index 8f935c7..29e060b 100644 Binary files a/asset/menu/2.2.1.1.chest.jpg and b/asset/menu/2.2.1.1.chest.jpg differ diff --git a/asset/menu/2.2.1.3.biceps.jpg b/asset/menu/2.2.1.3.biceps.jpg index 8f33b4a..9ed6701 100644 Binary files a/asset/menu/2.2.1.3.biceps.jpg and b/asset/menu/2.2.1.3.biceps.jpg differ diff --git a/asset/menu/2.2.1.4.triceps.jpg b/asset/menu/2.2.1.4.triceps.jpg index 8f1d3c7..2009b33 100644 Binary files a/asset/menu/2.2.1.4.triceps.jpg and b/asset/menu/2.2.1.4.triceps.jpg differ diff --git a/asset/menu/2.2.1.5.shoulders.jpg b/asset/menu/2.2.1.5.shoulders.jpg index 8c6f448..063ec9f 100644 Binary files a/asset/menu/2.2.1.5.shoulders.jpg and b/asset/menu/2.2.1.5.shoulders.jpg differ diff --git a/asset/menu/2.2.1.6.thigh.jpg b/asset/menu/2.2.1.6.thigh.jpg index 65635e8..1e0b6b3 100644 Binary files a/asset/menu/2.2.1.6.thigh.jpg and b/asset/menu/2.2.1.6.thigh.jpg differ diff --git a/asset/menu/2.2.1.7.back.jpg b/asset/menu/2.2.1.7.back.jpg index 316565c..c308c43 100644 Binary files a/asset/menu/2.2.1.7.back.jpg and b/asset/menu/2.2.1.7.back.jpg differ diff --git a/asset/menu/2.2.1.8.calf.jpg b/asset/menu/2.2.1.8.calf.jpg index 40f41ce..31da752 100644 Binary files a/asset/menu/2.2.1.8.calf.jpg and b/asset/menu/2.2.1.8.calf.jpg differ diff --git a/asset/menu/2.strength.jpg b/asset/menu/2.strength.jpg index 1f0ceba..3d6810c 100644 Binary files a/asset/menu/2.strength.jpg and b/asset/menu/2.strength.jpg differ diff --git a/asset/menu/3.bcs1.jpg b/asset/menu/3.bcs1.jpg index 4c1f0e8..0b26f8c 100644 Binary files a/asset/menu/3.bcs1.jpg and b/asset/menu/3.bcs1.jpg differ diff --git a/asset/menu/300m.jpg b/asset/menu/300m.jpg new file mode 100644 index 0000000..d17b843 Binary files /dev/null and b/asset/menu/300m.jpg differ diff --git a/asset/menu/400m.jpg b/asset/menu/400m.jpg new file mode 100644 index 0000000..b649b86 Binary files /dev/null and b/asset/menu/400m.jpg differ diff --git a/asset/menu/alternate_dumbbell_presses.jpg b/asset/menu/alternate_dumbbell_presses.jpg new file mode 100644 index 0000000..4d4a571 Binary files /dev/null and b/asset/menu/alternate_dumbbell_presses.jpg differ diff --git a/asset/menu/alternate_standing_shoulder_press.jpg b/asset/menu/alternate_standing_shoulder_press.jpg new file mode 100644 index 0000000..03ce3fb Binary files /dev/null and b/asset/menu/alternate_standing_shoulder_press.jpg differ diff --git a/asset/menu/arnold_press.jpg b/asset/menu/arnold_press.jpg new file mode 100644 index 0000000..9c9679f Binary files /dev/null and b/asset/menu/arnold_press.jpg differ diff --git a/asset/menu/bar_scott.jpg b/asset/menu/bar_scott.jpg new file mode 100644 index 0000000..f25ae16 Binary files /dev/null and b/asset/menu/bar_scott.jpg differ diff --git a/asset/menu/barbell_upright_row.jpg b/asset/menu/barbell_upright_row.jpg new file mode 100644 index 0000000..2154399 Binary files /dev/null and b/asset/menu/barbell_upright_row.jpg differ diff --git a/asset/menu/behind_the_neck_lat_pulldown.jpg b/asset/menu/behind_the_neck_lat_pulldown.jpg new file mode 100644 index 0000000..78874b9 Binary files /dev/null and b/asset/menu/behind_the_neck_lat_pulldown.jpg differ diff --git a/asset/menu/behind_the_neck_presses.jpg b/asset/menu/behind_the_neck_presses.jpg new file mode 100644 index 0000000..83af401 Binary files /dev/null and b/asset/menu/behind_the_neck_presses.jpg differ diff --git a/asset/menu/bent_arm_barbell_pullovers.jpg b/asset/menu/bent_arm_barbell_pullovers.jpg new file mode 100644 index 0000000..e944cb2 Binary files /dev/null and b/asset/menu/bent_arm_barbell_pullovers.jpg differ diff --git a/asset/menu/bent_knee_situps.jpg b/asset/menu/bent_knee_situps.jpg new file mode 100644 index 0000000..4d132af Binary files /dev/null and b/asset/menu/bent_knee_situps.jpg differ diff --git a/asset/menu/bent_over_lateral_raises_with_dumbbells.jpg b/asset/menu/bent_over_lateral_raises_with_dumbbells.jpg new file mode 100644 index 0000000..f37f18a Binary files /dev/null and b/asset/menu/bent_over_lateral_raises_with_dumbbells.jpg differ diff --git a/asset/menu/biceps_machine.jpg b/asset/menu/biceps_machine.jpg new file mode 100644 index 0000000..3545dd8 Binary files /dev/null and b/asset/menu/biceps_machine.jpg differ diff --git a/asset/menu/bmi.jpg b/asset/menu/bmi.jpg new file mode 100644 index 0000000..a437ae5 Binary files /dev/null and b/asset/menu/bmi.jpg differ diff --git a/asset/menu/bmr.jpg b/asset/menu/bmr.jpg new file mode 100644 index 0000000..bd72974 Binary files /dev/null and b/asset/menu/bmr.jpg differ diff --git a/asset/menu/cable_crosses.jpg b/asset/menu/cable_crosses.jpg new file mode 100644 index 0000000..42b32ec Binary files /dev/null and b/asset/menu/cable_crosses.jpg differ diff --git a/asset/menu/cable_flyes.jpg b/asset/menu/cable_flyes.jpg new file mode 100644 index 0000000..c8122f2 Binary files /dev/null and b/asset/menu/cable_flyes.jpg differ diff --git a/asset/menu/cable_rows.jpg b/asset/menu/cable_rows.jpg new file mode 100644 index 0000000..447fcf0 Binary files /dev/null and b/asset/menu/cable_rows.jpg differ diff --git a/asset/menu/chair_leg_raises.jpg b/asset/menu/chair_leg_raises.jpg new file mode 100644 index 0000000..59bfdd3 Binary files /dev/null and b/asset/menu/chair_leg_raises.jpg differ diff --git a/asset/menu/chest_press.jpg b/asset/menu/chest_press.jpg new file mode 100644 index 0000000..29e060b Binary files /dev/null and b/asset/menu/chest_press.jpg differ diff --git a/asset/menu/chest_press_machine.jpg b/asset/menu/chest_press_machine.jpg new file mode 100644 index 0000000..9c8198f Binary files /dev/null and b/asset/menu/chest_press_machine.jpg differ diff --git a/asset/menu/chins.jpg b/asset/menu/chins.jpg new file mode 100644 index 0000000..d7e76fc Binary files /dev/null and b/asset/menu/chins.jpg differ diff --git a/asset/menu/close_grip_front_lat_pulldown.jpg b/asset/menu/close_grip_front_lat_pulldown.jpg new file mode 100644 index 0000000..21c5fdd Binary files /dev/null and b/asset/menu/close_grip_front_lat_pulldown.jpg differ diff --git a/asset/menu/close_grip_pull_ups.jpg b/asset/menu/close_grip_pull_ups.jpg new file mode 100644 index 0000000..df1714d Binary files /dev/null and b/asset/menu/close_grip_pull_ups.jpg differ diff --git a/asset/menu/close_reverse_grip_lat_pulldown.jpg b/asset/menu/close_reverse_grip_lat_pulldown.jpg new file mode 100644 index 0000000..7b306d1 Binary files /dev/null and b/asset/menu/close_reverse_grip_lat_pulldown.jpg differ diff --git a/asset/menu/concentration.jpg b/asset/menu/concentration.jpg new file mode 100644 index 0000000..c416c57 Binary files /dev/null and b/asset/menu/concentration.jpg differ diff --git a/asset/menu/cooper.jpg b/asset/menu/cooper.jpg new file mode 100644 index 0000000..3cd6699 Binary files /dev/null and b/asset/menu/cooper.jpg differ diff --git a/asset/menu/crisscross.jpg b/asset/menu/crisscross.jpg new file mode 100644 index 0000000..4022f91 Binary files /dev/null and b/asset/menu/crisscross.jpg differ diff --git a/asset/menu/cross_bench_dumbbell_pullover.jpg b/asset/menu/cross_bench_dumbbell_pullover.jpg new file mode 100644 index 0000000..d9d0559 Binary files /dev/null and b/asset/menu/cross_bench_dumbbell_pullover.jpg differ diff --git a/asset/menu/deadlift.jpg b/asset/menu/deadlift.jpg new file mode 100644 index 0000000..b7da494 Binary files /dev/null and b/asset/menu/deadlift.jpg differ diff --git a/asset/menu/decline_bench_press.jpg b/asset/menu/decline_bench_press.jpg new file mode 100644 index 0000000..9a69f47 Binary files /dev/null and b/asset/menu/decline_bench_press.jpg differ diff --git a/asset/menu/decline_cable_flyes.jpg b/asset/menu/decline_cable_flyes.jpg new file mode 100644 index 0000000..992b1e9 Binary files /dev/null and b/asset/menu/decline_cable_flyes.jpg differ diff --git a/asset/menu/decline_dumbbell_bench_press.jpg b/asset/menu/decline_dumbbell_bench_press.jpg new file mode 100644 index 0000000..7d38b75 Binary files /dev/null and b/asset/menu/decline_dumbbell_bench_press.jpg differ diff --git a/asset/menu/decline_flyes.jpg b/asset/menu/decline_flyes.jpg new file mode 100644 index 0000000..93d087a Binary files /dev/null and b/asset/menu/decline_flyes.jpg differ diff --git a/asset/menu/donkey_calf_raises.jpg b/asset/menu/donkey_calf_raises.jpg new file mode 100644 index 0000000..22b6cb8 Binary files /dev/null and b/asset/menu/donkey_calf_raises.jpg differ diff --git a/asset/menu/dumbbell_alternate_bicep_curl.jpg b/asset/menu/dumbbell_alternate_bicep_curl.jpg new file mode 100644 index 0000000..84cd623 Binary files /dev/null and b/asset/menu/dumbbell_alternate_bicep_curl.jpg differ diff --git a/asset/menu/dumbell_bench_presses.jpg b/asset/menu/dumbell_bench_presses.jpg new file mode 100644 index 0000000..a538640 Binary files /dev/null and b/asset/menu/dumbell_bench_presses.jpg differ diff --git a/asset/menu/ez_bar_burl.jpg b/asset/menu/ez_bar_burl.jpg new file mode 100644 index 0000000..277365b Binary files /dev/null and b/asset/menu/ez_bar_burl.jpg differ diff --git a/asset/menu/flyes.jpg b/asset/menu/flyes.jpg new file mode 100644 index 0000000..8712e64 Binary files /dev/null and b/asset/menu/flyes.jpg differ diff --git a/asset/menu/forward_raise.jpg b/asset/menu/forward_raise.jpg new file mode 100644 index 0000000..42be25f Binary files /dev/null and b/asset/menu/forward_raise.jpg differ diff --git a/asset/menu/front_rear_lat_pulldown.jpg b/asset/menu/front_rear_lat_pulldown.jpg new file mode 100644 index 0000000..21c5fdd Binary files /dev/null and b/asset/menu/front_rear_lat_pulldown.jpg differ diff --git a/asset/menu/front_squat.jpg b/asset/menu/front_squat.jpg new file mode 100644 index 0000000..2cb3179 Binary files /dev/null and b/asset/menu/front_squat.jpg differ diff --git a/asset/menu/hack_squat.jpg b/asset/menu/hack_squat.jpg new file mode 100644 index 0000000..3406596 Binary files /dev/null and b/asset/menu/hack_squat.jpg differ diff --git a/asset/menu/hammer_curl.jpg b/asset/menu/hammer_curl.jpg new file mode 100644 index 0000000..25483eb Binary files /dev/null and b/asset/menu/hammer_curl.jpg differ diff --git a/asset/menu/hanging_leg_raises.jpg b/asset/menu/hanging_leg_raises.jpg new file mode 100644 index 0000000..af8078c Binary files /dev/null and b/asset/menu/hanging_leg_raises.jpg differ diff --git a/asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg b/asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg new file mode 100644 index 0000000..78c1026 Binary files /dev/null and b/asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg differ diff --git a/asset/menu/hyperextension.jpg b/asset/menu/hyperextension.jpg new file mode 100644 index 0000000..00ff3f4 Binary files /dev/null and b/asset/menu/hyperextension.jpg differ diff --git a/asset/menu/incline_cable_flyes.jpg b/asset/menu/incline_cable_flyes.jpg new file mode 100644 index 0000000..c8122f2 Binary files /dev/null and b/asset/menu/incline_cable_flyes.jpg differ diff --git a/asset/menu/incline_curl_with_dumbbels.jpg b/asset/menu/incline_curl_with_dumbbels.jpg new file mode 100644 index 0000000..a722aae Binary files /dev/null and b/asset/menu/incline_curl_with_dumbbels.jpg differ diff --git a/asset/menu/incline_dumbbell_press.jpg b/asset/menu/incline_dumbbell_press.jpg new file mode 100644 index 0000000..e4d6692 Binary files /dev/null and b/asset/menu/incline_dumbbell_press.jpg differ diff --git a/asset/menu/incline_flyes.jpg b/asset/menu/incline_flyes.jpg new file mode 100644 index 0000000..dc84818 Binary files /dev/null and b/asset/menu/incline_flyes.jpg differ diff --git a/asset/menu/incline_press.jpg b/asset/menu/incline_press.jpg new file mode 100644 index 0000000..71e3d47 Binary files /dev/null and b/asset/menu/incline_press.jpg differ diff --git a/asset/menu/incline_triceps_extension.jpg b/asset/menu/incline_triceps_extension.jpg new file mode 100644 index 0000000..caf1860 Binary files /dev/null and b/asset/menu/incline_triceps_extension.jpg differ diff --git a/asset/menu/leg_curls.jpg b/asset/menu/leg_curls.jpg new file mode 100644 index 0000000..086481e Binary files /dev/null and b/asset/menu/leg_curls.jpg differ diff --git a/asset/menu/leg_extension.jpg b/asset/menu/leg_extension.jpg new file mode 100644 index 0000000..98d888e Binary files /dev/null and b/asset/menu/leg_extension.jpg differ diff --git a/asset/menu/legpress.jpg b/asset/menu/legpress.jpg new file mode 100644 index 0000000..e778a67 Binary files /dev/null and b/asset/menu/legpress.jpg differ diff --git a/asset/menu/lunges.jpg b/asset/menu/lunges.jpg new file mode 100644 index 0000000..2721e38 Binary files /dev/null and b/asset/menu/lunges.jpg differ diff --git a/asset/menu/lunges_with_dumbbells.jpg b/asset/menu/lunges_with_dumbbells.jpg new file mode 100644 index 0000000..564bd1c Binary files /dev/null and b/asset/menu/lunges_with_dumbbells.jpg differ diff --git a/asset/menu/lying_alternating_leg_raises.jpg b/asset/menu/lying_alternating_leg_raises.jpg new file mode 100644 index 0000000..b7aa940 Binary files /dev/null and b/asset/menu/lying_alternating_leg_raises.jpg differ diff --git a/asset/menu/lying_biceps_cable_curl.jpg b/asset/menu/lying_biceps_cable_curl.jpg new file mode 100644 index 0000000..d154cfd Binary files /dev/null and b/asset/menu/lying_biceps_cable_curl.jpg differ diff --git a/asset/menu/lying_curls.jpg b/asset/menu/lying_curls.jpg new file mode 100644 index 0000000..9f49a1d Binary files /dev/null and b/asset/menu/lying_curls.jpg differ diff --git a/asset/menu/lying_leg_raises.jpg b/asset/menu/lying_leg_raises.jpg new file mode 100644 index 0000000..f8772fd Binary files /dev/null and b/asset/menu/lying_leg_raises.jpg differ diff --git a/asset/menu/lying_rear_delt_raise.jpg b/asset/menu/lying_rear_delt_raise.jpg new file mode 100644 index 0000000..9b2adba Binary files /dev/null and b/asset/menu/lying_rear_delt_raise.jpg differ diff --git a/asset/menu/lying_scissors.jpg b/asset/menu/lying_scissors.jpg new file mode 100644 index 0000000..69f8aff Binary files /dev/null and b/asset/menu/lying_scissors.jpg differ diff --git a/asset/menu/lying_triceps_extension.jpg b/asset/menu/lying_triceps_extension.jpg new file mode 100644 index 0000000..e506681 Binary files /dev/null and b/asset/menu/lying_triceps_extension.jpg differ diff --git a/asset/menu/machine_shoulder_press.jpg b/asset/menu/machine_shoulder_press.jpg new file mode 100644 index 0000000..b08a3af Binary files /dev/null and b/asset/menu/machine_shoulder_press.jpg differ diff --git a/asset/menu/oblique_crunch.jpg b/asset/menu/oblique_crunch.jpg new file mode 100644 index 0000000..3b6f398 Binary files /dev/null and b/asset/menu/oblique_crunch.jpg differ diff --git a/asset/menu/olympic_squat.jpg b/asset/menu/olympic_squat.jpg new file mode 100644 index 0000000..a4f0020 Binary files /dev/null and b/asset/menu/olympic_squat.jpg differ diff --git a/asset/menu/one_arm_row.jpg b/asset/menu/one_arm_row.jpg new file mode 100644 index 0000000..3a9f398 Binary files /dev/null and b/asset/menu/one_arm_row.jpg differ diff --git a/asset/menu/overhead_dumbbell_triceps_extension.jpg b/asset/menu/overhead_dumbbell_triceps_extension.jpg new file mode 100644 index 0000000..a5c896e Binary files /dev/null and b/asset/menu/overhead_dumbbell_triceps_extension.jpg differ diff --git a/asset/menu/peck_deck_flyes.jpg b/asset/menu/peck_deck_flyes.jpg new file mode 100644 index 0000000..b45a0a2 Binary files /dev/null and b/asset/menu/peck_deck_flyes.jpg differ diff --git a/asset/menu/plank.jpg b/asset/menu/plank.jpg new file mode 100644 index 0000000..aa2be37 Binary files /dev/null and b/asset/menu/plank.jpg differ diff --git a/asset/menu/pull_up.jpg b/asset/menu/pull_up.jpg new file mode 100644 index 0000000..697af26 Binary files /dev/null and b/asset/menu/pull_up.jpg differ diff --git a/asset/menu/pullups.jpg b/asset/menu/pullups.jpg new file mode 100644 index 0000000..c308c43 Binary files /dev/null and b/asset/menu/pullups.jpg differ diff --git a/asset/menu/pushup.jpg b/asset/menu/pushup.jpg new file mode 100644 index 0000000..e020fe5 Binary files /dev/null and b/asset/menu/pushup.jpg differ diff --git a/asset/menu/pushups.jpg b/asset/menu/pushups.jpg new file mode 100644 index 0000000..e020fe5 Binary files /dev/null and b/asset/menu/pushups.jpg differ diff --git a/asset/menu/pushups_dip.jpg b/asset/menu/pushups_dip.jpg new file mode 100644 index 0000000..bc32b44 Binary files /dev/null and b/asset/menu/pushups_dip.jpg differ diff --git a/asset/menu/reverse_crunches.jpg b/asset/menu/reverse_crunches.jpg new file mode 100644 index 0000000..84dada0 Binary files /dev/null and b/asset/menu/reverse_crunches.jpg differ diff --git a/asset/menu/roman_chair_situps.jpg b/asset/menu/roman_chair_situps.jpg new file mode 100644 index 0000000..c3cf94c Binary files /dev/null and b/asset/menu/roman_chair_situps.jpg differ diff --git a/asset/menu/russian_twist.jpg b/asset/menu/russian_twist.jpg new file mode 100644 index 0000000..6079df5 Binary files /dev/null and b/asset/menu/russian_twist.jpg differ diff --git a/asset/menu/seated_bar_twist.jpg b/asset/menu/seated_bar_twist.jpg new file mode 100644 index 0000000..62690dd Binary files /dev/null and b/asset/menu/seated_bar_twist.jpg differ diff --git a/asset/menu/seated_dumbbell_curl.jpg b/asset/menu/seated_dumbbell_curl.jpg new file mode 100644 index 0000000..075bf76 Binary files /dev/null and b/asset/menu/seated_dumbbell_curl.jpg differ diff --git a/asset/menu/seated_dumbbell_shoulder_press.jpg b/asset/menu/seated_dumbbell_shoulder_press.jpg new file mode 100644 index 0000000..a08f201 Binary files /dev/null and b/asset/menu/seated_dumbbell_shoulder_press.jpg differ diff --git a/asset/menu/seated_lateral_raises.jpg b/asset/menu/seated_lateral_raises.jpg new file mode 100644 index 0000000..d3ffc64 Binary files /dev/null and b/asset/menu/seated_lateral_raises.jpg differ diff --git a/asset/menu/seated_triceps_extension.jpg b/asset/menu/seated_triceps_extension.jpg new file mode 100644 index 0000000..729fdc1 Binary files /dev/null and b/asset/menu/seated_triceps_extension.jpg differ diff --git a/asset/menu/shrugs.jpg b/asset/menu/shrugs.jpg new file mode 100644 index 0000000..4e4aaa1 Binary files /dev/null and b/asset/menu/shrugs.jpg differ diff --git a/asset/menu/side_to_side_chop.jpg b/asset/menu/side_to_side_chop.jpg new file mode 100644 index 0000000..62677fb Binary files /dev/null and b/asset/menu/side_to_side_chop.jpg differ diff --git a/asset/menu/single_arm_bent_over_cable_reverse_fly.jpg b/asset/menu/single_arm_bent_over_cable_reverse_fly.jpg new file mode 100644 index 0000000..d2bf056 Binary files /dev/null and b/asset/menu/single_arm_bent_over_cable_reverse_fly.jpg differ diff --git a/asset/menu/single_arm_t-bar_rows.jpg b/asset/menu/single_arm_t-bar_rows.jpg new file mode 100644 index 0000000..a21fd3d Binary files /dev/null and b/asset/menu/single_arm_t-bar_rows.jpg differ diff --git a/asset/menu/single_hand_lateral_raises.jpg b/asset/menu/single_hand_lateral_raises.jpg new file mode 100644 index 0000000..8c6f448 Binary files /dev/null and b/asset/menu/single_hand_lateral_raises.jpg differ diff --git a/asset/menu/single_hand_lying_triceps_extension.jpg b/asset/menu/single_hand_lying_triceps_extension.jpg new file mode 100644 index 0000000..8c7cc54 Binary files /dev/null and b/asset/menu/single_hand_lying_triceps_extension.jpg differ diff --git a/asset/menu/sitting_knee_ups.jpg b/asset/menu/sitting_knee_ups.jpg new file mode 100644 index 0000000..6b81e82 Binary files /dev/null and b/asset/menu/sitting_knee_ups.jpg differ diff --git a/asset/menu/sitting_machine_calf_raises.jpg b/asset/menu/sitting_machine_calf_raises.jpg new file mode 100644 index 0000000..f76bf66 Binary files /dev/null and b/asset/menu/sitting_machine_calf_raises.jpg differ diff --git a/asset/menu/situps.jpg b/asset/menu/situps.jpg new file mode 100644 index 0000000..b9f8011 Binary files /dev/null and b/asset/menu/situps.jpg differ diff --git a/asset/menu/sizes.jpg b/asset/menu/sizes.jpg new file mode 100644 index 0000000..5b33d2a Binary files /dev/null and b/asset/menu/sizes.jpg differ diff --git a/asset/menu/smith_machine_chest_press.jpg b/asset/menu/smith_machine_chest_press.jpg new file mode 100644 index 0000000..52f32c3 Binary files /dev/null and b/asset/menu/smith_machine_chest_press.jpg differ diff --git a/asset/menu/squat.jpg b/asset/menu/squat.jpg new file mode 100644 index 0000000..58d2de2 Binary files /dev/null and b/asset/menu/squat.jpg differ diff --git a/asset/menu/squat_jump.jpg b/asset/menu/squat_jump.jpg new file mode 100644 index 0000000..5d19230 Binary files /dev/null and b/asset/menu/squat_jump.jpg differ diff --git a/asset/menu/squat_jump_weight.jpg b/asset/menu/squat_jump_weight.jpg new file mode 100644 index 0000000..8a24cdd Binary files /dev/null and b/asset/menu/squat_jump_weight.jpg differ diff --git a/asset/menu/squat_without_weight.jpg b/asset/menu/squat_without_weight.jpg new file mode 100644 index 0000000..8a24cdd Binary files /dev/null and b/asset/menu/squat_without_weight.jpg differ diff --git a/asset/menu/standing_barbell_curl.jpg b/asset/menu/standing_barbell_curl.jpg new file mode 100644 index 0000000..6ca960e Binary files /dev/null and b/asset/menu/standing_barbell_curl.jpg differ diff --git a/asset/menu/standing_biceps_cable_curl.jpg b/asset/menu/standing_biceps_cable_curl.jpg new file mode 100644 index 0000000..aae36e6 Binary files /dev/null and b/asset/menu/standing_biceps_cable_curl.jpg differ diff --git a/asset/menu/standing_cable_triceps_extension.jpg b/asset/menu/standing_cable_triceps_extension.jpg new file mode 100644 index 0000000..c0ab0ea Binary files /dev/null and b/asset/menu/standing_cable_triceps_extension.jpg differ diff --git a/asset/menu/standing_face_pull.jpg b/asset/menu/standing_face_pull.jpg new file mode 100644 index 0000000..875e6be Binary files /dev/null and b/asset/menu/standing_face_pull.jpg differ diff --git a/asset/menu/standing_leg_curls.jpg b/asset/menu/standing_leg_curls.jpg new file mode 100644 index 0000000..ce6cd85 Binary files /dev/null and b/asset/menu/standing_leg_curls.jpg differ diff --git a/asset/menu/standing_military_presses.jpg b/asset/menu/standing_military_presses.jpg new file mode 100644 index 0000000..ba17711 Binary files /dev/null and b/asset/menu/standing_military_presses.jpg differ diff --git a/asset/menu/standing_one_arm_cable_curl.jpg b/asset/menu/standing_one_arm_cable_curl.jpg new file mode 100644 index 0000000..ec621ec Binary files /dev/null and b/asset/menu/standing_one_arm_cable_curl.jpg differ diff --git a/asset/menu/standing_side_cable_laterals.jpg b/asset/menu/standing_side_cable_laterals.jpg new file mode 100644 index 0000000..8470686 Binary files /dev/null and b/asset/menu/standing_side_cable_laterals.jpg differ diff --git a/asset/menu/standing_single_arm_lateral_raises.jpg b/asset/menu/standing_single_arm_lateral_raises.jpg new file mode 100644 index 0000000..7e10a95 Binary files /dev/null and b/asset/menu/standing_single_arm_lateral_raises.jpg differ diff --git a/asset/menu/standing_triceps_extension.jpg b/asset/menu/standing_triceps_extension.jpg new file mode 100644 index 0000000..2214da6 Binary files /dev/null and b/asset/menu/standing_triceps_extension.jpg differ diff --git a/asset/menu/stiff_legged_deadlift.jpg b/asset/menu/stiff_legged_deadlift.jpg new file mode 100644 index 0000000..e765b0b Binary files /dev/null and b/asset/menu/stiff_legged_deadlift.jpg differ diff --git a/asset/menu/straight-arm_rope_pull-down.jpg b/asset/menu/straight-arm_rope_pull-down.jpg new file mode 100644 index 0000000..4622c8d Binary files /dev/null and b/asset/menu/straight-arm_rope_pull-down.jpg differ diff --git a/asset/menu/t_bar_rows.jpg b/asset/menu/t_bar_rows.jpg new file mode 100644 index 0000000..a8df430 Binary files /dev/null and b/asset/menu/t_bar_rows.jpg differ diff --git a/asset/menu/thigh_adductor.jpg b/asset/menu/thigh_adductor.jpg new file mode 100644 index 0000000..ef9aee7 Binary files /dev/null and b/asset/menu/thigh_adductor.jpg differ diff --git a/asset/menu/triceps_extension_on_cable_with_rope.jpg b/asset/menu/triceps_extension_on_cable_with_rope.jpg new file mode 100644 index 0000000..5866a0b Binary files /dev/null and b/asset/menu/triceps_extension_on_cable_with_rope.jpg differ diff --git a/asset/menu/triceps_kickback.jpg b/asset/menu/triceps_kickback.jpg new file mode 100644 index 0000000..b028e41 Binary files /dev/null and b/asset/menu/triceps_kickback.jpg differ diff --git a/asset/menu/triceps_pushdown.jpg b/asset/menu/triceps_pushdown.jpg new file mode 100644 index 0000000..80e56b5 Binary files /dev/null and b/asset/menu/triceps_pushdown.jpg differ diff --git a/asset/menu/twisted_crunches.jpg b/asset/menu/twisted_crunches.jpg new file mode 100644 index 0000000..8219fd4 Binary files /dev/null and b/asset/menu/twisted_crunches.jpg differ diff --git a/asset/menu/v_ups.jpg b/asset/menu/v_ups.jpg new file mode 100644 index 0000000..72c0391 Binary files /dev/null and b/asset/menu/v_ups.jpg differ diff --git a/asset/menu/wall_sit.jpg b/asset/menu/wall_sit.jpg new file mode 100644 index 0000000..7cbcdfb Binary files /dev/null and b/asset/menu/wall_sit.jpg differ diff --git a/asset/menu/weighted_bench_dip.jpg b/asset/menu/weighted_bench_dip.jpg new file mode 100644 index 0000000..f53d1d1 Binary files /dev/null and b/asset/menu/weighted_bench_dip.jpg differ diff --git a/asset/menu/wide_grip_behind_the_neck_pull_ups.jpg b/asset/menu/wide_grip_behind_the_neck_pull_ups.jpg new file mode 100644 index 0000000..38b501b Binary files /dev/null and b/asset/menu/wide_grip_behind_the_neck_pull_ups.jpg differ diff --git a/asset/menu/wide_grip_front_lat_pulldown.jpg b/asset/menu/wide_grip_front_lat_pulldown.jpg new file mode 100644 index 0000000..a6abff4 Binary files /dev/null and b/asset/menu/wide_grip_front_lat_pulldown.jpg differ diff --git a/i18n/en.json b/i18n/en.json index e4aba0a..107ddcc 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -28,6 +28,7 @@ "Selected Language": "Selected Language", "Please log in": "Please log in", + "Exception: Please log in": "Please log in", "Exception: Customer does not exist or the password is wrong": "The email does not exist or the password is wrong", "Exception: Facebook signup was not successful. Please try another method": "Facebook signup was not successful. Please try another method", "Exception: Customer exists": "The email address has been registered already", @@ -129,6 +130,9 @@ "Ectomorph": "Ectomorph", "Endomorph": "Endomorph", "Mesomorph": "Mesomorph", + "Ecto-Mesomorph": "Ecto-Mesomorph", + "Meso-Endomorph":"Meso-Endomorph", + "Ectomorph_desc": "Ectomorf", "Endomorph_desc":"Endomorf", @@ -338,6 +342,52 @@ "Or type the time manually:":"Or type the time manually", "sec":"sec", "min":"min", - "Please provide us some personal data":"Please provide us some personal data", - "To lift your experience using the app":"To lift your experience using the app" + "Edit Profile":"Edit Profile", + + + "Activity":"Activity", + "Body Type":"Body Type", + "Goal":"Goal", + "gain_muscle": "Gain Muscle", + "weight_loss":"Weight Loss", + "Set your goal":"Set your goal", + "Set your fitness level":"Set your fitness level", + "Set your body type":"Set your body type", + "These equipments and devices are available":"These equipments and devices are available", + + "Successful Registration":"Successful Registration", + "Now we would like to know you better to lift the experience of the app.":"Now we would like to know you better to lift the experience of the app.", + "Please go through the pages, it will take couple of minutes!":"Please go through the pages, it will take couple of minutes!", + + "Body Type Analyser":"Body Type Analyser", + "How likely is it true about you?":"How likely is it true about you?", + "Very unlikely":"Very unlikely", + "Maybe":"Maybe", + "Very likely":"Very likely", + "« Back":"« Back", + "1. Basicly I am skinny and bonny":"1. Basicly I am skinny and bonny", + "2. question":"2. question", + "3. question":"3. question", + "4. question":"4. question", + "5. question":"5. question", + "6. question":"6. question", + "7. question":"7. question", + "8. question":"8. question", + "9. question":"9. question", + "10. question":"10. question", + "11. question":"11. question", + "12. question":"12. question", + "13. question":"13. question", + "14. question":"14. question", + "15. question":"15. question", + "16. question":"16. question", + "17. question":"17. question", + "18. question":"18. question", + "19. question":"19. question", + "20. question":"20. question", + "21. question":"21. question", + "22. question":"22. question", + "Your Bodytype result":"Your Bodytype result", + "Change the weight to":"Change the weight to" + } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index 2931d04..149b0d2 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -28,6 +28,7 @@ "Selected Language": "Választott nyelv", "Please log in": "Kérlek jelentkezz be", + "Exception: Please log in": "Kérlek jelentkezz be", "Exception: Customer does not exist or the password is wrong": "A felhasználónév nem létezik vagy a jelszó rossz.", "Customer does not exist or the password is wrong": "A felhasználó nem létezik vagy a jelszó rossz.", "The email does not exist or the password is wrong": "A felhasználó nem létezik vagy a jelszó rossz.", @@ -83,7 +84,7 @@ "Endurance_desc":"

Erőállóképességi teszt lényege, ahogy az 1RM tesztnél is, hogy a Neked megfelelő SÚLY és ISMÉTLÉS számot tudjuk javasolni.

Nagyon fontos, hogy szabályosan és a kért ismétléssel dolgozz!

Ha a célod a hosszabb távú erő fenntartása, netán sportoló vagy, akkor feltétlen teszteld az erőállóképességi modulunkat is.


Miért az erőállóképesség?

Javítja az izmok oxigén és tápanyagellátottságát és ezáltal képes leszel egyre nagyobb súlyok egyre hosszabbtávon való megmozgatására. Például egyre több fekvőtámaszra és húzódzkodásra.

Kevésbé tömegnövelő hatású, ámbár atlétikus és nagyon erős testalkatot kölcsönöz, ha hosszútávon gyakorlod.

", "OneRepMax_desc":"

Az egy ismétléses maximum, vagy más néven 1RM ismerete számodra fontos lehet a Neked megfelelő SÚLY és ISMÉTLÉS kiszámításában.

Végezd el szabályosan(!) a tesztet, hogy a Neked legmegfelelőbb súlyokat és ismétléseket tudjuk javasolni a későbbiekben.

Ha a célod az izom, vagy az erőnövelés, akkor feltétlen csináld meg az 1RM teszteket!


Mi az 1RM?

Az a súly, amit egyetlen egyszer lennél képes szabályosan megmozgatni. Az egyszer szabályosan végrehajtott maximális súlyú gyakorlatból származtatjuk a céloknak megfelelő súly és ismétlésszámokat.

", - "Name": "Vezetkéknév", + "Name": "Vezetéknév", "Exercise": "Gyakorlat", "Quantity": "Mennyiség", "Unit": "Egység", @@ -132,9 +133,13 @@ "I am professional": "Professzionális sportoló vagyok", "Your Body Type": "Milyen a testtípusod?", "No item selected":"Nincs kiválasztott elem", - "Ectomorph": "Ectomorf", + "Ectomorph": "Ektomorf", "Endomorph":"Endomorf", "Mesomorph":"Mezomorf", + "Ecto-Mesomorph": "Ekto-Mesomorf", + "Meso-Endomorph":"Mezo-Endomorf", + + "Ectomorph_desc": "

A Te testtípusod, ha:

Természetesen, mint a többi testtípusnál itt sem beszélhetünk 100%-os egyezésről, de fontos a választás a személyre szabottság érdekében. Előfordul, hogy egy ectomorph zsírfelesleggel is rendelkezik. Ekkor az ízületek vékonysága és az izomzat viselkedése a döntő szempont.

", "Endomorph_desc":"

A te testtípusod, ha úgy érzed, hogy a testalkatod az ektomorf szöges ellentéte.

Itt sem beszélhetünk 100%-os egyezésről, de fontos a személyre szabottság miatt. Előfordul, hogy egy endomorf nehezen különböztethető meg a mezomorftól. Ekkor vedd figyelembe a bordakosár méretét és a derekat. Oldalról egy mezomorf laposabb mellkassal, hassal rendelkezhet az eredendően „erős” tömöttebb, netán elhízott megjelenés a döntő szempont. Minden alma és körte forma ide sorolható.

", @@ -330,10 +335,55 @@ "Suggestions based on your actual status":"Intelligens javaslatok az állapotod alapján", "Special customized training plans":"Speciális testreszabott edzéstervek", - "Step": "Lépés:", + "Step": "Lépés", "Or type the time manually:":"Vagy jelöld ki az időt kézzel", "sec":"mp", "min":"perc", - "Please provide us some personal data":"Kérlek adj meg néhány adatot,", - "To lift your experience using the app":"Hogy emelni tudjuk az app élményét" + "Edit Profile":"Profil szerkesztése", + + "Activity":"Fizikai állapot", + "Body Type":"Testtípus", + "Goal":"Cél", + "gain_muscle": "Izomépítés", + "weight_loss":"Fogyás", + "Set your goal":"Mi a célod?", + "Set your fitness level":"Milyen a fizikai állapotod?", + "Set your body type":"Milyen a testtípusod?", + "These equipments and devices are available":"Ezek az eszközök állnak a rendelkezésedre", + + "Successful Registration":"Sikeres regisztráció", + "Now we would like to know you better to lift the experience of the app.":"Most meg szeretnénk téged jobban ismerni, hogy az applikáció jobban illeszkedjen hozzád.", + "Please go through the pages, it will take couple of minutes!":"Kérlek menj át a következő oldalakon, néhány percet vesz csak igénybe!", + + "Body Type Analyser":"Testtípus analizátor", + "How likely is it true about you?":"Mennyire igaz rád az állítás?", + "Very unlikely":"Biztos nem", + "Maybe":"Talán", + "Very likely":"Biztosan", + "« Back":"« Vissza", + "1. Basicly I am skinny and bonny":"1. Alapvetően vékony csontos testalkat vagyok", + "2. question":"2. Hosszú végtagok, keskeny vállak jellemzőek rám", + "3. question":"3. Nehezen tudok izmot növelni", + "4. question":"4. Mellkasom, derekam közel egyforma szélességű", + "5. question":"5. Pálcika volt a becenevem az oviban", + "6. question":"6. Könnyen elveszítem a felszedett izmot", + "7. question":"7. Tudtommal alacsony a testzsírom", + "8. question":"8. Alapvetően sportos, atletikus testalkat vagyok", + "9. question":"9. Széles kulcscsontom és vállam van", + "10. question":"10. Keskeny a csípőm és sportos a derekam", + "11. question":"11. Gyorsan izmosodok", + "12. question":"12. Szélesebb a mellkasom a derekamnál", + "13. question":"13. Akár lehetnék én a Dávid szobor", + "14. question":"14. Erős vádli és alkar", + "15. question":"15. Széles bordakosaram van", + "16. question":"16. Vastag széles ízületeim vannak", + "17. question":"17. Erős a csontozatom", + "18. question":"18. Zsírosabb, de izmos vagyok", + "19. question":"19. Szélesebb a csípőm a mellkasomnál", + "20. question":"20. Hordó is lehetne a becenevem", + "21. question":"21. Nehezen fogyok, könnyebben hízok", + "22. question":"22. Erős vaskos testalkat vagyok", + "Your Bodytype result":"Testtípus eredményed", + "Change the weight to":"Súly változtatása" + } \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ad35364..1bc6c3d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -153,13 +153,15 @@ PODS: - nanopb/encode (= 1.30906.0) - nanopb/decode (1.30906.0) - nanopb/encode (1.30906.0) + - package_info (0.0.1): + - Flutter - path_provider (0.0.1): - Flutter - PromisesObjC (1.2.12) - Protobuf (3.14.0) - Purchases (3.9.2): - PurchasesCoreSwift (= 3.9.2) - - purchases_flutter (2.0.2): + - purchases_flutter (2.0.3): - Flutter - PurchasesHybridCommon (= 1.5.0) - PurchasesCoreSwift (3.9.2) @@ -190,6 +192,7 @@ DEPENDENCIES: - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - google_sign_in (from `.symlinks/plugins/google_sign_in/ios`) + - package_info (from `.symlinks/plugins/package_info/ios`) - path_provider (from `.symlinks/plugins/path_provider/ios`) - purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) @@ -251,6 +254,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_secure_storage/ios" google_sign_in: :path: ".symlinks/plugins/google_sign_in/ios" + package_info: + :path: ".symlinks/plugins/package_info/ios" path_provider: :path: ".symlinks/plugins/path_provider/ios" purchases_flutter: @@ -299,11 +304,12 @@ SPEC CHECKSUMS: GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9 GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52 nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc + package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97 Protobuf: 0cde852566359049847168e51bd1c690e0f70056 Purchases: d8a798c9c7552fe66b550bf314a143e94ffa70c8 - purchases_flutter: f97230b7edf32be4155b3dcce8e790a77df3fab1 + purchases_flutter: c1ef4056da1346795a708bdefce81e0a56e8134f PurchasesCoreSwift: ea4eabae180416e580ac60366f41aa1fefec0693 PurchasesHybridCommon: d9bfb34309db4c9ba82a6f7f3a6275c13befdca7 shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 417a41e..dbacf6c 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -388,7 +388,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -405,7 +405,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.5; + MARKETING_VERSION = 1.1.6; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -531,7 +531,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -548,7 +548,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.5; + MARKETING_VERSION = 1.1.6; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -566,7 +566,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -583,7 +583,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.5; + MARKETING_VERSION = 1.1.6; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/bloc/account/account_bloc.dart b/lib/bloc/account/account_bloc.dart index f44057e..78d126a 100644 --- a/lib/bloc/account/account_bloc.dart +++ b/lib/bloc/account/account_bloc.dart @@ -4,6 +4,7 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; +import 'package:aitrainer_app/util/enums.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:meta/meta.dart'; @@ -16,12 +17,47 @@ class AccountBloc extends Bloc { bool loggedIn = false; int traineeId = 0; AccountBloc({this.customerRepository}) : super(AccountInitial()) { - if ( Cache().userLoggedIn != null ) { + if (Cache().userLoggedIn != null) { customerRepository.customer = Cache().userLoggedIn; loggedIn = true; } } + String getAccurateBodyType() { + String bodyType = ("Set your body type"); + int _ecto = 0; + int _mezo = 0; + int _endo = 0; + _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt(); + _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt(); + _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt(); + if (_ecto == 0 && _mezo == 0 && _endo == 0) { + return bodyType; + } + int bodyTypeValue; + if (_ecto < 50) { + bodyTypeValue = (50 + ((50 / (_mezo + _endo)) * _endo)).toInt(); + } else if (_endo < 50) { + bodyTypeValue = (0 + ((50 / (_mezo + _ecto)) * _mezo)).toInt(); + } else { + // random answers probably + bodyTypeValue = (0 + ((100 / (_endo + _ecto))) * _endo).toInt(); + } + print("BodyType value " + bodyTypeValue.toString()); + if (bodyTypeValue < 20) { + bodyType = ("Ectomorph"); + } else if (bodyTypeValue >= 25 && bodyTypeValue < 40) { + bodyType = ("Ecto") + "-" + ("Mesomorph"); + } else if (bodyTypeValue >= 40 && bodyTypeValue < 60) { + bodyType = ("Mesomorph"); + } else if (bodyTypeValue >= 60 && bodyTypeValue < 80) { + bodyType = ("Meso") + "-" + ("Endomorph"); + } else { + bodyType = ("Endomorph"); + } + return bodyType; + } + @override Stream mapEventToState( AccountEvent event, @@ -42,11 +78,11 @@ class AccountBloc extends Bloc { customerRepository.emptyTrainees(); loggedIn = false; yield AccountLoggedOut(); - } else if ( event is AccountGetTrainees) { + } else if (event is AccountGetTrainees) { yield AccountLoading(); await customerRepository.getTrainees(); yield AccountReady(); - } else if ( event is AccountSelectTrainee ) { + } else if (event is AccountSelectTrainee) { yield AccountLoading(); customerRepository.setTrainee(event.traineeId); Cache().setTrainee(customerRepository.getTraineeById(event.traineeId)); @@ -55,7 +91,7 @@ class AccountBloc extends Bloc { this.traineeId = event.traineeId; yield AccountReady(); } - } on Exception catch(e) { + } on Exception catch (e) { yield AccountError(message: e.toString()); } } diff --git a/lib/bloc/body_type/bodytype_bloc.dart b/lib/bloc/body_type/bodytype_bloc.dart new file mode 100644 index 0000000..482f94a --- /dev/null +++ b/lib/bloc/body_type/bodytype_bloc.dart @@ -0,0 +1,239 @@ +import 'dart:async'; + +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/customer_property.dart'; +import 'package:aitrainer_app/model/property.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:aitrainer_app/service/customer_service.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'bodytype_event.dart'; +part 'bodytype_state.dart'; + +class BodytypeBloc extends Bloc { + static const int numberQuestions = 22; + final CustomerRepository repository; + final List questions = List(); + final List answers = List(); + final weights = List.generate(numberQuestions, (i) => List(3), growable: false); + + BodytypeBloc({this.repository}) : super(BodytypeInitial()) { + questions.add("1. Basicly I am skinny and bonny"); + questions.add("2. question"); + questions.add("3. question"); + questions.add("4. question"); + questions.add("5. question"); + questions.add("6. question"); + questions.add("7. question"); + questions.add("8. question"); + questions.add("9. question"); + questions.add("10. question"); + questions.add("11. question"); + questions.add("12. question"); + questions.add("13. question"); + questions.add("14. question"); + questions.add("15. question"); + questions.add("16. question"); + questions.add("17. question"); + questions.add("18. question"); + questions.add("19. question"); + questions.add("20. question"); + questions.add("21. question"); + questions.add("22. question"); + for (int i = 0; i < numberQuestions; i++) { + answers.add(0); + } + weights[0] = [0, 3, 7]; + weights[1] = [0, 3, 7]; + weights[2] = [0, 3, 7]; + weights[3] = [0, 3, 7]; + weights[4] = [0, 3, 7]; + weights[5] = [0, 3, 7]; + weights[6] = [0, 3, 7]; + + weights[7] = [3, 7, 0]; + weights[8] = [5, 7, 0]; + weights[9] = [0, 7, 3]; + weights[10] = [5, 5, 0]; + weights[11] = [7, 5, 0]; + weights[12] = [7, 5, 0]; + weights[13] = [5, 5, 0]; + + weights[14] = [7, 3, 0]; + weights[15] = [7, 3, 0]; + weights[16] = [7, 3, 0]; + weights[17] = [7, 3, 0]; + weights[18] = [7, 0, 0]; + weights[19] = [7, 0, 0]; + weights[20] = [7, 3, 0]; + weights[21] = [7, 3, 0]; + + final double value = repository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()); + if (value != null) { + _ecto = value.toInt(); + _mezo = repository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt(); + _endo = repository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt(); + print("** Init ecto: " + _ecto.toString() + " mezo: " + _mezo.toString() + " endo: " + _endo.toString()); + if (_ecto > 0 && _mezo > 0 && _endo > 0) { + calculateBodyType(init: true); + origBodyTypeValue = bodyTypeValue; + } + } + } + + int value = 0; + int step = 1; + int bodyTypeValue = 0; + int origBodyTypeValue = 0; + int _ecto = 0; + int _mezo = 0; + int _endo = 0; + + @override + Stream mapEventToState( + BodytypeEvent event, + ) async* { + try { + if (event is BodytypeClick) { + yield BodytypeLoading(); + this.value = event.value; + answers[step - 1] = value; + calculateBodyType(); + await saveToDB(); + if (step >= questions.length) { + yield BodytypeFinished(); + return; + } + step++; + yield BodytypeReady(); + } else if (event is BodytypeBack) { + yield BodytypeLoading(); + if (step == 1) { + yield BodytypeReady(); + return; + } + step--; + this.value = answers[step - 1]; + yield BodytypeReady(); + } + } on Exception catch (e) { + yield BodytypeError(error: e.toString()); + } + } + + bool showResults() { + return this.state == BodytypeFinished() || origBodyTypeValue > 0; + } + + Future saveToDB() async { + await savePropertyDB(PropertyEnum.Ectomorph.toStr(), _ecto.toDouble()); + await savePropertyDB(PropertyEnum.Mesomorph.toStr(), _mezo.toDouble()); + await savePropertyDB(PropertyEnum.Endomorph.toStr(), _endo.toDouble()); + } + + Future savePropertyDB(String name, double value) async { + final now = DateTime.now(); + Property property = repository.propertyRepository.getPropertyByName(name); + if (property != null) { + int propertyId = property.propertyId; + CustomerProperty customerProperty = repository.getCustomerProperty(name); + if (customerProperty == null || customerProperty.customerPropertyId == null) { + customerProperty = + CustomerProperty(customerId: Cache().userLoggedIn.customerId, propertyId: propertyId, propertyValue: value, dateAdd: now); + + CustomerProperty newProperty = await CustomerApi().addProperty(customerProperty); + repository.setCustomerProperty(name, value, id: newProperty.customerPropertyId); + } else { + customerProperty.propertyValue = value; + customerProperty.dateAdd = now; + await CustomerApi().updateProperty(customerProperty); + repository.setCustomerProperty(name, value); + } + } + } + + String getQuestion() { + return questions[step - 1]; + } + + int getValue() { + return answers[this.step - 1]; + } + + int getPrevValue() { + return step < 2 ? 0 : answers[this.step - 2]; + } + + int getBodyTypeValue() { + return bodyTypeValue; + } + + void calculateBodyType({bool init = false}) { + if (!init) { + _endo = 0; + _mezo = 0; + _ecto = 0; + for (int index = 0; index < step; index++) { + _endo += getValueByWeight(weights[index][0], answers[index]); + _mezo += getValueByWeight(weights[index][1], answers[index]); + _ecto += getValueByWeight(weights[index][2], answers[index]); + } + print("ecto: " + _ecto.toString() + " mezo: " + _mezo.toString() + " endo: " + _endo.toString()); + } + + if (_ecto < 50) { + bodyTypeValue = (50 + ((50 / (_mezo + _endo)) * _endo)).toInt(); + } else if (_endo < 50) { + bodyTypeValue = (0 + ((50 / (_mezo + _ecto)) * _mezo)).toInt(); + } else { + // random answers probably + bodyTypeValue = (0 + ((100 / (_endo + _ecto))) * _endo).toInt(); + } + origBodyTypeValue = 0; + print("bodyTypeValue: " + bodyTypeValue.toString()); + } + + int getValueByWeight(int weight, int answer) { + if (answer == 4) { + if (weight > 3 && weight < 7) { + return ((weight - (5 - answer) * 1.25)).round(); + } else if (weight >= 7) { + return ((weight - (5 - answer) * 2)).round(); + } else { + return (weight + (5 - answer) * 1.25).round(); + } + } else if (answer == 3) { + if (weight > 3 && weight < 7) { + return ((weight - (5 - answer))).round(); + } else if (weight >= 7) { + return ((weight - (5 - answer) * 2)).round(); + } else { + return ((weight + (5 - answer) * 1.5)).round(); + } + } else if (answer == 2) { + if (weight > 3 && weight < 7) { + return ((weight - (5 - answer))).round(); + } else if (weight >= 7) { + return ((weight - (5 - answer) * 2)).round(); + } else if (weight == 3) { + return ((weight + (5 - answer) * 0.25)).round(); + } else { + return ((weight + (5 - answer) * 1.75)).round(); + } + } else if (answer == 1) { + if (weight > 3 && weight < 7) { + return ((weight - (5 - answer))).round(); + } else if (weight >= 7) { + return ((weight - (5 - answer) * 1.85)).round(); + } else if (weight == 3) { + return weight; + } else { + return ((weight + (5 - answer) * 1.85)).round(); + } + } else { + return weight; + } + } +} diff --git a/lib/bloc/body_type/bodytype_event.dart b/lib/bloc/body_type/bodytype_event.dart new file mode 100644 index 0000000..ba94362 --- /dev/null +++ b/lib/bloc/body_type/bodytype_event.dart @@ -0,0 +1,28 @@ +part of 'bodytype_bloc.dart'; + +abstract class BodytypeEvent extends Equatable { + const BodytypeEvent(); + + @override + List get props => []; +} + +class BodytypeLoad extends BodytypeEvent { + const BodytypeLoad(); +} + +class BodytypeSave extends BodytypeEvent { + const BodytypeSave(); +} + +class BodytypeClick extends BodytypeEvent { + final int value; + const BodytypeClick({this.value}); + + @override + List get props => [value]; +} + +class BodytypeBack extends BodytypeEvent { + const BodytypeBack(); +} diff --git a/lib/bloc/body_type/bodytype_state.dart b/lib/bloc/body_type/bodytype_state.dart new file mode 100644 index 0000000..4bd18e9 --- /dev/null +++ b/lib/bloc/body_type/bodytype_state.dart @@ -0,0 +1,32 @@ +part of 'bodytype_bloc.dart'; + +abstract class BodytypeState extends Equatable { + const BodytypeState(); + + @override + List get props => []; +} + +class BodytypeInitial extends BodytypeState { + const BodytypeInitial(); +} + +class BodytypeLoading extends BodytypeState { + const BodytypeLoading(); +} + +class BodytypeReady extends BodytypeState { + const BodytypeReady(); +} + +class BodytypeFinished extends BodytypeState { + const BodytypeFinished(); +} + +class BodytypeError extends BodytypeState { + final String error; + const BodytypeError({this.error}); + + @override + List get props => [error]; +} diff --git a/lib/bloc/customer_change_form_bloc.dart b/lib/bloc/customer_change_form_bloc.dart deleted file mode 100644 index 2e99860..0000000 --- a/lib/bloc/customer_change_form_bloc.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:aitrainer_app/repository/customer_repository.dart'; -import 'package:flutter_form_bloc/flutter_form_bloc.dart'; - -class CustomerChangeFormBloc extends FormBloc { - final CustomerRepository customerRepository; - - int weight = 60; - int birthYear = 1990; - - final emailField = TextFieldBloc( - validators: [ - FieldBlocValidators.required, - ], - ); - - final firstNameField = TextFieldBloc( - validators: [ - FieldBlocValidators.required, - ], - ); - - final nameField = TextFieldBloc(); - final passwordField = TextFieldBloc( - validators: [ - //FieldBlocValidators.confirmPassword(passwordField), - ], - ); - final birthYearField = InputFieldBloc(initialValue: 1990); - final weightField = InputFieldBloc(initialValue: 60); - final genderField = InputFieldBloc(initialValue: 0); - - final goalField = TextFieldBloc(); - - CustomerChangeFormBloc({this.customerRepository}) { - addFieldBlocs(fieldBlocs: [ - emailField, - firstNameField, - nameField, - passwordField, - birthYearField, - weightField, - genderField, - goalField, - ]); - - emailField.updateInitialValue(customerRepository.customer.email); - firstNameField.updateInitialValue(customerRepository.customer.firstname); - nameField.updateInitialValue(customerRepository.customer.name); - birthYearField.updateInitialValue(customerRepository.customer.birthYear); - weightField.updateInitialValue(customerRepository.customer.getProperty("weight").toInt()); - - int initialGender = customerRepository.getGenderByDBValue(customerRepository.sex) == "m" ? 0 : 1; - genderField.updateInitialValue(initialGender); - - firstNameField.onValueChanges(onData: (previous, current) async* { - customerRepository.setFirstName(current.value); - }); - nameField.onValueChanges(onData: (previous, current) async* { - customerRepository.setName(current.value); - }); - /*birthYearField.onValueChanges(onData: (previous, current) async* { - customerRepository.setBirthYear(current.valueToInt); - }); - weightField.onValueChanges(onData: (previous, current) async* { - customerRepository.setWeight(current.valueToInt); - }); - - customerRepository.genders.forEach((element) { - genderField.addItem(element.name); - });*/ - - genderField.onValueChanges(onData: (previous, current) async* { - String dbValue = customerRepository.getGenderByName(current.value.toString()); - customerRepository.setSex(dbValue); - }); - } - - int getGender() { - return customerRepository.customer.sex == "M" ? 0 : 1; - } - - void switchGender(int index) { - String dbValue; - if (index == 0) { - dbValue = customerRepository.getGenderByName("Man"); - } else if (index == 1) { - dbValue = customerRepository.getGenderByName("Woman"); - } - customerRepository.setSex(dbValue); - genderField.add(UpdateFieldBlocValue(dbValue)); - } - - void changeWeight(int value) { - customerRepository.setWeight(value); - weight = value; - weightField.updateValue(value); - } - - changeBirthYear(int value) { - customerRepository.setBirthYear(value); - birthYear = value; - birthYearField.updateValue(value); - } - - @override - void onSubmitting() async { - try { - emitLoading(progress: 30); - // Emit either Loaded or Error - await customerRepository.saveCustomer(); - emitSuccess(canSubmitAgain: true); - } on Exception catch (ex) { - emitFailure(failureResponse: ex.toString()); - } - } - - @override - Future close() { - emailField.close(); - firstNameField.close(); - nameField.close(); - passwordField.close(); - birthYearField.close(); - weightField.close(); - genderField.close(); - goalField.close(); - return super.close(); - } -} diff --git a/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart b/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart index 151d245..0dfdfc4 100644 --- a/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart +++ b/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart @@ -3,6 +3,8 @@ import 'dart:async'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_device.dart'; import 'package:aitrainer_app/repository/customer_exercise_device_repository.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; @@ -17,6 +19,7 @@ class CustomerExerciseDeviceBloc extends Bloc "2"); await repository.addDevice(event.device); Cache().initBadges(); yield CustomerExerciseDeviceReady(); diff --git a/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart b/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart index 8d5e463..cf14bd7 100644 --- a/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart +++ b/lib/bloc/development_by_muscle/development_by_muscle_bloc.dart @@ -9,7 +9,9 @@ import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/calculate.dart'; import 'package:aitrainer_app/util/common.dart'; +import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/group_data.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; @@ -282,7 +284,9 @@ class DevelopmentByMuscleBloc extends Bloc getData() async { workoutTreeRepository.sortedTree = null; diff --git a/lib/bloc/exercise_control/exercise_control_bloc.dart b/lib/bloc/exercise_control/exercise_control_bloc.dart index ccb4350..55a6241 100644 --- a/lib/bloc/exercise_control/exercise_control_bloc.dart +++ b/lib/bloc/exercise_control/exercise_control_bloc.dart @@ -33,6 +33,7 @@ class ExerciseControlBloc extends Bloc { try { if (event is ExerciseLogLoad) { yield ExerciseLogLoading(); - Flurry.logEvent("exerciseLog"); + Track().track(TrackingEvent.exercise_log_open); yield ExerciseLogReady(); } else if (event is ExerciseLogDelete) { yield ExerciseLogLoading(); exerciseRepository.exerciseList.remove(event.exercise); await exerciseRepository.deleteExercise(event.exercise); - Flurry.logEvent("exerciseDelete"); + Track().track(TrackingEvent.exercise_log_delete); yield ExerciseLogReady(); } else if (event is ExerciseResult) { yield ExerciseLogLoading(); - Flurry.logEvent("exerciseResult"); + Track().track(TrackingEvent.exercise_log_result); yield ExerciseLogReady(); } } on Exception catch (e) { diff --git a/lib/bloc/exercise_new/exercise_new_bloc.dart b/lib/bloc/exercise_new/exercise_new_bloc.dart index 608a7b6..c3355a5 100644 --- a/lib/bloc/exercise_new/exercise_new_bloc.dart +++ b/lib/bloc/exercise_new/exercise_new_bloc.dart @@ -8,9 +8,10 @@ import 'package:aitrainer_app/model/fitness_state.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:flurry/flurry.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; @@ -352,7 +353,7 @@ class ExerciseNewBloc extends Bloc with Logg changedWeight = false; this.changedSizes = false; Cache().initBadges(); - Flurry.logEvent("Sizes"); + Track().track(TrackingEvent.sizes); yield ExerciseNewReady(); } else if (event is ExerciseNewSizeChange) { yield ExerciseNewLoading(); @@ -366,8 +367,7 @@ class ExerciseNewBloc extends Bloc with Logg await exerciseRepository.addExercise(); menuBloc.add(MenuTreeDown(parent: 0)); Cache().initBadges(); - Flurry.logEvent("newExercise"); - Flurry.logEvent("newExercise " + exerciseRepository.exerciseType.name); + Track().track(TrackingEvent.exercise_new, eventValue: exerciseRepository.exerciseType.name); yield ExerciseNewReady(); } else if (event is ExerciseNewBMIAnimate) { yield ExerciseNewLoading(); diff --git a/lib/bloc/exercise_plan/exercise_plan_bloc.dart b/lib/bloc/exercise_plan/exercise_plan_bloc.dart index 817b83b..01a6d49 100644 --- a/lib/bloc/exercise_plan/exercise_plan_bloc.dart +++ b/lib/bloc/exercise_plan/exercise_plan_bloc.dart @@ -4,9 +4,10 @@ import 'package:aitrainer_app/model/model_change.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:flurry/flurry.dart'; import 'package:meta/meta.dart'; part 'exercise_plan_event.dart'; @@ -48,7 +49,7 @@ class ExercisePlanBloc extends Bloc { try { if (event is ExercisePlanLoad) { yield ExercisePlanLoading(); - Flurry.logEvent("exercisePlan"); + Track().track(TrackingEvent.my_custom_exercise_plan); await this.getData(); yield ExercisePlanReady(); } @@ -98,7 +99,7 @@ class ExercisePlanBloc extends Bloc { if (exercisePlanRepository.getExercisePlanDetailSize() != 0) { exercisePlanRepository.saveExercisePlan(); - Flurry.logEvent("SaveExercisePlan"); + Track().track(TrackingEvent.my_custom_exercise_plan_save); } yield ExercisePlanReady(); diff --git a/lib/bloc/login/login_bloc.dart b/lib/bloc/login/login_bloc.dart index 7a09816..05e6c33 100644 --- a/lib/bloc/login/login_bloc.dart +++ b/lib/bloc/login/login_bloc.dart @@ -5,13 +5,13 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; import 'package:aitrainer_app/service/exercise_tree_service.dart'; -import 'package:aitrainer_app/service/exercisetype_service.dart'; +import 'package:aitrainer_app/service/exercise_type_service.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:flurry/flurry.dart'; import 'package:flutter/material.dart'; part 'login_event.dart'; @@ -51,7 +51,7 @@ class LoginBloc extends Bloc with Trans { yield LoginLoading(); await userRepository.getUser(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); - Flurry.logEvent("Login"); + Track().track(TrackingEvent.login, eventValue: "email"); Cache().setLoginType(LoginType.email); yield LoginSuccess(); } else if (event is LoginFB) { @@ -59,24 +59,21 @@ class LoginBloc extends Bloc with Trans { Cache().setLoginType(LoginType.fb); await userRepository.getUserByFB(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); - Flurry.logEvent("Login"); - Flurry.logEvent("LoginFB"); + Track().track(TrackingEvent.login, eventValue: "FB"); yield LoginSuccess(); } else if (event is LoginGoogle) { yield LoginLoading(); Cache().setLoginType(LoginType.google); await userRepository.getUserByGoogle(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); - Flurry.logEvent("Login"); - Flurry.logEvent("LoginGoogle"); + Track().track(TrackingEvent.login, eventValue: "Google"); yield LoginSuccess(); } else if (event is LoginApple) { yield LoginLoading(); Cache().setLoginType(LoginType.apple); await userRepository.getUserByApple(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); - Flurry.logEvent("Login"); - Flurry.logEvent("LoginApple"); + Track().track(TrackingEvent.login, eventValue: "Apple"); yield LoginSuccess(); } else if (event is RegistrationSubmit) { yield LoginLoading(); @@ -87,7 +84,7 @@ class LoginBloc extends Bloc with Trans { await userRepository.addUser(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); await saveCustomer(); - Flurry.logEvent("Registration"); + Track().track(TrackingEvent.registration, eventValue: "email"); Cache().setLoginType(LoginType.email); yield LoginSuccess(); } else if (event is RegistrationFB) { @@ -100,8 +97,7 @@ class LoginBloc extends Bloc with Trans { await userRepository.addUserFB(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); await saveCustomer(); - Flurry.logEvent("RegistrationFB"); - Flurry.logEvent("Registration"); + Track().track(TrackingEvent.registration, eventValue: "FB"); yield LoginSuccess(); } else if (event is RegistrationGoogle) { yield LoginLoading(); @@ -113,8 +109,7 @@ class LoginBloc extends Bloc with Trans { await userRepository.addUserGoogle(); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); await saveCustomer(); - Flurry.logEvent("RegistrationGoogle"); - Flurry.logEvent("Registration"); + Track().track(TrackingEvent.registration, eventValue: "Google"); yield LoginSuccess(); } else if (event is RegistrationApple) { yield LoginLoading(); @@ -124,10 +119,11 @@ class LoginBloc extends Bloc with Trans { } Cache().setLoginType(LoginType.apple); await userRepository.addUserApple(); - accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); await saveCustomer(); - Flurry.logEvent("RegistrationApple"); - Flurry.logEvent("Registration"); + Track().track(TrackingEvent.registration); + Track().track(TrackingEvent.registration, eventValue: "Apple"); + yield LoginSuccess(); } else if (event is DataProtectionClicked) { yield LoginLoading(); diff --git a/lib/bloc/sales/sales_bloc.dart b/lib/bloc/sales/sales_bloc.dart index 9de73e3..8d63f27 100644 --- a/lib/bloc/sales/sales_bloc.dart +++ b/lib/bloc/sales/sales_bloc.dart @@ -7,9 +7,11 @@ import 'package:aitrainer_app/model/product.dart'; import 'package:aitrainer_app/model/product_test.dart'; import 'package:aitrainer_app/model/purchase.dart'; import 'package:aitrainer_app/service/logging.dart'; -import 'package:aitrainer_app/service/purchase.dart'; +import 'package:aitrainer_app/service/purchase_service.dart'; import 'package:aitrainer_app/util/common.dart'; +import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/purchases.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flurry/flurry.dart'; @@ -32,8 +34,7 @@ class SalesBloc extends Bloc with Logging { if (event is SalesLoad) { yield SalesLoading(); log("Load Sales"); - Common.sendMessage("Salespage Load"); - Flurry.logEvent("SalesPageOpen"); + Track().track(TrackingEvent.sales_page); //await PlatformPurchaseApi().initPurchasePlatform(); await RevenueCatPurchases().getOfferings(); this.getProductSet(); @@ -45,7 +46,7 @@ class SalesBloc extends Bloc with Logging { yield SalesLoading(); final int productId = event.productId; log("Requesting purchase for: " + productId.toString()); - Flurry.logEvent("PurchaseRequest"); + Track().track(TrackingEvent.purchase_request); final Product selectedProduct = this.getSelectedProduct(productId); log("SelectedProduct for purchase " + selectedProduct.toString()); await RevenueCatPurchases().makePurchase(selectedProduct); @@ -55,7 +56,7 @@ class SalesBloc extends Bloc with Logging { purchase.purchaseSum = 0; purchase.currency = "EUR"; await PurchaseApi().savePurchase(purchase); - Flurry.logEvent("PurchaseSuccessful"); + Track().track(TrackingEvent.purchase_successful, eventValue: selectedProduct.localizedPrice.toString()); Common.sendMessage("Purchase: " + purchase.toJson().toString()); } yield SalesSuccessful(); diff --git a/lib/bloc/session/session_bloc.dart b/lib/bloc/session/session_bloc.dart index 23d2cb3..dee7093 100644 --- a/lib/bloc/session/session_bloc.dart +++ b/lib/bloc/session/session_bloc.dart @@ -2,13 +2,10 @@ import 'dart:async'; import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; import 'package:aitrainer_app/localization/app_language.dart'; -import 'package:aitrainer_app/service/exercise_tree_service.dart'; -import 'package:aitrainer_app/service/exercisetype_service.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/session.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; -import 'package:flurry/flurry.dart'; part 'session_event.dart'; part 'session_state.dart'; @@ -32,7 +29,6 @@ class SessionBloc extends Bloc with Logging { String lang = AppLanguage().appLocal.languageCode; log("Change lang to $lang"); settingsBloc.add(SettingsChangeLanguage(language: lang)); - Flurry.logEvent("Enter"); yield SessionReady(); } } on Exception catch (ex) { diff --git a/lib/bloc/settings/settings_bloc.dart b/lib/bloc/settings/settings_bloc.dart index 3215ff6..abc9aab 100644 --- a/lib/bloc/settings/settings_bloc.dart +++ b/lib/bloc/settings/settings_bloc.dart @@ -4,6 +4,8 @@ import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; @@ -35,6 +37,7 @@ class SettingsBloc extends Bloc with Logging { if (event is SettingsChangeLanguage) { yield SettingsLoading(); await _changeLang(event.language); + Track().track(TrackingEvent.settings_lang); yield SettingsReady(_locale); } else if (event is SettingsGetLanguage) { await AppLanguage().fetchLocale(); @@ -44,6 +47,7 @@ class SettingsBloc extends Bloc with Logging { yield SettingsLoading(); final bool live = event.live; Cache().setServer(live); + Track().track(TrackingEvent.settings_server); yield SettingsReady(_locale); } else if (event is SettingsSetHardware) { yield SettingsLoading(); diff --git a/lib/library/fade_in.dart b/lib/library/fade_in.dart new file mode 100644 index 0000000..42a0a4b --- /dev/null +++ b/lib/library/fade_in.dart @@ -0,0 +1,148 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +class FadeIn extends StatefulWidget { + /// Fade-in controller + final FadeInController controller; + + /// Child widget to fade-in + final Widget child; + + /// Duration of fade-in. Defaults to 250ms + final Duration duration; + + /// Fade-in curve. Defaults to [Curves.easeIn] + final Curve curve; + + const FadeIn({ + Key key, + this.controller, + this.child, + this.duration = const Duration(milliseconds: 250), + this.curve = Curves.easeIn, + }) : super(key: key); + + @override + _FadeInState createState() => _FadeInState(); +} + +enum FadeInAction { + fadeIn, + fadeOut, +} + +/// Fade-in controller which dispatches fade-in/fade-out actions +class FadeInController { + final _streamController = StreamController(); + + /// Automatically starts the initial fade-in. Defaults to true + final bool autoStart; + + FadeInController({this.autoStart = true}); + + void dispose() => _streamController.close(); + + /// Fades-in child + void fadeIn() => run(FadeInAction.fadeIn); + + /// Fades-out child + void fadeOut() => run(FadeInAction.fadeOut); + + /// Dispatches a [FadeInAction] + void run(FadeInAction action) => _streamController.add(action); + + /// Stream of [FadeInAction]s dispatched by this controller + Stream get stream => _streamController.stream; +} + +class _FadeInState extends State with TickerProviderStateMixin { + AnimationController _controller; + StreamSubscription _listener; + + @override + void initState() { + super.initState(); + + _controller = AnimationController( + vsync: this, + duration: widget.duration, + ); + + _setupCurve(); + + if (widget.controller?.autoStart != false) { + fadeIn(); + } + + _listen(); + } + + void _setupCurve() { + final curve = CurvedAnimation(parent: _controller, curve: widget.curve); + + Tween( + begin: 0.0, + end: 1.0, + ).animate(curve); + } + + void _listen() { + if (_listener != null) { + _listener.cancel(); + _listener = null; + } + + if (widget.controller != null) { + _listener = widget.controller.stream.listen(_onAction); + } + } + + void _onAction(FadeInAction action) { + switch (action) { + case FadeInAction.fadeIn: + fadeIn(); + break; + case FadeInAction.fadeOut: + fadeOut(); + break; + } + } + + @override + void didUpdateWidget(FadeIn oldWidget) { + if (oldWidget.controller != widget.controller) { + _listen(); + } + + if (oldWidget.duration != widget.duration) { + _controller.duration = widget.duration; + } + + if (oldWidget.curve != widget.curve) { + _setupCurve(); + } + + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return FadeTransition( + opacity: _controller, + child: widget.child, + ); + } + + /// Fades-in child + void fadeIn() => _controller.forward(); + + /// Fades-out child + void fadeOut() => _controller.reverse(); +} diff --git a/lib/library/numberpicker.dart b/lib/library/numberpicker.dart deleted file mode 100644 index 17575d0..0000000 --- a/lib/library/numberpicker.dart +++ /dev/null @@ -1,807 +0,0 @@ -import 'dart:math' as math; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; -import 'package:infinite_listview/infinite_listview.dart'; - -/// Created by Marcin Szałek - -///Define a text mapper to transform the text displayed by the picker -typedef String TextMapper(String numberText); - -///NumberPicker is a widget designed to pick a number between #minValue and #maxValue -class NumberPicker extends StatelessWidget { - ///height of every list element for normal number picker - ///width of every list element for horizontal number picker - static const double kDefaultItemExtent = 60.0; - - ///width of list view for normal number picker - ///height of list view for horizontal number picker - static const double kDefaultListViewCrossAxisSize = 120.0; - - ///constructor for horizontal number picker - NumberPicker.horizontal({ - Key key, - @required int initialValue, - @required this.minValue, - @required this.maxValue, - @required this.onChanged, - this.textMapper, - this.itemExtent = kDefaultItemExtent, - this.listViewHeight = kDefaultListViewCrossAxisSize, - this.step = 1, - this.zeroPad = false, - this.highlightSelectedValue = true, - this.decoration, - this.haptics = false, - this.textStyle, - this.textStyleHighlighted - }) : assert(initialValue != null), - assert(minValue != null), - assert(maxValue != null), - assert(maxValue > minValue), - assert(initialValue >= minValue && initialValue <= maxValue), - assert(step > 0), - selectedIntValue = initialValue, - selectedDecimalValue = -1, - decimalPlaces = 0, - intScrollController = ScrollController( - initialScrollOffset: (initialValue - minValue) ~/ step * itemExtent, - ), - scrollDirection = Axis.horizontal, - decimalScrollController = null, - listViewWidth = 3 * itemExtent, - infiniteLoop = false, - integerItemCount = (maxValue - minValue) ~/ step + 1, - super(key: key); - - ///constructor for integer number picker - NumberPicker.integer({ - Key key, - @required int initialValue, - @required this.minValue, - @required this.maxValue, - @required this.onChanged, - this.textMapper, - this.itemExtent = kDefaultItemExtent, - this.listViewWidth = kDefaultListViewCrossAxisSize, - this.step = 1, - this.scrollDirection = Axis.vertical, - this.infiniteLoop = false, - this.zeroPad = false, - this.highlightSelectedValue = true, - this.decoration, - this.haptics = false, - this.textStyle, - this.textStyleHighlighted - }) : assert(initialValue != null), - assert(minValue != null), - assert(maxValue != null), - assert(maxValue > minValue), - assert(initialValue >= minValue && initialValue <= maxValue), - assert(step > 0), - assert(scrollDirection != null), - selectedIntValue = initialValue, - selectedDecimalValue = -1, - decimalPlaces = 0, - intScrollController = infiniteLoop - ? InfiniteScrollController( - initialScrollOffset: - (initialValue - minValue) ~/ step * itemExtent, - ) - : ScrollController( - initialScrollOffset: - (initialValue - minValue) ~/ step * itemExtent, - ), - decimalScrollController = null, - listViewHeight = 3 * itemExtent, - integerItemCount = (maxValue - minValue) ~/ step + 1, - super(key: key); - - ///constructor for decimal number picker - NumberPicker.decimal({ - Key key, - @required double initialValue, - @required this.minValue, - @required this.maxValue, - @required this.onChanged, - this.textMapper, - this.decimalPlaces = 1, - this.itemExtent = kDefaultItemExtent, - this.listViewWidth = kDefaultListViewCrossAxisSize, - this.highlightSelectedValue = true, - this.decoration, - this.haptics = false, - this.textStyle, - this.textStyleHighlighted - }) : assert(initialValue != null), - assert(minValue != null), - assert(maxValue != null), - assert(decimalPlaces != null && decimalPlaces > 0), - assert(maxValue > minValue), - assert(initialValue >= minValue && initialValue <= maxValue), - selectedIntValue = initialValue.floor(), - selectedDecimalValue = ((initialValue - initialValue.floorToDouble()) * - math.pow(10, decimalPlaces)) - .round(), - intScrollController = ScrollController( - initialScrollOffset: (initialValue.floor() - minValue) * itemExtent, - ), - decimalScrollController = ScrollController( - initialScrollOffset: ((initialValue - initialValue.floorToDouble()) * - math.pow(10, decimalPlaces)) - .roundToDouble() * - itemExtent, - ), - listViewHeight = 3 * itemExtent, - step = 1, - scrollDirection = Axis.vertical, - integerItemCount = maxValue.floor() - minValue.floor() + 1, - infiniteLoop = false, - zeroPad = false, - super(key: key); - - ///called when selected value changes - final ValueChanged onChanged; - - ///min value user can pick - final int minValue; - - ///max value user can pick - final int maxValue; - - ///build the text of each item on the picker - final TextMapper textMapper; - - ///inidcates how many decimal places to show - /// e.g. 0=>[1,2,3...], 1=>[1.0, 1.1, 1.2...] 2=>[1.00, 1.01, 1.02...] - final int decimalPlaces; - - ///height of every list element in pixels - final double itemExtent; - - ///height of list view in pixels - final double listViewHeight; - - ///width of list view in pixels - final double listViewWidth; - - ///ScrollController used for integer list - final ScrollController intScrollController; - - ///ScrollController used for decimal list - final ScrollController decimalScrollController; - - ///Currently selected integer value - final int selectedIntValue; - - ///Currently selected decimal value - final int selectedDecimalValue; - - ///If currently selected value should be highlighted - final bool highlightSelectedValue; - - ///Decoration to apply to central box where the selected value is placed - final Decoration decoration; - - ///Step between elements. Only for integer datePicker - ///Examples: - /// if step is 100 the following elements may be 100, 200, 300... - /// if min=0, max=6, step=3, then items will be 0, 3 and 6 - /// if min=0, max=5, step=3, then items will be 0 and 3. - final int step; - - /// Direction of scrolling - final Axis scrollDirection; - - ///Repeat values infinitely - final bool infiniteLoop; - - ///Pads displayed integer values up to the length of maxValue - final bool zeroPad; - - ///Amount of items - final int integerItemCount; - - ///Whether to trigger haptic pulses or not - final bool haptics; - - ///TextStyle of the non-highlighted numbers - final TextStyle textStyle; - -///TextStyle of the highlighted numbers - final TextStyle textStyleHighlighted; - - // - //----------------------------- PUBLIC ------------------------------ - // - - /// Used to animate integer number picker to new selected value - void animateInt(int valueToSelect) { - int diff = valueToSelect - minValue; - int index = diff ~/ step; - animateIntToIndex(index); - } - - /// Used to animate integer number picker to new selected index - void animateIntToIndex(int index) { - _animate(intScrollController, index * itemExtent); - } - - /// Used to animate decimal part of double value to new selected value - void animateDecimal(int decimalValue) { - _animate(decimalScrollController, decimalValue * itemExtent); - } - - /// Used to animate decimal number picker to selected value - void animateDecimalAndInteger(double valueToSelect) { - animateInt(valueToSelect.floor()); - animateDecimal(((valueToSelect - valueToSelect.floorToDouble()) * - math.pow(10, decimalPlaces)) - .round()); - } - - // - //----------------------------- VIEWS ----------------------------- - // - - ///main widget - @override - Widget build(BuildContext context) { - final ThemeData themeData = Theme.of(context); - - if (infiniteLoop) { - return _integerInfiniteListView(themeData); - } - if (decimalPlaces == 0) { - return _integerListView(themeData); - } else { - return Row( - children: [ - _integerListView(themeData), - _decimalListView(themeData), - ], - mainAxisAlignment: MainAxisAlignment.center, - ); - } - } - - Widget _integerListView(ThemeData themeData) { - TextStyle defaultStyle = textStyle == null ? - themeData.textTheme.body1 : textStyle; - TextStyle selectedStyle = textStyleHighlighted == null ? - themeData.textTheme.headline.copyWith(color: themeData.accentColor) - : textStyleHighlighted; - - var listItemCount = integerItemCount + 2; - - return Listener( - onPointerUp: (ev) { - ///used to detect that user stopped scrolling - if (intScrollController.position.activity is HoldScrollActivity) { - animateInt(selectedIntValue); - } - }, - child: NotificationListener( - child: Container( - height: listViewHeight, - width: listViewWidth, - child: Stack( - children: [ - ListView.builder( - scrollDirection: scrollDirection, - controller: intScrollController, - itemExtent: itemExtent, - itemCount: listItemCount, - cacheExtent: _calculateCacheExtent(listItemCount), - itemBuilder: (BuildContext context, int index) { - final int value = _intValueFromIndex(index); - - //define special style for selected (middle) element - final TextStyle itemStyle = - value == selectedIntValue && highlightSelectedValue - ? selectedStyle - : defaultStyle; - - double top = defaultStyle != null && defaultStyle.fontSize != null - ? listViewHeight / 2 - defaultStyle.fontSize / 2 - 15 - : listViewHeight / 2 - 22; - double left = defaultStyle != null && defaultStyle.fontSize != null - ? listViewWidth / 6 - defaultStyle.fontSize / 2 - 10 - : listViewHeight / 2 - 27; - - bool isExtra = index == 0 || index == listItemCount - 1; - - return isExtra - ? Container() //empty first and last element - : Center( - child: value != selectedIntValue ? - Container( - padding: EdgeInsets.only(top: 15, left: 10, right: 5, bottom: 10), - child: Stack( - children: [ - Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: value < selectedIntValue ? Alignment.centerRight : Alignment.centerLeft, - end: value < selectedIntValue ? Alignment.centerLeft : Alignment.centerRight, - colors: [Colors.white12, Colors.black12]), - borderRadius: BorderRadius.circular(8.0), - ), - ), - Positioned( - top: top, - left: left, - child: - Text( - getDisplayedValue(value), - style: itemStyle, - ), - - ), - ], - ) - ) : - - Text( - getDisplayedValue(value), - style: itemStyle, - ), - ); - }, - ), - _NumberPickerSelectedItemDecoration( - axis: scrollDirection, - itemExtent: itemExtent, - decoration: decoration, - ), - ], - ), - ), - onNotification: _onIntegerNotification, - ), - ); - } - - Widget _decimalListView(ThemeData themeData) { - TextStyle defaultStyle = textStyle == null ? - themeData.textTheme.body1 : textStyle; - TextStyle selectedStyle = textStyleHighlighted == null ? - themeData.textTheme.headline.copyWith(color: themeData.accentColor) - : textStyleHighlighted; - - - int decimalItemCount = - selectedIntValue == maxValue ? 3 : math.pow(10, decimalPlaces) + 2; - - return Listener( - onPointerUp: (ev) { - ///used to detect that user stopped scrolling - if (decimalScrollController.position.activity is HoldScrollActivity) { - animateDecimal(selectedDecimalValue); - } - }, - child: NotificationListener( - child: Container( - height: listViewHeight, - width: listViewWidth, - child: Stack( - children: [ - ListView.builder( - controller: decimalScrollController, - itemExtent: itemExtent, - itemCount: decimalItemCount, - itemBuilder: (BuildContext context, int index) { - final int value = index - 1; - - //define special style for selected (middle) element - final TextStyle itemStyle = - value == selectedDecimalValue && highlightSelectedValue - ? selectedStyle - : defaultStyle; - - bool isExtra = index == 0 || index == decimalItemCount - 1; - - return isExtra - ? Container() //empty first and last element - : Center( - child: Text( - value.toString().padLeft(decimalPlaces, '0'), - style: itemStyle, - ), - ); - }, - ), - _NumberPickerSelectedItemDecoration( - axis: scrollDirection, - itemExtent: itemExtent, - decoration: decoration, - ), - ], - ), - ), - onNotification: _onDecimalNotification, - ), - ); - } - - Widget _integerInfiniteListView(ThemeData themeData) { - TextStyle defaultStyle = textStyle == null ? - themeData.textTheme.body1 : textStyle; - TextStyle selectedStyle = textStyleHighlighted == null ? - themeData.textTheme.headline.copyWith(color: themeData.accentColor) - : textStyleHighlighted; - - - return Listener( - onPointerUp: (ev) { - ///used to detect that user stopped scrolling - if (intScrollController.position.activity is HoldScrollActivity) { - _animateIntWhenUserStoppedScrolling(selectedIntValue); - } - }, - child: NotificationListener( - child: Container( - height: listViewHeight, - width: listViewWidth, - child: Stack( - children: [ - InfiniteListView.builder( - controller: intScrollController, - itemExtent: itemExtent, - itemBuilder: (BuildContext context, int index) { - final int value = _intValueFromIndex(index); - - //define special style for selected (middle) element - final TextStyle itemStyle = - value == selectedIntValue && highlightSelectedValue - ? selectedStyle - : defaultStyle; - - return Center( - child: Text( - getDisplayedValue(value), - style: itemStyle, - ), - ); - }, - ), - _NumberPickerSelectedItemDecoration( - axis: scrollDirection, - itemExtent: itemExtent, - decoration: decoration, - ), - ], - ), - ), - onNotification: _onIntegerNotification, - ), - ); - } - - String getDisplayedValue(int value) { - final text = zeroPad - ? value.toString().padLeft(maxValue.toString().length, '0') - : value.toString(); - return textMapper != null ? textMapper(text) : text; - } - - // - // ----------------------------- LOGIC ----------------------------- - // - - int _intValueFromIndex(int index) { - index--; - index %= integerItemCount; - return minValue + index * step; - } - - bool _onIntegerNotification(Notification notification) { - if (notification is ScrollNotification) { - //calculate - int intIndexOfMiddleElement = - (notification.metrics.pixels / itemExtent).round(); - if (!infiniteLoop) { - intIndexOfMiddleElement = - intIndexOfMiddleElement.clamp(0, integerItemCount - 1); - } - int intValueInTheMiddle = _intValueFromIndex(intIndexOfMiddleElement + 1); - intValueInTheMiddle = _normalizeIntegerMiddleValue(intValueInTheMiddle); - - if (_userStoppedScrolling(notification, intScrollController)) { - //center selected value - animateIntToIndex(intIndexOfMiddleElement); - } - - //update selection - if (intValueInTheMiddle != selectedIntValue) { - num newValue; - if (decimalPlaces == 0) { - //return integer value - newValue = (intValueInTheMiddle); - } else { - if (intValueInTheMiddle == maxValue) { - //if new value is maxValue, then return that value and ignore decimal - newValue = (intValueInTheMiddle.toDouble()); - animateDecimal(0); - } else { - //return integer+decimal - double decimalPart = _toDecimal(selectedDecimalValue); - newValue = ((intValueInTheMiddle + decimalPart).toDouble()); - } - } - if (haptics) { - HapticFeedback.selectionClick(); - } - onChanged(newValue); - } - } - return true; - } - - bool _onDecimalNotification(Notification notification) { - if (notification is ScrollNotification) { - //calculate middle value - int indexOfMiddleElement = - (notification.metrics.pixels + listViewHeight / 2) ~/ itemExtent; - int decimalValueInTheMiddle = indexOfMiddleElement - 1; - decimalValueInTheMiddle = - _normalizeDecimalMiddleValue(decimalValueInTheMiddle); - - if (_userStoppedScrolling(notification, decimalScrollController)) { - //center selected value - animateDecimal(decimalValueInTheMiddle); - } - - //update selection - if (selectedIntValue != maxValue && - decimalValueInTheMiddle != selectedDecimalValue) { - double decimalPart = _toDecimal(decimalValueInTheMiddle); - double newValue = ((selectedIntValue + decimalPart).toDouble()); - if (haptics) { - HapticFeedback.selectionClick(); - } - onChanged(newValue); - } - } - return true; - } - - ///There was a bug, when if there was small integer range, e.g. from 1 to 5, - ///When user scrolled to the top, whole listview got displayed. - ///To prevent this we are calculating cacheExtent by our own so it gets smaller if number of items is smaller - double _calculateCacheExtent(int itemCount) { - double cacheExtent = 250.0; //default cache extent - if ((itemCount - 2) * kDefaultItemExtent <= cacheExtent) { - cacheExtent = ((itemCount - 3) * kDefaultItemExtent); - } - return cacheExtent; - } - - ///When overscroll occurs on iOS, - ///we can end up with value not in the range between [minValue] and [maxValue] - ///To avoid going out of range, we change values out of range to border values. - int _normalizeMiddleValue(int valueInTheMiddle, int min, int max) { - return math.max(math.min(valueInTheMiddle, max), min); - } - - int _normalizeIntegerMiddleValue(int integerValueInTheMiddle) { - //make sure that max is a multiple of step - int max = (maxValue ~/ step) * step; - return _normalizeMiddleValue(integerValueInTheMiddle, minValue, max); - } - - int _normalizeDecimalMiddleValue(int decimalValueInTheMiddle) { - return _normalizeMiddleValue( - decimalValueInTheMiddle, 0, math.pow(10, decimalPlaces) - 1); - } - - ///indicates if user has stopped scrolling so we can center value in the middle - bool _userStoppedScrolling( - Notification notification, - ScrollController scrollController, - ) { - return notification is UserScrollNotification && - notification.direction == ScrollDirection.idle && - scrollController.position.activity is! HoldScrollActivity; - } - - /// Allows to find currently selected element index and animate this element - /// Use it only when user manually stops scrolling in infinite loop - void _animateIntWhenUserStoppedScrolling(int valueToSelect) { - // estimated index of currently selected element based on offset and item extent - int currentlySelectedElementIndex = - intScrollController.offset ~/ itemExtent; - - // when more(less) than half of the top(bottom) element is hidden - // then we should increment(decrement) index in case of positive(negative) offset - if (intScrollController.offset > 0 && - intScrollController.offset % itemExtent > itemExtent / 2) { - currentlySelectedElementIndex++; - } else if (intScrollController.offset < 0 && - intScrollController.offset % itemExtent < itemExtent / 2) { - currentlySelectedElementIndex--; - } - - animateIntToIndex(currentlySelectedElementIndex); - } - - ///converts integer indicator of decimal value to double - ///e.g. decimalPlaces = 1, value = 4 >>> result = 0.4 - /// decimalPlaces = 2, value = 12 >>> result = 0.12 - double _toDecimal(int decimalValueAsInteger) { - return double.parse((decimalValueAsInteger * math.pow(10, -decimalPlaces)) - .toStringAsFixed(decimalPlaces)); - } - - ///scroll to selected value - _animate(ScrollController scrollController, double value) { - scrollController.animateTo( - value, - duration: Duration(seconds: 1), - curve: ElasticOutCurve(), - ); - } -} - -class _NumberPickerSelectedItemDecoration extends StatelessWidget { - final Axis axis; - final double itemExtent; - final Decoration decoration; - - const _NumberPickerSelectedItemDecoration( - {Key key, - @required this.axis, - @required this.itemExtent, - @required this.decoration}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Center( - child: IgnorePointer( - child: Container( - width: isVertical ? double.infinity : itemExtent, - height: isVertical ? itemExtent : double.infinity, - decoration: decoration, - ), - ), - ); - } - - bool get isVertical => axis == Axis.vertical; -} - -///Returns AlertDialog as a Widget so it is designed to be used in showDialog method -class NumberPickerDialog extends StatefulWidget { - final int minValue; - final int maxValue; - final int initialIntegerValue; - final double initialDoubleValue; - final int decimalPlaces; - final Widget title; - final EdgeInsets titlePadding; - final Widget confirmWidget; - final Widget cancelWidget; - final int step; - final bool infiniteLoop; - final bool zeroPad; - final bool highlightSelectedValue; - final Decoration decoration; - final TextMapper textMapper; - final bool haptics; - - ///constructor for integer values - NumberPickerDialog.integer({ - @required this.minValue, - @required this.maxValue, - @required this.initialIntegerValue, - this.title, - this.titlePadding, - this.step = 1, - this.infiniteLoop = false, - this.zeroPad = false, - this.highlightSelectedValue = true, - this.decoration, - this.textMapper, - this.haptics = false, - Widget confirmWidget, - Widget cancelWidget, - }) : confirmWidget = confirmWidget ?? Text("OK"), - cancelWidget = cancelWidget ?? Text("CANCEL"), - decimalPlaces = 0, - initialDoubleValue = -1.0; - - ///constructor for decimal values - NumberPickerDialog.decimal({ - @required this.minValue, - @required this.maxValue, - @required this.initialDoubleValue, - this.decimalPlaces = 1, - this.title, - this.titlePadding, - this.highlightSelectedValue = true, - this.decoration, - this.textMapper, - this.haptics = false, - Widget confirmWidget, - Widget cancelWidget, - }) : confirmWidget = confirmWidget ?? Text("OK"), - cancelWidget = cancelWidget ?? Text("CANCEL"), - initialIntegerValue = -1, - step = 1, - infiniteLoop = false, - zeroPad = false; - - @override - State createState() => _NumberPickerDialogControllerState( - initialIntegerValue, initialDoubleValue); -} - -class _NumberPickerDialogControllerState extends State { - int selectedIntValue; - double selectedDoubleValue; - - _NumberPickerDialogControllerState( - this.selectedIntValue, this.selectedDoubleValue); - - void _handleValueChanged(num value) { - if (value is int) { - setState(() => selectedIntValue = value); - } else { - setState(() => selectedDoubleValue = value); - } - } - - NumberPicker _buildNumberPicker() { - if (widget.decimalPlaces > 0) { - return NumberPicker.decimal( - initialValue: selectedDoubleValue, - minValue: widget.minValue, - maxValue: widget.maxValue, - decimalPlaces: widget.decimalPlaces, - highlightSelectedValue: widget.highlightSelectedValue, - decoration: widget.decoration, - onChanged: _handleValueChanged, - textMapper: widget.textMapper, - haptics: widget.haptics, - ); - } else { - return NumberPicker.integer( - initialValue: selectedIntValue, - minValue: widget.minValue, - maxValue: widget.maxValue, - step: widget.step, - infiniteLoop: widget.infiniteLoop, - zeroPad: widget.zeroPad, - highlightSelectedValue: widget.highlightSelectedValue, - decoration: widget.decoration, - onChanged: _handleValueChanged, - textMapper: widget.textMapper, - haptics: widget.haptics, - ); - } - } - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: widget.title, - titlePadding: widget.titlePadding, - content: _buildNumberPicker(), - actions: [ - FlatButton( - onPressed: () => Navigator.of(context).pop(), - child: widget.cancelWidget, - ), - FlatButton( - onPressed: () => Navigator.of(context).pop(widget.decimalPlaces > 0 - ? selectedDoubleValue - : selectedIntValue), - child: widget.confirmWidget), - ], - ); - } -} diff --git a/lib/library/tree_view.dart b/lib/library/tree_view.dart index 2f63329..ecac80d 100644 --- a/lib/library/tree_view.dart +++ b/lib/library/tree_view.dart @@ -81,17 +81,17 @@ class __TreeViewDataState extends State<_TreeViewData> { subscription = stream.listen((value) { if (value) { final double positionY = TreeViewStream().positionY; - print("pos " + + /* print("pos " + positionY.toString() + " height: " + cHeight.toString() + " controller offset " + _controller.offset.toString() + " controller initial " + - _controller.initialScrollOffset.toString()); + _controller.initialScrollOffset.toString()); */ if (positionY > cHeight - 190) { final double offset = positionY + 40; - print("antimateTo " + offset.toString()); + //print("antimateTo " + offset.toString()); _controller.animateTo(offset, duration: Duration(milliseconds: 300), curve: Curves.easeIn); } } diff --git a/lib/main.dart b/lib/main.dart index 4c9ac16..1b22712 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,7 @@ import 'package:aitrainer_app/service/firebase_api.dart'; import 'package:aitrainer_app/util/session.dart'; import 'package:aitrainer_app/view/account.dart'; import 'package:aitrainer_app/view/custom_exercise_page.dart'; -import 'package:aitrainer_app/view/customer_bodytype_page.dart'; +import 'package:aitrainer_app/view/customer_bodytype_animation.dart'; import 'package:aitrainer_app/view/customer_exercise_device.dart'; import 'package:aitrainer_app/view/customer_fitness_page.dart'; import 'package:aitrainer_app/view/customer_goal_page.dart'; @@ -196,7 +196,7 @@ class WorkoutTestApp extends StatelessWidget { 'customerModifyPage': (context) => CustomerModifyPage(), 'customerGoalPage': (context) => CustomerGoalPage(), 'customerFitnessPage': (context) => CustomerFitnessPage(), - 'customerBodyTypePage': (context) => CustomerBodyTypePage(), + 'customerBodyTypePage': (context) => CustomerBodyTypeAnimationPage(), 'customerWelcomePage': (context) => CustomerWelcomePage(), 'customerExerciseDevicePage': (context) => CustomerExerciseDevicePage(), 'exerciseNewPage': (context) => ExerciseNewPage(), diff --git a/lib/model/cache.dart b/lib/model/cache.dart index e943f88..977896a 100644 --- a/lib/model/cache.dart +++ b/lib/model/cache.dart @@ -11,18 +11,15 @@ import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/purchase.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; -import 'package:aitrainer_app/repository/exercise_repository.dart'; -import 'package:aitrainer_app/service/customer_exercise_device_service.dart'; -import 'package:aitrainer_app/service/customer_service.dart'; -import 'package:aitrainer_app/service/exercise_device_service.dart'; -import 'package:aitrainer_app/service/exercise_tree_service.dart'; -import 'package:aitrainer_app/service/exercisetype_service.dart'; import 'package:aitrainer_app/service/firebase_api.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/service/package_service.dart'; import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/env.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:flurry/flurry.dart'; import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; +import 'package:package_info/package_info.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; @@ -76,6 +73,7 @@ class Cache with Logging { Customer userLoggedIn; String firebaseUid; LoginType loginType; + PackageInfo packageInfo; bool hasPurchased = false; @@ -201,7 +199,7 @@ class Cache with Logging { } else if (loginType == LoginType.email.toString()) { type = LoginType.email; } - print("LoginType: " + loginType == null ? "NULL" : loginType); + //print("LoginType: " + loginType == null ? "NULL" : loginType); Cache().setLoginType(type); } @@ -316,7 +314,7 @@ class Cache with Logging { List getExerciseTypes() => this._exerciseTypes; - ExerciseType getExercise(int exerciseTypeId) { + ExerciseType getExerciseTypeById(int exerciseTypeId) { ExerciseType exerciseType; this._exerciseTypes.forEach((element) { if (element.exerciseTypeId == exerciseTypeId) { @@ -420,6 +418,10 @@ class Cache with Logging { CustomerRepository customerRepository = CustomerRepository(); _badges = LinkedHashMap(); customerRepository.setCustomer(userLoggedIn); + int _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt(); + int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt(); + int _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt(); + print("endo " + _endo.toString() + " mezo " + _mezo.toString()); if (this.userLoggedIn != null) { if (this.userLoggedIn.birthYear == null || this.userLoggedIn.birthYear == 0) { setBadge("personalData", true); @@ -431,6 +433,7 @@ class Cache with Logging { } if (userLoggedIn.properties == null || userLoggedIn.properties.isEmpty) { setBadge("personalData", true); + setBadge("bodyType", true); setBadge("Sizes", true); setBadge("BMI", true); setBadge("BMR", true); @@ -442,12 +445,29 @@ class Cache with Logging { setBadge("My Body", true); setBadgeNr("home", 1); } + if (_ecto == 0 && _mezo == 0 && _endo == 0) { + setBadge("account", true); + setBadge("bodyType", true); + } + if (this._exercises == null || this._exercises.length == 0) { + setBadge("home", true); + setBadge("Strength", true); + setBadge("Cardio", true); + } if (customerRepository.getHeight() == 0) { setBadge("BMI", true); setBadge("BMR", true); setBadge("My Body", true); setBadgeNr("home", 1); } + if (userLoggedIn.goal == null) { + setBadge("Goal", true); + setBadge("account", true); + } + if (userLoggedIn.fitnessLevel == null) { + setBadge("FitnessLevel", true); + setBadge("account", true); + } } log("Badges: " + _badges.toString()); } @@ -463,31 +483,13 @@ class Cache with Logging { Future initCustomer(int customerId) async { log(" *** initCustomer"); - await CustomerApi().getCustomer(customerId); + await PackageApi().getCustomerPackage(customerId); Flurry.setUserId(customerId.toString()); - final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); - Cache().setCustomerDevices(customerDevices); - if (this._exerciseTree == null) { - await ExerciseTreeApi().getExerciseTree(); - } - if (this._exerciseTypes == null) { - await ExerciseTypeApi().getExerciseTypes(); - } - - await ExerciseDeviceApi().getDevices(); - - ExerciseRepository exerciseRepository = ExerciseRepository(); - await exerciseRepository.getExercisesByCustomer(customerId); - - CustomerRepository customerRepository = CustomerRepository(customer: this.userLoggedIn); - await customerRepository.getPurchase(); - await customerRepository.getProductTests(); - - //this.hasPurchased = this._purchases.isNotEmpty; await setLoginTypeFromPrefs(); Cache().startPage = "home"; + Track().track(TrackingEvent.enter); } AccessToken get getAccessTokenFacebook => accessTokenFacebook; diff --git a/lib/model/customer.dart b/lib/model/customer.dart index 8da85f3..29bb142 100644 --- a/lib/model/customer.dart +++ b/lib/model/customer.dart @@ -1,4 +1,6 @@ import 'dart:collection'; +import 'package:flutter_form_bloc/flutter_form_bloc.dart'; + import 'customer_property.dart'; class Customer { @@ -11,7 +13,6 @@ class Customer { int customerId; String password; int birthYear; - //int weight; String goal; String fitnessLevel; String bodyType; @@ -19,28 +20,30 @@ class Customer { int trainer; int dataPolicyAllowed; String firebaseUid; + DateTime dateAdd; + DateTime dateChange; LinkedHashMap properties = LinkedHashMap(); - Customer({ - this.customerId, - this.name, - this.firstname, - this.email, - this.sex, - this.age, - this.active, - this.password, - this.birthYear, - this.bodyType, - this.fitnessLevel, - this.goal, - //this.weight, - this.admin, - this.trainer, - this.dataPolicyAllowed, - this.firebaseUid, - }); + Customer( + {this.customerId, + this.name, + this.firstname, + this.email, + this.sex, + this.age, + this.active, + this.password, + this.birthYear, + this.bodyType, + this.fitnessLevel, + this.goal, + this.admin, + this.trainer, + this.dataPolicyAllowed, + this.firebaseUid, + this.dateAdd, + this.dateChange}); Customer.fromJson(Map json) { this.customerId = json['customerId']; @@ -54,10 +57,13 @@ class Customer { this.bodyType = json['bodyType']; this.fitnessLevel = json['fitnessLevel']; this.goal = json['goal']; - //this.weight = json['weight']; this.admin = json['admin']; + this.trainer = json['trainer']; this.firebaseUid = json['firebaseUid']; + + this.dateAdd = json['dateAdd'] == null ? DateTime.parse("0000-00-00") : DateTime.parse(json['dateAdd']); + this.dateChange = json['dateChange'] == null ? DateTime.parse("0000-00-00") : DateTime.parse(json['dateChange']); } Map toJson() => { @@ -72,10 +78,11 @@ class Customer { "bodyType": bodyType, "fitnessLevel": fitnessLevel, "goal": goal, - //"weight": weight, "admin": admin, "trainer": trainer, "dataPolicyAllowed": dataPolicyAllowed, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + "dateChange": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateChange), }; double getProperty(String propertyName) { diff --git a/lib/model/customer_property.dart b/lib/model/customer_property.dart index 7f7a61d..038b17b 100644 --- a/lib/model/customer_property.dart +++ b/lib/model/customer_property.dart @@ -1,6 +1,7 @@ import 'package:flutter_form_bloc/flutter_form_bloc.dart'; class CustomerProperty { + int customerPropertyId; int propertyId; int customerId; DateTime dateAdd; @@ -10,16 +11,29 @@ class CustomerProperty { CustomerProperty({this.propertyId, this.customerId, this.dateAdd, this.propertyValue}); CustomerProperty.fromJson(Map json) { + this.customerPropertyId = json['customerPropertyId']; this.propertyId = json['propertyId']; this.customerId = json['customerId']; this.dateAdd = json['propertyName']; this.propertyValue = json['propertyValue']; } - Map toJson() => { + Map toJson() { + if (customerPropertyId != null) { + return { + "customerPropertyId": this.customerPropertyId, "propertyId": this.propertyId, "customerId": this.customerId, "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), "propertyValue": this.propertyValue }; + } else { + return { + "propertyId": this.propertyId, + "customerId": this.customerId, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + "propertyValue": this.propertyValue + }; + } + } } diff --git a/lib/model/tracking.dart b/lib/model/tracking.dart new file mode 100644 index 0000000..d728574 --- /dev/null +++ b/lib/model/tracking.dart @@ -0,0 +1,24 @@ +import 'dart:io'; + +import 'package:aitrainer_app/model/cache.dart'; +import 'package:intl/intl.dart'; + +class Tracking { + int customerId; + DateTime dateAdd; + String event; + String eventValue; + String area; + String platform; + String version; + + Map toJson() => { + "customerId": customerId, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + "event": event, + "eventValue": eventValue, + "area": Platform.localeName, + "platform": Platform.isAndroid ? "Android" : "iOS", + "version": Cache().packageInfo.version + "+" + Cache().packageInfo.buildNumber + }; +} diff --git a/lib/repository/customer_repository.dart b/lib/repository/customer_repository.dart index 3df20b9..35745b3 100644 --- a/lib/repository/customer_repository.dart +++ b/lib/repository/customer_repository.dart @@ -4,12 +4,13 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; import 'package:aitrainer_app/model/customer_property.dart'; import 'package:aitrainer_app/model/product_test.dart'; +import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/purchase.dart'; import 'package:aitrainer_app/repository/property_repository.dart'; import 'package:aitrainer_app/service/customer_service.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/product_test_service.dart'; -import 'package:aitrainer_app/service/purchase.dart'; +import 'package:aitrainer_app/service/purchase_service.dart'; import 'package:aitrainer_app/util/not_found_exception.dart'; class GenderItem { @@ -115,7 +116,7 @@ class CustomerRepository with Logging { this.setCustomerProperty(propertyName, height.toDouble()); } - setCustomerProperty(String propertyName, double value) { + setCustomerProperty(String propertyName, double value, {id = 0}) { if (this.customer.properties[propertyName] == null) { this.customer.properties[propertyName] = CustomerProperty( propertyId: propertyRepository.getPropertyByName("Height").propertyId, @@ -126,6 +127,9 @@ class CustomerRepository with Logging { } this.customer.properties[propertyName].dateAdd = DateTime.now(); this.customer.properties[propertyName].newData = true; + if (id > 0) { + this.customer.properties[propertyName].customerPropertyId = id; + } } double getWeight() { @@ -137,7 +141,7 @@ class CustomerRepository with Logging { } double getCustomerPropertyValue(String propertyName) { - if (this.customer.properties[propertyName] == null) { + if (this.customer == null || this.customer.properties == null || this.customer.properties[propertyName] == null) { return 0.0; } else { return this.customer.properties[propertyName].propertyValue; @@ -196,6 +200,16 @@ class CustomerRepository with Logging { }); } + Future savePropertyByName(String name) async { + await Future.forEach(this._allProperties, (element) async { + final CustomerProperty customerProperty = element; + final Property property = propertyRepository.getPropertyByName(name); + if (property.propertyId == customerProperty.propertyId) { + await CustomerApi().updateProperty(customerProperty); + } + }); + } + Future getTraineeAsCustomer() async { this._trainee = await CustomerApi().getTrainee(Cache().userLoggedIn.customerId); return _trainee; diff --git a/lib/repository/exercise_repository.dart b/lib/repository/exercise_repository.dart index 38e2359..a7affed 100644 --- a/lib/repository/exercise_repository.dart +++ b/lib/repository/exercise_repository.dart @@ -290,7 +290,7 @@ class ExerciseRepository { String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd); //print(" -- $prevExerciseTypeId - $prevDate"); if (!(exerciseTypeId == prevExerciseTypeId && prevDate == exerciseDate)) { - ExerciseType exerciseType = Cache().getExercise(prevExercise.exerciseTypeId); + ExerciseType exerciseType = Cache().getExerciseTypeById(prevExercise.exerciseTypeId); String unit = exerciseType.unitQuantityUnit != null ? exerciseType.unitQuantityUnit : prevExercise.unit; prevExercise.summary = summary + " " + unit; exerciseLogList.add(prevExercise); @@ -302,7 +302,8 @@ class ExerciseRepository { if (prevCount > 0) delimiter = ", "; double quantity = exercise.quantity == null ? 0 : exercise.quantity; summary += delimiter + quantity.toStringAsFixed(0); - ExerciseType exerciseType = Cache().getExercise(exercise.exerciseTypeId); + ExerciseType exerciseType = Cache().getExerciseTypeById(exercise.exerciseTypeId); + //print("exerciseType " + (exerciseType == null ? "NULL" : exerciseType.name) + " ID " + exercise.exerciseTypeId.toString()); if (exerciseType.unitQuantity == "1") { summary += "x" + exercise.unitQuantity.toStringAsFixed(0); } diff --git a/lib/repository/workout_tree_repository.dart b/lib/repository/workout_tree_repository.dart index 0aac94b..22e9684 100644 --- a/lib/repository/workout_tree_repository.dart +++ b/lib/repository/workout_tree_repository.dart @@ -7,7 +7,7 @@ import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/exercise_tree_service.dart'; -import 'package:aitrainer_app/service/exercisetype_service.dart'; +import 'package:aitrainer_app/service/exercise_type_service.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:flutter/material.dart'; @@ -22,7 +22,7 @@ class Antagonist { static int backNr = 4; static String shoulder = "Shoulders"; static int shoulderNr = 5; - static String core = "Core"; + static String core = "Core & ABS"; static int coreNr = 6; static String thigh = "Thigh"; static int thighNr = 7; @@ -48,6 +48,7 @@ class WorkoutTreeRepository with Logging { }; Future createTree() async { + //if (Cache().getExerciseTree().length > 0 || Cache().getWorkoutMenuTree().length > 0) return; isEnglish = AppLanguage().appLocal == Locale('en'); log("** Start creating tree on lang: " + AppLanguage().appLocal.languageCode + diff --git a/lib/service/customer_service.dart b/lib/service/customer_service.dart index 81763e8..9bc13b4 100644 --- a/lib/service/customer_service.dart +++ b/lib/service/customer_service.dart @@ -21,6 +21,7 @@ class CustomerApi with Logging { } Future saveCustomer(Customer customer) async { + customer.dateChange = DateTime.now(); String body = JsonEncoder().convert(customer.toJson()); log(" ===== saving customer id: " + customer.customerId.toString() + ":" + body); await _client.post("customers/" + customer.customerId.toString(), body); @@ -32,6 +33,8 @@ class CustomerApi with Logging { } Future addCustomer(Customer customer) async { + customer.dateAdd = DateTime.now(); + customer.dateChange = DateTime.now(); String body = JsonEncoder().convert(customer.toJson()); log(" ===== add new customer: " + body); await _client.post("customers", body); @@ -84,7 +87,7 @@ class CustomerApi with Logging { Cache().userLoggedIn = customer; final List properties = await this.getActualProperties(customer.customerId); if (properties != null) { - this._initProperties(properties); + this.initProperties(properties); } } on FormatException { throw new Exception(responseBody); @@ -103,7 +106,7 @@ class CustomerApi with Logging { //log(" ---- Props: " + properties.toJson().toString()); //await Cache().initCustomer(customerId); if (properties != null) { - this._initProperties(properties); + this.initProperties(properties); } } on Exception catch (exception) { log("Exception: " + exception.toString()); @@ -113,7 +116,7 @@ class CustomerApi with Logging { } } - void _initProperties(List customerProperties) { + void initProperties(final List customerProperties) { List properties = Cache().getProperties(); Customer customer = Cache().userLoggedIn; customer.properties = LinkedHashMap(); @@ -190,22 +193,53 @@ class CustomerApi with Logging { return properties; } - Future addProperty(CustomerProperty property) async { + Future addProperty(CustomerProperty property) async { String body = JsonEncoder().convert(property.toJson()); log(" ===== add new customer property: " + body); - final String responseBody = await _client.post("customer_property", body); + CustomerProperty customerProperty; + String responseBody; try { + responseBody = await _client.post("customer_property", body); + log(" responseBody: " + responseBody); int status = jsonDecode(responseBody)['status']; if (status != null) { throw new Exception(jsonDecode(responseBody)['error']); } else { - CustomerProperty customerProperty = CustomerProperty.fromJson(jsonDecode(responseBody)); + customerProperty = CustomerProperty.fromJson(jsonDecode(responseBody)); if (customerProperty == null) { throw new Exception("Property Insert was not successful"); } } } on FormatException { throw new Exception(responseBody); + } on Exception catch (e) { + throw new Exception(e); } + return customerProperty; + } + + Future updateProperty(CustomerProperty property) async { + String body = JsonEncoder().convert(property.toJson()); + CustomerProperty customerProperty; + log(" ===== update customer property: " + body); + String responseBody; + try { + responseBody = await _client.post("customer_property/update/" + property.customerPropertyId.toString(), body); + log(" responseBody: " + responseBody); + int status = jsonDecode(responseBody)['status']; + if (status != null) { + throw new Exception(jsonDecode(responseBody)['error']); + } else { + customerProperty = CustomerProperty.fromJson(jsonDecode(responseBody)); + if (customerProperty == null) { + throw new Exception("Property Update was not successful"); + } + } + } on FormatException { + throw new Exception(responseBody); + } on Exception catch (e) { + throw new Exception(e); + } + return customerProperty; } } diff --git a/lib/service/exercise_service.dart b/lib/service/exercise_service.dart index 02ec870..2a50c6b 100644 --- a/lib/service/exercise_service.dart +++ b/lib/service/exercise_service.dart @@ -6,14 +6,6 @@ import 'package:aitrainer_app/service/logging.dart'; class ExerciseApi with Logging { final APIClient _client = new APIClient(); - Future> getExerciseTypes(String param) async { - final body = await _client.get("exercises", param); - final Iterable json = jsonDecode(body); - final List exerciseTypes = json.map((exerciseType) => Exercise.fromJson(exerciseType)).toList(); - - return exerciseTypes; - } - Future saveExercise(Exercise exercise) async { String body = JsonEncoder().convert(exercise.toJson()); log(" ===== saving exercise id: " + exercise.exerciseId.toString() + ":" + body); diff --git a/lib/service/exercise_tree_service.dart b/lib/service/exercise_tree_service.dart index cab67e2..734dfd4 100644 --- a/lib/service/exercise_tree_service.dart +++ b/lib/service/exercise_tree_service.dart @@ -20,7 +20,7 @@ class ExerciseTreeApi with Logging { if (exerciseTree != null) { await Future.forEach(exerciseTree, (element) async { //exerciseTree.forEach((element) async { - element.imageUrl = await _buildImage(element.imageUrl, element.treeId); + element.imageUrl = await buildImage(element.imageUrl, element.treeId); }); log("ExerciseTree downloaded"); Cache().setExerciseTree(exerciseTree); @@ -29,7 +29,7 @@ class ExerciseTreeApi with Logging { return exerciseTree; } - Future _buildImage(String imageUrl, int treeId) async { + Future buildImage(String imageUrl, int treeId) async { String assetImage = 'asset/menu/' + imageUrl.substring(7); return await rootBundle.load(assetImage).then((value) { return assetImage; @@ -41,7 +41,7 @@ class ExerciseTreeApi with Logging { } Future> getExerciseTreeParents(List exerciseTree) async { - List copyList = this._copyList(exerciseTree); + List copyList = this.copyList(exerciseTree); final String body = await _client.get("exercise_tree_parents", ""); Iterable json = jsonDecode(body); @@ -71,7 +71,7 @@ class ExerciseTreeApi with Logging { return exerciseTree; } - List _copyList(List tree) { + List copyList(List tree) { final List copyList = List(); tree.forEach((element) { final ExerciseTree copy = element.copy(-1); diff --git a/lib/service/exercisetype_service.dart b/lib/service/exercise_type_service.dart similarity index 56% rename from lib/service/exercisetype_service.dart rename to lib/service/exercise_type_service.dart index 99aa308..7bac308 100644 --- a/lib/service/exercisetype_service.dart +++ b/lib/service/exercise_type_service.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:aitrainer_app/library/image_cache.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/service/api.dart'; @@ -14,9 +13,8 @@ class ExerciseTypeApi with Logging { final Iterable json = jsonDecode(body); final List exerciseTypes = json.map((exerciseType) => ExerciseType.fromJson(exerciseType)).toList(); if (exerciseTypes != null) { - exerciseTypes.forEach((element) async { - element.imageUrl = await _buildImage(element.imageUrl, element.exerciseTypeId); - //ImageCache().downloadAndSaveImage(element.exerciseTypeId, element.imageUrl); + await Future.forEach(exerciseTypes, (element) async { + element.imageUrl = await buildImage(element.imageUrl, element.exerciseTypeId); }); log("ExerciseTypes downloaded"); Cache().setExerciseTypes(exerciseTypes); @@ -25,7 +23,7 @@ class ExerciseTypeApi with Logging { return exerciseTypes; } - Future _buildImage(String imageUrl, int exerciseTypeId) async { + Future buildImage(String imageUrl, int exerciseTypeId) async { if (imageUrl.length > 8) { String assetImage = 'asset/menu/' + imageUrl.substring(7); return rootBundle.load(assetImage).then((value) { @@ -39,16 +37,4 @@ class ExerciseTypeApi with Logging { return imageUrl; } } - - Future saveExerciseType(ExerciseType exerciseType) async { - String body = JsonEncoder().convert(exerciseType.toJson()); - log(" ===== saving exerciseType id: " + exerciseType.exerciseTypeId.toString() + ":" + body); - await _client.post("exercise_type/" + exerciseType.exerciseTypeId.toString(), body); - } - - Future addExerciseType(ExerciseType exerciseType) async { - String body = JsonEncoder().convert(exerciseType.toJson()); - log(" ===== add new exerciseType: " + body); - await _client.post("exercise_type", body); - } } diff --git a/lib/service/package_service.dart b/lib/service/package_service.dart new file mode 100644 index 0000000..44282c0 --- /dev/null +++ b/lib/service/package_service.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/customer.dart'; +import 'package:aitrainer_app/model/customer_exercise_device.dart'; +import 'package:aitrainer_app/model/customer_property.dart'; +import 'package:aitrainer_app/model/exercise.dart'; +import 'package:aitrainer_app/model/exercise_device.dart'; +import 'package:aitrainer_app/model/exercise_result.dart'; +import 'package:aitrainer_app/model/exercise_tree.dart'; +import 'package:aitrainer_app/model/exercise_tree_parents.dart'; +import 'package:aitrainer_app/model/exercise_type.dart'; +import 'package:aitrainer_app/model/product.dart'; +import 'package:aitrainer_app/model/product_test.dart'; +import 'package:aitrainer_app/model/property.dart'; +import 'package:aitrainer_app/model/purchase.dart'; +import 'package:aitrainer_app/service/api.dart'; +import 'package:aitrainer_app/service/exercise_type_service.dart'; +import 'package:aitrainer_app/util/not_found_exception.dart'; + +import 'customer_service.dart'; +import 'exercise_tree_service.dart'; + +class PackageApi { + final APIClient _client = new APIClient(); + + Future getPackage() async { + List exerciseTree; + List exerciseTreeParents; + final body = await _client.get("app_package/", ""); + + final List models = body.split("|||"); + await Future.forEach(models, (element) async { + final List headRecord = element.split("***"); + final Iterable json = jsonDecode(headRecord[1]); + if (headRecord[0] == "ExerciseDevice") { + final List devices = json.map((device) => ExerciseDevice.fromJson(device)).toList(); + Cache().setDevices(devices); + } else if (headRecord[0] == "Product") { + final List products = json.map((product) => Product.fromJson(product)).toList(); + Cache().setProducts(products); + } else if (headRecord[0] == "Property") { + final List properties = json.map((property) => Property.fromJson(property)).toList(); + Cache().setProperties(properties); + } else if (headRecord[0] == "ExerciseTree") { + exerciseTree = json.map((exerciseTree) => ExerciseTree.fromJson(exerciseTree)).toList(); + } else if (headRecord[0] == "ExerciseType") { + final List exerciseTypes = json.map((exerciseType) => ExerciseType.fromJson(exerciseType)).toList(); + if (exerciseTypes != null) { + await Future.forEach(exerciseTypes, (element) async { + element.imageUrl = await ExerciseTypeApi().buildImage(element.imageUrl, element.exerciseTypeId); + }); + Cache().setExerciseTypes(exerciseTypes); + } + } else if (headRecord[0] == "ExerciseAbility") { + } else if (headRecord[0] == "ExerciseTreeParents") { + exerciseTreeParents = json.map((exerciseTreeParent) => ExerciseTreeParents.fromJson(exerciseTreeParent)).toList(); + } + }); + + exerciseTree = this.getExerciseTreeParents(exerciseTree, exerciseTreeParents); + if (exerciseTree != null) { + await Future.forEach(exerciseTree, (element) async { + element.imageUrl = await ExerciseTreeApi().buildImage(element.imageUrl, element.treeId); + }); + Cache().setExerciseTree(exerciseTree); + } + + return; + } + + List getExerciseTreeParents(final List exerciseTree, final List exerciseTreeParents) { + List copyList = ExerciseTreeApi().copyList(exerciseTree); + + int treeIndex = 0; + copyList.forEach((element) async { + int index = 0; + exerciseTreeParents.forEach((parent) { + if (parent.exerciseTreeChildId == element.treeId) { + if (index > 0) { + ExerciseTree newElement = element.copy(parent.exerciseTreeParentId); + exerciseTree.add(newElement); + } else { + element.parentId = parent.exerciseTreeParentId; + exerciseTree[treeIndex].parentId = parent.exerciseTreeParentId; + } + index++; + } + }); + + treeIndex++; + }); + + return exerciseTree; + } + + Future getCustomerPackage(int customerId) async { + try { + final body = await _client.get("app_customer_package/" + customerId.toString(), ""); + + final List models = body.split("|||"); + await Future.forEach(models, (element) async { + final List headRecord = element.split("***"); + //print("Class " + headRecord[0]); + if (headRecord[0] == "Customer") { + Customer customer = Customer.fromJson(jsonDecode(headRecord[1])); + Cache().userLoggedIn = customer; + } else if (headRecord[0] == "CustomerExerciseDevice") { + final Iterable json = jsonDecode(headRecord[1]); + final List devices = json.map((device) => CustomerExerciseDevice.fromJson(device)).toList(); + Cache().setCustomerDevices(devices); + // ToDo + } else if (headRecord[0] == "Exercises") { + final Iterable json = jsonDecode(headRecord[1]); + final List exercises = json.map((exerciseType) => Exercise.fromJson(exerciseType)).toList(); + Cache().setExercises(exercises); + } else if (headRecord[0] == "ProductTest") { + final Iterable json = jsonDecode(headRecord[1]); + final List productTests = json.map((productTest) => ProductTest.fromJson(productTest)).toList(); + Cache().productTests = productTests; + } else if (headRecord[0] == "Purchase") { + final Iterable json = jsonDecode(headRecord[1]); + final List purchases = json.map((purchase) => Purchase.fromJson(purchase)).toList(); + Cache().setPurchases(purchases); + } else if (headRecord[0] == "CustomerProperty") { + final Iterable json = jsonDecode(headRecord[1]); + final List customerProperties = json.map((property) => CustomerProperty.fromJson(property)).toList(); + CustomerApi().initProperties(customerProperties); + } else if (headRecord[0] == "ExerciseResult") { + final Iterable json = jsonDecode(headRecord[1]); + final List exerciseResults = json.map((exerciseResult) { + ExerciseResult item = ExerciseResult.fromJson(exerciseResult); + return item; + }).toList(); + // ToDo + } + }); + } on NotFoundException catch (_) { + throw Exception("Please log in"); + } + } +} diff --git a/lib/service/purchase.dart b/lib/service/purchase_service.dart similarity index 100% rename from lib/service/purchase.dart rename to lib/service/purchase_service.dart diff --git a/lib/service/tracking_service.dart b/lib/service/tracking_service.dart new file mode 100644 index 0000000..76dab05 --- /dev/null +++ b/lib/service/tracking_service.dart @@ -0,0 +1,14 @@ +import 'package:aitrainer_app/model/tracking.dart'; +import 'package:aitrainer_app/service/logging.dart'; +import 'dart:convert'; +import 'api.dart'; + +class TrackingApi with Logging { + final APIClient _client = new APIClient(); + + Future saveTracking(Tracking tracking) async { + String body = JsonEncoder().convert(tracking.toJson()); + log(" ===== saving tracking:" + body); + await _client.post("tracking/", body); + } +} diff --git a/lib/util/enums.dart b/lib/util/enums.dart index 35f9fe8..779ac2b 100644 --- a/lib/util/enums.dart +++ b/lib/util/enums.dart @@ -4,3 +4,61 @@ extension LoginTypeExt on LoginType { bool equalsTo(LoginType type) => this.toString() == type.toString(); bool equalsStringTo(String type) => this.toString() == type; } + +enum TrackingEvent { + enter, + login, + logout, + registration, + home, + sizes, + sizes_save, + my_development, + my_exerciseplan, + account, + settings, + sales_page, + purchase_request, + purchase_successful, + exercise_new, + result, + exercise_log, + exercise_log_open, + exercise_log_delete, + exercise_log_result, + my_body_development, + my_muscle_development, + my_size_development, + my_custom_exercise_plan, + my_custom_exercise_plan_save, + my_exercise_plan_execute_open, + my_exercise_plan_execute_save, + my_special_plan, + my_suggested_plan, + prediction, + + exercise_device, + customer_change, + settings_lang, + settings_server +} + +T enumFromString(Iterable values, String value) { + return values.firstWhere((type) => type.toString().split(".").last == value, orElse: () => null); +} + +extension TrackingEventExt on TrackingEvent { + String enumToString() => this.toString().split(".").last; + + bool equalsTo(TrackingEvent event) => this.toString() == event.toString(); + bool equalsStringTo(String event) => this.toString() == event; +} + +enum PropertyEnum { Ectomorph, Mesomorph, Endomorph } + +extension PropertyExt on PropertyEnum { + String toStr() => this.toString().split(".").last; + + bool equalsTo(PropertyEnum event) => this.toString() == event.toString(); + bool equalsStringTo(String event) => this.toString() == event; +} diff --git a/lib/util/purchases.dart b/lib/util/purchases.dart index c17b8fd..458bdc6 100644 --- a/lib/util/purchases.dart +++ b/lib/util/purchases.dart @@ -26,6 +26,7 @@ class RevenueCatPurchases with Logging { await Purchases.setup("yLxGFWaeRtThLImqznvBnUEKjgArSsZE", appUserId: Cache().userLoggedIn.customerId.toString()); appUserId = await Purchases.appUserID; log("AppUserId: " + appUserId); + await Purchases.setAllowSharingStoreAccount(true); await this.restore(); } } diff --git a/lib/util/session.dart b/lib/util/session.dart index 663e5cf..6f8cb87 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -2,13 +2,17 @@ import 'dart:io'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/main.dart'; import 'package:aitrainer_app/service/api.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/service/package_service.dart'; import 'package:aitrainer_app/service/product_service.dart'; import 'package:aitrainer_app/service/property_service.dart'; import 'package:aitrainer_app/util/purchases.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/services.dart'; +import 'package:package_info/package_info.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:aitrainer_app/model/cache.dart'; @@ -21,6 +25,7 @@ class Session with Logging { log(" -- Session: await prefs.."); _sharedPreferences = await _prefs; print("Platform: " + Platform.localeName); + Cache().packageInfo = await PackageInfo.fromPlatform(); if (Cache().firstLoad) { log(" -- Session: fetch locale.."); await AppLanguage().getLocale(_sharedPreferences); @@ -30,10 +35,6 @@ class Session with Logging { Cache().getHardware(_sharedPreferences); await _fetchToken(_sharedPreferences); await RevenueCatPurchases().initPlatform(); - //initDeviceLocale(); - - // Create the initialization Future outside of `build`: - } } @@ -70,8 +71,8 @@ class Session with Logging { prefs.setString(Cache.authTokenKey, responseJson['token']); Cache().authToken = responseJson['token']; Cache().firebaseUid = prefs.get(Cache.firebaseUidKey); - await PropertyApi().getProperties(); - await ProductApi().getProducts(); + await PackageApi().getPackage(); + if (prefs.get(Cache.customerIdKey) == null) { log("************** Registration"); // registration diff --git a/lib/util/track.dart b/lib/util/track.dart new file mode 100644 index 0000000..f39e09e --- /dev/null +++ b/lib/util/track.dart @@ -0,0 +1,31 @@ +import 'package:aitrainer_app/main.dart'; +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/service/tracking_service.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:flurry/flurry.dart'; +import 'package:aitrainer_app/model/tracking.dart' as model; + +class Track with Logging { + static final Track _singleton = Track._internal(); + + factory Track() { + return _singleton; + } + + Track._internal(); + + void track(TrackingEvent event, {String eventValue = ""}) { + if (!isInDebugMode) { + Flurry.logEvent(event.toString()); + model.Tracking tracking = model.Tracking(); + tracking.customerId = Cache().userLoggedIn.customerId; + tracking.event = event.enumToString(); + if (eventValue.isNotEmpty) { + tracking.eventValue = eventValue; + } + tracking.dateAdd = DateTime.now(); + TrackingApi().saveTracking(tracking); + } + } +} diff --git a/lib/view/account.dart b/lib/view/account.dart index 7ba89e3..1430a53 100644 --- a/lib/view/account.dart +++ b/lib/view/account.dart @@ -1,8 +1,13 @@ +import 'dart:collection'; + import 'package:aitrainer_app/bloc/account/account_bloc.dart'; +import 'package:aitrainer_app/library/custom_icon_icons.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/util/common.dart'; +import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -24,7 +29,7 @@ class AccountPage extends StatelessWidget with Trans { body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -35,41 +40,27 @@ class AccountPage extends StatelessWidget with Trans { SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } else if (state is AccountLoading) {} }, builder: (context, state) { - if (state is AccountInitial) { - String customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; - if (customerName.length < 3) { - customerName = t("Personal data"); - } - - return accountWidget(context, customerName, accountBloc); - } else if (state is AccountLoggedIn) { - String customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; - - if (customerName.length < 3) { - customerName = t("Personal data"); - } - return accountWidget(context, customerName, accountBloc); - } else if (state is AccountLoggedOut) { - String customerName = ""; - if (customerName.length < 3) { - customerName = t("Personal data"); - } - return accountWidget(context, customerName, accountBloc); - } else if (state is AccountReady) { - String customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; - if (customerName.length < 3) { - customerName = t("Personal data"); - } - return accountWidget(context, customerName, accountBloc); - } else { - return accountWidget(context, t("Personal data"), accountBloc); - } + return accountWidget(context, accountBloc); }), ), bottomNavigationBar: BottomNavigator(bottomNavIndex: 3)); } - ListView accountWidget(BuildContext context, String customerName, AccountBloc accountBloc) { + ListView accountWidget(BuildContext context, AccountBloc accountBloc) { + String customerName = ""; + String goal = t("Set your goal"); + String fitnessLevel = t("Set your fitness level"); + String bodyType = ""; + if (accountBloc.customerRepository.customer != null) { + customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; + customerName = customerName.length < 3 ? t("Personal data") : customerName; + goal = accountBloc.customerRepository.customer.goal != null ? t(accountBloc.customerRepository.customer.goal) : goal; + fitnessLevel = accountBloc.customerRepository.customer.fitnessLevel != null + ? t(capitalize(accountBloc.customerRepository.customer.fitnessLevel)) + : fitnessLevel; + bodyType = accountBloc.getAccurateBodyType(); + } + final HashMap args = HashMap(); return ListView(padding: EdgeInsets.only(top: 35), children: [ ListTile( leading: Common.badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity), @@ -84,7 +75,68 @@ class AccountPage extends StatelessWidget with Trans { onPressed: () => { if (accountBloc.customerRepository.customer != null && Cache().userLoggedIn != null) { - Navigator.of(context).pushNamed('customerModifyPage'), + args['personal_data'] = true, + Navigator.of(context).pushNamed('customerModifyPage', arguments: args), + } + }, + ), + ), + ListTile( + leading: Common.badgedIcon(Colors.grey, Icons.arrow_forward_sharp, "Goal"), //Icon(Icons.arrow_forward_sharp), + subtitle: Text(t("Goal")), + title: FlatButton( + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(goal, style: TextStyle(color: Colors.blue)), + Icon(Icons.arrow_forward_ios), + ]), + textColor: Colors.grey, + color: Colors.white, + onPressed: () => { + if (accountBloc.customerRepository.customer != null && Cache().userLoggedIn != null) + { + args['personal_data'] = true, + args['bloc'] = accountBloc.customerRepository, + Navigator.of(context).pushNamed('customerGoalPage', arguments: args), + } + }, + ), + ), + ListTile( + leading: Common.badgedIcon(Colors.grey, Icons.perm_contact_cal, "FitnessLevel"), //Icon(Icons.perm_contact_cal), + subtitle: Text(t("Activity")), + title: FlatButton( + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(fitnessLevel, style: TextStyle(color: Colors.blue)), + Icon(Icons.arrow_forward_ios), + ]), + textColor: Colors.grey, + color: Colors.white, + onPressed: () => { + if (accountBloc.customerRepository.customer != null && Cache().userLoggedIn != null) + { + args['personal_data'] = true, + args['bloc'] = accountBloc.customerRepository, + Navigator.of(context).pushNamed('customerFitnessPage', arguments: args), + } + }, + ), + ), + ListTile( + leading: Common.badgedIcon(Colors.grey, CustomIcon.people_arrows, "bodyType"), //Icon(CustomIcon.people_arrows), + subtitle: Text(t("Body Type")), + title: FlatButton( + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(t(bodyType), style: TextStyle(color: Colors.blue)), + Icon(Icons.arrow_forward_ios), + ]), + textColor: Colors.grey, + color: Colors.white, + onPressed: () => { + if (accountBloc.customerRepository.customer != null && Cache().userLoggedIn != null) + { + args['personal_data'] = true, + args['bloc'] = accountBloc.customerRepository, + Navigator.of(context).pushNamed('customerBodyTypePage', arguments: args), } }, ), @@ -99,6 +151,7 @@ class AccountPage extends StatelessWidget with Trans { ListTile element = ListTile(); element = ListTile( leading: Common.badgedIcon(Colors.grey, Icons.device_hub, "customerDevice"), + subtitle: Text(t("These equipments and devices are available")), title: FlatButton( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -240,4 +293,11 @@ class AccountPage extends StatelessWidget with Trans { ], )); } + + String capitalize(String s) { + if (s == null || s.isEmpty) { + return " "; + } + return s[0].toUpperCase() + s.substring(1); + } } diff --git a/lib/view/custom_exercise_page.dart b/lib/view/custom_exercise_page.dart index 635305a..1d6e4fa 100644 --- a/lib/view/custom_exercise_page.dart +++ b/lib/view/custom_exercise_page.dart @@ -64,7 +64,7 @@ class _CustomExerciseNewPageState extends State with Logging height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), diff --git a/lib/view/customer_bodytype_animation.dart b/lib/view/customer_bodytype_animation.dart new file mode 100644 index 0000000..1ace66c --- /dev/null +++ b/lib/view/customer_bodytype_animation.dart @@ -0,0 +1,675 @@ +import 'dart:collection'; +import 'dart:ui'; + +import 'package:aitrainer_app/bloc/body_type/bodytype_bloc.dart'; +import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/app_bar.dart'; +import 'package:aitrainer_app/widgets/dialog_html.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_form_bloc/flutter_form_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:liquid_progress_indicator/liquid_progress_indicator.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; +import 'package:rainbow_color/rainbow_color.dart'; + +class CustomerBodyTypeAnimationPage extends StatefulWidget { + @override + _CustomerBodyTypeAnimationPageState createState() => _CustomerBodyTypeAnimationPageState(); +} + +class _CustomerBodyTypeAnimationPageState extends State with Trans { + bool fulldata; + + @override + Widget build(BuildContext context) { + CustomerRepository customerRepository; + dynamic args = ModalRoute.of(context).settings.arguments; + if (args is HashMap && args['personal_data'] != null) { + fulldata = args['personal_data']; + customerRepository = args['bloc']; + } else { + customerRepository = ModalRoute.of(context).settings.arguments; + } + + setContext(context); + return Scaffold( + appBar: AppBarNav(depth: 0), + body: Container( + height: double.infinity, + width: double.infinity, + alignment: Alignment.center, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_G_background.jpg'), + fit: BoxFit.cover, + alignment: Alignment.topCenter, + ), + ), + child: BlocProvider( + create: (context) => BodytypeBloc(repository: customerRepository), + child: BlocConsumer(listener: (context, state) { + if (state is BodytypeError) { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.error, style: TextStyle(color: Colors.white)))); + } + }, builder: (context, state) { + final bloc = BlocProvider.of(context); + return ModalProgressHUD( + child: getBodyTypeAnimation(bloc), + inAsyncCall: state is BodytypeLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); + }))), + ); + } + + Widget getBodyTypeAnimation(BodytypeBloc bloc) { + return Column( + children: [ + Text(t("Body Type Analyser"), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 24, + color: Colors.yellow[300], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )), + SizedBox( + height: 30, + ), + _AnimatedLiquidCustomProgressIndicator( + percentFrom: ((bloc.step - 1) / 22 * 100).toInt(), + percentTo: (bloc.step / 22 * 100).toInt(), + ), + Divider( + color: Colors.transparent, + ), + Text(t("How likely is it true about you?"), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 16, + color: Colors.yellow[300], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )), + SizedBox( + height: 30, + ), + Divider( + color: Colors.white54, + ), + Question( + bloc: bloc, + text: bloc.getQuestion(), + ), + Divider(color: Colors.transparent), + drawCircles(bloc), + Divider( + color: Colors.transparent, + ), + getLegend("Very unlikely", "Maybe", "Very likely"), + Divider(color: Colors.transparent), + InkWell( + onTap: () => bloc.add(BodytypeBack()), + child: Text(t("« Back"), + textAlign: TextAlign.center, + style: GoogleFonts.inter( + fontSize: 16, + color: Colors.blue[300], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ))), + Divider( + color: Colors.white54, + ), + SizedBox( + height: 20, + ), + bloc.showResults() + ? Text(t("Your Bodytype result"), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 20, + color: Colors.yellow[300], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )) + : Offstage(), + SizedBox( + height: 30, + ), + bloc.showResults() ? BodyTypeResult(bloc: bloc) : Offstage(), + Divider( + color: Colors.transparent, + ), + bloc.showResults() + ? getLegend(PropertyEnum.Ectomorph.toStr(), PropertyEnum.Mesomorph.toStr(), PropertyEnum.Endomorph.toStr(), info: true) + : Offstage(), + ], + ); + } + + Widget getLegend(String text1, String text2, String text3, {bool info = false}) { + return Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(t(text1), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 14, + color: Colors.green[300], + shadows: [ + Shadow( + offset: Offset(2.0, 2.0), + blurRadius: 14.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )), + info + ? GestureDetector( + onTap: () => showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t(text1), + htmlData: t(text1 + "_desc"), + ); + }), + child: Icon( + Icons.info_outline_rounded, + color: Colors.yellow[100], + )) + : Offstage(), + SizedBox( + width: 5, + ), + Text(t(text2), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 14, + color: Colors.green[300], + shadows: [ + Shadow( + offset: Offset(2.0, 2.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )), + info + ? GestureDetector( + onTap: () => showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t(text2), + htmlData: t(text2 + "_desc"), + ); + }), + child: Icon( + Icons.info_outline_rounded, + color: Colors.yellow[100], + )) + : Offstage(), + SizedBox( + width: 5, + ), + Text(t(text3), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 14, + color: Colors.green[300], + shadows: [ + Shadow( + offset: Offset(2.0, 2.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )), + info + ? GestureDetector( + onTap: () => showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t(text3), + htmlData: t(text3 + "_desc"), + ); + }), + child: Icon( + Icons.info_outline_rounded, + color: Colors.yellow[100], + )) + : Offstage(), + ]); + } + + Widget drawCircles(BodytypeBloc bloc) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + CircleButton(value: 1, bloc: bloc, onTap: () => bloc.add(BodytypeClick(value: 1))), + CircleButton(value: 2, bloc: bloc, onTap: () => bloc.add(BodytypeClick(value: 2))), + CircleButton(value: 3, bloc: bloc, onTap: () => bloc.add(BodytypeClick(value: 3))), + CircleButton(value: 4, bloc: bloc, onTap: () => bloc.add(BodytypeClick(value: 4))), + CircleButton(value: 5, bloc: bloc, onTap: () => bloc.add(BodytypeClick(value: 5))), + ], + ); + } +} + +class BodyTypeResult extends StatefulWidget { + final BodytypeBloc bloc; + const BodyTypeResult({this.bloc}); + @override + _BodyTypeResultState createState() => _BodyTypeResultState(); +} + +class _BodyTypeResultState extends State with TickerProviderStateMixin { + Animation colorAnim; + AnimationController colorController; + + @override + void initState() { + buildAnimation(); + super.initState(); + } + + void buildAnimation() { + colorController = AnimationController(duration: Duration(seconds: 2), vsync: this); + colorAnim = RainbowColorTween([ + Colors.green[800], + Colors.green[700], + Colors.green[600], + Colors.green[500], + Colors.green[400], + Colors.green[300], + Colors.green[200], + Colors.green[100], + Color(0xffb4f500), + ]).animate(colorController) + ..addListener(() { + setState(() {}); + }); + colorController.forward(); + } + + @override + void didUpdateWidget(BodyTypeResult oldWidget) { + buildAnimation(); + + super.didUpdateWidget(oldWidget); + } + + @override + void dispose() { + colorController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(left: 15, right: 15), + width: MediaQuery.of(context).size.width - 20, + height: 5, + child: CustomPaint( + painter: CurvePainter(value: widget.bloc.getBodyTypeValue(), color: colorAnim.value), + )); + } +} + +class CurvePainter extends CustomPainter { + final linePainter = Paint(); + final circlePainter = Paint(); + final Color color; + + final int value; + CurvePainter({this.value, this.color}); + + @override + void paint(Canvas canvas, Size size) { + var paint = linePainter; + paint.color = Colors.green[800]; + paint.strokeWidth = 5; + paint.style = PaintingStyle.fill; + + canvas.drawLine( + Offset(0, size.height / 2), + Offset(size.width, size.height / 2), + paint, + ); + + paint.strokeWidth = 12; + canvas.drawCircle(Offset(size.width / 2, size.height / 2), 6, paint); + canvas.drawCircle(Offset(0, size.height / 2), 6, paint); + canvas.drawCircle(Offset(size.width, size.height / 2), 6, paint); + + var paint2 = circlePainter; + paint2.color = this.color; //Color(0xffb4f500); + paint2.strokeWidth = 30; + canvas.drawCircle(Offset(size.width * (value / 100), size.height / 2), 15, paint2); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) { + return false; + } +} + +class Question extends StatefulWidget { + final String text; + final BodytypeBloc bloc; + const Question({this.text, this.bloc}); + + @override + _QuestionState createState() => _QuestionState(); +} + +class _QuestionState extends State with TickerProviderStateMixin { + AnimationController _controller; + Animation _animation; + @override + void initState() { + super.initState(); + buildAnimation(); + } + + @override + void didUpdateWidget(Question oldWidget) { + if (oldWidget.text != widget.text) { + buildAnimation(); + } + super.didUpdateWidget(oldWidget); + } + + void buildAnimation() { + _controller = AnimationController(duration: const Duration(milliseconds: 1000), vsync: this); + _animation = CurvedAnimation(parent: _controller, curve: Curves.slowMiddle); + + _controller.forward(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(left: 10, right: 10), + child: FadeTransition( + key: ValueKey(widget.text), + opacity: _animation, + child: Text(AppLocalizations.of(context).translate(widget.bloc.getQuestion()), + textAlign: TextAlign.center, + maxLines: 3, + style: GoogleFonts.archivoBlack( + fontSize: 18, + color: Color(0xffb4f500), + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + )))); + } +} + +class CircleButton extends StatefulWidget { + final GestureTapCallback onTap; + final BodytypeBloc bloc; + final int value; + + CircleButton({Key key, this.onTap, this.bloc, this.value}) : super(key: key); + + @override + _CircleButtonState createState() => _CircleButtonState(); +} + +class _CircleButtonState extends State with TickerProviderStateMixin { + Animation colorAnim; + AnimationController colorController; + + @override + void initState() { + buildAnimation(); + super.initState(); + } + + @override + void dispose() { + colorController.dispose(); + super.dispose(); + } + + @override + void didUpdateWidget(CircleButton oldWidget) { + if (widget.bloc.getPrevValue() == widget.value) { + buildAnimation(); + } + super.didUpdateWidget(oldWidget); + } + + void buildAnimation() { + colorController = AnimationController(duration: Duration(seconds: 2), vsync: this); + colorAnim = RainbowColorTween([ + Color(0xffb4f500), + Color(0xffb4f500), + Color(0xffb4f500), + Color(0xffb4f500), + Color(0xffb4f500), + Color(0xffb4f500), + Colors.green[100], + Colors.green[200], + Colors.green[300], + Colors.green[400], + Colors.green[500], + Colors.green[600], + Colors.green[700], + Colors.green[800], + ]).animate(colorController) + ..addListener(() { + setState(() {}); + }); + colorController.forward(); + } + + @override + Widget build(BuildContext context) { + final double size = 50.0; + return InkResponse( + onTap: () => { + widget.bloc.add(BodytypeClick(value: widget.value)), + }, + child: Container( + key: UniqueKey(), + width: size, + height: size, + decoration: BoxDecoration( + color: widget.value == widget.bloc.getPrevValue() ? colorAnim.value : Colors.green[800], + shape: BoxShape.circle, + ))); + } +} + +class _AnimatedLiquidCustomProgressIndicator extends StatefulWidget { + final int percentTo; + final int percentFrom; + + const _AnimatedLiquidCustomProgressIndicator({this.percentTo, this.percentFrom}); + + @override + State createState() => _AnimatedLiquidCustomProgressIndicatorState(); +} + +class _AnimatedLiquidCustomProgressIndicatorState extends State<_AnimatedLiquidCustomProgressIndicator> with TickerProviderStateMixin { + AnimationController _animationController; + bool switching = false; + + @override + void didChangeDependencies() { + buildAnimation(); + super.didChangeDependencies(); + } + + @override + void didUpdateWidget(_AnimatedLiquidCustomProgressIndicator oldWidget) { + if (oldWidget.percentFrom != widget.percentFrom) { + buildAnimation(); + } + super.didUpdateWidget(oldWidget); + } + + void buildAnimation() { + _animationController = AnimationController( + lowerBound: (widget.percentFrom / 100).toDouble(), + upperBound: (widget.percentTo / 100).toDouble(), + vsync: this, + duration: Duration(seconds: 3), + )..addListener(() { + setState(() {}); + }); + + _animationController.forward(); + } + + @override + void initState() { + buildAnimation(); + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final percentage = _animationController.value * 100; + return Center( + key: ValueKey(widget.percentFrom), + child: LiquidCustomProgressIndicator( + value: _animationController.value, + direction: Axis.vertical, + backgroundColor: Colors.white, + valueColor: AlwaysStoppedAnimation(Colors.blue[200]), + shapePath: _buildHeartPath(), + center: Text( + "${percentage.toStringAsFixed(0)}%", + style: TextStyle( + color: Colors.blue[800], + fontSize: 20.0, + fontWeight: FontWeight.bold, + ), + ), + ), + ); + } + + Path _buildHeartPath() { + return Path() + ..moveTo(55, 15) + ..cubicTo(55, 12, 50, 0, 30, 0) + ..cubicTo(0, 0, 0, 37.5, 0, 37.5) + ..cubicTo(0, 55, 20, 77, 55, 95) + ..cubicTo(90, 77, 110, 55, 110, 37.5) + ..cubicTo(110, 37.5, 110, 0, 80, 0) + ..cubicTo(65, 0, 55, 12, 55, 15) + ..close(); + } + + Path _buildManPath() { + return Path() + ..moveTo(55, 15) + ..cubicTo(75, 20, 75, 32, 68, 38) + ..lineTo(68, 43) + ..lineTo(116, 43) + ..lineTo(116, 55) + ..lineTo(75, 55) + ..conicTo(68, 80, 80, 120, 20) + ..lineTo(68, 120) + ..lineTo(55, 90) + ..lineTo(42, 120) + ..lineTo(20, 120) + ..conicTo(42, 80, 40, 55, 40) + ..lineTo(0, 55) + ..lineTo(0, 43) + ..lineTo(48, 43) + ..lineTo(48, 38) + ..cubicTo(25, 20, 25, 32, 55, 15) + ..close(); + } +} diff --git a/lib/view/customer_bodytype_page.dart b/lib/view/customer_bodytype_page.dart index fbd7378..c169416 100644 --- a/lib/view/customer_bodytype_page.dart +++ b/lib/view/customer_bodytype_page.dart @@ -1,8 +1,10 @@ +import 'dart:collection'; + import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:aitrainer_app/widgets/app_bar_progress.dart'; import 'package:aitrainer_app/widgets/dialog_html.dart'; import 'package:badges/badges.dart'; import 'package:flutter/material.dart'; @@ -26,18 +28,30 @@ class BodyTypeItem { class _CustomerBodyTypePageState extends State with Trans { String selected; + bool fulldata = false; @override Widget build(BuildContext context) { - final CustomerRepository customerRepository = ModalRoute.of(context).settings.arguments; + CustomerRepository customerRepository; + dynamic args = ModalRoute.of(context).settings.arguments; + if (args is HashMap && args['personal_data'] != null) { + fulldata = args['personal_data']; + customerRepository = args['bloc']; + } else { + customerRepository = ModalRoute.of(context).settings.arguments; + } final double cWidth = MediaQuery.of(context).size.width * 0.75; setContext(context); return Scaffold( - appBar: AppBarMin(), + appBar: fulldata + ? AppBarMin( + back: true, + ) + : AppBarProgress(min: 76, max: 100), body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -178,11 +192,11 @@ class _CustomerBodyTypePageState extends State with Trans RaisedButton( color: Colors.orange, textColor: Colors.white, - child: InkWell(child: Text(AppLocalizations.of(context).translate("Next"))), + child: Text(fulldata ? t("Save") : t("Next")), onPressed: () => { changeBloc.add(CustomerSave()), Navigator.of(context).pop(), - Navigator.of(context).pushNamed("customerWelcomePage", arguments: customerRepository) + if (fulldata == false) {Navigator.of(context).pushNamed("customerWelcomePage", arguments: customerRepository)} }, ) ], diff --git a/lib/view/customer_exercise_device.dart b/lib/view/customer_exercise_device.dart index a149d7e..3652a75 100644 --- a/lib/view/customer_exercise_device.dart +++ b/lib/view/customer_exercise_device.dart @@ -27,7 +27,7 @@ class CustomerExerciseDevicePage extends StatelessWidget with Trans { padding: EdgeInsets.all(10), decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -189,7 +189,7 @@ class CustomerExerciseDevicePage extends StatelessWidget with Trans { devices.sort((a, b) => a.sort.compareTo(b.sort)); devices.forEach((element) { if (element.place == false) { - final String url = "asset/image/" + element.imageUrl.substring(7); + final String url = "asset/equipment/" + element.imageUrl.substring(7); ImageButton button = ImageButton( width: cWidth / 2 - 10, height: cWidth / 2 - 10, @@ -219,7 +219,7 @@ class CustomerExerciseDevicePage extends StatelessWidget with Trans { devices.sort((a, b) => a.sort.compareTo(b.sort)); devices.forEach((element) { if (element.place) { - final String url = "asset/image/" + element.imageUrl.substring(7); + final String url = "asset/equipment/" + element.imageUrl.substring(7); ImageButton button = ImageButton( width: cWidth - 60, height: cWidth / 2 - 40, diff --git a/lib/view/customer_fitness_page.dart b/lib/view/customer_fitness_page.dart index cb43aa0..f30e3ed 100644 --- a/lib/view/customer_fitness_page.dart +++ b/lib/view/customer_fitness_page.dart @@ -1,7 +1,12 @@ +import 'dart:collection'; + import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/model/fitness_state.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:aitrainer_app/widgets/app_bar_progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -17,51 +22,45 @@ class CustomerFitnessPage extends StatefulWidget { } } -/* class FitnessItem { - static String beginner = "beginner"; - static String intermediate = "intermediate"; - static String advanced = "advanced"; - static String professional = "professional"; -} - */ //TODO // dropbox for professional sport -class _CustomerFitnessPageState extends State { +class _CustomerFitnessPageState extends State with Trans { String selected; + bool fulldata = false; @override Widget build(BuildContext context) { + setContext(context); final double cWidth = MediaQuery.of(context).size.width * 0.75; - final CustomerRepository customerRepository = ModalRoute.of(context).settings.arguments; + CustomerRepository customerRepository; + dynamic args = ModalRoute.of(context).settings.arguments; + if (args is HashMap && args['personal_data'] != null) { + fulldata = args['personal_data']; + customerRepository = args['bloc']; + } else { + customerRepository = ModalRoute.of(context).settings.arguments; + } + selected = customerRepository.customer.fitnessLevel; return Scaffold( - appBar: AppBar( - title: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Image.asset( - 'asset/image/WT_long_logo.png', - fit: BoxFit.cover, - height: 65.0, - ), - ], - ), - backgroundColor: Colors.transparent, - ), + appBar: fulldata + ? AppBarMin( + back: true, + ) + : AppBarProgress(max: 75, min: 51), body: BlocProvider( create: (context) => CustomerChangeBloc(customerRepository: customerRepository), child: Builder(builder: (context) { // ignore: close_sinks CustomerChangeBloc changeBloc = BlocProvider.of(context); - return SingleChildScrollView( scrollDirection: Axis.vertical, child: Container( padding: EdgeInsets.only(bottom: 200), decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -75,7 +74,7 @@ class _CustomerFitnessPageState extends State { alignment: WrapAlignment.center, children: [ Text( - AppLocalizations.of(context).translate("Your Fitness State"), + t("Your Fitness State"), textAlign: TextAlign.center, style: TextStyle(color: Colors.orange, fontSize: 42, fontFamily: 'Arial', fontWeight: FontWeight.w900), ) @@ -86,11 +85,11 @@ class _CustomerFitnessPageState extends State { width: cWidth, child: Column( children: [ - Text(AppLocalizations.of(context).translate("Beginner"), + Text(t("Beginner"), textWidthBasis: TextWidthBasis.longestLine, style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900)), Text( - AppLocalizations.of(context).translate("I am beginner"), + t("I am beginner"), style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), ], @@ -111,14 +110,14 @@ class _CustomerFitnessPageState extends State { children: [ InkWell( child: Text( - AppLocalizations.of(context).translate("Intermediate"), + t("Intermediate"), style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), ), highlightColor: Colors.white, ), InkWell( child: Text( - AppLocalizations.of(context).translate("I am intermediate"), + t("I am intermediate"), style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), highlightColor: Colors.white, @@ -143,14 +142,14 @@ class _CustomerFitnessPageState extends State { children: [ InkWell( child: Text( - AppLocalizations.of(context).translate("Advanced"), + t("Advanced"), style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), ), highlightColor: Colors.white, ), InkWell( child: Text( - AppLocalizations.of(context).translate("I am advanced"), + t("I am advanced"), style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), highlightColor: Colors.white, @@ -203,11 +202,11 @@ class _CustomerFitnessPageState extends State { RaisedButton( color: Colors.orange, textColor: Colors.white, - child: InkWell(child: Text(AppLocalizations.of(context).translate("Next"))), + child: Text(fulldata ? t("Save") : t("Next")), onPressed: () => { changeBloc.add(CustomerSave()), Navigator.of(context).pop(), - Navigator.of(context).pushNamed("customerBodyTypePage", arguments: customerRepository) + if (!fulldata) {Navigator.of(context).pushNamed("customerBodyTypePage", arguments: customerRepository)} }, ) ], diff --git a/lib/view/customer_goal_page.dart b/lib/view/customer_goal_page.dart index f9b523a..6873a63 100644 --- a/lib/view/customer_goal_page.dart +++ b/lib/view/customer_goal_page.dart @@ -1,6 +1,11 @@ +import 'dart:collection'; + import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:aitrainer_app/widgets/app_bar_progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; @@ -16,31 +21,33 @@ class CustomerGoalPage extends StatefulWidget { State createState() => _CustomerGoalPage(); } -class _CustomerGoalPage extends State { +class _CustomerGoalPage extends State with Trans { String selected; + bool fulldata = false; @override Widget build(BuildContext context) { - final CustomerRepository customerRepository = ModalRoute.of(context).settings.arguments; + setContext(context); + + CustomerRepository customerRepository; + dynamic args = ModalRoute.of(context).settings.arguments; + if (args is HashMap && args['personal_data'] != null) { + fulldata = args['personal_data']; + customerRepository = args['bloc']; + } else { + customerRepository = ModalRoute.of(context).settings.arguments; + } return Scaffold( - appBar: AppBar( - title: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Image.asset( - 'asset/image/WT_long_logo.png', - fit: BoxFit.cover, - height: 65.0, - ), - ], - ), - backgroundColor: Colors.transparent, - ), + appBar: fulldata + ? AppBarMin( + back: true, + ) + : AppBarProgress(max: 50, min: 26), body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -67,7 +74,7 @@ class _CustomerGoalPage extends State { Stack(alignment: Alignment.bottomLeft, overflow: Overflow.visible, children: [ FlatButton( child: Image.asset( - "asset/image/Gain_muscle.png", + "asset/image/Gain_muscle.jpg", height: 180, ), padding: EdgeInsets.all(0.0), @@ -90,7 +97,7 @@ class _CustomerGoalPage extends State { Stack(alignment: Alignment.bottomLeft, overflow: Overflow.visible, children: [ FlatButton( child: Image.asset( - "asset/image/WT_weight_loss.png", + "asset/image/WT_weight_loss.jpg", height: 180, ), padding: EdgeInsets.all(0.0), @@ -113,12 +120,12 @@ class _CustomerGoalPage extends State { RaisedButton( color: Colors.orange, textColor: Colors.white, - child: InkWell(child: Text(AppLocalizations.of(context).translate("Next"))), + child: Text(fulldata ? t("Save") : t("Next")), onPressed: () => { //changingViewModel.saveCustomer(), changeBloc.add(CustomerSave()), Navigator.of(context).pop(), - Navigator.of(context).pushNamed("customerFitnessPage", arguments: changeBloc.customerRepository) + if (!fulldata) {Navigator.of(context).pushNamed("customerFitnessPage", arguments: changeBloc.customerRepository)} }, ) ], diff --git a/lib/view/customer_modify_page.dart b/lib/view/customer_modify_page.dart index f3df99c..39e84df 100644 --- a/lib/view/customer_modify_page.dart +++ b/lib/view/customer_modify_page.dart @@ -1,10 +1,13 @@ +import 'dart:collection'; + import 'package:aitrainer_app/bloc/account/account_bloc.dart'; import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; -import 'package:aitrainer_app/library/numberpicker.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/util/enums.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:aitrainer_app/widgets/app_bar_progress.dart'; +import 'package:aitrainer_app/widgets/number_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; @@ -19,9 +22,15 @@ import '../library_keys.dart'; // ignore: must_be_immutable class CustomerModifyPage extends StatelessWidget with Trans { final GlobalKey _scaffoldKey = new GlobalKey(); + bool fulldata = false; @override Widget build(BuildContext context) { + dynamic arguments = ModalRoute.of(context).settings.arguments; + if (arguments is HashMap && arguments['personal_data'] != null) { + fulldata = arguments['personal_data']; + } + setContext(context); // ignore: close_sinks final accountBloc = BlocProvider.of(context); @@ -34,13 +43,15 @@ class CustomerModifyPage extends StatelessWidget with Trans { return Scaffold( resizeToAvoidBottomInset: true, - appBar: AppBarMin( - back: true, - ), + appBar: fulldata + ? AppBarMin( + back: true, + ) + : AppBarProgress(max: 25, min: 0), body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), @@ -56,7 +67,11 @@ class CustomerModifyPage extends StatelessWidget with Trans { SnackBar(backgroundColor: Colors.orange, content: Text(message, style: TextStyle(color: Colors.white)))); } } else if (state is CustomerSaveSuccess) { - Navigator.of(context).pushNamed("customerGoalPage", arguments: customerBloc.customerRepository); + if (fulldata) { + Navigator.of(context).pop(); + } else { + Navigator.of(context).pushNamed("customerGoalPage", arguments: customerBloc.customerRepository); + } } }, builder: (context, state) { @@ -83,14 +98,11 @@ class CustomerModifyPage extends StatelessWidget with Trans { alignment: Alignment.center, child: Column( children: [ - Text(t("Please provide us some personal data"), - style: GoogleFonts.inter(color: Colors.indigo, fontSize: 16), textAlign: TextAlign.center), - Text(t("To lift your experience using the app"), - style: GoogleFonts.inter(color: Colors.orange[700], fontSize: 16), textAlign: TextAlign.center), + Text(t("Edit Profile"), style: GoogleFonts.inter(color: Colors.indigo, fontSize: 16), textAlign: TextAlign.center), Divider( color: Colors.transparent, ), - Cache().getLoginType() == LoginType.email + Cache().getLoginType() == LoginType.email || fulldata ? TextFormField( key: LibraryKeys.loginEmailField, decoration: InputDecoration( @@ -148,7 +160,7 @@ class CustomerModifyPage extends StatelessWidget with Trans { Divider( color: Colors.transparent, ), - Cache().getLoginType() != LoginType.apple + Cache().getLoginType() != LoginType.apple || fulldata ? TextFormField( decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), @@ -173,7 +185,7 @@ class CustomerModifyPage extends StatelessWidget with Trans { Divider( color: Colors.transparent, ), - Cache().getLoginType() != LoginType.apple + Cache().getLoginType() != LoginType.apple || fulldata ? TextFormField( decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), @@ -203,75 +215,51 @@ class CustomerModifyPage extends StatelessWidget with Trans { children: [ Expanded( flex: 4, - child: Text(t("Birth Year"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14)), + child: Text(t("Birth Year"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)), ), - Flexible( - fit: FlexFit.tight, - flex: 8, - child: NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: customerBloc.year, + NumberPickerWidget( minValue: 1930, maxValue: 2100, - - step: 1, - textStyle: TextStyle(fontWeight: FontWeight.bold), - textStyleHighlighted: TextStyle(fontSize: 16, color: Colors.indigo, fontWeight: FontWeight.bold), - onChanged: (value) => {customerBloc.add(CustomerBirthYearChange(year: value))}, - listViewHeight: 60, - //decoration: _decoration, - ), - ), + initalValue: customerBloc.year.toInt(), + unit: " ", + color: Colors.indigo, + onChange: (value) => {customerBloc.add(CustomerBirthYearChange(year: value.toInt()))}), SizedBox(width: 80), ], ), + Divider(), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 4, - child: Text(t("Weight"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14)), + child: Text(t("Weight"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)), ), - Flexible( - fit: FlexFit.tight, - flex: 8, - child: NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: customerBloc.weight.toInt(), + NumberPickerWidget( minValue: 0, maxValue: 200, - step: 1, - textStyle: TextStyle(fontWeight: FontWeight.bold), - textStyleHighlighted: TextStyle(fontSize: 18, color: Colors.indigo, fontWeight: FontWeight.bold), - onChanged: (value) => {customerBloc.add(CustomerWeightChange(weight: value))}, - listViewHeight: 60, - ), - ), + initalValue: customerBloc.weight.toInt(), + unit: " ", + color: Colors.indigo, + onChange: (value) => {customerBloc.add(CustomerWeightChange(weight: value.toInt()))}), SizedBox(width: 80), ], ), + Divider(), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( flex: 4, - child: Text(t("Height"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14)), + child: Text(t("Height"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)), ), - Flexible( - fit: FlexFit.tight, - flex: 8, - child: NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: customerBloc.height.toInt(), + NumberPickerWidget( minValue: 0, maxValue: 230, - step: 1, - textStyle: TextStyle(fontWeight: FontWeight.bold), - textStyleHighlighted: TextStyle(fontSize: 18, color: Colors.indigo, fontWeight: FontWeight.bold), - onChanged: (value) => {customerBloc.add(CustomerHeightChange(height: value))}, - listViewHeight: 60, - ), - ), + initalValue: customerBloc.height.toInt(), + unit: " ", + color: Colors.indigo[300], + onChange: (value) => {customerBloc.add(CustomerHeightChange(height: value.toInt()))}), SizedBox(width: 80), ], ), @@ -298,7 +286,7 @@ class CustomerModifyPage extends StatelessWidget with Trans { children: [ Image.asset('asset/icon/gomb_orange_a.png', width: 140, height: 60), Text( - t("Next"), + fulldata ? t("Save") : t("Next"), style: TextStyle(fontSize: 16, color: Colors.white), ), ], diff --git a/lib/view/customer_welcome_page.dart b/lib/view/customer_welcome_page.dart index 34de59b..de6751b 100644 --- a/lib/view/customer_welcome_page.dart +++ b/lib/view/customer_welcome_page.dart @@ -35,7 +35,7 @@ class _CustomerWelcomePageState extends State { body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_welcome.png'), + image: AssetImage('asset/image/WT_welcome.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), diff --git a/lib/view/evaluation.dart b/lib/view/evaluation.dart index d6d3218..e06ec85 100644 --- a/lib/view/evaluation.dart +++ b/lib/view/evaluation.dart @@ -35,10 +35,10 @@ class EvaluationPage extends StatelessWidget with Trans { String imageUrl = ""; if (Cache().userLoggedIn.sex == "m") { resultType = ResultType.man; - imageUrl = 'asset/image/WT_Results_for_men.png'; + imageUrl = 'asset/image/WT_Results_for_men.jpg'; } else { resultType = ResultType.man; - imageUrl = 'asset/image/WT_Results_for_female.png'; + imageUrl = 'asset/image/WT_Results_for_female.jpg'; } if (arguments['past'] != null && arguments['past'] == true) { @@ -53,7 +53,7 @@ class EvaluationPage extends StatelessWidget with Trans { } if (exerciseRepository.exerciseType.getAbility().equalsTo(ExerciseAbility.running)) { resultType = ResultType.running; - imageUrl = 'asset/image/WT_Results_for_runners.png'; + imageUrl = 'asset/image/WT_Results_for_runners.jpg'; } setContext(context); @@ -81,11 +81,6 @@ class EvaluationPage extends StatelessWidget with Trans { if (state is ResultError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.error, style: TextStyle(color: Colors.white)))); - } else if (state is ResultLoading) { - Scaffold.of(context).showSnackBar(SnackBar( - duration: Duration(milliseconds: 100), - backgroundColor: Colors.transparent, - content: Container(child: Center(child: CircularProgressIndicator())))); } }, builder: (context, state) { final resultBloc = BlocProvider.of(context); @@ -110,9 +105,9 @@ class EvaluationPage extends StatelessWidget with Trans { SliverAppBar( pinned: true, backgroundColor: Colors.transparent, - expandedHeight: 120.0, - collapsedHeight: 80, - toolbarHeight: 30, + expandedHeight: 100.0, + collapsedHeight: 100, + toolbarHeight: 40, automaticallyImplyLeading: false, flexibleSpace: FlexibleSpaceBar( title: Text(exerciseName, @@ -120,8 +115,8 @@ class EvaluationPage extends StatelessWidget with Trans { maxLines: 3, //softWrap: true, style: GoogleFonts.archivoBlack( - fontSize: 24, - color: Colors.white, + fontSize: 20, + color: Colors.yellow[300], shadows: [ Shadow( offset: Offset(5.0, 5.0), diff --git a/lib/view/exercise_control_page.dart b/lib/view/exercise_control_page.dart index 0536877..1e7baaa 100644 --- a/lib/view/exercise_control_page.dart +++ b/lib/view/exercise_control_page.dart @@ -78,8 +78,8 @@ class _ExerciseControlPage extends State with Trans { decoration: BoxDecoration( image: DecorationImage( image: Cache().userLoggedIn.sex == "m" - ? AssetImage("asset/image/WT_Results_for_men.png") - : AssetImage("asset/image/WT_Results_for_female.png"), + ? AssetImage("asset/image/WT_Results_for_men.jpg") + : AssetImage("asset/image/WT_Results_for_female.jpg"), fit: BoxFit.cover, alignment: Alignment.topCenter, ), @@ -229,7 +229,7 @@ class _ExerciseControlPage extends State with Trans { numberPickForm(exerciseBloc, 3), ]), ))), - bottomNavigationBar: BottomNavigator(bottomNavIndex: 1), + //bottomNavigationBar: BottomNavigator(bottomNavIndex: 1), ), ); } @@ -253,19 +253,7 @@ class _ExerciseControlPage extends State with Trans { } Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) { - String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max."; - String textInstruction = ""; - textInstruction = t("Please repeat with ") + - exerciseBloc.unitQuantity.toStringAsFixed(0) + - " " + - exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + - t("hu_with") + - " " + - strTimes + - " " + - t( - "times!", - ); + final String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max."; String title = (step + 1).toString() + "/4 " + t("Control Exercise:"); LinkedHashMap args = LinkedHashMap(); @@ -275,44 +263,55 @@ class _ExerciseControlPage extends State with Trans { title, style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold), ), - RichText( - text: TextSpan( - style: GoogleFonts.inter( - fontSize: 16, - fontWeight: FontWeight.normal, - color: Colors.yellow[300], - ), - children: [ - TextSpan(text: t("Please repeat with ")), - TextSpan( - text: exerciseBloc.unitQuantity.toStringAsFixed(0) + " " + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit, + GestureDetector( + onTap: () => showDialog( + context: context, + builder: (BuildContext context) { + return UnitQuantityControl( + exerciseBloc: exerciseBloc, + step: step, + ); + }), + child: RichText( + text: TextSpan( style: GoogleFonts.inter( fontSize: 16, - fontWeight: FontWeight.bold, - color: Colors.yellow[400], + fontWeight: FontWeight.normal, + color: Colors.yellow[300], ), - ), - TextSpan( - text: t("hu_with") + - " " + - strTimes + - " " + - t( - "times!", - )) - ]), - ), - /* Text( - textInstruction, - style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 16), - ), */ + children: [ + TextSpan(text: t("Please repeat with ")), + TextSpan( + text: + exerciseBloc.unitQuantity.toStringAsFixed(0) + " " + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit, + style: GoogleFonts.inter( + decoration: TextDecoration.underline, + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.yellow[100], + ), + ), + TextSpan(text: t("hu_with") + " "), + TextSpan( + text: strTimes + " ", + style: GoogleFonts.inter( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.yellow[100], + )), + TextSpan( + text: t( + "times!", + )), + ]), + )), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ NumberPickerWidget( minValue: 0, maxValue: 200, - initalValue: exerciseBloc.quantity.toInt(), + initalValue: exerciseBloc.quantity.round(), unit: t("reps"), color: Colors.yellow[50], onChange: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}), @@ -354,3 +353,104 @@ class _ExerciseControlPage extends State with Trans { ); } } + +class UnitQuantityControl extends StatefulWidget { + final ExerciseControlBloc exerciseBloc; + final int step; + const UnitQuantityControl({this.exerciseBloc, this.step}); + @override + _UnitQuantityControlState createState() => _UnitQuantityControlState(); +} + +class _UnitQuantityControlState extends State with Trans { + double changedValue; + @override + Widget build(BuildContext context) { + changedValue = widget.exerciseBloc.unitQuantity; + setContext(context); + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(31), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + contentBox(context) { + return Stack(alignment: AlignmentDirectional.topStart, children: [ + Container( + padding: EdgeInsets.only(left: 20, top: 24, right: 20, bottom: 30), + margin: EdgeInsets.only(top: 30), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)], + image: DecorationImage( + image: AssetImage('asset/image/WT_results_background.jpg'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Text( + t("Change the weight to"), + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack( + fontSize: 24, + color: Colors.yellow[100], + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 12.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + ), + SizedBox( + height: 20, + ), + NumberPickerWidget( + minValue: (widget.exerciseBloc.unitQuantity - 10).round(), + maxValue: (widget.exerciseBloc.unitQuantity + 10).round(), + initalValue: widget.exerciseBloc.unitQuantity.round(), + unit: t("kg"), + color: Colors.yellow[50], + onChange: (value) => {changedValue = value}), + Align( + alignment: Alignment.center, + child: GestureDetector( + onTap: () => { + widget.exerciseBloc.add(ExerciseControlUnitQuantityChange(quantity: changedValue.toDouble(), step: widget.step)), + Navigator.of(context).pop(), + }, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_orange_c.png', width: 100, height: 45), + Text( + t("OK"), + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ], + ))), + ])), + GestureDetector( + onTap: () => Navigator.of(context).pop(), + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: 28, + child: Text( + "X", + style: GoogleFonts.archivoBlack(fontSize: 32, color: Colors.white54), + ), + )), + ]); + } +} diff --git a/lib/view/exercise_execute_page.dart b/lib/view/exercise_execute_page.dart index b0b3c97..a6802aa 100644 --- a/lib/view/exercise_execute_page.dart +++ b/lib/view/exercise_execute_page.dart @@ -49,8 +49,8 @@ class _ExerciseExecutePage extends State with Trans { decoration: BoxDecoration( image: DecorationImage( image: customerId == Cache().userLoggedIn.customerId - ? AssetImage('asset/image/WT_black_background.png') - : AssetImage('asset/image/WT_light_background.png'), + ? AssetImage('asset/image/WT_black_background.jpg') + : AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/exercise_execute_plan_add_page.dart b/lib/view/exercise_execute_plan_add_page.dart index 52c3b4c..2dc888d 100644 --- a/lib/view/exercise_execute_plan_add_page.dart +++ b/lib/view/exercise_execute_plan_add_page.dart @@ -2,16 +2,18 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_execute_plan/exercise_execute_plan_bloc.dart'; import 'package:aitrainer_app/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart'; +import 'package:aitrainer_app/library/custom_icon_icons.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; -import 'package:aitrainer_app/library/numberpicker.dart'; +import 'package:aitrainer_app/widgets/number_picker.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:modal_progress_hud/modal_progress_hud.dart'; class ExerciseExecutePlanAddPage extends StatefulWidget { @@ -19,6 +21,15 @@ class ExerciseExecutePlanAddPage extends StatefulWidget { } class _ExerciseExecuteAddPage extends State with Trans { + final ScrollController _controller = ScrollController(); + double offset = 0; + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { LinkedHashMap arguments = ModalRoute.of(context).settings.arguments; @@ -44,7 +55,9 @@ class _ExerciseExecuteAddPage extends State with Tra }, builder: (context, state) { // ignore: close_sinks final exerciseBloc = BlocProvider.of(context); - + if (state is ExerciseExecutePlanAddReady) { + _controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn); + } return ModalProgressHUD( child: getControlForm(exerciseBloc), inAsyncCall: state is ExerciseExecutePlanAddLoading, @@ -69,7 +82,7 @@ class _ExerciseExecuteAddPage extends State with Tra height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), @@ -79,16 +92,33 @@ class _ExerciseExecuteAddPage extends State with Tra child: SingleChildScrollView( scrollDirection: Axis.vertical, physics: BouncingScrollPhysics(), - controller: ScrollController( - initialScrollOffset: exerciseBloc.scrollOffset, - ), + controller: _controller, child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Text(t("Save Exercise")), + Text( + t("Save Exercise"), + style: GoogleFonts.inter(fontSize: 16, color: Colors.orange[50]), + ), Text( exerciseName, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange), + style: GoogleFonts.archivoBlack( + fontSize: 24, + color: Colors.orange[700], + shadows: [ + Shadow( + offset: Offset(2.0, 2.0), + blurRadius: 6.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + textAlign: TextAlign.center, overflow: TextOverflow.fade, - maxLines: 1, + maxLines: 3, softWrap: true, ), Divider( @@ -115,52 +145,85 @@ class _ExerciseExecuteAddPage extends State with Tra Divider( color: Colors.transparent, ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.baseline, - children: [ - Text( - t("Execute the") + " ", - style: TextStyle(fontWeight: FontWeight.bold), - ), - Text( - (i + 1).toString() + ". ", - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), - ), - Text( - t("set!"), - style: TextStyle(fontWeight: FontWeight.bold), - ), - ], + RichText( + text: TextSpan( + style: GoogleFonts.inter( + fontSize: 16, + fontWeight: FontWeight.normal, + color: Colors.yellow[300], + shadows: [ + Shadow( + offset: Offset(2.0, 2.0), + blurRadius: 6.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 12.0, + color: Colors.black54, + ), + ], + ), + children: [ + TextSpan(text: t("Execute the") + " "), + TextSpan( + text: (i + 1).toString() + ". ", + style: GoogleFonts.inter( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.yellow[600], + ), + ), + TextSpan(text: t("set!")) + ]), ), Divider( color: Colors.transparent, ), - Text(t("Please repeat with") + - " " + - exerciseBloc.unitQuantity.toStringAsFixed(0) + - " " + - exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + - " " + - exerciseBloc.exercisePlanRepository.getActualPlanDetail().repeats.toString() + - " " + - t("times!")), - Row(children: [ - NumberPicker.horizontal( - highlightSelectedValue: (i + 1) == exerciseBloc.step, - initialValue: exerciseBloc.unitQuantity.toInt(), - minValue: 0, - maxValue: 650, - step: 1, - textStyle: TextStyle(fontWeight: FontWeight.bold), - textStyleHighlighted: TextStyle(fontSize: 24, color: Colors.indigo, fontWeight: FontWeight.bold), - onChanged: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeUnitQuantity(quantity: value.toDouble()))}, - listViewHeight: 80, - //decoration: _decoration, - ), - Text(exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit), + Row(mainAxisAlignment: MainAxisAlignment.start, children: [ + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit == null + ? Offstage() + : NumberPickerWidget( + minValue: 0, + maxValue: 1000, + fontSize: 16, + initalValue: exerciseBloc.unitQuantity.toInt(), + unit: t(exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit), + color: Colors.yellow[50], + onChange: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeUnitQuantity(quantity: value.toDouble()))}), + NumberPickerWidget( + minValue: 0, + maxValue: 200, + fontSize: 16, + initalValue: exerciseBloc.quantity.toInt(), + unit: t(exerciseBloc.exerciseRepository.exerciseType.unit), //t("repeat"), + color: Colors.yellow[50], + onChange: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeQuantity(quantity: value.toDouble()))}), ]), - Row(children: [ + FlatButton( + padding: EdgeInsets.all(0), + textColor: Colors.white, + focusColor: Colors.blueAccent, + onPressed: () => { + if (exerciseBloc.step == i + 1) {exerciseBloc.add(ExerciseExecutePlanAddSubmit())}, + if (i + 1 == exerciseBloc.countSteps) {Navigator.of(context).pop()} + }, + child: exerciseBloc.step == i + 1 + ? Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60), + Text( + t("Save"), + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ], + ) + : Stack( + alignment: Alignment.center, + children: getButton(i + 1, exerciseBloc), + )), + /* Row(children: [ NumberPicker.horizontal( highlightSelectedValue: (i + 1) == exerciseBloc.step, initialValue: exerciseBloc.quantity.toInt(), @@ -174,8 +237,8 @@ class _ExerciseExecuteAddPage extends State with Tra //decoration: _decoration, ), Text(t("repeat")), - ]), - RaisedButton( + ]), */ + /* RaisedButton( padding: EdgeInsets.all(0), textColor: Colors.white, color: exerciseBloc.step == i + 1 ? Colors.blue : Colors.black26, @@ -187,7 +250,7 @@ class _ExerciseExecuteAddPage extends State with Tra child: Text( t("Save"), style: TextStyle(fontSize: 12), - )), + )), */ Divider(), ], ); @@ -195,4 +258,22 @@ class _ExerciseExecuteAddPage extends State with Tra } return listColumns; } + + List getButton(int step, ExerciseExecutePlanAddBloc exerciseBloc) { + List widgets = List(); + if (step < exerciseBloc.step) { + widgets.add(Icon( + CustomIcon.check_circle, + color: Color(0xffb4f500), + size: 36, + )); + } else { + widgets.add(Icon( + CustomIcon.question, + color: Colors.grey[700], + size: 36, + )); + } + return widgets; + } } diff --git a/lib/view/exercise_log_page.dart b/lib/view/exercise_log_page.dart index deca86c..da17d0f 100644 --- a/lib/view/exercise_log_page.dart +++ b/lib/view/exercise_log_page.dart @@ -58,8 +58,8 @@ class _ExerciseLogPage extends State with Trans, Common { decoration: BoxDecoration( image: DecorationImage( image: customerId == Cache().userLoggedIn.customerId - ? AssetImage('asset/image/WT_black_background.png') - : AssetImage('asset/image/WT_light_background.png'), + ? AssetImage('asset/image/WT_black_background.jpg') + : AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/exercise_new_page.dart b/lib/view/exercise_new_page.dart index 2a2d827..d2d2d3e 100644 --- a/lib/view/exercise_new_page.dart +++ b/lib/view/exercise_new_page.dart @@ -16,6 +16,7 @@ import 'package:aitrainer_app/widgets/bmi_widget.dart'; import 'package:aitrainer_app/widgets/bmr_widget.dart'; import 'package:aitrainer_app/widgets/size_widget.dart'; import 'package:aitrainer_app/widgets/time_picker.dart'; +import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -33,6 +34,29 @@ class ExerciseNewPage extends StatefulWidget { class _ExerciseNewPageState extends State with Trans, Logging { final FocusNode _nodeText1 = FocusNode(); final FocusNode _nodeText2 = FocusNode(); + final _controller1 = TextEditingController(); + final _controller2 = TextEditingController(); + + initState() { + super.initState(); + _controller1.text = "30"; + _nodeText1.addListener(() { + if (_nodeText1.hasFocus) { + _controller1.selection = TextSelection(baseOffset: 0, extentOffset: _controller1.text.length); + } + }); + + SchedulerBinding.instance.addPostFrameCallback((_) { + // ignore: close_sinks + final menuBloc = BlocProvider.of(context); + _controller2.text = menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString() ? "12" : "20"; + _nodeText2.addListener(() { + if (_nodeText2.hasFocus) { + _controller2.selection = TextSelection(baseOffset: 0, extentOffset: _controller2.text.length); + } + }); + }); + } KeyboardActionsConfig _buildConfig(BuildContext context) { return KeyboardActionsConfig( @@ -150,7 +174,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), @@ -234,18 +258,20 @@ class _ExerciseNewPageState extends State with Trans, Logging { Divider( color: Colors.transparent, ), - Text( - t("Step" + ": " + "1/4"), - style: GoogleFonts.inter( - fontSize: 22, - color: Colors.white, - fontWeight: FontWeight.bold, - ), - maxLines: 3, - textAlign: TextAlign.center, - overflow: TextOverflow.fade, - softWrap: true, - ), + exerciseBloc.exerciseRepository.exerciseType.unitQuantity == "1" + ? Text( + t("Step") + ": " + "1/4", + style: GoogleFonts.inter( + fontSize: 22, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + maxLines: 3, + textAlign: TextAlign.center, + overflow: TextOverflow.fade, + softWrap: true, + ) + : Offstage(), Divider( color: Colors.transparent, ), @@ -278,6 +304,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextFormField( focusNode: _nodeText1, + controller: _controller1, decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), labelText: t(bloc.exerciseRepository.exerciseType.unitQuantityUnit), @@ -290,7 +317,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { borderSide: BorderSide(color: Colors.white12, width: 0.4), ), ), - initialValue: "30", + //initialValue: "30", keyboardType: TextInputType.numberWithOptions(decimal: true), textInputAction: TextInputAction.done, style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.yellow[300]), @@ -388,6 +415,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { Column row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextFormField( focusNode: _nodeText2, + controller: _controller2, decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), labelText: t(bloc.exerciseRepository.exerciseType.unit), @@ -400,7 +428,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { borderSide: BorderSide(color: Colors.black26, width: 0.4), ), ), - initialValue: bloc.quantity.toStringAsFixed(0), + //initialValue: bloc.quantity.toStringAsFixed(0), keyboardType: TextInputType.number, textInputAction: TextInputAction.next, style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.orange[200]), diff --git a/lib/view/exercise_plan_custom_detail_add_page.dart b/lib/view/exercise_plan_custom_detail_add_page.dart index 4a0136e..e94f1b1 100644 --- a/lib/view/exercise_plan_custom_detail_add_page.dart +++ b/lib/view/exercise_plan_custom_detail_add_page.dart @@ -15,6 +15,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:keyboard_actions/keyboard_actions_config.dart'; import 'package:keyboard_actions/keyboard_actions_item.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; class ExercisePlanDetailAddPage extends StatefulWidget { @override @@ -104,21 +105,21 @@ class _ExercisePlanDetailAddPage extends State with T ..add(ExercisePlanCustomAddLoad()), child: BlocConsumer( listener: (context, state) { - if (state is ExercisePlanCustomAddLoading) { - //LoadingDialog.show(context); - } else if (state is ExercisePlanCustomAddError) { - //LoadingDialog.hide(context); + if (state is ExercisePlanCustomAddError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } }, builder: (context, state) { - if (state is ExercisePlanCustomAddReady) { - //LoadingDialog.hide(context); - } // ignore: close_sinks final bloc = BlocProvider.of(context); - return getForm(bloc, workoutMenuTree); + return ModalProgressHUD( + child: getForm(bloc, workoutMenuTree), + inAsyncCall: state is ExercisePlanCustomAddLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); }, )); } @@ -130,6 +131,12 @@ class _ExercisePlanDetailAddPage extends State with T ? bloc.exercisePlanRepository.getActualPlanDetail().exerciseType.name : bloc.exercisePlanRepository.getActualPlanDetail().exerciseType.nameTranslation; } + final bool weightVisible = bloc.exercisePlanRepository.getActualPlanDetail().exerciseType.unitQuantityUnit != null; + String summary = bloc.serie.toStringAsFixed(0) + " x " + bloc.quantity.toStringAsFixed(0); + if (bloc.quantityUnit > 0) { + summary += " x " + bloc.quantityUnit.toStringAsFixed(0) + " kg"; + } + final String unit = bloc.exercisePlanRepository.getActualPlanDetail().exerciseType.unit; return Form( child: Scaffold( resizeToAvoidBottomInset: true, @@ -139,7 +146,7 @@ class _ExercisePlanDetailAddPage extends State with T height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), @@ -195,7 +202,7 @@ class _ExercisePlanDetailAddPage extends State with T TextFormField( decoration: InputDecoration( contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), - labelText: t('Repeats'), + labelText: t(unit), fillColor: Colors.white24, labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), filled: true, @@ -210,37 +217,33 @@ class _ExercisePlanDetailAddPage extends State with T keyboardType: TextInputType.number, style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeQuantity(quantity: double.parse(value)))}), - //]), + Divider(), - TextFormField( - decoration: InputDecoration( - contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), - labelText: t('Weight'), - fillColor: Colors.white24, - labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), - filled: true, - border: OutlineInputBorder( - gapPadding: 2.0, - borderRadius: BorderRadius.circular(12.0), - borderSide: BorderSide(color: Colors.green[50], width: 0.4), - ), - ), - focusNode: _nodeText3, - initialValue: bloc.quantityUnit.toStringAsFixed(0), - keyboardType: TextInputType.numberWithOptions(decimal: true), - style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), - onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeQuantityUnit(quantity: double.parse(value)))}), - //]), + weightVisible + ? TextFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + labelText: t('Weight'), + fillColor: Colors.white24, + labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), + filled: true, + border: OutlineInputBorder( + gapPadding: 2.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + focusNode: _nodeText3, + initialValue: bloc.quantityUnit.toStringAsFixed(0), + keyboardType: TextInputType.numberWithOptions(decimal: true), + style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), + onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeQuantityUnit(quantity: double.parse(value)))}) + : Offstage(), Divider(), Text( - bloc.serie.toStringAsFixed(0) + - " x " + - bloc.quantity.toStringAsFixed(0) + - " x " + - bloc.quantityUnit.toStringAsFixed(0) + - " kg", + summary, style: TextStyle(fontSize: 24, fontWeight: FontWeight.normal, color: Colors.yellow[50]), ), Divider(), diff --git a/lib/view/exercise_plan_custom_page.dart b/lib/view/exercise_plan_custom_page.dart index 8ca19e7..d435fd1 100644 --- a/lib/view/exercise_plan_custom_page.dart +++ b/lib/view/exercise_plan_custom_page.dart @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; class ExercisePlanCustomPage extends StatefulWidget { @override @@ -51,8 +52,8 @@ class _ExercisePlanCustomPage extends State with Trans { decoration: BoxDecoration( image: DecorationImage( image: customerId == Cache().userLoggedIn.customerId - ? AssetImage('asset/image/WT_black_background.png') - : AssetImage('asset/image/WT_light_background.png'), + ? AssetImage('asset/image/WT_black_background.jpg') + : AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -65,17 +66,15 @@ class _ExercisePlanCustomPage extends State with Trans { ), backgroundColor: Colors.orange, )); - } else if (state is ExercisePlanLoading) { - //LoadingDialog.show(context); } - }, - // ignore: missing_return - builder: (context, state) { - if (state is ExercisePlanReady) { - //LoadingDialog.hide(context); - return exerciseWidget(bloc); - } - return Container(); + }, builder: (context, state) { + return ModalProgressHUD( + child: exerciseWidget(bloc), + inAsyncCall: state is ExercisePlanLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); })), bottomNavigationBar: BottomNavigator(bottomNavIndex: 2), ); @@ -138,6 +137,7 @@ class _ExercisePlanCustomPage extends State with Trans { List _getChildList(List listWorkoutTree, ExercisePlanBloc bloc) { List list = List(); listWorkoutTree.forEach((element) { + final String unitQuantityUnit = element.exerciseType.unitQuantityUnit != null ? element.exerciseType.unitQuantityUnit : ""; list.add(TreeViewChild( startExpanded: false, parent: Card( @@ -180,20 +180,11 @@ class _ExercisePlanCustomPage extends State with Trans { bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].repeats.toString() + " x " + bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].weightEquation + - " " + - element.exerciseType.unitQuantityUnit, + unitQuantityUnit, style: TextStyle(fontSize: 9, color: Colors.green), ), onTap: () => clickAddDetail(bloc, element), ), - /* IconButton( - padding: EdgeInsets.all(0), - icon: Icon( - Icons.info, - color: Colors.black12, - ), - onPressed: () {}, - ), */ ]), )), children: [])); diff --git a/lib/view/exercise_type_description.dart b/lib/view/exercise_type_description.dart index 02755c0..a07b76e 100644 --- a/lib/view/exercise_type_description.dart +++ b/lib/view/exercise_type_description.dart @@ -7,46 +7,43 @@ import 'package:flutter/material.dart'; class ExerciseTypeDescription extends StatelessWidget { @override Widget build(BuildContext context) { - final ExerciseRepository exerciseRepository = - ModalRoute.of(context).settings.arguments; + final ExerciseRepository exerciseRepository = ModalRoute.of(context).settings.arguments; String exerciseDescription = AppLanguage().appLocal == Locale("en") ? exerciseRepository.exerciseType.description : exerciseRepository.exerciseType.descriptionTranslation; - - String exerciseName = AppLanguage().appLocal == Locale("en") ? - exerciseRepository.exerciseType.name : - exerciseRepository.exerciseType.nameTranslation; + String exerciseName = + AppLanguage().appLocal == Locale("en") ? exerciseRepository.exerciseType.name : exerciseRepository.exerciseType.nameTranslation; return Scaffold( - appBar: AppBarMin(back: true,), + appBar: AppBarMin( + back: true, + ), body: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), - fit: BoxFit.fill, - alignment: Alignment.center, + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_light_background.jpg'), + fit: BoxFit.fill, + alignment: Alignment.center, + ), ), - ), - padding: EdgeInsets.only(left: 20, top: 20, right: 15), - child: ListView( - - children: [ - Text(exerciseName, - style: TextStyle(color: Colors.blueGrey, - fontSize: 20, fontWeight: FontWeight.bold), + padding: EdgeInsets.only(left: 20, top: 20, right: 15), + child: ListView(children: [ + Text( + exerciseName, + style: TextStyle(color: Colors.blueGrey, fontSize: 20, fontWeight: FontWeight.bold), + ), + Divider( + color: Colors.transparent, ), - Divider(color: Colors.transparent,), InkWell( - child: Text(exerciseDescription, - style: TextStyle(color: Colors.blueGrey, - fontSize: 18, fontWeight: FontWeight.normal),), + child: Text( + exerciseDescription, + style: TextStyle(color: Colors.blueGrey, fontSize: 18, fontWeight: FontWeight.normal), + ), ), - ] - ) - ) - ); + ]))); } } diff --git a/lib/view/login.dart b/lib/view/login.dart index cd4d7a7..bcaf4e8 100644 --- a/lib/view/login.dart +++ b/lib/view/login.dart @@ -56,7 +56,7 @@ class LoginPage extends StatelessWidget with Trans { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_login.png'), + image: AssetImage('asset/image/WT_login.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/menu_page.dart b/lib/view/menu_page.dart index 89f5a7f..074d3db 100644 --- a/lib/view/menu_page.dart +++ b/lib/view/menu_page.dart @@ -36,7 +36,7 @@ class _MenuPage extends State { body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_menu_dark.png'), + image: AssetImage('asset/image/WT_menu_dark.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), diff --git a/lib/view/mydevelopment_body_page.dart b/lib/view/mydevelopment_body_page.dart index 8bdc2cf..b186e80 100644 --- a/lib/view/mydevelopment_body_page.dart +++ b/lib/view/mydevelopment_body_page.dart @@ -4,7 +4,6 @@ import 'package:aitrainer_app/library/radar_chart.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart'; -import 'package:flurry/flurry.dart'; import 'package:flutter/scheduler.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/util/common.dart'; @@ -27,7 +26,6 @@ class _MyDevelopmentBodyPage extends State with Trans, Co @override void initState() { super.initState(); - Flurry.logEvent("myDevelopmentBody"); if (!Cache().hasPurchased || true) { Timer( Duration(milliseconds: 2000), @@ -69,8 +67,8 @@ class _MyDevelopmentBodyPage extends State with Trans, Co decoration: BoxDecoration( image: DecorationImage( image: customerId == Cache().userLoggedIn.customerId - ? AssetImage('asset/image/WT_light_background.png') - : AssetImage('asset/image/WT_menu_dark.png'), + ? AssetImage('asset/image/WT_light_background.jpg') + : AssetImage('asset/image/WT_menu_dark.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/mydevelopment_muscle_page.dart b/lib/view/mydevelopment_muscle_page.dart index 65dc5c2..e7aae14 100644 --- a/lib/view/mydevelopment_muscle_page.dart +++ b/lib/view/mydevelopment_muscle_page.dart @@ -11,7 +11,6 @@ import 'package:aitrainer_app/bloc/development_by_muscle/development_by_muscle_b import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/library/tree_view.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; -import 'package:flurry/flurry.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -32,7 +31,6 @@ class _MyDevelopmentMuscleState extends State with Comm @override void initState() { super.initState(); - Flurry.logEvent("myDevelopmentMuscle"); if (!Cache().hasPurchased) { Timer( Duration(milliseconds: 2000), @@ -71,7 +69,7 @@ class _MyDevelopmentMuscleState extends State with Comm padding: EdgeInsets.all(20), decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_menu_dark.png'), + image: AssetImage('asset/image/WT_menu_dark.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/mydevelopment_page.dart b/lib/view/mydevelopment_page.dart index e3fa85f..c1ad145 100644 --- a/lib/view/mydevelopment_page.dart +++ b/lib/view/mydevelopment_page.dart @@ -3,8 +3,9 @@ import 'dart:collection'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart'; -import 'package:flurry/flurry.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; @@ -34,7 +35,7 @@ class _MyDevelopmentPage extends State with Trans { padding: EdgeInsets.all(10), decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_menu_dark.png'), + image: AssetImage('asset/image/WT_menu_dark.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -68,8 +69,11 @@ class _MyDevelopmentPage extends State with Trans { image: "asset/image/testemfejl400x400.jpg", left: 5, onTap: () => { - args['customerId'] = Cache().userLoggedIn.customerId, - Navigator.of(context).pushNamed('mydevelopmentBodyPage', arguments: args) + if (Cache().userLoggedIn != null) + { + args['customerId'] = Cache().userLoggedIn.customerId, + Navigator.of(context).pushNamed('mydevelopmentBodyPage', arguments: args) + } }, isLocked: true, ), @@ -101,7 +105,7 @@ class _MyDevelopmentPage extends State with Trans { backgroundColor: Colors.black54.withOpacity(0.4))), image: "asset/image/predictions.jpg", onTap: () => { - Flurry.logEvent("Predictions"), + Track().track(TrackingEvent.prediction), showDialog( context: context, builder: (BuildContext context) { @@ -138,10 +142,13 @@ class _MyDevelopmentPage extends State with Trans { color: Colors.black12, focusColor: Colors.blueAccent, onPressed: () => { - args['exerciseRepository'] = exerciseRepository, - args['customerRepository'] = customerRepository, - args['customerId'] = Cache().getTrainee().customerId, - Navigator.of(context).pushNamed('exerciseLogPage', arguments: args) + if (Cache().getTrainee() != null) + { + args['exerciseRepository'] = exerciseRepository, + args['customerRepository'] = customerRepository, + args['customerId'] = Cache().getTrainee().customerId, + Navigator.of(context).pushNamed('exerciseLogPage', arguments: args) + }, }, child: Text( t("My Trainee's Exercise Logs"), @@ -153,10 +160,12 @@ class _MyDevelopmentPage extends State with Trans { } void callBackExerciseLog(ExerciseRepository exerciseRepository, CustomerRepository customerRepository) { - final LinkedHashMap args = LinkedHashMap(); - args['exerciseRepository'] = exerciseRepository; - args['customerRepository'] = customerRepository; - args['customerId'] = Cache().userLoggedIn.customerId; - Navigator.of(context).pushNamed('exerciseLogPage', arguments: args); + if (Cache().userLoggedIn != null) { + final LinkedHashMap args = LinkedHashMap(); + args['exerciseRepository'] = exerciseRepository; + args['customerRepository'] = customerRepository; + args['customerId'] = Cache().userLoggedIn.customerId; + Navigator.of(context).pushNamed('exerciseLogPage', arguments: args); + } } } diff --git a/lib/view/myexcercise_plan_page.dart b/lib/view/myexcercise_plan_page.dart index c0bde14..aa5e43c 100644 --- a/lib/view/myexcercise_plan_page.dart +++ b/lib/view/myexcercise_plan_page.dart @@ -2,12 +2,13 @@ import 'dart:collection'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart'; import 'package:aitrainer_app/widgets/image_button.dart'; -import 'package:flurry/flurry.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -33,7 +34,7 @@ class _MyExercisePlanPage extends State with Trans, Logging padding: EdgeInsets.all(10), decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_menu_dark.png'), + image: AssetImage('asset/image/WT_menu_dark.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -54,9 +55,12 @@ class _MyExercisePlanPage extends State with Trans, Logging image: "asset/image/exercise_plan_custom.jpg", left: 5, onTap: () => { - args['exerciseRepository'] = exerciseRepository, - args['customerId'] = Cache().userLoggedIn.customerId, - Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args) + if (Cache().userLoggedIn != null) + { + args['exerciseRepository'] = exerciseRepository, + args['customerId'] = Cache().userLoggedIn.customerId, + Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args) + } }, isLocked: false, ), @@ -74,8 +78,11 @@ class _MyExercisePlanPage extends State with Trans, Logging top: 130, left: 5, onTap: () => { - args['customerId'] = Cache().userLoggedIn.customerId, - Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) + if (Cache().userLoggedIn != null) + { + args['customerId'] = Cache().userLoggedIn.customerId, + Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) + } }, isLocked: false, ), @@ -92,7 +99,7 @@ class _MyExercisePlanPage extends State with Trans, Logging image: "asset/image/exercise_plan_suggested.jpg", left: 2, onTap: () => { - Flurry.logEvent("SuggestedTrainingPlan"), + Track().track(TrackingEvent.my_suggested_plan), showDialog( context: context, builder: (BuildContext context) { @@ -121,7 +128,7 @@ class _MyExercisePlanPage extends State with Trans, Logging image: "asset/image/exercise_plan_stars.jpg", left: 5, onTap: () => { - Flurry.logEvent("SpecialTraining Programs"), + Track().track(TrackingEvent.my_special_plan), showDialog( context: context, builder: (BuildContext context) { @@ -150,7 +157,7 @@ class _MyExercisePlanPage extends State with Trans, Logging image: "asset/image/exercise_plan_stars.jpg", left: 5, onTap: () => { - Flurry.logEvent("StarTrainingPlan"), + showDialog( context: context, builder: (BuildContext context) { @@ -189,9 +196,12 @@ class _MyExercisePlanPage extends State with Trans, Logging color: Colors.black12, focusColor: Colors.blueAccent, onPressed: () => { - args['exerciseRepository'] = exerciseRepository, - args['customerId'] = Cache().getTrainee().customerId, - Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args) + if (Cache().getTrainee() != null) + { + args['exerciseRepository'] = exerciseRepository, + args['customerId'] = Cache().getTrainee().customerId, + Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args) + } }, child: Text( t("My Trainee's Plan"), @@ -212,8 +222,11 @@ class _MyExercisePlanPage extends State with Trans, Logging color: Colors.black12, focusColor: Colors.blueAccent, onPressed: () => { - args['customerId'] = Cache().getTrainee().customerId, - Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) + if (Cache().getTrainee() != null) + { + args['customerId'] = Cache().getTrainee().customerId, + Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) + } }, child: Text( t("Execute My Trainee's Training Plan"), diff --git a/lib/view/registration.dart b/lib/view/registration.dart index e917440..44f4266 100644 --- a/lib/view/registration.dart +++ b/lib/view/registration.dart @@ -6,6 +6,7 @@ import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:aitrainer_app/widgets/dialog_common.dart'; import 'package:aitrainer_app/widgets/dialog_long.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -39,7 +40,21 @@ class RegistrationPage extends StatelessWidget with Trans { SnackBar(backgroundColor: Colors.orange, content: Text(message, style: TextStyle(color: Colors.white)))); } } else if (state is LoginSuccess) { - Navigator.of(context).pushNamed('customerModifyPage'); + //Navigator.of(context).pushNamed('customerModifyPage'); + showDialog( + context: context, + builder: (BuildContext context) { + return DialogCommon( + title: t("Successful Registration"), + descriptions: t("Now we would like to know you better to lift the experience of the app."), + description2: t("Please go through the pages, it will take couple of minutes!"), + text: "OK", + onTap: () => {Navigator.of(context).pushNamed('customerModifyPage')}, + onCancel: () => { + Navigator.of(context).pushNamed("home"), + }, + ); + }); } }, builder: (context, state) { final loginBloc = BlocProvider.of(context); @@ -61,7 +76,7 @@ class RegistrationPage extends StatelessWidget with Trans { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_login.png'), + image: AssetImage('asset/image/WT_login.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -109,16 +124,6 @@ class RegistrationPage extends StatelessWidget with Trans { ], ), ListTile(title: Text(t("OR"), style: GoogleFonts.inter())), - /* Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - InkWell( - child: Text(AppLocalizations.of(context).translate('SignUp with Email'), - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), - ), - ], - ), */ - TextFormField( key: LibraryKeys.loginEmailField, decoration: InputDecoration( diff --git a/lib/view/reset_password.dart b/lib/view/reset_password.dart index 6912bd4..a9ca47a 100644 --- a/lib/view/reset_password.dart +++ b/lib/view/reset_password.dart @@ -44,7 +44,7 @@ class ResetPasswordPage extends StatelessWidget with Trans { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_login.png'), + image: AssetImage('asset/image/WT_login.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/sales_page.dart b/lib/view/sales_page.dart index 1ad4cb4..22f9412 100644 --- a/lib/view/sales_page.dart +++ b/lib/view/sales_page.dart @@ -60,7 +60,7 @@ class SalesPage extends StatelessWidget with Trans, Logging { return Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/view/settings.dart b/lib/view/settings.dart index 2f16d90..c8a8f5d 100644 --- a/lib/view/settings.dart +++ b/lib/view/settings.dart @@ -29,7 +29,7 @@ class SettingsPage extends StatelessWidget with Trans { body: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), @@ -78,7 +78,7 @@ class SettingsPage extends StatelessWidget with Trans { } ListTile getServer(SettingsBloc settingsBloc) { - if (Cache().userLoggedIn.admin != 1) { + if (Cache().userLoggedIn == null || Cache().userLoggedIn.admin != 1) { return ListTile( title: Container(), ); diff --git a/lib/widgets/app_bar.dart b/lib/widgets/app_bar.dart index 9b06f27..bf01e90 100644 --- a/lib/widgets/app_bar.dart +++ b/lib/widgets/app_bar.dart @@ -5,7 +5,6 @@ import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/common.dart'; -import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/lib/widgets/app_bar_progress.dart b/lib/widgets/app_bar_progress.dart new file mode 100644 index 0000000..792f8f1 --- /dev/null +++ b/lib/widgets/app_bar_progress.dart @@ -0,0 +1,75 @@ +import 'package:aitrainer_app/util/common.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:liquid_progress_indicator/liquid_progress_indicator.dart'; + +class AppBarProgress extends StatefulWidget implements PreferredSizeWidget { + final int max; + final int min; + const AppBarProgress({this.max, this.min}); + + @override + _AppBarNav createState() => _AppBarNav(); + + @override + Size get preferredSize => const Size.fromHeight(50); +} + +class _AppBarNav extends State with SingleTickerProviderStateMixin, Common { + AnimationController _animationController; + + @override + void initState() { + _animationController = AnimationController( + lowerBound: (widget.min).toDouble(), + upperBound: (widget.max).toDouble(), + //upperBound: (widget.value / 100).toDouble(), + vsync: this, + duration: Duration(seconds: 3), + ); + + _animationController.addListener(() => setState(() {})); + _animationController.forward(); + //Future.delayed(Duration(seconds: 3)).then((value) => _animationController.repeat()); + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: Colors.black, + title: getAnimatedWidget(), + leading: IconButton( + icon: Icon(Icons.arrow_back, color: Colors.white), + onPressed: () => {Navigator.of(context).pop()}, + )); + } + + Widget getAnimatedWidget() { + final percentage = _animationController.value; + return Container( + width: double.infinity, + height: 35, + padding: EdgeInsets.symmetric(horizontal: 24.0), + child: LiquidLinearProgressIndicator( + value: _animationController.value / 100, + backgroundColor: Colors.black, + valueColor: AlwaysStoppedAnimation(Color(0xffb4f500)), + borderRadius: 12.0, + center: Text( + "${percentage.toStringAsFixed(0)}%", + style: TextStyle( + color: Colors.yellow[50], + fontSize: 20.0, + fontWeight: FontWeight.bold, + ), + ), + )); + } +} diff --git a/lib/widgets/bmi_widget.dart b/lib/widgets/bmi_widget.dart index 1ebd740..343e651 100644 --- a/lib/widgets/bmi_widget.dart +++ b/lib/widgets/bmi_widget.dart @@ -84,7 +84,7 @@ class _BMIState extends State with Trans { height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), @@ -141,7 +141,7 @@ class _BMIState extends State with Trans { Container( padding: EdgeInsets.only(left: 30, right: 30), child: Image.asset( - "asset/image/BMI_graph_c.png", + "asset/image/BMI_graph_C.png", ), ), Positioned( diff --git a/lib/widgets/bmr_widget.dart b/lib/widgets/bmr_widget.dart index 4054e04..9e2640d 100644 --- a/lib/widgets/bmr_widget.dart +++ b/lib/widgets/bmr_widget.dart @@ -99,7 +99,7 @@ class _BMRState extends State with Trans { height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart index bb4c540..279aca6 100644 --- a/lib/widgets/bottom_nav.dart +++ b/lib/widgets/bottom_nav.dart @@ -1,8 +1,10 @@ import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/common.dart'; +import 'package:aitrainer_app/util/enums.dart'; +import 'package:aitrainer_app/util/track.dart'; import 'package:aitrainer_app/util/trans.dart'; -import 'package:flurry/flurry.dart'; import 'package:flutter/material.dart'; import 'package:gradient_bottom_navigation_bar/gradient_bottom_navigation_bar.dart'; @@ -23,6 +25,19 @@ class _NawDrawerWidget extends State with Trans, Logging { super.initState(); } + @override + void didUpdateWidget(BottomNavigator oldWidget) { + Cache().initBadges(); + + super.didUpdateWidget(oldWidget); + } + + @override + void didChangeDependencies() { + Cache().initBadges(); + super.didChangeDependencies(); + } + @override Widget build(BuildContext context) { final Color bgrColor = Color(0xffb4f500); @@ -87,30 +102,30 @@ class _NawDrawerWidget extends State with Trans, Logging { switch (index) { case 0: Navigator.of(context).pop(); - Flurry.logEvent("Home"); + Track().track(TrackingEvent.home); Navigator.of(context).pushNamed('home'); break; case 1: Navigator.of(context).pop(); - Flurry.logEvent("myDevelopment"); + Track().track(TrackingEvent.my_development); Navigator.of(context).pushNamed('myDevelopment'); break; case 2: Navigator.of(context).pop(); - Flurry.logEvent("myExercisePlan"); + Track().track(TrackingEvent.my_exerciseplan); Navigator.of(context).pushNamed('myExercisePlan'); break; case 3: Navigator.of(context).pop(); - Flurry.logEvent("Account"); + Track().track(TrackingEvent.account); Navigator.of(context).pushNamed('account'); break; case 4: Navigator.of(context).pop(); - Flurry.logEvent("Settings"); + Track().track(TrackingEvent.settings); Navigator.of(context).pushNamed('settings'); break; diff --git a/lib/widgets/dialog_common.dart b/lib/widgets/dialog_common.dart index f5a6537..12f0077 100644 --- a/lib/widgets/dialog_common.dart +++ b/lib/widgets/dialog_common.dart @@ -49,7 +49,7 @@ class _DialogPremiumState extends State with Trans { borderRadius: BorderRadius.circular(24), boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)], image: DecorationImage( - image: AssetImage('asset/image/WT_black_G_background.png'), + image: AssetImage('asset/image/WT_black_G_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/widgets/dialog_long.dart b/lib/widgets/dialog_long.dart index dcfcee7..86c174c 100644 --- a/lib/widgets/dialog_long.dart +++ b/lib/widgets/dialog_long.dart @@ -360,7 +360,7 @@ class _DialogPremiumState extends State with Trans { borderRadius: BorderRadius.circular(24), boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)], image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), + image: AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/widgets/dialog_premium.dart b/lib/widgets/dialog_premium.dart index f841812..24a8249 100644 --- a/lib/widgets/dialog_premium.dart +++ b/lib/widgets/dialog_premium.dart @@ -72,7 +72,7 @@ class _DialogPremiumState extends State with Trans { borderRadius: BorderRadius.circular(24), boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)], image: DecorationImage( - image: AssetImage('asset/image/WT_black_G_background.png'), + image: AssetImage('asset/image/WT_black_G_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/widgets/home.dart b/lib/widgets/home.dart index eb2d225..83bfd9e 100644 --- a/lib/widgets/home.dart +++ b/lib/widgets/home.dart @@ -79,8 +79,9 @@ class _HomePageState extends State with Logging { return MenuPage(parent: 0); } } else { - log("else"); - return MenuPage(parent: 0); + log("home: unknown state"); + //return MenuPage(parent: 0); + return LoginPage(); } }), ); diff --git a/lib/widgets/image_button.dart b/lib/widgets/image_button.dart index 8da9af7..bfc9de2 100644 --- a/lib/widgets/image_button.dart +++ b/lib/widgets/image_button.dart @@ -58,7 +58,7 @@ class ImageButton extends StatelessWidget { return Stack(alignment: AlignmentDirectional.bottomStart, children: [ FlatButton( child: image == null - ? _getButtonImage("asset/image/WT_menu_dark.png") + ? _getButtonImage("asset/image/WT_menu_dark.jpg") : isMarked ? Stack( children: [ @@ -103,31 +103,39 @@ class ImageButton extends StatelessWidget { ], )), )), - Cache().hasPurchased + isMarked == null || Cache().hasPurchased + ? Offstage() + : Stack(alignment: Alignment.topCenter, children: [ + Positioned( + top: 10, + left: (width / 2 - 30) / 2 - 75, + child: !isLocked + ? Offstage() + : GestureDetector( + child: Image.asset( + 'asset/image/lock.png', + height: 150, + width: 150, + ), + onTap: onTap ?? onTap, + )) + ]), + isLocked == null ? Offstage() : Stack(alignment: Alignment.topCenter, children: [ Positioned( top: 10, left: (width / 2 - 30) / 2 - 75, - child: this.isLocked + child: isMarked ? GestureDetector( child: Image.asset( - 'asset/image/lock.png', - height: 150, - width: 150, + 'asset/image/haken.png', + height: 70, + width: 70, ), onTap: onTap ?? onTap, ) - : isMarked - ? GestureDetector( - child: Image.asset( - 'asset/image/haken.png', - height: 70, - width: 70, - ), - onTap: onTap ?? onTap, - ) - : Container(), + : Offstage(), ) ]), ] diff --git a/lib/widgets/loading.dart b/lib/widgets/loading.dart index 08139a3..6f47e22 100644 --- a/lib/widgets/loading.dart +++ b/lib/widgets/loading.dart @@ -6,7 +6,7 @@ class LoadingScreenMain extends StatelessWidget { @override Widget build(BuildContext context) { final Image _backgroundImage = Image.asset( - 'asset/image/WT01_loading_layers.png', + 'asset/image/WT_loading_layers.jpg', fit: BoxFit.cover, height: double.infinity, width: double.infinity, diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index 03b2239..4365124 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -142,19 +142,23 @@ class _MenuPageWidgetState extends State with Trans, Logging { ]))))); }); } + /* LiveSliverList sliverList = LiveSliverList( + // And attach root sliver scrollController to widgets + controller: scrollController, + + itemCount: _columnChildren.length, + reAnimateOnVisibility: false, + showItemDuration: Duration(milliseconds: 100), + itemBuilder: (BuildContext context, int index, Animation animation) => FadeTransition( + opacity: animation, + child: _columnChildren[index], + ), + */ //delegate: SliverChildListDelegate(_columnChildren), + SliverList sliverList = SliverList( - //itemCount: _columnChildren.length, - //reAnimateOnVisibility: false, - //showItemDuration: Duration(milliseconds: 150), - //itemBuilder: (BuildContext context, int index, Animation animation) => FadeTransition( - // opacity: animation, - // child: _columnChildren[index], - //), - //controller: scrollController, delegate: SliverChildListDelegate(_columnChildren), ); - slivers.add(sliverList); return slivers; } @@ -377,11 +381,12 @@ class _MenuPageWidgetState extends State with Trans, Logging { borderRadius: BorderRadius.circular(24.0), child: Container( color: Colors.transparent, - child: FadeInImage( - fadeInDuration: Duration(milliseconds: 200), + child: Image.asset(workoutTree.imageName), + /* FadeInImage( + fadeInDuration: Duration(milliseconds: 50), image: AssetImage(workoutTree.imageName), placeholder: MemoryImage(kTransparentImage), - ), + ), */ )); } } diff --git a/lib/widgets/number_picker.dart b/lib/widgets/number_picker.dart index 831159e..1758381 100644 --- a/lib/widgets/number_picker.dart +++ b/lib/widgets/number_picker.dart @@ -2,6 +2,7 @@ import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +// ignore: must_be_immutable class NumberPickerWidget extends StatefulWidget { final Function(double) onChange; final int minValue; @@ -9,18 +10,35 @@ class NumberPickerWidget extends StatefulWidget { final int initalValue; final String unit; final Color color; + double fontSize; - const NumberPickerWidget({Key key, this.minValue, this.maxValue, this.initalValue, this.unit, this.color, this.onChange}) - : super(key: key); + NumberPickerWidget({Key key, this.minValue, this.maxValue, this.initalValue, this.unit, this.fontSize, this.color, this.onChange}) + : super(key: key) { + fontSize = fontSize ?? 20; + } @override _NumberPickerWidgetState createState() => _NumberPickerWidgetState(); } class _NumberPickerWidgetState extends State with Trans { + FixedExtentScrollController _scrollController; + + @override + void initState() { + super.initState(); + _scrollController = FixedExtentScrollController(initialItem: widget.initalValue); + } + + @override + void didUpdateWidget(NumberPickerWidget oldWidget) { + super.didUpdateWidget(oldWidget); + _scrollController.animateToItem(widget.initalValue, duration: Duration(milliseconds: 100), curve: Curves.easeIn); + } + Widget durationPicker({bool inSeconds = false, bool inHundredths = false}) { double value = 0; return CupertinoPicker( - scrollController: FixedExtentScrollController(initialItem: widget.initalValue), + scrollController: _scrollController, backgroundColor: Colors.transparent, onSelectedItemChanged: (x) { currentData = x.toDouble(); @@ -29,7 +47,8 @@ class _NumberPickerWidgetState extends State with Trans { setState(() {}); widget.onChange(value); }, - children: List.generate(widget.maxValue, (index) => Text('$index ' + widget.unit, style: TextStyle(color: widget.color))), + children: List.generate( + widget.maxValue, (index) => Text('$index ' + widget.unit, style: TextStyle(color: widget.color, fontSize: widget.fontSize))), itemExtent: 40, ); } @@ -40,16 +59,16 @@ class _NumberPickerWidgetState extends State with Trans { setContext(context); return Container( //color: Colors.white24, - width: MediaQuery.of(context).size.width * .45, + width: MediaQuery.of(context).size.width * .40, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 5.0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( color: Colors.transparent, - width: MediaQuery.of(context).size.width * .3, + width: MediaQuery.of(context).size.width * .35, child: Center( child: Container( color: Colors.transparent, diff --git a/lib/widgets/sales_button.dart b/lib/widgets/sales_button.dart index 722cd6b..6642f38 100644 --- a/lib/widgets/sales_button.dart +++ b/lib/widgets/sales_button.dart @@ -41,7 +41,7 @@ class SalesButton extends StatelessWidget { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_sales_background_3x5.png'), + image: AssetImage('asset/image/WT_sales_background_3x5.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), diff --git a/lib/widgets/size_widget.dart b/lib/widgets/size_widget.dart index 1567cf7..1828149 100644 --- a/lib/widgets/size_widget.dart +++ b/lib/widgets/size_widget.dart @@ -32,7 +32,7 @@ class _SizeState extends State with Trans { height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), + image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), diff --git a/pubspec.lock b/pubspec.lock index b82c789..9e72d93 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -623,6 +623,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.3.1+1" + liquid_progress_indicator: + dependency: "direct main" + description: + name: liquid_progress_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.2" logging: dependency: transitive description: @@ -707,6 +714,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.3" + package_info: + dependency: "direct main" + description: + name: package_info + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.3+4" path: dependency: transitive description: @@ -839,7 +853,7 @@ packages: name: purchases_flutter url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" quiver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 70e8f20..816ae1c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.1.5+54 +version: 1.1.6+55 environment: sdk: ">=2.7.0 <3.0.0" @@ -44,13 +44,15 @@ dependencies: badges: ^1.1.4 #health: ^3.0.0 stop_watch_timer: ^0.6.0+1 - #geolocator: ^6.1.13 + #location: ^3.2.4 modal_progress_hud: ^0.1.3 flutter_html: ^1.1.1 wakelock: ^0.2.1+1 timeline_tile: ^1.0.0 - purchases_flutter: ^2.0.0 + purchases_flutter: ^2.0.3 network_image_to_byte: ^0.0.1 + package_info: ^0.4.3+4 + liquid_progress_indicator: ^0.3.2 firebase_core: ^0.5.0 @@ -62,7 +64,6 @@ dependencies: apple_sign_in: ^0.1.0 crypto: ^2.1.5 transparent_image: ^1.0.0 - #flutter_fadein: ^1.1.1 #auto_animated: ^2.1.0 flurry: ^0.0.7 @@ -125,30 +126,31 @@ flutter: - asset/icon/gomb_zold_b-1.png - asset/icon/gomb_zold_a.png - asset/icon/gomb_sarga_a.png - - asset/image/WT_menu_welcome.png - - asset/image/WT01_loading_layers.png - - asset/image/WT_menu_backround.png - - asset/image/WT_black_background.png - - asset/image/WT_black_G_background.png - - asset/image/WT_plainblack_background.png - - asset/image/WT_login.png - - asset/image/dots.gif + + - asset/image/WT_loading_layers.jpg + - asset/image/WT_menu_backround.jpg + - asset/image/WT_black_background.jpg + - asset/image/WT_black_G_background.jpg + - asset/image/WT_plainblack_background.jpg + - asset/image/WT_login.jpg - asset/image/WT_long_logo.png - - asset/image/WT_light_background.png - - asset/image/WT_sales_background.png - - asset/image/WT_sales_background_3x5.png - - asset/image/WT_menu_dark.png - - asset/image/Gain_muscle.png - - asset/image/WT_weight_loss.png - - asset/image/WT_welcome.png - - asset/image/WT_Results_for_runners.png - - asset/image/WT_Results_for_female.png - - asset/image/WT_Results_for_men.png + - asset/image/WT_light_background.jpg + - asset/image/WT_sales_background.jpg + - asset/image/WT_sales_background_3x5.jpg + - asset/image/WT_menu_dark.jpg + - asset/image/Gain_muscle.jpg + - asset/image/WT_weight_loss.jpg + - asset/image/WT_welcome.jpg + - asset/image/WT_Results_for_runners.jpg + - asset/image/WT_Results_for_female.jpg + - asset/image/WT_Results_for_men.jpg - asset/image/WT_results_background.jpg + - asset/image/button_fb.png - asset/image/button_apple.png - asset/image/button_google.png - asset/image/lock.png + - asset/image/add_test.png - asset/image/testemfejl400x400.jpg - asset/image/izomcsop400400.jpg - asset/image/edzesnaplom400400.jpg @@ -161,34 +163,10 @@ flutter: - asset/image/man_sizes.png - asset/image/woman_sizes.png - asset/image/merleg.png - - asset/image/BMI_graph_c.png + - asset/image/BMI_graph_C.png - asset/image/BMI_mutato.png - - asset/image/equipment_specialshome.jpg - - asset/image/equipment_none.jpg - - asset/image/equipment_cables.jpg - - asset/image/equipment_weightplates.jpg - - asset/image/equipment_kettlebells.jpg - - asset/image/equipment_bands.jpg - - asset/image/equipment_ez-baar_.jpg - - asset/image/equipment_exerciseball.jpg - - asset/image/equipment_strap.jpg - - asset/image/equipment_roll.jpg - - asset/image/equipment_instabils.jpg - - asset/image/equipment_medicine.jpg - - asset/image/equipment_rope.jpg - - asset/image/equipment_home.jpg - - asset/image/equipment_baar.jpg - - asset/image/equipment_others.jpg - - asset/image/equipment_barbells.jpg - - asset/image/equipment_machine.jpg - - asset/image/equipment_street.jpg - - asset/image/equipment_dumbbells.jpg - - asset/image/equipment_home_place.jpg - - asset/image/equipment_gym_place.jpg - - asset/image/equipment_street_place.jpg - - asset/image/ankle_weight.png - - asset/image/vest_weight.png - asset/image/haken.png + - asset/image/pict_calorie.png - asset/image/pict_development_by_bodypart_percent.png - asset/image/pict_distance_m.png @@ -201,7 +179,33 @@ flutter: - asset/image/pict_steps.png - asset/image/pict_time_h.png - asset/image/pict_hypertrophy.png - - asset/image/pict_weight_volumen_tonna.png + - asset/image/pict_weight_volumen_tonna.png + + - asset/equipment/equipment_specialshome.jpg + - asset/equipment/equipment_none.jpg + - asset/equipment/equipment_cables.jpg + - asset/equipment/equipment_weightplates.jpg + - asset/equipment/equipment_kettlebells.jpg + - asset/equipment/equipment_bands.jpg + - asset/equipment/equipment_ez-baar_.jpg + - asset/equipment/equipment_exerciseball.jpg + - asset/equipment/equipment_strap.jpg + - asset/equipment/equipment_roll.jpg + - asset/equipment/equipment_instabils.jpg + - asset/equipment/equipment_medicine.jpg + - asset/equipment/equipment_rope.jpg + - asset/equipment/equipment_home.jpg + - asset/equipment/equipment_baar.jpg + - asset/equipment/equipment_others.jpg + - asset/equipment/equipment_barbells.jpg + - asset/equipment/equipment_machine.jpg + - asset/equipment/equipment_street.jpg + - asset/equipment/equipment_dumbbells.jpg + - asset/equipment/equipment_home_place.jpg + - asset/equipment/equipment_gym_place.jpg + - asset/equipment/equipment_street_place.jpg + - asset/equipment/equipment_ankle_weight.jpg + - asset/equipment/equipment_vest_weight.jpg - asset/menu/1.cardio.jpg - asset/menu/1.1.aerob.jpg @@ -218,6 +222,125 @@ flutter: - asset/menu/2.2.1.7.back.jpg - asset/menu/2.2.1.8.calf.jpg - asset/menu/3.bcs1.jpg + - asset/menu/300m.jpg + - asset/menu/400m.jpg + - asset/menu/alternate_dumbbell_presses.jpg + - asset/menu/alternate_standing_shoulder_press.jpg + - asset/menu/arnold_press.jpg + - asset/menu/bar_scott.jpg + - asset/menu/barbell_upright_row.jpg + - asset/menu/behind_the_neck_lat_pulldown.jpg + - asset/menu/behind_the_neck_presses.jpg + - asset/menu/bent_arm_barbell_pullovers.jpg + - asset/menu/bent_knee_situps.jpg + - asset/menu/bent_over_lateral_raises_with_dumbbells.jpg + - asset/menu/biceps_machine.jpg + - asset/menu/bmi.jpg + - asset/menu/bmr.jpg + - asset/menu/cable_crosses.jpg + - asset/menu/cable_flyes.jpg + - asset/menu/cable_rows.jpg + - asset/menu/chair_leg_raises.jpg + - asset/menu/chest_press_machine.jpg + - asset/menu/chest_press.jpg + - asset/menu/chins.jpg + - asset/menu/close_grip_front_lat_pulldown.jpg + - asset/menu/close_grip_pull_ups.jpg + - asset/menu/concentration.jpg + - asset/menu/cooper.jpg + - asset/menu/crisscross.jpg + - asset/menu/cross_bench_dumbbell_pullover.jpg + - asset/menu/deadlift.jpg + - asset/menu/decline_dumbbell_bench_press.jpg + - asset/menu/decline_cable_flyes.jpg + - asset/menu/donkey_calf_raises.jpg + - asset/menu/dumbbell_alternate_bicep_curl.jpg + - asset/menu/dumbell_bench_presses.jpg + - asset/menu/ez_bar_burl.jpg + - asset/menu/flyes.jpg + - asset/menu/forward_raise.jpg + - asset/menu/front_rear_lat_pulldown.jpg + - asset/menu/front_squat.jpg + - asset/menu/hack_squat.jpg + - asset/menu/hammer_curl.jpg + - asset/menu/hanging_leg_raises.jpg + - asset/menu/head-on-bench_dumbbell_rear_delt_raise.jpg + - asset/menu/hyperextension.jpg + - asset/menu/incline_cable_flyes.jpg + - asset/menu/incline_curl_with_dumbbels.jpg + - asset/menu/incline_dumbbell_press.jpg + - asset/menu/incline_flyes.jpg + - asset/menu/incline_press.jpg + - asset/menu/incline_triceps_extension.jpg + - asset/menu/leg_curls.jpg + - asset/menu/leg_extension.jpg + - asset/menu/legpress.jpg + - asset/menu/lunges_with_dumbbells.jpg + - asset/menu/lunges.jpg + - asset/menu/lying_alternating_leg_raises.jpg + - asset/menu/lying_biceps_cable_curl.jpg + - asset/menu/lying_curls.jpg + - asset/menu/lying_leg_raises.jpg + - asset/menu/lying_rear_delt_raise.jpg + - asset/menu/lying_scissors.jpg + - asset/menu/lying_triceps_extension.jpg + - asset/menu/machine_shoulder_press.jpg + - asset/menu/oblique_crunch.jpg + - asset/menu/olympic_squat.jpg + - asset/menu/one_arm_row.jpg + - asset/menu/overhead_dumbbell_triceps_extension.jpg + - asset/menu/peck_deck_flyes.jpg + - asset/menu/plank.jpg + - asset/menu/pull_up.jpg + - asset/menu/pullups.jpg + - asset/menu/pushups.jpg + - asset/menu/reverse_crunches.jpg + - asset/menu/roman_chair_situps.jpg + - asset/menu/russian_twist.jpg + - asset/menu/seated_bar_twist.jpg + - asset/menu/seated_dumbbell_curl.jpg + - asset/menu/seated_dumbbell_shoulder_press.jpg + - asset/menu/seated_lateral_raises.jpg + - asset/menu/seated_triceps_extension.jpg + - asset/menu/shrugs.jpg + - asset/menu/side_to_side_chop.jpg + - asset/menu/single_arm_bent_over_cable_reverse_fly.jpg + - asset/menu/single_arm_t-bar_rows.jpg + - asset/menu/single_hand_lateral_raises.jpg + - asset/menu/single_hand_lying_triceps_Extension.jpg + - asset/menu/sitting_knee_ups.jpg + - asset/menu/sitting_machine_calf_raises.jpg + - asset/menu/situps.jpg + - asset/menu/sizes.jpg + - asset/menu/smith_machine_chest_press.jpg + - asset/menu/squat_jump_weight.jpg + - asset/menu/squat_jump.jpg + - asset/menu/squat_without_weight.jpg + - asset/menu/squat.jpg + - asset/menu/standing_barbell_curl.jpg + - asset/menu/standing_biceps_cable_curl.jpg + - asset/menu/standing_cable_triceps_extension.jpg + - asset/menu/standing_face_pull.jpg + - asset/menu/standing_leg_curls.jpg + - asset/menu/standing_military_presses.jpg + - asset/menu/standing_one_arm_cable_curl.jpg + - asset/menu/standing_side_cable_laterals.jpg + - asset/menu/standing_single_arm_lateral_raises.jpg + - asset/menu/standing_triceps_extension.jpg + - asset/menu/stiff_legged_deadlift.jpg + - asset/menu/straight-arm_rope_pull-down.jpg + - asset/menu/t_bar_rows.jpg + - asset/menu/thigh_adductor.jpg + - asset/menu/triceps_extension_on_cable_with_rope.jpg + - asset/menu/triceps_kickback.jpg + - asset/menu/triceps_pushdown.jpg + - asset/menu/twisted_crunches.jpg + - asset/menu/v_ups.jpg + - asset/menu/wall_sit.jpg + - asset/menu/weighted_bench_dip.jpg + - asset/menu/wide_grip_behind_the_neck_pull_ups.jpg + - asset/menu/wide_grip_front_lat_pulldown.jpg + - i18n/en.json - i18n/hu.json diff --git a/test/account_bloc_test.dart b/test/account_bloc_test.dart index 7cfb618..60268ab 100644 --- a/test/account_bloc_test.dart +++ b/test/account_bloc_test.dart @@ -4,9 +4,7 @@ import 'package:mockito/mockito.dart'; import 'package:test/test.dart' as test; import 'package:flutter_test/flutter_test.dart'; -class MockCustomerRepository extends Mock implements CustomerRepository { - -} +class MockCustomerRepository extends Mock implements CustomerRepository {} void main() { MockCustomerRepository customerRepository; @@ -16,7 +14,7 @@ void main() { test.setUp(() { customerRepository = MockCustomerRepository(); - accountBloc = AccountBloc(customerRepository: customerRepository); + accountBloc = AccountBloc(customerRepository: customerRepository); }); test.tearDown(() { @@ -28,52 +26,48 @@ void main() { }); group('Account', () { - test.test( - 'emits [loading, logged in] when the customer clicked login', - () { - final expectedResponse = [ - AccountLoading(), - AccountLoggedIn(), - ]; + test.test('emits [loading, logged in] when the customer clicked login', () { + final expectedResponse = [ + AccountLoading(), + AccountLoggedIn(), + ]; - //verify(accountBloc.customerRepository.customer == null); + //verify(accountBloc.customerRepository.customer == null); - expectLater( - accountBloc, emitsInOrder(expectedResponse), - ); + expectLater( + accountBloc, + emitsInOrder(expectedResponse), + ); - accountBloc.add(AccountLogin()); - }); + accountBloc.add(AccountLogin()); + }); }); - test.test( - 'emits [loading, logged out] when the customer clicked logout', - () { - final expectedResponse = [ - AccountLoading(), - AccountLoggedOut(), - ]; + test.test('emits [loading, logged out] when the customer clicked logout', () { + final expectedResponse = [ + AccountLoading(), + AccountLoggedOut(), + ]; - expectLater( - accountBloc, emitsInOrder(expectedResponse), - ); + expectLater( + accountBloc, + emitsInOrder(expectedResponse), + ); - accountBloc.add(AccountLogout()); - }); + accountBloc.add(AccountLogout()); + }); - test.test( - 'emits [loading, logged out] when the customer data changed', - () { - final expectedResponse = [ - AccountLoading(), - AccountReady(), - ]; + test.test('emits [loading, logged out] when the customer data changed', () { + final expectedResponse = [ + AccountLoading(), + AccountReady(), + ]; - expectLater( - accountBloc, emitsInOrder(expectedResponse), - ); - - accountBloc.add(AccountChangeCustomer()); - }); + expectLater( + accountBloc, + emitsInOrder(expectedResponse), + ); + accountBloc.add(AccountChangeCustomer()); + }); } diff --git a/test/body_type_bloc_test.dart b/test/body_type_bloc_test.dart new file mode 100644 index 0000000..6fb7051 --- /dev/null +++ b/test/body_type_bloc_test.dart @@ -0,0 +1,63 @@ +import 'package:aitrainer_app/bloc/body_type/bodytype_bloc.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart' as test; +import 'package:flutter_test/flutter_test.dart'; + +class MockCustomerRepository extends Mock implements CustomerRepository {} + +void main() { + BodytypeBloc bloc; + + TestWidgetsFlutterBinding.ensureInitialized(); + + test.setUp(() { + bloc = BodytypeBloc(); + }); + + test.tearDown(() { + bloc.close(); + }); + + test.test('initial state is correct', () { + expect(bloc.state, BodytypeInitial()); + }); + + group('getValueByWeight', () { + test.test('check differnt weights and answers', () { + List weights = [0, 3, 7]; + List answers = [1, 2, 3, 4, 5]; + + expect(bloc.getValueByWeight(weights[0], answers[4]), 0); + expect(bloc.getValueByWeight(weights[0], answers[3]), 1); + expect(bloc.getValueByWeight(weights[0], answers[2]), 3); + expect(bloc.getValueByWeight(weights[0], answers[1]), 5); + expect(bloc.getValueByWeight(weights[0], answers[0]), 7); + + expect(bloc.getValueByWeight(weights[1], answers[4]), 3); + expect(bloc.getValueByWeight(weights[1], answers[3]), 4); + expect(bloc.getValueByWeight(weights[1], answers[2]), 6); + expect(bloc.getValueByWeight(weights[1], answers[1]), 4); + expect(bloc.getValueByWeight(weights[1], answers[0]), 3); + + expect(bloc.getValueByWeight(weights[2], answers[4]), 7); + expect(bloc.getValueByWeight(weights[2], answers[3]), 5); + expect(bloc.getValueByWeight(weights[2], answers[2]), 3); + expect(bloc.getValueByWeight(weights[2], answers[1]), 1); + expect(bloc.getValueByWeight(weights[2], answers[0]), 0); + + List weights2 = [5, 5, 0]; + expect(bloc.getValueByWeight(weights2[0], answers[4]), 5); + expect(bloc.getValueByWeight(weights2[0], answers[3]), 4); + expect(bloc.getValueByWeight(weights2[0], answers[2]), 3); + expect(bloc.getValueByWeight(weights2[0], answers[1]), 2); + expect(bloc.getValueByWeight(weights2[0], answers[0]), 1); + + expect(bloc.getValueByWeight(weights2[2], answers[4]), 0); + expect(bloc.getValueByWeight(weights2[2], answers[3]), 1); + expect(bloc.getValueByWeight(weights2[2], answers[2]), 3); + expect(bloc.getValueByWeight(weights2[2], answers[1]), 5); + expect(bloc.getValueByWeight(weights2[2], answers[0]), 7); + }); + }); +}