diff --git a/README.md b/README.md index 16bc94f..fd96672 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,5 @@ The WorkoutTest Mobile Application -Prototye 1.1.2f +live 1.1.3 diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..e008bbb 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png index d2eafe9..96542d7 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..e2fc904 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png index 0469334..599b77d 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..723aea0 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png index f52be7d..c0b36cb 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..74b9c8d 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png index da7894f..355ce67 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..2ed2b14 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png index f3cf9c2..98a3a0c 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png and b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/asset/data/menu_live.sql b/asset/data/menu_live.sql new file mode 100644 index 0000000..10cd507 --- /dev/null +++ b/asset/data/menu_live.sql @@ -0,0 +1,1432 @@ + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+02:00"; + +DELETE FROM `exercise_device`; +INSERT INTO `exercise_device` (`exercise_device_id`, `name`, `description`, `image_url`, `sort`, `place`) VALUES +(1, 'Dumbbells', '', 'images/equipment_dumbbells.jpg', 5, 0), +(2, 'Calisthenics', '', 'images/equipment_street.jpg', 20, 0), +(3, 'Gym Machine', '', 'images/equipment_machine.jpg', 4, 0), +(4, 'Barbell', '', 'images/equipment_barbells.jpg', 6, 0), +(5, 'Others', '', 'images/equipment_others.jpg', 21, 0), +(6, 'Baar', '', 'images/equipment_baar.jpg', 13, 0), +(7, 'Home', '', 'images/equipment_home.jpg', 17, 0), +(8, 'Rope', '', 'images/equipment_rope.jpg', 14, 0), +(9, 'Medicineball', '', 'images/equipment_medicine.jpg', 15, 0), +(10, 'Instabils', '', 'images/equipment_instabils.jpg', 16, 0), +(11, 'Roll', '', 'images/equipment_roll.jpg', 9, 0), +(12, 'Strap', '', 'images/equipment_strap.jpg', 10, 0), +(13, 'Exercise ball', '', 'images/equipment_exerciseball.jpg', 8, 0), +(14, 'EZ-baar', '', 'images/equipment_ez-baar_.jpg', 7, 0), +(15, 'Bands', '', 'images/equipment_bands.jpg', 11, 0), +(16, 'Kettlebell', '', 'images/equipment_kettlebells.jpg', 12, 0), +(17, 'Weight Plate', '', 'images/equipment_weightplates.jpg', 8, 0), +(18, 'Cable', '', 'images/equipment_cables.jpg', 7, 0), +(19, 'None', '', 'images/equipment_none.jpg', 18, 0), +(20, 'Specials for home', '', 'images/equipment_specialshome.jpg', 19, 0), +(21, 'HOME', 'Helyszín', 'images/equipment_home_place.jpg', 1, 1), +(22, 'STREET', '', 'images/equipment_street_place.jpg', 3, 1), +(23, 'GYM', '', 'images/equipment_gym_place.jpg', 2, 1), +(24, 'Ankle Weight', '', 'images/_ankle_weight.JPG', 20, 0), +(25, 'Weighted Vest', '', 'images/_weighted_vest.JPG', 21, 0); + +DELETE FROM `exercise_device_translation`; +INSERT INTO `exercise_device_translation` (`translation_id`, `exercise_device_id`, `language_code`, `name`) VALUES +(1, 1, 'hu', 'Kézisúlyzó'), +(2, 2, 'hu', 'Saját testsúly'), +(3, 3, 'hu', 'Edzőtermi gép'), +(4, 4, 'hu', 'Súlyzó (kétkezes)'), +(5, 5, 'hu', 'Egyebek'), +(6, 6, 'hu', 'Cső'), +(7, 7, 'hu', 'Otthon'), +(8, 8, 'hu', 'Ugrókötél'), +(9, 9, 'hu', 'Medicinlabda'), +(10, 10, 'hu', 'Instabil eszközök'), +(11, 11, 'hu', 'Henger'), +(12, 12, 'hu', 'Edzőheveder'), +(13, 13, 'hu', 'Fitnesz labda'), +(14, 14, 'hu', 'Franciarúd'), +(15, 15, 'hu', 'Szalag'), +(16, 16, 'hu', 'Kettlebell'), +(17, 17, 'hu', 'Tárcsa'), +(18, 18, 'hu', 'Kábeles gépek'), +(19, 19, 'hu', 'Nincs kiegészítő'), +(20, 20, 'hu', 'Otthoni spec. kiegészítők'), +(21, 21, 'hu', 'OTTHON'), +(22, 22, 'hu', 'STREET'), +(23, 23, 'hu', 'Edzőterem'), +(24, 24, 'hu', 'Bokasúly'), +(25, 25, 'hu', 'Súlymellény'); + +DELETE FROM `exercise_tree`; +INSERT INTO `exercise_tree` (`tree_id`, `parent_id`, `name`, `image_url`, `active`) VALUES +(3, 0, 'Cardio', 'images/1.cardio.png', 1), +(4, 0, 'Strength', 'images/2.strength.png', 1), +(5, 0, 'Body Compositions', 'images/3.bcs1.png', 1), +(7, 3, 'Aerob', 'images/1.1.aerob.png', 1), +(8, 3, 'Anaerob', 'images/1.2.anaerob.png', 1), +(9, 4, 'One Rep Max', 'images/2.2.1.1RM.png', 1), +(10, 4, 'Endurance', 'images/2.1.endurance.png', 1), +(11, 5, 'BMI', 'images/3.1.BMI.png', 0), +(12, 5, 'BMR', 'images/3.2.BMR.png', 0), +(13, 5, 'Sizes', 'images/3.3.sizes.png', 0), +(14, 9, 'Chest', 'images/2.2.1.1.chestpress.png', 1), +(15, 9, 'Biceps', 'images/2.2.1.3.biceps.png', 1), +(16, 9, 'Triceps', 'images/2.2.1.4.triceps.png', 1), +(17, 9, 'Shoulders', 'images/2.2.1.5.shoulders.png', 1), +(18, 9, 'Thigh', 'images/squat.jpg', 1), +(19, 9, 'Calf', 'images/calf.png', 1), +(20, 9, 'Back', 'images/Back_pullup.png', 1), +(21, 9, 'Core', 'images/2.1.6.core.png', 1), +(22, 0, 'Home', 'images/oko_haztartas2.png', 0), +(23, 3, 'VO2max test', 'images/1.2.VO22max.png', 1); + +DELETE FROM `exercise_tree_parents`; +INSERT INTO `exercise_tree_parents` (`exercise_tree_parents_id`, `exercise_tree_parent_id`, `exercise_tree_child_id`) VALUES +(1, 0, 3), +(2, 0, 4), +(3, 0, 5), +(4, 22, 22), +(5, 3, 7), +(6, 3, 8), +(7, 4, 9), +(8, 4, 10), +(9, 5, 11), +(10, 5, 12), +(11, 5, 13), +(12, 9, 14), +(13, 9, 15), +(14, 9, 16), +(15, 9, 17), +(16, 9, 18), +(17, 9, 19), +(18, 9, 20), +(19, 9, 21), +(32, 10, 21), +(33, 10, 20), +(34, 10, 19), +(35, 10, 18), +(36, 10, 17), +(37, 10, 16), +(38, 10, 15), +(39, 10, 14), +(40, 3, 23); + +DELETE FROM `exercise_tree_translation`; +INSERT INTO `exercise_tree_translation` (`translation_id`, `tree_id`, `language_code`, `name`) VALUES +(1, 3, 'hu', 'Kardió'), +(2, 4, 'hu', 'Erő'), +(4, 7, 'hu', 'Aerob'), +(5, 8, 'hu', 'Anaerob'), +(6, 9, 'hu', 'Max Erő'), +(7, 10, 'hu', 'Erőállóképesség'), +(8, 11, 'hu', 'Testtömegindex'), +(9, 12, 'hu', 'Anyagcsere'), +(10, 13, 'hu', 'Méretek'), +(11, 14, 'hu', 'Mellizom'), +(12, 15, 'hu', 'Bicepsz'), +(13, 16, 'hu', 'Tricepsz'), +(14, 17, 'hu', 'Vállak'), +(15, 18, 'hu', 'Comb'), +(16, 19, 'hu', 'Vádli'), +(17, 20, 'hu', 'Hát'), +(18, 21, 'hu', 'Core (Törzs-has)'), +(19, 22, 'hu', 'Otthoni gyakorlatok'), +(20, 23, 'hu', 'VO2max teszt'); + +DELETE FROM `exercise_type`; +INSERT INTO `exercise_type` (`exercise_type_id`, `tree_id`, `name`, `description`, `unit`, `unit_quantity`, `unit_quantity_unit`, `active`, `base`) VALUES +(1, 0, 'Melső fekvőtámasz 1 perc', 'Ezt igazolja a 2016 márciusában beállított guinness rekord is,\r\namelyben KJ Joseph 1 perc alatt 82 szabályos karhajlítás-nyújtást\r\nvégzett.', 'repeat', 60, 'second', NULL, 0), +(2, 0, 'Húzódzkodás', 'Ennek a gyakorlatnak a 24 órás csúcstartója Joonas Mäkipelto 5050\r\ngyakorlattal.', 'repeat', NULL, NULL, NULL, 0), +(3, 0, 'Melső fekvőtámasz 30mp', 'A gyakorlatot 30 másodperc alatt olyan sokszor kell végrehajtani, ahányszor a\r\nfelvételiző képes rá. Azonban törekedni kell a szabályos végrehajtásra, ugyanis csak azokat\r\nszámolják. A nők esetében 20, a férfiak esetében 35 gyakorlatot kell végrehajtani a maximális\r\npont megszerzéséért. A gyakorlat akkor sikeres, ha a női legalább 1, a férfi felvételiző\r\nlegalább 11 gyakorlatot képes végrehajtani.', 'repeat', 30, 'second', NULL, 0), +(4, 0, 'Melső fekvőtámasz 2perc', 'Magyar Honvédség: A gyakorlat végrehajtására 2 perc áll rendelkezésre. Ennek során csak a szabályosan a\r\nfentiekben leírt módon végrehajtott gyakorlat értékelhető. Férfiaknál 70 karhajlítás nyújtást\r\nkell végrehajtani a maximális pontért.', 'repeat', 120, 'second', NULL, 0), +(5, 0, 'Hajlított karú függés', 'A gyakorlat addig tart, amíg a végrehajtó szemmagassága a kiinduló helyzettől\r\nsüllyedve a keresztvas alá nem kerül. Az értékeléshez stopperórát alkalmaznak, és az\r\neredmény másodperc pontossággal kerül megállapításra. Nők esetében 45, férfiak\r\ntekintetében 73 másodperctől jár a maximális pontszám. A gyakorlat sikeres végrehajtásához\r\nlegalább 8, 10 másodpercig kell megtartaniuk a kiinduló helyzetet a női és a férfi\r\nfelvételizőknek.\r\n\r\nA NKE-RTK-án lévő hallgatók egyéni rekordjai Iván Viktor 90s, Kiss Regina 74s', 'second', NULL, NULL, NULL, 0), +(6, 9, 'Fekvenyomás', 'A fekvenyomás egy alapgyakorlat, amely elsődlegesen a mellizmokat veszi célba, de másodlagos mozgatóként a tricepsz és a deltaizmok is fejlődnek általa. Testépítők kedvenc gyakorlata. Kiemelten fontos gyakorlat a mellizmok edzésében, ezért törekedjünk a megfelelő súllyal való, megfelelő számú szabályos ismétlés végrehajtására.\r\n\r\nKiinduló helyzet:\r\nHáton fekvésben a padon, kezeinket a váll szélességénél kb. egy ököllel szélesebben fogva a rudat (van egy jelzés a rúdon, ahol a gyűrűs ujjnak a helye van).\r\n\r\nVégrehajtás:\r\nA rúd kiemelése után a mellkas közepéig engedjük le a rudat, majd kinyomjuk függőlegesen. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint.\r\n\r\nJótanács: \r\nFigyeljünk a folyamatos légzésre, azaz nyomáskor kilégzés, mellkasra engedéskor kilégzést használj. Hátad maradjon a padon. Ne homoríts! Mindig figyeljünk a megfelelő súly kiválasztására. Ha szükséges kérjünk meg egy társat segítségül az utolsó ismétlésünk biztonságos végrehajtása érdekében.', 'repeat', NULL, NULL, NULL, 0), +(7, 0, '4x10m-es ingafutás', 'A legjobb pontszámért 9,4 s illetve 8,8s alatt kell teljesíteni a nőknek, férfiaknak. A\r\ngyakorlat sikertelen 11,8 s illetve 11,2 s-on túl.', 'second', NULL, NULL, NULL, 0), +(8, 0, 'Helyből távolugrás', 'Byron Jones 2015-ben a 3,73 méteres ugrásával érte el a világcsúcsot.\r\nA nőknek 220 cm-re, a férfiak 250 cm-re kell ugraniuk a maximális pontért. A\r\nminimális távolság 172cm illetve 198 cm.', 'meter', NULL, NULL, NULL, 0), +(9, 0, 'Felülés hanyattfekvésből', 'Az NKE-RTK hallgatói közül Papp Zsófia 66 db-ot, Gál Valentin 80\r\ndb-ot csinált 1 perc leforgása alatt.\r\nElső ütemre megtörténik a felülés, ami akkor szabályos, ha valamelyik könyök érinti a\r\ntérdet. Második ütemre vissza kell térni a kiinduló helyzetbe. A maximális pont eléréséhez 1\r\nperc alatt 45 illetve 55 ismétlést kell végezni a nőknek illetve a férfiaknak. A minimumhoz 7\r\nés 25 ismétlés szükséges.', 'repeat', NULL, NULL, NULL, 0), +(10, 0, 'Felülés hajlított térddel', 'Magyar Honvédség: A kiinduló helyzet hajlított ülés, ennek során a sarkak a talajon, a térd 90 fokban meghajlítva\r\nvan.\r\nA gyakorlat végrehajtására két perc áll rendelkezésre. Ennek során csak a szabályosan,\r\na fentiekben leírt módon végrehajtott gyakorlat értékelhető. Férfiaknál, nőknél egyaránt 90\r\ngyakorlatot kell végrehajtani a maximális pontért. Amennyiben a megadott időkeret alatt nem\r\nsikerül legalább 25 szabályos gyakorlatot végrehajtani, úgy az sikertelennek minősül.', 'repeat', NULL, NULL, NULL, 0), +(11, 0, 'Síkfutás 2000m', 'A maximálisan megszerezhető pontot az a felvételiző gyűjtheti be, aki a távot nők\r\nesetében 10:00 perc alatt, férfiak esetében 7:35 perc alatt teljesíti. A gyakorlat sikeres\r\nteljesítésére nők esetében maximum 16:00 perc, férfiak esetében 13:30 perc áll rendelkezésre.', 'second', NULL, NULL, NULL, 0), +(31, 8, '300m', '', 'second', NULL, NULL, 1, 0), +(32, 8, '400m', '', 'second', NULL, NULL, 1, 0), +(33, 10, 'Pushups', '', 'repeat', NULL, NULL, 1, 0), +(34, 10, 'Timed Pushups', '', 'repeat', 1, 'second', 1, 0), +(35, 10, 'Squats', '', 'repeat', 0, NULL, 1, 0), +(36, 10, 'Sit-ups', '', 'repeat', NULL, NULL, 1, 0), +(37, 14, 'Chest Press', '', 'repeat', 1, 'kilogram', 1, 1), +(38, 10, 'Pull Ups', '', 'repeat', NULL, NULL, 1, 0), +(53, 10, 'Plank', 'Plank description', 'second', NULL, NULL, 1, 0), +(54, 14, 'Dumbbel Bench Presses', '', 'repeat', 1, 'kilogram', 1, 1), +(55, 14, 'Incline Press', '', 'repeat', 1, 'kilogram', 1, 1), +(56, 14, 'Close Grip Bench Press', '', 'repeat', 1, 'kilogram', 1, 0), +(57, 14, 'Incline Dumbbell Presses', '', 'repeat', 1, 'kilogram', 1, 0), +(58, 14, 'Decline Bench Presses', '', 'repeat', 1, 'kilogram', 1, 0), +(64, 14, 'Chest press smith machine', '', 'repeat', 1, 'kilogram', 1, 0), +(65, 14, 'Cross-Bench Dumbbell Pullover', '', 'repeat', 1, 'kilogram', 1, 0), +(69, 14, 'Decline Dumbbell Bench Press', '', 'repeat', 1, 'kilogram', 1, 0), +(70, 14, 'Chest press machine', '', 'repeat', 1, 'kilogram', 1, 0), +(71, 14, 'Smith machine chest press', '', 'repeat', 1, 'kilogram', 1, 0), +(72, 14, 'Flyes', '', 'repeat', 1, 'kilogram', 1, 0), +(73, 14, 'Incline Flyes', '', 'repeat', 1, 'kilogram', 1, 0), +(74, 14, 'Decline Flyes', '', 'repeat', 1, 'kilogram', 1, 0), +(75, 14, 'Cable Flyes', '', 'repeat', 1, 'kilogram', 1, 0), +(76, 14, 'Incline cable flyes', '', 'repeat', 1, 'kilogram', 1, 0), +(77, 14, 'Decline cable flyes', '', 'repeat', 1, 'kilogram', 1, 0), +(78, 14, 'Peck-Deck Flyes', '', 'repeat', 1, 'kilogram', 1, 1), +(79, 14, 'Cross-Bench Dumbbell Pullover', '', 'repeat', 1, 'kilogram', 1, 0), +(80, 14, 'Cable Crosses', '', 'repeat', 1, 'kilogram', 1, 0), +(81, 20, 'Cable Rows', '', 'repeat', 1, 'kilogram', 1, 0), +(82, 20, 'T-bar Rows', '', 'repeat', 1, 'kilogram', 1, 0), +(83, 20, 'One Arm Row', '', 'repeat', 1, 'kilogram', 1, 0), +(84, 20, 'Single arm T-bar rows', '', 'repeat', 1, 'kilogram', 1, 0), +(85, 20, 'Close Grip Pull-Ups', '', 'repeat', 1, 'kilogram', 1, 0), +(86, 20, 'Wide Grip behind the neck Pull-Ups', '', 'repeat', 1, 'kilogram', 1, 1), +(87, 20, 'Wide Grip Front Lat Pulldown', '', 'repeat', 1, 'kilogram', 1, 0), +(88, 20, 'Close Grip Front Lat Pulldown', '', 'repeat', 1, 'kilogram', 1, 0), +(89, 20, 'Close Reverse Grip Lat Pulldown', '', 'repeat', 1, 'kilogram', 1, 0), +(90, 20, 'Behind the neck lat pulldown', '', 'repeat', 1, 'kilogram', 1, 1), +(91, 20, 'Front-Rear Lat Pulldown', '', 'repeat', 1, 'kilogram', 1, 0), +(92, 21, 'Hyperextension', '', 'repeat', 1, 'kilogram', 1, 0), +(93, 20, 'Straight-arm rope pull-down', '', 'repeat', 1, 'kilogram', 1, 0), +(94, 20, 'Bent Arm Barbell Pullovers', '', 'repeat', 1, 'kilogram', 1, 0), +(95, 17, 'Machine shoulder press', '', 'repeat', 1, 'kilogram', 1, 1), +(96, 17, 'Behind The Neck Presses', '', 'repeat', 1, 'kilogram', 1, 1), +(97, 17, 'Alternating standing shoulder press', '', 'repeat', 1, 'kilogram', 1, 0), +(98, 17, 'Seated dumbbell shoulder press', '', 'repeat', 1, 'kilogram', 1, 0), +(99, 17, 'Alternate Dumbbell Presses', '', 'repeat', 1, 'kilogram', 1, 0), +(100, 17, 'Arnold-press', '', 'repeat', 1, 'kilogram', 1, 1), +(101, 17, 'Lying rear delt raise', '', 'repeat', 1, 'kilogram', 1, 0), +(102, 17, 'Seated lateral raises', '', 'repeat', 1, 'kilogram', 1, 0), +(103, 17, 'Standing Lateral Raises', '', 'repeat', 1, 'kilogram', 1, 0), +(104, 17, 'Standing Side Cable Laterals', '', 'repeat', 1, 'kilogram', 1, 0), +(105, 17, 'Head-on-bench dumbbell rear delt raise', 'vagy Bent Over Lateral Raises With Dumbbells', 'repeat', 1, 'kilogram', 1, 0), +(106, 17, 'Bent Over Lateral Raises With Dumbbells', '', 'repeat', 1, 'kilogram', 1, 0), +(107, 17, 'Single-Arm Bent-Over Cable Reverse Fly', '', 'repeat', 1, 'kilogram', 1, 0), +(108, 17, 'Single hand lateral raises', '', 'repeat', 1, 'kilogram', 1, 0), +(109, 17, 'Forward Raise With Dumbbell Or Barbell', '', 'repeat', 1, 'kilogram', 1, 0), +(110, 17, 'Barbell Upright Row', '', 'repeat', 1, 'kilogram', 1, 0), +(111, 17, 'Standing Military Presses', '', 'repeat', 1, 'kilogram', 1, 0), +(112, 17, 'Shrugs', '', 'repeat', 1, 'kilogram', 1, 0), +(113, 17, 'Seated Dumbbell Press', '', 'repeat', 1, 'kilogram', 1, 0), +(114, 7, 'Cooper Test', 'Measure how many meters you can run in 12 minutes', 'meter', 0, NULL, 1, 0), +(115, 17, 'Standing face pull', '', 'repeat', 1, 'kilogram', 1, 0), +(116, 16, 'Triceps Pushdown', '', 'repeat', 1, 'kilogram', 1, 1), +(117, 16, 'Triceps Extension On Cable With Rope', '', 'repeat', 1, 'kilogram', 1, 0), +(118, 16, 'Close Grip Bench Press', '', 'repeat', 1, 'kilogram', 1, 0), +(119, 16, 'Overhead Dumbbell Triceps Extension', '', 'repeat', 1, 'kilogram', 1, 0), +(120, 16, 'Seated Triceps Extension', '', 'repeat', 1, 'kilogram', 1, 0), +(121, 16, 'Incline Triceps Extension', '', 'repeat', 1, 'kilogram', 1, 0), +(122, 16, 'Lying Triceps Extension', '', 'repeat', 1, 'kilogram', 1, 0), +(123, 16, 'Standing Triceps Extension', '', 'repeat', 1, 'kilogram', 1, 0), +(124, 16, 'Single hand Lying Triceps Extension', '', 'repeat', 1, 'kilogram', 1, 0), +(125, 16, 'Triceps Kickback', '', 'repeat', 1, 'kilogram', 1, 0), +(126, 16, 'Pushups - Dip', '', 'repeat', 1, 'kilogram', 1, 1), +(127, 16, 'Weighted bench dip', '', 'repeat', 1, 'kilogram', 1, 0), +(128, 15, 'Standing Barbell Curl', '', 'repeat', 1, 'kilogram', 1, 1), +(129, 15, 'Seated Dumbbell Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(130, 15, 'Lying Curls', '', 'repeat', 1, 'kilogram', 1, 0), +(131, 15, 'Dumbbell Alternate Bicep Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(132, 9, 'Custom', '', 'repeat', 1, 'kilogram', 1, 0), +(133, 15, 'EZ Bar Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(134, 15, 'Biceps Machine', '', 'repeat', 1, 'kilogram', 1, 1), +(135, 15, 'EZ-Bar Scott Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(136, 15, 'Standing One-Arm Cable Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(137, 15, 'Standing Biceps Cable Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(138, 15, 'Lying Biceps Cable Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(139, 15, 'Incline Curl With Dumbbells', '', 'repeat', 1, 'kilogram', 1, 0), +(140, 15, 'Concentration Curl', '', 'repeat', 1, 'kilogram', 1, 0), +(141, 15, 'Chins', '', 'repeat', 1, 'kilogram', 1, 0), +(142, 15, 'Hammer Curls', '', 'repeat', 1, 'kilogram', 1, 1), +(143, 18, 'Squat', '', 'repeat', 1, 'kilogram', 1, 1), +(144, 18, 'Front Squat', '', 'repeat', 1, 'kilogram', 1, 0), +(145, 18, 'Olympic Squat', '', 'repeat', 1, 'kilogram', 1, 1), +(146, 18, 'Hack-Squat', '', 'repeat', 1, 'kilogram', 1, 1), +(147, 18, 'Sissy-squat', '', 'repeat', 1, 'kilogram', 1, 0), +(148, 18, 'Squat Jump', '', 'repeat', 1, 'kilogram', 1, 0), +(149, 18, 'Standing Leg Curls', '', 'repeat', 1, 'kilogram', 1, 0), +(150, 18, 'Seated Leg Curls', '', 'repeat', 1, 'kilogram', 1, 1), +(151, 18, 'Leg Extension', '', 'repeat', 1, 'kilogram', 1, 1), +(152, 18, 'Leg Press', '', 'repeat', 1, 'kilogram', 1, 1), +(153, 18, 'Lunges', '', 'repeat', 1, 'kilogram', 1, 0), +(154, 18, 'Lunges with dumbells', '', 'repeat', 1, 'kilogram', 1, 0), +(155, 18, 'Stiff Legged Deadlift', '', 'repeat', 1, 'kilogram', 1, 0), +(156, 19, 'Donkey Calf Raises', '', 'repeat', 1, 'kilogram', 1, 1), +(157, 19, 'Sitting Machine Calf Raises', '', 'repeat', 1, 'kilogram', 1, 0), +(158, 19, 'Sitting Machine Calf Raises', '', 'repeat', 1, 'kilogram', 1, 0), +(159, 9, 'Control', '', 'repeat', 1, 'kilogram', 0, 0), +(160, 21, 'Deadlift', '', 'repeat', 1, 'kilogram', 1, 1), +(161, 18, 'Thigh adductor', '', 'repeat', 1, 'kilogram', 1, 1), +(162, 5, 'Sizes', '', 'centimeter', 0, NULL, 1, 0), +(168, 0, 'Faltámasz', '', 'second', 0, NULL, 1, 0), +(169, 0, 'Pop Squat', '(switched hands)\r\nttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'repeat', 0, 0), +(170, 0, 'Lunge Drive Combo', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'repeat', 0, 0), +(171, 0, 'Push Up & Reach', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'repeat', 0, 0), +(172, 0, 'Speed Skater', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'repeat', 0, 0), +(173, 0, 'Jumping Jacks', 'https://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'repeat', 0, 0), +(174, 0, 'Crab Dance', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'repeat', 0, 0), +(175, 0, 'Side lunge & reach', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(176, 0, 'Ninja Squat Pulse', 'https://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(177, 0, 'Squat Jacks', 'https://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(178, 0, 'Mountain climbers', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=cnyTQDSE884', 'repeat', 0, 'kilogram', 0, 0), +(179, 0, 'Oblique/Rock climbers', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(180, 0, 'Hip twister', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(181, 0, 'Bicycle crunch', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(182, 0, 'Jump Squat', 'https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(183, 0, 'Spot Sprint', 'https://www.youtube.com/watch?v=kTvHJe6_h1c', 'repeat', 0, 'kilogram', 0, 0), +(184, 0, 'T-Push Ups', '(two sided exercise)\r\nhttps://www.youtube.com/watch?v=kTvHJe6_h1c', 'repeat', 0, 'kilogram', 0, 0), +(185, 0, 'Laydawn Push Ups', 'https://www.youtube.com/watch?v=ldPoLW-Z_fk', 'repeat', 0, 'kilogram', 0, 0), +(186, 0, 'Burpees_v1', 'https://www.youtube.com/watch?v=qLBImHhCXSw', 'repeat', 0, 'kilogram', 0, 0), +(187, 0, 'Burpees_v2', 'https://www.youtube.com/watch?v=ldPoLW-Z_fk', 'repeat', 0, 'kilogram', 0, 0), +(188, 0, 'Skate Steps', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=IbU-7yVAoTM', 'repeat', 0, 'kilogram', 0, 0), +(189, 0, 'Touch Lunge & Kick', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=IbU-7yVAoTM', 'repeat', 0, 'kilogram', 0, 0), +(190, 0, 'Plank', 'https://www.youtube.com/watch?v=1V64QSE-96Y&t=1516s', 'repeat', 0, 'kilogram', 0, 0), +(191, 0, 'Hip Dip Plank', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=1V64QSE-96Y&t=1516s', 'repeat', 0, 'kilogram', 0, 0), +(192, 0, 'Side Plank', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=m0cfOQA17t0', 'repeat', 0, 'kilogram', 0, 0), +(193, 0, 'Plank Toe Taps', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=m0cfOQA17t0', 'repeat', 0, 'kilogram', 0, 0), +(194, 0, 'Walking Plank', 'https://www.youtube.com/watch?v=m0cfOQA17t0', 'repeat', 0, 'kilogram', 0, 0), +(195, 0, 'Knee Drive Twister', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=1V64QSE-96Y&t=1516s', 'repeat', 0, 'kilogram', 0, 0), +(196, 0, 'Bird-Dog Plank', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=Qff2gyaBa4g&t=1570s', 'repeat', 0, 'kilogram', 0, 0), +(197, 0, 'Side Bridge & Kick', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=Qff2gyaBa4g&t=1570s', 'repeat', 0, 'kilogram', 0, 0), +(198, 0, 'Warrior Lunge', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=Qff2gyaBa4g&t=1570s', 'repeat', 0, 'kilogram', 0, 0), +(199, 0, 'Warrior Lunge Combo', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=8fJk2ZLRoIE', 'repeat', 0, 'kilogram', 0, 0), +(200, 0, 'Low Lunge', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=Qff2gyaBa4g&t=1570s', 'repeat', 0, 'kilogram', 0, 0), +(201, 0, 'Leg Drop', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=SOsVjNUf1OI', 'repeat', 0, 'kilogram', 0, 0), +(202, 0, 'Butterfly Twist', 'https://www.youtube.com/watch?v=SOsVjNUf1OI', 'repeat', 0, 'kilogram', 0, 0), +(203, 0, 'Bear Kick Back', '(two sided exercise) \r\nhttps://www.youtube.com/watch?v=SOsVjNUf1OI', 'repeat', 0, 'kilogram', 0, 0), +(204, 0, 'Down Dog Crunch', '(two sided exercise) https://www.youtube.com/watch?v=8fJk2ZLRoIE', 'repeat', 0, 'kilogram', 0, 0), +(205, 0, 'Warrior III. Flow', '(two sided exercise) https://www.youtube.com/watch?v=8fJk2ZLRoIE', 'repeat', 0, 'kilogram', 0, 0), +(206, 0, 'Side Bridge & Lift', '(two sided exercise) https://www.youtube.com/watch?v=8fJk2ZLRoIE', 'repeat', 0, 'kilogram', 0, 0), +(207, 0, 'Plank Leg Lift', 'https://www.youtube.com/watch?v=m0cfOQA17t0', 'repeat', 0, 'kilogram', 0, 0), +(208, 0, 'Side Plank', '(two sided exercise) https://www.youtube.com/watch?v=m0cfOQA17t0', 'repeat', 0, 'kilogram', 0, 0), +(209, 0, 'Push Ups', 'https://www.youtube.com/watch?v=d8BFKmkmxV4', 'repeat', 0, 'kilogram', 0, 0), +(210, 0, 'Plank & Tap', 'https://www.youtube.com/watch?v=d8BFKmkmxV4', 'repeat', 0, 'kilogram', 0, 0), +(211, 0, 'Star Jumps', 'https://www.youtube.com/watch?v=d8BFKmkmxV4', 'repeat', 0, 'kilogram', 0, 0), +(212, 0, 'Plank Stroke', '(two sided exercise) https://www.youtube.com/watch?v=Fu1EcSaMZMY -> 05:19', 'repeat', 0, 'kilogram', 0, 0), +(213, 0, 'Dolphin Push Ups', 'https://www.youtube.com/watch?v=Fu1EcSaMZMY', 'repeat', 0, 'kilogram', 0, 0), +(214, 0, 'Super V Squeeze', 'https://www.youtube.com/watch?v=Fu1EcSaMZMY', 'repeat', 0, 'kilogram', 0, 0), +(215, 0, 'Inchworm Jack', 'https://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(216, 0, 'Squat and Leg lift', '(two sided exercise) https://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(217, 0, 'Lunge Leg', '(two sided exercise) https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(218, 0, '1-Leg Deadlift', '(two sided exercise) https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(219, 0, 'Deadlift', 'https://www.youtube.com/watch?v=dBJry3tcX0Q', 'repeat', 0, 'kilogram', 0, 0), +(220, 0, 'In and out squat', '(two sided exercise) https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(221, 0, 'Side Lunge', '(two sided exercise) https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(222, 0, 'Prisoner Stand Ups', '(left & right legs) https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(223, 0, 'Squat', 'https://www.youtube.com/watch?v=ZgDudqUjQIw', 'repeat', 0, 'kilogram', 0, 0), +(224, 0, 'Sumo Squat', 'https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(225, 0, 'Curtsey and Side Lift', '(two sided exercise) https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(226, 0, 'Wall Sit', 'https://www.youtube.com/watch?v=7WQRjMjCkvI&t=807s', 'repeat', 0, 'kilogram', 0, 0), +(227, 0, 'Booty Burn', '(two sided exercise) https://www.youtube.com/watch?v=ldPoLW-Z_fk', 'repeat', 0, 'kilogram', 0, 0), +(228, 0, 'Shuffle Steps', '(two sided exercise) https://www.youtube.com/watch?v=31BiQiXk8jQ', 'repeat', 0, 'kilogram', 0, 0), +(229, 0, 'Rear Leg Lift', '(two sided exercise) https://www.youtube.com/watch?v=pcJsP4gogsI', 'repeat', 0, 'kilogram', 0, 0), +(230, 0, 'Side Lift', '(two sided exercise) https://www.youtube.com/watch?v=pcJsP4gogsI', 'repeat', 0, 'kilogram', 0, 0), +(231, 0, 'Curtsey', '(two sided exercise)', 'repeat', 0, 'kilogram', 0, 0), +(232, 0, 'Leg Lift', '(two sided exercise) https://www.youtube.com/watch?v=dg2wzHf8vY4', 'repeat', 0, 'kilogram', 0, 0), +(233, 0, 'Bridge & Kick', '(two sided exercise) https://www.youtube.com/watch?v=dg2wzHf8vY4', 'repeat', 0, 'kilogram', 0, 0), +(234, 0, 'In & Out Laydawn Heel Tuch', 'https://www.youtube.com/watch?v=dg2wzHf8vY4', 'repeat', 0, 'kilogram', 0, 0), +(235, 0, 'Inner Leg Lift_v1', '(two sided exercise) https://www.youtube.com/watch?v=dg2wzHf8vY4', 'repeat', 0, 'kilogram', 0, 0), +(236, 0, 'Inner Leg Lift_v2', '(two sided exercise) https://www.youtube.com/watch?v=lNrFl557i1k', 'repeat', 0, 'kilogram', 0, 0), +(237, 0, 'Pinguin Crunch', '(two sided exercise) https://www.youtube.com/watch?v=IbU-7yVAoTM', 'repeat', 0, 'kilogram', 0, 0), +(238, 0, 'Riverse Tuck & Kick Out', 'https://www.youtube.com/watch?v=IbU-7yVAoTM', 'repeat', 0, 'kilogram', 0, 0), +(239, 0, 'Bent Knee V-crunch', 'https://www.youtube.com/watch?v=IbU-7yVAoTM', 'repeat', 0, 'kilogram', 0, 0), +(240, 0, 'Pike Kick', '(two sided exercise) https://www.youtube.com/watch?v=Qia2ZXEzyLw&t=349s', 'repeat', 0, 'kilogram', 0, 0), +(241, 0, 'Side Kick', '(two sided exercise) https://www.youtube.com/watch?v=Qia2ZXEzyLw&t=349s', 'repeat', 0, 'kilogram', 0, 0), +(242, 0, 'Riverse Crunch', 'https://www.youtube.com/watch?v=WjRGHsy8Qx8', 'repeat', 0, 'kilogram', 0, 0), +(243, 0, 'Scissor Kicks', 'https://www.youtube.com/watch?v=WjRGHsy8Qx8', 'repeat', 0, 'kilogram', 0, 0), +(244, 0, 'Scissor Kicks with Toe Touch', '(two sided exercise) https://www.youtube.com/watch?v=WjRGHsy8Qx8', 'repeat', 0, 'kilogram', 0, 0), +(245, 0, 'Prayer Crunch', 'https://www.youtube.com/watch?v=WjRGHsy8Qx8', 'repeat', 0, 'kilogram', 0, 0), +(246, 0, 'Full Body Crunch', 'https://www.youtube.com/watch?v=1V64QSE-96Y&t=1516s', 'repeat', 0, 'kilogram', 0, 0), +(247, 0, 'Unicorn Crunch', 'https://www.youtube.com/watch?v=1V64QSE-96Y&t=1516s', 'repeat', 0, 'kilogram', 0, 0), +(248, 0, 'Rainbow „V”', 'https://www.youtube.com/watch?v=k0emMmLD1AE', 'repeat', 0, 'kilogram', 0, 0), +(249, 0, 'Butterfly Sit Up', 'https://www.youtube.com/watch?v=k0emMmLD1AE', 'repeat', 0, 'kilogram', 0, 0), +(250, 0, 'Russian Twist', '(two sided exercise) https://www.youtube.com/watch?v=JMRfGPLGB0w', 'repeat', 0, 'kilogram', 0, 0), +(251, 0, 'Tricep Press', '(two sided exercise) https://www.youtube.com/watch?v=Fu1EcSaMZMY', 'repeat', 0, 'kilogram', 0, 0), +(252, 0, 'Robot Row Combo', 'https://www.youtube.com/watch?v=Fu1EcSaMZMY', 'repeat', 0, 'kilogram', 0, 0), +(253, 0, 'Side Bridge & Squeeze', '(two sided exercise) https://www.youtube.com/watch?v=Fu1EcSaMZMY', 'repeat', 0, 'kilogram', 0, 0), +(254, 0, 'Underhand Row', 'https://www.youtube.com/watch?v=irv7XgPkrvs', 'repeat', 0, 'kilogram', 0, 0), +(255, 0, 'Tricep Kick Back', '(two sided exercise) https://www.youtube.com/watch?v=irv7XgPkrvs', 'repeat', 0, 'kilogram', 0, 0), +(256, 0, 'Lateral Combo', 'https://www.youtube.com/watch?v=irv7XgPkrvs', 'repeat', 0, 'kilogram', 0, 0), +(257, 0, 'One Arm Raw', '(two sided exercise) https://www.youtube.com/watch?v=irv7XgPkrvs', 'repeat', 0, 'kilogram', 0, 0), +(258, 0, 'Chest Press', 'https://www.youtube.com/watch?v=irv7XgPkrvs', 'repeat', 0, 'kilogram', 0, 0), +(259, 0, 'High Pull', 'https://www.youtube.com/watch?v=irv7XgPkrvs', 'repeat', 0, 'kilogram', 0, 0), +(261, 0, 'BMI', '', 'calories', 0, 'kilogram', 1, 0), +(262, 0, 'BMR', '', 'calories', 0, NULL, 1, 0); + +DELETE FROM `exercise_type_alternative`; +INSERT INTO `exercise_type_alternative` (`exercise_type_alternative_id`, `exercise_type_parent_id`, `exercise_type_child_id`) VALUES +(1, 35, 169), +(2, 153, 170), +(3, 33, 171); + + +DELETE FROM `exercise_type_device`; +INSERT INTO `exercise_type_device` (`exercise_type_device_id`, `exercise_type_id`, `exercise_device_id`) VALUES +(1, 37, 4), +(2, 72, 1), +(3, 72, 16), +(4, 76, 18), +(5, 53, 2), +(6, 53, 7), +(7, 53, 19), +(8, 36, 2), +(9, 36, 19), +(10, 36, 7), +(11, 38, 2), +(12, 38, 6), +(13, 38, 7), +(14, 35, 1), +(15, 35, 2), +(16, 35, 4), +(17, 35, 7), +(18, 35, 9), +(19, 35, 10), +(20, 35, 12), +(21, 35, 13), +(22, 35, 16), +(23, 35, 17), +(24, 35, 18), +(25, 35, 19), +(26, 35, 20), +(27, 33, 2), +(28, 33, 7), +(29, 33, 10), +(30, 33, 15), +(31, 33, 17), +(32, 33, 19), +(33, 55, 1), +(34, 55, 4), +(35, 55, 16), +(36, 56, 1), +(37, 56, 4), +(38, 56, 16), +(39, 57, 1), +(40, 57, 16), +(41, 58, 1), +(42, 58, 4), +(43, 58, 16), +(44, 64, 3), +(45, 65, 1), +(46, 65, 9), +(47, 65, 16), +(48, 65, 20), +(49, 69, 1), +(50, 69, 16), +(51, 70, 3), +(52, 71, 3), +(53, 73, 1), +(54, 73, 16), +(55, 75, 18), +(56, 77, 18), +(57, 78, 3), +(58, 79, 1), +(59, 79, 16), +(60, 79, 9), +(61, 80, 18), +(62, 81, 18), +(63, 82, 4), +(64, 83, 1), +(65, 83, 16), +(66, 83, 20), +(67, 84, 4), +(68, 84, 5), +(69, 85, 6), +(70, 85, 2), +(71, 85, 7), +(72, 85, 19), +(73, 86, 6), +(74, 86, 19), +(75, 86, 2), +(76, 86, 7), +(77, 87, 6), +(78, 87, 2), +(79, 87, 19), +(80, 87, 7), +(81, 88, 6), +(82, 88, 2), +(83, 88, 19), +(84, 88, 7), +(85, 89, 6), +(86, 89, 7), +(87, 89, 2), +(88, 89, 19), +(92, 90, 3), +(93, 91, 2), +(94, 91, 7), +(95, 91, 6), +(96, 91, 19), +(97, 92, 3), +(98, 92, 2), +(99, 92, 7), +(100, 92, 19), +(101, 93, 18), +(102, 94, 1), +(103, 94, 16), +(104, 94, 9), +(105, 95, 3), +(106, 96, 4), +(107, 96, 1), +(108, 96, 16), +(109, 96, 7), +(110, 96, 5), +(111, 97, 1), +(112, 97, 7), +(113, 97, 16), +(114, 97, 20), +(115, 98, 1), +(116, 98, 7), +(117, 98, 16), +(118, 98, 20), +(119, 99, 1), +(120, 99, 16), +(121, 99, 7), +(122, 99, 20), +(123, 100, 1), +(124, 100, 16), +(125, 100, 7), +(126, 100, 20), +(127, 101, 1), +(128, 101, 7), +(129, 101, 20), +(130, 102, 1), +(131, 102, 7), +(132, 102, 16), +(133, 102, 20), +(134, 103, 1), +(135, 103, 16), +(136, 103, 7), +(137, 103, 20), +(138, 104, 18), +(139, 105, 1), +(140, 105, 16), +(141, 105, 7), +(142, 105, 20), +(143, 106, 1), +(144, 106, 16), +(145, 106, 7), +(146, 106, 20), +(147, 107, 18), +(148, 108, 1), +(149, 108, 16), +(150, 108, 7), +(151, 108, 20), +(152, 109, 1), +(153, 109, 16), +(154, 109, 7), +(155, 109, 20), +(156, 109, 17), +(157, 109, 4), +(158, 110, 4), +(159, 110, 14), +(160, 110, 7), +(161, 110, 15), +(162, 111, 4), +(163, 112, 1), +(164, 112, 16), +(165, 112, 5), +(166, 113, 4), +(167, 113, 7), +(168, 112, 7), +(169, 111, 7), +(170, 115, 18), +(171, 116, 18), +(172, 117, 18), +(173, 118, 4), +(174, 118, 14), +(175, 118, 7), +(176, 119, 1), +(177, 119, 16), +(178, 119, 7), +(179, 119, 20), +(180, 120, 1), +(181, 120, 7), +(182, 120, 16), +(183, 120, 20), +(184, 120, 15), +(185, 121, 1), +(186, 121, 14), +(187, 121, 4), +(188, 121, 7), +(189, 122, 1), +(190, 122, 4), +(191, 122, 14), +(192, 122, 7), +(193, 123, 4), +(194, 123, 14), +(195, 123, 4), +(196, 123, 7), +(197, 124, 1), +(198, 124, 16), +(199, 124, 7), +(200, 124, 20), +(201, 125, 1), +(202, 125, 7), +(203, 125, 20), +(204, 126, 3), +(205, 126, 7), +(206, 126, 2), +(207, 127, 2), +(208, 127, 3), +(209, 127, 7), +(210, 128, 4), +(211, 128, 7), +(212, 128, 14), +(213, 129, 1), +(214, 129, 16), +(215, 129, 7), +(216, 129, 20), +(217, 130, 1), +(218, 130, 16), +(219, 130, 7), +(220, 130, 20), +(221, 131, 1), +(222, 131, 16), +(223, 131, 7), +(224, 131, 20), +(225, 133, 14), +(226, 133, 7), +(227, 134, 3), +(228, 135, 3), +(229, 135, 14), +(230, 137, 18), +(231, 138, 18), +(232, 139, 1), +(233, 139, 16), +(234, 139, 7), +(235, 139, 20), +(236, 140, 1), +(237, 140, 16), +(238, 140, 7), +(239, 140, 20), +(240, 141, 2), +(241, 141, 7), +(242, 141, 6), +(243, 142, 1), +(244, 142, 7), +(245, 142, 20), +(246, 142, 15), +(247, 143, 4), +(248, 143, 1), +(249, 143, 9), +(250, 143, 16), +(251, 143, 10), +(252, 143, 19), +(253, 143, 20), +(254, 143, 7), +(255, 143, 2), +(256, 143, 6), +(257, 143, 14), +(258, 143, 12), +(259, 143, 13), +(260, 143, 17), +(261, 143, 19), +(262, 144, 1), +(263, 144, 16), +(264, 144, 9), +(265, 144, 14), +(266, 144, 4), +(267, 146, 3), +(268, 147, 3), +(269, 148, 19), +(270, 148, 9), +(271, 148, 2), +(272, 148, 7), +(273, 148, 20), +(274, 149, 3), +(275, 150, 3), +(276, 151, 3), +(277, 151, 7), +(278, 151, 15), +(279, 152, 3), +(280, 153, 2), +(281, 153, 19), +(282, 153, 7), +(283, 154, 1), +(284, 154, 16), +(285, 154, 7), +(286, 154, 20), +(287, 155, 1), +(288, 155, 16), +(289, 155, 4), +(290, 155, 5), +(291, 155, 7), +(292, 156, 19), +(293, 156, 2), +(294, 156, 7), +(295, 157, 3), +(296, 158, 3), +(297, 160, 1), +(298, 160, 4), +(299, 160, 14), +(300, 160, 5), +(301, 160, 7), +(302, 161, 3), +(303, 161, 23), +(304, 160, 23), +(305, 160, 21), +(306, 158, 23), +(307, 157, 23), +(308, 156, 21), +(309, 156, 23), +(310, 156, 22), +(311, 155, 23), +(312, 155, 21), +(313, 140, 23), +(314, 140, 23), +(315, 140, 21), +(316, 141, 21), +(317, 141, 22), +(318, 141, 23), +(319, 142, 21), +(320, 142, 23), +(321, 143, 21), +(322, 143, 22), +(323, 143, 23), +(324, 144, 21), +(325, 144, 22), +(326, 144, 23), +(327, 145, 4), +(328, 145, 19), +(329, 145, 21), +(330, 145, 23), +(331, 145, 22), +(332, 145, 2), +(333, 146, 23), +(334, 147, 23), +(335, 148, 21), +(336, 148, 22), +(337, 148, 23), +(338, 149, 23), +(339, 150, 23), +(340, 151, 23), +(341, 152, 23), +(342, 153, 21), +(343, 153, 22), +(344, 153, 23), +(345, 154, 21), +(346, 154, 23), +(347, 120, 21), +(348, 120, 23), +(349, 121, 21), +(350, 121, 23), +(351, 122, 21), +(352, 122, 23), +(353, 123, 21), +(354, 123, 23), +(355, 124, 21), +(356, 124, 23), +(357, 125, 21), +(358, 125, 23), +(359, 126, 21), +(360, 126, 22), +(361, 126, 23), +(362, 127, 21), +(363, 127, 22), +(364, 127, 23), +(365, 128, 21), +(366, 128, 23), +(367, 129, 21), +(368, 129, 23), +(369, 130, 21), +(370, 130, 23), +(371, 131, 21), +(372, 131, 23), +(373, 133, 21), +(374, 133, 23), +(375, 134, 23), +(376, 135, 23), +(377, 136, 18), +(378, 136, 23), +(379, 137, 23), +(380, 138, 23), +(381, 139, 23), +(382, 139, 21), +(383, 100, 21), +(384, 100, 23), +(385, 101, 21), +(386, 101, 23), +(387, 102, 21), +(388, 102, 23), +(389, 103, 21), +(390, 103, 23), +(391, 104, 23), +(392, 105, 21), +(393, 105, 23), +(394, 106, 21), +(395, 106, 23), +(396, 107, 23), +(397, 108, 21), +(398, 108, 23), +(399, 109, 21), +(400, 109, 23), +(401, 110, 21), +(402, 110, 23), +(403, 111, 21), +(404, 111, 23), +(405, 112, 21), +(406, 112, 23), +(407, 113, 21), +(408, 113, 23), +(409, 114, 22), +(410, 115, 23), +(411, 116, 23), +(412, 117, 23), +(413, 118, 21), +(414, 118, 23), +(415, 119, 21), +(416, 119, 23), +(417, 81, 23), +(418, 82, 23), +(419, 83, 21), +(420, 83, 23), +(421, 84, 23), +(422, 85, 21), +(423, 85, 22), +(424, 85, 23), +(425, 86, 21), +(426, 86, 22), +(427, 86, 23), +(428, 87, 21), +(429, 87, 22), +(430, 87, 23), +(431, 88, 21), +(432, 88, 22), +(433, 88, 23), +(434, 89, 21), +(435, 89, 22), +(436, 89, 23), +(437, 90, 23), +(438, 90, 23), +(439, 91, 21), +(440, 91, 22), +(441, 91, 23), +(442, 92, 21), +(443, 92, 22), +(444, 92, 23), +(445, 93, 23), +(446, 94, 21), +(447, 94, 23), +(448, 95, 23), +(449, 96, 21), +(450, 96, 23), +(451, 97, 21), +(452, 97, 23), +(453, 98, 21), +(454, 98, 23), +(455, 99, 21), +(456, 99, 23), +(457, 31, 22), +(458, 32, 22), +(459, 33, 21), +(460, 33, 22), +(461, 33, 23), +(462, 36, 21), +(463, 36, 22), +(464, 36, 23), +(465, 37, 21), +(466, 37, 23), +(467, 38, 21), +(468, 38, 22), +(469, 38, 23), +(470, 53, 21), +(471, 53, 22), +(472, 53, 23), +(473, 54, 1), +(474, 54, 16), +(475, 54, 7), +(476, 54, 20), +(477, 54, 21), +(478, 54, 23), +(479, 55, 21), +(480, 55, 23), +(481, 56, 21), +(482, 56, 23), +(483, 57, 21), +(484, 57, 23), +(485, 58, 23), +(486, 64, 23), +(487, 65, 21), +(488, 65, 23), +(489, 69, 21), +(490, 69, 23), +(491, 70, 23), +(492, 71, 23), +(493, 72, 21), +(494, 72, 23), +(495, 73, 21), +(496, 73, 23), +(497, 74, 1), +(498, 74, 16), +(499, 74, 21), +(500, 74, 23), +(501, 75, 23), +(502, 76, 23), +(503, 77, 23), +(504, 78, 23), +(505, 79, 21), +(506, 79, 23), +(507, 80, 23), +(508, 168, 7), +(509, 169, 7), +(510, 169, 2), +(511, 169, 19), +(512, 170, 7), +(513, 170, 2), +(514, 170, 19), +(515, 171, 7), +(516, 171, 2), +(517, 171, 19), +(518, 172, 7), +(519, 172, 2), +(520, 172, 19), +(521, 173, 7), +(522, 173, 2), +(523, 173, 19), +(524, 174, 2), +(525, 174, 7), +(526, 174, 19); + + +DELETE FROM `exercise_type_image`; +INSERT INTO `exercise_type_image` (`image_id`, `exercise_type_id`, `name`, `type`, `url`) VALUES +(5, 37, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(11, 53, 'menu', 'menu', 'images/3.bcs1.png'), +(12, 31, '300m', 'menu', 'images/1.2.1.300m.png'), +(13, 33, 'Menu', 'menu', 'images/2.1.2.pushup.png'), +(14, 32, '400m', 'menu', 'images/1.2.2.400m.png'), +(15, 38, 'Menu', 'menu', 'images/2.2.1.2.pullups.png'), +(16, 54, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(18, 65, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(20, 114, 'menu', 'menu', 'images/1.1.1.cooper.png'), +(21, 132, 'menu', 'menu', 'images/2.2.1.1RM.png'), +(22, 35, 'menu', 'menu', 'images/2.1.4.squats.png'), +(23, 159, 'Menu', 'menu', 'images/Gain_muscle.png'), +(24, 130, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(25, 156, 'kép1', 'menu', 'images/2.1.4.squats.png'), +(26, 152, 'kép1', 'menu', 'images/legpress.jpg'), +(27, 146, 'kép1', 'menu', 'images/2.1.4.squats.png'), +(28, 143, 'kép1', 'menu', 'images/squat_vFeugl9.jpg'), +(29, 134, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(30, 116, 'menu', 'menu', 'images/cable_triceps.png'), +(31, 100, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(32, 96, 'menu', 'menu', 'images/shoulder_press.png'), +(33, 78, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(34, 128, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(35, 126, 'menu', 'menu', 'images/tricdip.jpg'), +(37, 86, 'Menu', 'menu', 'images/Back_pullup.png'), +(38, 90, 'Menu', 'menu', 'images/Back_pullup.png'), +(39, 161, 'kép1', 'menu', 'images/2.1.4.squats.png'), +(40, 160, 'Menu', 'menu', 'images/2.1.4.squats.png'), +(41, 154, 'Menu', 'menu', 'images/2.1.4.squats.png'), +(42, 151, 'kép1', 'menu', 'images/legpress.jpg'), +(43, 150, 'kép1', 'menu', 'images/legpress.jpg'), +(44, 145, 'kép1', 'menu', 'images/2.1.4.squats.png'), +(45, 142, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(46, 95, 'menu', 'menu', 'images/shoulder_press.png'), +(47, 75, 'Menu', 'menu', 'images/kabeles_tarogatas.png'), +(48, 55, 'Menu', 'menu', 'images/incline_press.png'), +(49, 57, 'Menu', 'menu', 'images/incline_dumbbel_press.png'), +(50, 56, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(51, 58, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(52, 64, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(53, 69, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(54, 70, 'Menu', 'menu', 'images/chest_machine.png'), +(55, 71, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(56, 72, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(57, 73, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(58, 74, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(59, 76, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(60, 77, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(61, 79, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(62, 80, 'Menu', 'menu', 'images/2.2.1.1.chestpress.png'), +(63, 81, 'Menu', 'menu', 'images/Back_pullup.png'), +(64, 82, 'Menu', 'menu', 'images/Back_pullup.png'), +(65, 83, 'Menu', 'menu', 'images/Back_pullup.png'), +(66, 84, 'Menu', 'menu', 'images/Back_pullup.png'), +(67, 85, 'Menu', 'menu', 'images/Back_pullup.png'), +(68, 91, 'Menu', 'menu', 'images/Back_pullup.png'), +(69, 93, 'Menu', 'menu', 'images/Back_pullup.png'), +(70, 98, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(71, 99, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(72, 101, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(73, 102, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(74, 103, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(75, 104, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(76, 105, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(77, 106, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(78, 107, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(79, 108, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(80, 109, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(81, 110, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(82, 111, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(83, 112, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(84, 113, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(86, 115, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(87, 97, 'Menu', 'menu', 'images/2.2.1.5.shoulders.png'), +(88, 124, 'menu', 'menu', 'images/tricdip.jpg'), +(89, 125, 'menu', 'menu', 'images/tricdip.jpg'), +(90, 127, 'menu', 'menu', 'images/tricdip.jpg'), +(91, 124, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(92, 124, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(93, 125, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(94, 127, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(95, 129, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(96, 131, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(97, 133, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(98, 125, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(99, 136, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(100, 137, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(101, 138, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(102, 139, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(103, 140, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(104, 141, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(105, 135, 'Menu', 'menu', 'images/2.2.1.3.biceps.png'), +(106, 144, 'menu', 'menu', 'images/2.1.4.squats.png'), +(107, 144, 'menu', 'menu', 'images/2.1.4.squats.png'), +(108, 147, 'menu', 'menu', 'images/2.1.4.squats.png'), +(109, 148, 'menu', 'menu', 'images/2.1.4.squats.png'), +(110, 149, 'menu', 'menu', 'images/2.1.4.squats.png'), +(111, 153, 'menu', 'menu', 'images/2.1.4.squats.png'), +(112, 155, 'menu', 'menu', 'images/2.1.4.squats.png'), +(113, 157, 'menu', 'menu', 'images/2.1.4.squats.png'), +(114, 158, 'menu', 'menu', 'images/2.1.4.squats.png'), +(115, 162, 'menu', 'menu', 'images/3.3.sizes.png'), +(116, 168, 'Menu', 'image', 'images/squat_uHyWvQ2.jpg'), +(117, 169, 'Pop Squat', 'image', 'images/pop_squat.JPG'), +(118, 170, 'Lunge Drive Combo', 'image', 'images/capture2.JPG'), +(119, 171, 'Push Up & Reach', 'image', 'images/Capture3.JPG'), +(120, 172, 'Speed Skater', 'image', 'images/Capture4.JPG'), +(121, 173, 'Jumping Jacks', 'image', 'images/Capture5.JPG'), +(122, 174, 'Crab Dance', 'image', 'images/Capture6.JPG'), +(123, 175, 'Side lunge & reach', 'image', 'images/Capture7.JPG'), +(124, 176, 'Ninja Squat Pulse', 'image', 'images/Capture8.JPG'), +(125, 177, 'Squat Jacks', 'image', 'images/Capture9.JPG'), +(126, 178, 'Mountain climbers', 'image', 'images/Capture10.JPG'), +(127, 179, 'Oblique/Rock climbers', 'image', 'images/Capture11.JPG'), +(128, 180, 'Hip twister', 'image', 'images/Capture12.JPG'), +(129, 181, 'Bicycle crunch', 'image', 'images/Capture13.JPG'), +(130, 182, 'Jump Squat', 'image', 'images/Capture14.JPG'), +(131, 183, 'Spot Sprint', 'image', 'images/Capture15.JPG'), +(132, 184, 'T-Push Ups', 'image', 'images/Capture16.JPG'), +(133, 185, 'Laydawn Push Ups', 'image', 'images/Capture17.JPG'), +(134, 186, 'Burpees_v1', 'image', 'images/Capture18.JPG'), +(135, 187, 'Burpees_v2', 'image', 'images/Capture19.JPG'), +(136, 188, 'Skate Steps', 'image', 'images/Capture20.JPG'), +(137, 189, 'Touch Lunge & Kick', 'image', 'images/Capture21.JPG'), +(138, 190, 'Plank', 'image', 'images/Capture22.JPG'), +(139, 191, 'Hip Dip Plank', 'image', 'images/Capture23.JPG'), +(140, 192, 'Side Plank', 'image', 'images/Capture24.JPG'), +(141, 193, 'Plank Toe Taps', 'image', 'images/Capture25.JPG'), +(142, 194, 'Walking Plank', 'image', 'images/Capture26.JPG'), +(143, 195, 'Knee Drive Twister', 'image', 'images/Capture27.JPG'), +(144, 196, 'Bird-Dog Plank', 'image', 'images/Capture28.JPG'), +(145, 197, 'Side Bridge & Kick', 'image', 'images/Capture29.JPG'), +(146, 198, 'Warrior Lunge', 'image', 'images/Capture30.JPG'), +(147, 199, 'Warrior Lunge Combo', 'image', 'images/Capture31.JPG'), +(148, 200, 'Low Lunge', 'image', 'images/Capture32.JPG'), +(149, 201, 'Leg Drop', 'image', 'images/Capture33.JPG'), +(150, 202, 'Butterfly Twist', 'image', 'images/Capture34.JPG'), +(151, 203, 'Bear Kick Back', 'image', 'images/Capture35.JPG'), +(152, 204, 'Down Dog Crunch', 'image', 'images/Capture36.JPG'), +(153, 205, 'Warrior III. Flow', 'image', 'images/Capture37.JPG'), +(154, 206, 'Side Bridge & Lift', 'image', 'images/Capture38.JPG'), +(155, 207, 'Plank Leg Lift', 'image', 'images/Capture39.JPG'), +(156, 208, 'Side Plank', 'image', 'images/Capture40.JPG'), +(157, 209, 'Push Ups', 'image', 'images/Capture41.JPG'), +(158, 210, 'Plank & Tap', 'image', 'images/Capture42.JPG'), +(159, 211, 'Star Jumps', 'image', 'images/Capture43.JPG'), +(160, 212, 'Plank Stroke', 'image', 'images/Capture44.JPG'), +(161, 213, 'Dolphin Push Ups', 'image', 'images/Capture45.JPG'), +(162, 214, 'Super V Squeeze', 'image', 'images/Capture46.JPG'), +(163, 215, 'Inchworm Jack', 'image', 'images/Capture47.JPG'), +(164, 216, 'Squat and Leg lift', 'image', 'images/Capture48.JPG'), +(165, 217, 'Lunge Leg', 'image', 'images/Capture49.JPG'), +(166, 218, '1-Leg Deadlift', 'image', 'images/Capture50.JPG'), +(167, 219, 'Deadlift', 'image', 'images/Capture51.JPG'), +(168, 220, 'In and out squat', 'image', 'images/Capture52.JPG'), +(169, 221, 'Side Lunge', 'image', 'images/Capture53.JPG'), +(170, 222, 'Prisoner Stand Ups', 'image', 'images/Capture54.JPG'), +(171, 223, 'Squat', 'image', 'images/Capture55.JPG'), +(172, 224, 'Sumo Squat', 'image', 'images/Capture56.JPG'), +(173, 225, 'Curtsey and Side Lift', 'image', 'images/Capture57.JPG'), +(174, 226, 'Wall Sit', 'image', 'images/Capture58.JPG'), +(175, 227, 'Booty Burn', 'image', 'images/Capture59.JPG'), +(176, 228, 'Shuffle Steps', 'image', 'images/Capture60.JPG'), +(177, 229, 'Rear Leg Lift', 'image', 'images/Capture61.JPG'), +(178, 230, 'Side Lift', 'image', 'images/Capture62.JPG'), +(179, 231, 'Curtsey', 'image', 'images/Capture63.JPG'), +(180, 232, 'Leg Lift', 'image', 'images/Capture64.JPG'), +(181, 233, 'Bridge & Kick', 'image', 'images/Capture65.JPG'), +(182, 234, 'In & Out Laydawn Heel Tuch', 'image', 'images/Capture66.JPG'), +(183, 235, 'Inner Leg Lift_v1', 'image', 'images/Capture67.JPG'), +(184, 236, 'Inner Leg Lift_v2', 'image', 'images/Capture68.JPG'), +(185, 237, 'Pinguin Crunch', 'image', 'images/Capture69.JPG'), +(186, 238, 'Riverse Tuck & Kick Out', 'image', 'images/Capture70.JPG'), +(187, 239, 'Bent Knee V-crunch', 'image', 'images/Capture71.JPG'), +(188, 240, 'Pike Kick', 'image', 'images/Capture72.JPG'), +(189, 241, 'Side Kick', 'image', 'images/Capture73.JPG'), +(190, 242, 'Riverse Crunch', 'image', 'images/Capture74.JPG'), +(191, 243, 'Scissor Kicks', 'image', 'images/Capture75.JPG'), +(192, 244, 'Scissor Kicks with Toe Touch', 'image', 'images/Capture76.JPG'), +(193, 245, 'Prayer Crunch', 'image', 'images/Capture77.JPG'), +(194, 246, 'Full Body Crunch', 'image', 'images/Capture78.JPG'), +(195, 247, 'Unicorn Crunch', 'image', 'images/Capture79.JPG'), +(196, 248, 'Rainbow „V”', 'image', 'images/Capture80.JPG'), +(197, 249, 'Butterfly Sit Up', 'image', 'images/Capture81.JPG'), +(198, 250, 'Russian Twist', 'image', 'images/Capture82.JPG'), +(199, 251, 'Tricep Press', 'image', 'images/Capture83.JPG'), +(200, 252, 'Robot Row Combo', 'image', 'images/Capture84.JPG'), +(201, 253, 'Side Bridge & Squeeze', 'image', 'images/Capture85.JPG'), +(202, 254, 'Underhand Row', 'image', 'images/Capture86.JPG'), +(203, 255, 'Tricep Kick Back', 'image', 'images/Capture87.JPG'), +(204, 256, 'Lateral Combo', 'image', 'images/Capture88.JPG'), +(205, 257, 'One Arm Raw', 'image', 'images/Capture89.JPG'), +(206, 258, 'Chest Press', 'image', 'images/Capture90.JPG'), +(207, 259, 'High Pull', 'image', 'images/Capture91.JPG'), +(209, 261, 'Menu', 'image', 'images/3.1.BMI.png'), +(210, 262, 'Menu', 'image', 'images/3.2.BMR.png'); + + +DELETE FROM `exercise_type_parents`; +INSERT INTO `exercise_type_parents` (`exercise_type_parents_id`, `exercise_tree_id`, `exercise_type_id`) VALUES +(1, 0, 1), +(2, 0, 2), +(3, 0, 3), +(4, 0, 4), +(5, 0, 5), +(6, 0, 7), +(7, 0, 8), +(8, 0, 9), +(9, 0, 10), +(10, 0, 11), +(16, 5, 162), +(17, 7, 114), +(18, 8, 31), +(19, 8, 32), +(20, 9, 6), +(21, 9, 132), +(22, 22, 159), +(23, 10, 33), +(24, 10, 34), +(25, 10, 35), +(26, 10, 36), +(27, 10, 38), +(28, 10, 53), +(29, 14, 37), +(30, 14, 54), +(31, 14, 55), +(32, 14, 56), +(33, 14, 57), +(34, 14, 58), +(35, 14, 64), +(36, 14, 65), +(37, 14, 69), +(38, 14, 70), +(39, 14, 71), +(40, 14, 72), +(41, 14, 73), +(42, 14, 74), +(43, 14, 75), +(44, 14, 76), +(45, 14, 77), +(46, 14, 78), +(47, 14, 79), +(48, 14, 80), +(49, 15, 128), +(50, 15, 129), +(51, 15, 130), +(52, 15, 131), +(53, 15, 133), +(54, 15, 134), +(55, 15, 135), +(56, 15, 136), +(57, 15, 137), +(58, 15, 138), +(59, 15, 139), +(60, 15, 140), +(61, 15, 141), +(62, 15, 142), +(63, 16, 116), +(64, 16, 117), +(65, 16, 118), +(66, 16, 119), +(67, 16, 120), +(68, 16, 121), +(69, 16, 122), +(70, 16, 123), +(71, 16, 124), +(72, 16, 125), +(73, 16, 126), +(74, 16, 127), +(75, 17, 95), +(76, 17, 96), +(77, 17, 97), +(78, 17, 98), +(79, 17, 99), +(80, 17, 100), +(81, 17, 101), +(82, 17, 102), +(83, 17, 103), +(84, 17, 104), +(85, 17, 105), +(86, 17, 106), +(87, 17, 107), +(88, 17, 108), +(89, 17, 109), +(90, 17, 110), +(91, 17, 111), +(92, 17, 112), +(93, 17, 113), +(94, 17, 115), +(95, 18, 143), +(96, 18, 144), +(97, 18, 145), +(98, 18, 146), +(99, 18, 147), +(100, 18, 148), +(101, 18, 149), +(102, 18, 150), +(103, 18, 151), +(104, 18, 152), +(105, 18, 153), +(106, 18, 154), +(107, 18, 155), +(108, 18, 161), +(109, 19, 156), +(110, 19, 157), +(111, 19, 158), +(112, 20, 81), +(113, 20, 82), +(114, 20, 83), +(115, 20, 84), +(116, 20, 85), +(117, 20, 86), +(118, 20, 87), +(119, 20, 88), +(120, 20, 89), +(121, 20, 90), +(122, 20, 91), +(123, 20, 93), +(124, 20, 94), +(125, 21, 92), +(126, 21, 160), +(128, 19, 168), +(129, 22, 169), +(130, 10, 169), +(131, 22, 170), +(132, 10, 170), +(133, 22, 171), +(134, 10, 171), +(135, 22, 172), +(136, 10, 172), +(137, 22, 173), +(138, 10, 173), +(140, 5, 261), +(141, 5, 262); + + +DELETE FROM `exercise_type_translation`; +INSERT INTO `exercise_type_translation` (`translation_id`, `language_code`, `exercise_type_id`, `name`, `description`) VALUES +(2, 'hu', 33, 'Fekvőtámasz', 'fekvőtámasz'), +(5, 'hu', 37, 'Fekvenyomás', 'A fekvenyomás egy alapgyakorlat, amely elsődlegesen a mellizmokat veszi célba, de másodlagos mozgatóként a tricepsz és a deltaizmok is fejlődnek általa. Testépítők kedvenc gyakorlata. Kiemelten fontos gyakorlat a mellizmok edzésében, ezért törekedjünk a megfelelő súllyal való, megfelelő számú szabályos ismétlés végrehajtására.\r\n\r\nKiinduló helyzet:\r\nHáton fekvésben a padon, kezeinket a váll szélességénél kb. egy ököllel szélesebben fogva a rudat (van egy jelzés a rúdon, ahol a gyűrűs ujjnak a helye van).\r\n\r\nVégrehajtás:\r\nA rúd kiemelése után a mellkas közepéig engedjük le a rudat, majd kinyomjuk függőlegesen. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint.\r\n\r\nJótanács: \r\nFigyeljünk a folyamatos légzésre, azaz nyomáskor kilégzés, mellkasra engedéskor kilégzést használj. Hátad maradjon a padon. Ne homoríts! Mindig figyeljünk a megfelelő súly kiválasztására. Ha szükséges kérjünk meg egy társat segítségül az utolsó ismétlésünk biztonságos végrehajtása érdekében.'), +(11, 'hu', 53, 'Plank', ''), +(12, 'hu', 31, '300m', ''), +(13, 'hu', 32, '400m', ''), +(14, 'hu', 38, 'Húzodszkodás', 'A széles fogású húzódzkodás a széles hátizmok fejlesztésére alkalmas leginkább.\r\nKiinduló helyzet\r\nKapaszkodj egy rúdba a fejed fölött olyan széles fogással, amely legalább 30 cm-rel szélesebb a vállaknál mindkét oldalon. \r\nA mozgás\r\nHúzd fel magadat, miközben a könyöködet mindvégig hátrafeszíted. A felső pont elérése után ereszkedj le, amíg a hátizmaid teljesen meg nem nyúlnak, majd ismételd a mozdulatot.'), +(15, 'hu', 54, 'Fekvenyomás egykezes súlyzókkal', 'A fekvenyomás egykezes súlyzókkal alapvetően a mellizom belső, középső részét edzi meg, de az egész mellizmot stimulálja. Deltaizmok és a tricepsz szintén résztvevői a gyakorlat végrehajtásnak.\r\n\r\nKiinduló helyzet\r\nHaton fekvésben vállszélesen teljesen kinyújtott karral kell tartani a súlyokat normál fogással a padlóhoz képest merőleges helyzetben.\r\n\r\nVégrehajtás:\r\nMindkét súlyt engedjük le a mellkasmellé. A felkart a testre majdnem merőleges síkban tartva a mozdulat közben. A leengedés végpontján visszanyomjuk a súlyzókat a kiinduló helyzetbe.\r\n\r\nTipp:\r\nAz alkar végig maradjon függőleges pozícióban. Mivel a fekvenyomás egykezes súlyzókkal nagyobb mozgástartpmányt tesz lehetővé, így egy stabil tartás mellett nagyobb terhelést tud biztosítani a mellizmoknak.'), +(16, 'hu', 55, 'Fekvenyomás ferdepadon', 'A fekvenyomás ferde padon a mellizmok felső részét edzi meg igazán. Közreműködőként a deltaizmok elülső részét és tricepszet edzi meg. Előszeretettel használjuk azért mert már a kulcscsont alól domborítja az izmokat.\r\n\r\nKiinduló helyzet:\r\nHáton fekve 35-45 fok közötti dőlésű padon. Kezeinket a váll szélességénél kb. egy ököllel szélesebben fogva a rudat (van egy jelzés a rúdon, ahol a gyűrűs ujjnak a helye van).\r\n\r\nVégrehajtás:\r\nA rúd kiemelése után a mellkas kulcscsont alatti részéig engedjük le a rudat, majd kinyomjuk függőlegesen. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint.\r\n\r\nTipp:\r\nSzélesebb fogásnál nagyobb bedurranást érhetünk el. A fekvenyomás ferdepadon a normál fekvenyomáshoz képest célszerűbb gyakorlat lehet, hogyha a mellizom felső részei kevésbé fejlettek.'), +(17, 'hu', 56, 'Szűk fogásos fekvenyomás', 'A szűk fogásos fekvenyomás elsődlegesen a mellizmokat, de azon belül is az eredésközeli, azaz a szegycsonti részt edzi meg. Sokkal jobban veszi igénybe a tricepszet, mint a normál fekvenyomás.\r\n\r\nKiinduló helyzet\r\nHányat fekvés a padon a vállszélességnél szűkebb normál fogásban. Kinyomjuk a súlyt a mellkasunk felé és ügyelünk arra, hogy a könyök minimálisan hajlítva maradjon.\r\n\r\nA mozgás\r\nA rúd kiemelése után a mellkas közepéig engedjük le a rudat, majd kinyomjuk függőlegesen. Minél szélesebb fogást használsz, annál nagyobb terhelés tevődik át a mellizom belső részéről a külső részére. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint. Figyeljünk a könyökünkre, hogy ne nyújtsuk ki a kezet! Ha szükséges kérjünk meg egy társat segítségül az utolsó ismétlésünk biztonságos végrehajtása érdekében.'), +(18, 'hu', 57, 'Fekvenyomás ferde padon egykezes súlyzókkal', 'A ferdepados fekvenyomás egykezes súlyzókkal a mellizmok kulcscsonti felső részét stimulálja. Elsősorban a mellkas felső belső részét hivatott megedzeni, de szinergistaként az elülső delta és a tricepsz is részt vesz a gyakorlatban\r\n\r\n\r\nKiinduló helyzet\r\nMint minden ferdepados mell gyakorlatot ezt is 35-40 fokos padon végezzük. Minél magasabb a dőlésszög, annál inkább a vállak veszik át a mozgatás szerepét.\r\nA mozgás\r\nA kiinduló helyzetből a súlyokat minél mélyebbre engedjük a mellkasunk mellé, majd innen nyomjuk ki egyszerre függőlegesen. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint.'), +(19, 'hu', 58, 'Fekvenyomás negatív ferdepadon', 'A fekvenyomás negatív ferdepadon elsősorban a mellizom alsó részét stimulálja. \r\nKiinduló helyzet\r\nHáton fekvésben vállszélesen teljesen kinyújtott karral kell tartani a rudat normál fogással a padlóhoz képest merőleges helyzetben.\r\nVégrehajtás:\r\nA súlyt engedjük le a mellkasra. A leengedés végpontján visszanyomjuk a rudat a kiinduló helyzetbe. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint.'), +(20, 'hu', 69, 'Fekvenyomás negatív ferde padon egykezes súlyzókkal', 'A fekvenyomás negatív ferdepadon elsősorban a mellizom alsó részét stimulálja. \r\nKiinduló helyzet\r\nHáton fekvésben vállszélesen teljesen kinyújtott karral kell tartani a súlyokat normál fogással a padlóhoz képest merőleges helyzetben.\r\n\r\nVégrehajtás:\r\nA súlyzókat engedjük le a mellkasra. A leengedés végpontján visszanyomjuk a kiinduló helyzetbe. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint.'), +(22, 'hu', 70, 'Fekvenyomás gépen', 'A fekvenyomást helyettesíthetjük gépekkel, ha szükséges. Ebben az esetben le kell mondanunk a normál fekvenyomás adta stabilizáló és kiegészítő terhelés kapó izmok stimulálásáról. Elsősorban akkor ajánljuk, amikor nincsen társ, de szeretnénk nagy súlyokkal edzeni. Kezdőknek is tökéletes kiegészítője a normál fekvenyomásnak.'), +(23, 'hu', 71, 'Fekvenyomás Smith gépen (erőkeretben)', 'A fekvenyomás erőkeretben lehetővé teszi, hogy segítő nélkül is biztonságosan tudjuk végrehajtani a gyakorlatot.\r\n\r\nKiinduló helyzet\r\n\r\nÁllítsd be a gépet úgy, hogy ha a rudat leengedjük a mellkasra, akkor még legyen egy kevés hely a test és a rúd között. Háton fekvésben a padon, kezeinket a váll szélességénél kb. egy ököllel szélesebben fogva a rudat (van egy jelzés a rúdon, ahol a gyűrűs ujjnak a helye van).\r\n\r\nVégrehajtás:\r\nA rúd kiemelése után a mellkas közepéig engedjük le a rudat, majd kinyomjuk függőlegesen. Ismételjük meg a mozgást az edzéstervben írt ismétlésszám szerint'), +(24, 'hu', 72, 'Tárogatás egyenes padon', 'Ez a mozgás a mellizmokat és a deltaizmokat fejleszti.\r\n\r\nKiinduló helyzet\r\n\r\nHáton fekvésben a padon, mindkét kezében egy egykezes súlyzót tartunk nyújtott karral függőlegesen a mellkas fölött.\r\n\r\nA mozgás\r\n\r\nA súlyzókat engedjük le a könyököket enyhén behajlítva és távolítsuk a törzsünktől oldalirányba és lefelé olyan mélyre, ahol kellemes feszülést nem érzünk a mellkasi területen. Felkaroknak jelentősen testvonala alá kell mennie.\r\n\r\nTipp\r\n\r\nFigyeljünk oda az enyhén behajlított könyökre. Ez nem csak az ízületet védi meg, hanem csak így edződik meg igazán a mellkas területe. A legalsó ponton vegyünk mély lélegzetet, hogy minél jobban tágulhasson a mellkas.'), +(25, 'hu', 73, 'Tárogatás ferde padon', 'Kiinduló helyzet\r\n\r\nMint minden ferdepados mell gyakorlatot ezt is 35-40 fokos padon végezzük. Háton fekvésben a padon, mindkét kezében egy egykezes súlyzót tartunk nyújtott karral függőlegesen a mellkas fölött.\r\n\r\nA mozgás\r\nA súlyzókat engedjük le a könyököket enyhén behajlítva és távolítsuk a törzsünktől oldalirányba és lefelé olyan mélyre, ahol kellemes feszülést nem érzünk a mellkasi területen. Felkaroknak jelentősen testvonala alá kell mennie.\r\n\r\ntipp\r\nFigyeljünk oda az enyhén behajlított könyökre. Ez nem csak az ízületet védi meg, hanem csak így edződik meg igazán a mellkas területe. A legalsó ponton vegyünk mély lélegzetet, hogy minél jobban tágulhasson a mellkas.'), +(26, 'hu', 74, 'Tárogatás negatív ferdepadon', 'Kiinduló helyzet\r\n\r\nFeküdj hanyatt negatív ferde padon, mindkét kezében egy egykezes súlyzót tartunk nyújtott karral függőlegesen a mellkas fölött.\r\n\r\nA mozgás\r\nA súlyzókat engedjük le a könyököket enyhén behajlítva és távolítsuk a törzsünktől oldalirányba és lefelé olyan mélyre, ahol kellemes feszülést nem érzünk a mellkasi területen. Felkaroknak jelentősen testvonala alá kell mennie.\r\n\r\ntipp\r\n\r\nFigyeljünk oda az enyhén behajlított könyökre. Ez nem csak az ízületet védi meg, hanem csak így edződik meg igazán a mellkas területe. A legalsó ponton vegyünk mély lélegzetet, hogy minél jobban tágulhasson a mellkas.'), +(27, 'hu', 75, 'Tárogatás kábellel egyenes padon', 'A gyakorlat nagyon hasonló a normál tárogatáshoz. A különbség mindössze annyi, hogy két csiga között végezzük kábellel a tárogatást. A gyakorlat elsősorban a mell belső részét edzi meg.'), +(28, 'hu', 76, 'Tárogatás kábellel ferde padon', 'A gyakorlat nagyon hasonló a normál tárogatáshoz. A különbség mindössze annyi, hogy két csiga között végezzük kábellel a tárogatást. A gyakorlat elsősorban a mell belső felső részét edzi meg.'), +(29, 'hu', 77, 'Tárogatás kábellel negatív ferde padon', 'A gyakorlat nagyon hasonló a normál tárogatáshoz. A különbség mindössze annyi, hogy két csiga között végezzük kábellel a tárogatást. A gyakorlat elsősorban a mell belső alsó részét edzi meg.'), +(30, 'hu', 78, 'Tárogatás Peck-Deck gépen', 'A tárogatás pec-deck gépen az ízületeket kímélve remekül fejleszti a mellizom belső részeit. A kézisúlyzós tárogatáshoz képest itt a karokkal zárt állapotban, csúcsösszehúzódáskor is van terhelés.\r\nKiinduló helyzet\r\nÁllítsuk be az ülésmagasságot és ülj je kényelmesen mellgépre. Fogd meg a gép fogantyúit. (Eltérés van egyes gépek között, de legtöbbször a használati utasítás egy rajzon látható)\r\nA mozgás\r\nA mellizom megfeszítésével nyomjuk össze a karokat. Lassú, de ellenőrzött mozgással engedjük vissza a karokat a kiinduló helyzetbe. A fej mindvégig a pozíciójában marad.'), +(31, 'hu', 79, 'Áthúzás egykezes súlyzóval', 'Az áthúzás mellre a legjobb gyakorlat a mellkas tágítására. Fejleszti a melleken kívül a hát és az elülső fűrészizmokat. \r\n\r\nKiinduló helyzet\r\n\r\nFogjunk meg egy kézi súlyzót a tárcsa, vagy a gömb része alatt úgy, hogy az összezárt tenyerünk és hüvelykujjaink között lóghasson a rúd része. Feküdjünk hanyatt keresztbe egy padon úgy, hogy csak a vállak és a hát felső része érintse a padot. A csípőt tartsuk minél mélyebb pozícióban. A súlyt tartsuk enyhén hajlított karokkal függőlegesen a mellkas fölött.\r\n\r\nA mozgás\r\nKocentráltan eresszük le a súlyt a fej fölött hátra olyan alacsonyra, ahonnan még biztonságosan vissza tudjuk hozni a kiinduló pozícióba. Ismételd a mozgást az előírt számban.'), +(32, 'hu', 80, 'Csigás keresztezés', ''), +(33, 'hu', 81, 'Kábeles evezés', 'Ezt a gyakorlatot hosszú kábeles géppel kell végezni. Rögzítse a lábát a készüléken, majd húzza a fogantyút a teste középső része felé, vízszintes irányban. Maradjon ebben a helyzetben egy másodpercig, majd engedje a karját lassan kinyúlni, amíg a széles hátizmok meg nem feszülnek. Húzza be a fogantyút újból, és ismételje a mozdulatot. A karok kinyúlásakor próbáljon meg maximális hátizom-feszülésre törekedni.'), +(34, 'hu', 82, 'T-rudas evezés', 'A T-rudas evezés egy kiváló gyakorlat a hátizom vastagságának növelésére.\r\nKiinduló helyzet\r\nRagadd meg a fogantyút, vagy rudat, és egyenesedj fel vele kb 45 fokos szögig a törzseddel.\r\nA mozgás\r\nHúzd a hasadhoz a rudat/fogantyút, majd amikor a rúdra pakolt tárcsák megérintik a hasadat, engedd lassan vissza a kar nyújtott pozíciójáig a súlyokat. Ügyelj rá, hogy ekkor a hátizom is megnyúljon, ne csak a karodat nyújtsd ki. Ezzel a gyakorlattal rendkívül jó izomérzet érhető el, ha nem érzed a hátadat a gyakorlatok közben, mindenképpen érdemes tenni vele egy próbát.'), +(35, 'hu', 83, 'Fűrészelés', 'Egykezes döntött törzsű evezés - Fűrészelés\r\n\r\nAz egykezes döntött törzsű evezés kézisúlyzóval a hát felső izmait, különösen a széles hátizmokat és a karhajlító izmokat, főleg a kétfejű karizmot dolgoztatja meg.\r\nKiinduló helyzet\r\nHajolj előre, az egyik karod és az egyik térded egy padon támaszkodik. Nyúlj le a másik karoddal, és ragadd meg a padlón fekvő egykezes súlyzót.\r\nA mozgás\r\nEmeld a súlyzót vállad magasságáig, vagy még feljebb, hátizmaidat használva. Lassan ereszd vissza a kézisúlyzót, hadd nyúljon ki jól a hátizom, mad ismételd a mozdulatot.'), +(36, 'hu', 84, 'Egykezes evezés T-rúddal', 'Amennyiben az erre a célra szolgáló gépen végzed a T-rudas evezést, van lehetőséged kipróbálni az egykezes változatot is, ami jóval koncentráltabb végrehajtást tesz lehetővé, mint a kétkezes T-rudas evezés - cserébe picit talán kényelmetlenebb. De egy próbát mindenképpen megér! Ugyanúgy a hátizom vastagságának növelésére alkalmas elsősorban, bár tudni kell, hogy nincs kifejezetten a hátat CSAK vastagító, vagy szélesítő gyakorlat. \r\n\r\nKiinduló helyzet\r\nUgyanazt a pozíciót vedd fel, mint a T-rudas evezés esetében, de csak az egyik kezeddel fogd meg a fogantyút.\r\n\r\nA mozgás\r\nA könyöködre koncentrálva húzd a súlyt fel a hasadig, majd engedd vissza, a hátizmokat a lehető legjobban megnyújtva.'), +(37, 'hu', 85, 'úzódzkodás szűk fogással', 'A húzódzkodás szűk fogással hátizom alsó-külső részét stimulálja leginkább,valamint a fogás és végrehajtás módjától függően a bicepsz is jelentős terhelést kap.\r\nKiinduló helyzet\r\nFogd meg a rudat a vállszélességnél nem szélesebb fogással, a tenyered nézzen magad felé. Használhatsz háromszög fogantyút is - amennyiben a hátad erősítése a fő cél, és nem a bicepszedé, akkor ez a megoldás még jobb is.\r\nA mozgás\r\nEngedd teljesen megnyúlni a hátizmokat, majd a hátad erejével húzd fel magad, amennyire csak lehetséges. Legjobb ha a mellkasod megérinti a rudat. Utána lassan engedd vissza magad, ügyelve a hátizom megnyúlására.'), +(38, 'hu', 86, 'Széles fogású húzódzkodás nyakhoz', 'A széles fogású húzódzkodás nyakhoz a széles hátizmot stimulálja leginkább, de a bicepsz és az alkar is jelentős másodlagos terhelést kap.\r\nKiinduló helyzet\r\nKapaszkodj egy rúdba a fejed fölött olyan széles fogással, amely legalább 30 cm-rel szélesebb a vállaknál mindkét oldalon.\r\nA mozgás\r\nHúzd fel magadat, miközben a könyöködet mindvégig hátrafeszíted. A felső pont elérése után ereszkedj le, amíg a hátizmaid teljesen meg nem nyúlnak, majd ismételd a mozdulatot.'), +(39, 'hu', 87, 'Mellhez húzás szeles fogassal', 'A mellhez húzás széles fogással a széles hátizmokat dolgoztatja meg elsősorban, de a bicepsz és az alkar is kap másodlagos terhelést. A cél az, hogy ezt minél inkább kiküszöböld.\r\nKiinduló helyzet\r\nFogd meg a rudat olyan széles fogással, hogy a lehúzáskor az alkarod függőleges pozícióban legyen. \r\nA mozgás\r\nHúzd le a rudat a könyöködre koncentrálva - ez segít, hogy kikapcsold a bicepszedet a munkából amennyire lehet.'), +(40, 'hu', 88, 'Mellhez húzás szűk fogassal', 'A mellhez húzás szűk fogással a hátizom alsó-külső régióit dolgoztatja meg elsősorban,de természetesen a felső rész is kap a terhelésből, ilyen szinten ez nem izolálható terület.\r\nKiinduló helyzet\r\nÜlj le egy lehúzó hátgép elé vagy térdelj le ha a gép nem elég magas. Fogd meg a rudat szűk fogással (kb. 15-20 cm), vagy legjobb, ha szűk fogantyút használsz.\r\nA mozgás\r\nHúzd le a rudat addig, amíg a melled felső részét meg nem érinti. Lassan engedd vissza a rudat a kiinduló pozícióba.'), +(41, 'hu', 89, 'Mellhez húzás szűk fordított fogassal', 'A mellhez húzás szűk fordított fogással megdolgoztatja a hátizmokat és a bicepszedet is - rajtad múlik, melyik kapja a nagyobb hangsúlyt, attól függ, \"hogyan húzod\" a rudat.\r\nKiinduló helyzet\r\nRagadd meg a rudat úgy, hogy a tenyereid magad felé nézzenek. A fogásszélesség ne legyen nagyobb a vállszélességnél. \r\nA mozgás\r\nHúzd le a rudat a mellkasodhoz, majd miután megérintette azt, engedd vissza, ügyelve arra hogy a hátizmok szépen megnyúljanak a mozdulat során.'), +(42, 'hu', 90, 'Nyakhoz húzás hátgépen', ''), +(43, 'hu', 91, 'Váltott mellhez nyakhoz húzás', 'A váltogatott mellhez-nyakhoz húzás kifejezetten a széles hátizom megdolgoztatásáraalkalmas.\r\nKiinduló helyzet\r\nFogd meg a rudat olyan széles fogással, hogy a lehúzáskor az alkarod függőleges pozícióban legyen. \r\nA mozgás\r\nHúzd le a rudat a könyöködre koncentrálva a mellkasodhoz - ez segít, hogy kikapcsold a bicepszedet a munkából amennyire lehet. Engedd vissza a rudat, majd húzd le a tarkódhoz ugyanilyen módon, aztán onnan is engedd vissza, majd ismét jöhet a mellhez húzás, és így tovább.'), +(44, 'hu', 92, 'Hiperhajlítás', 'A hiperhajlítás a törzsegyenesítő izmokat dolgoztatja meg, de a farizmok és a combhajlító is bele tud szólni a munkába.\r\nKiinduló helyzet\r\nA gyakorlatot egy kifejezetten erre célra szolgáló padon végzik. Egészen a legutóbbi időkig egy magas padot vagy asztalt használtak erre a célra. Feküdj fel a gépre úgy, hogy a csípőd már lelógjon róla. Ha asztalon végzed a gyakorlatot, akkor edzőpartnerre lesz szükséged, aki lefogja a lábaidat. A felsőtestnek teljesen szabadon kell mozognia.\r\nA mozgás\r\nA kezedet tedd a tarkódra, vagy fond össze a mellkasodon, és engedd előre a törzsedet, hogy szabadon lógjon. Innen emelkedj fel, a hátizom erejét használva egészen addig, amíg a tested ki nem egyenesedik. Ereszkedj vissza, majd ismételd a mozdulatot. Soha ne legyen görbe a hátad, és ne is homorítsd túlságosan.'), +(45, 'hu', 93, 'Csigás letolás nyújtott karral', 'A csigás letolás nyújtott karral a széles hátizmot és a fűrészizmokat dolgoztatja megleginkább.\r\nKiinduló helyzet\r\nÁllj meg a felső csiga előtt szemben. Egy kétkezes egyenes rudat, vagy egy kötelet is használhatsz a gyakorlathoz. Dőlj előre kb 45 fokban. Nyújtott karral ragadd meg a rudat vagy kötelet.\r\nA mozgás\r\nMerev karral a hátizom erejével húzd le magad elé (vagy mellé, ha kötelet használsz) a karodat, és amikor az alsó ponthoz értél, feszíts rá a hátadra. Lassan engedd vissza a karjaidat, és hagyd, hogy a hátizom teljesen megnyúljon.'), +(46, 'hu', 94, 'Áthúzás hajlított karral', 'Az áthúzás hajlított karral a mellizmot, a tricepszet, a fűrészizmot, felső hátizmokat, ezen belül is különösen a széles hátizmot építi.\r\nKiinduló helyzet\r\nFeküdj a hátadra egy padon úgy, hogy fejed lelógjon a pad végén, a kétkezes súlyzó a padlón, közvetlenül a fejed mögött legyen.\r\nA mozgás\r\nNyúlj hátra, és ragadd meg a rudat, vállszélességnél kicsít közelebbi fogásvétellel, majd hajlított könyökkel emeld át a fejed fölött a súlyzót. Engedd vissza, majd ismételd a mozdulatot.'), +(47, 'hu', 95, 'Vállgépen nyomás', 'A vállgépen nyomás a vállizom első és oldalsó fejét terheli meg leginkább, de másodlagos terhelést kap a tricepsz, és csekély mértékben a mellizom felső rostjai.\r\nKiinduló helyzet\r\nVedd fel a gépben a számodra legideálisabb pozíciót, a hátad legyen egyenes, mint a szabadsúlyos nyomás esetében. Fogd meg a karokat az adott gép által lehetővé tett fogással.\r\nA mozgás\r\nNyomd ki a kart, tartsd meg egy pillanatra, majd lassan engedd vissza. Vigyázz, hogy ne akaszd ki a könyöködet, ne nyújtsd ki teljesen a karjaidat a mozgástartomány felső holtpontján!'), +(48, 'hu', 96, 'Nyakból nyomás', 'A nyak mögül nyomás rúddal a felsőtest nagy izmait fejleszti, nevezetesen deltaizmot,csuklyásizmot, kis mértékben a mellizmot, tricepszedet és néhányat a hát felső részének izmai közül.\r\nKiinduló helyzet\r\nÜlj le egy egyenes padra úgy, hogy a hátad mögött legyen a súlytartó állvány. Olyan széles fogással fogd meg a rudat, hogy amikor felkarjaid párhuzamosak a padlóval, az alkarok merőlegesen, függőlegesen álljanak.\r\nA mozgás\r\nEreszd le a súlyt a nyak mögött olyan mélyre, amennyire csak lehet, majd azonnal emeld fel, amint eléri a trapézizmot. A rúd nem rugózhat vissza a vállaidról. Könyöködet az egész mozdulat során tartsd annyira hátul, amennyire csak lehet. Amikor a karok kinyúlnak a fej fölött, ne nyújtsd ki a karjaidat teljesen, ne akaszd ki a könyöködet. Folytasd a nyomásokat fel és le, ritmusosan, szünet nélkül.'), +(49, 'hu', 97, 'Fej fölé nyomás egykezes súlyzóval állvá', 'A fej fölé nyomás egykezes súlyzóval állva elsősorban a vállizom első és oldalsó fejét dolgoztatja meg. Másodlagos terhelést kap a tricepsz.\r\nKiinduló helyzet\r\nTarts egy pár egykezes súlyzót vállmagasságban, állj kis terpeszállásba, egyenes háttal,miközben egyenesen előre nézel.\r\nA mozgás\r\nNyomd ki a súlyzókat a fejed fölé, majd engedd vissza a súlyzókat a kiinduló helyzetbe. A felső ponton ne akaszd ki a könyöködet, tehát a karjaidat ne nyújst ki teljesen a mozgástartomány felső holtpontján!'), +(50, 'hu', 98, 'Fej fölé nyomás egykezes súlyzóval', ''), +(51, 'hu', 99, 'Váltott karú fej fölé nyomás', 'A váltott karú fejfölé nyomás a vállizom első és oldalsó fejét stimulálja, illetve kifejezetten hasonló stimulst biztosít, mint a párhuzamos nyomással végzett verzió.\r\nKiinduló helyzet\r\nÜlő helyzetben, egyenes háttal dolgozz. Kiinduló helyzetben mindkét kezedben tarts egy kézisúlyzót vállmagasságban, befelé vagy előre néző tenyérrel. Szorítsd hátra a könyöködet, hogy a terhelést az oldalsó deltaizmokra összpontosítsd.\r\nMozgás\r\nA gyakorlatot a gyengébbik kezeddel kezdd el, és felváltva nyomd ki hol az egyik, hol a másik súlyt. Amint az egyik karod kiegyenesedik, utána rögtön engedd vissza és ezzel párhuzamosan folytasd a gyakorlatot a másik karral. A gyakorlat helyettesíthető klasszikus kézisúlyzós vállból nyomással. Mivel a gykorlat kivitelezése közben könnyebb kizökkenni a mozgástartomány szabályosságából, mintha egyszerre nyomnánk ki mindkét súlyzót, ezért a sérülésveszély ennél a gyakorlatnál valamivel nagyobb, mint a párhuzamos nyomással végezhető vállgyakorlatok esetében.'), +(52, 'hu', 100, 'Arnold nyomás', 'Ez a gyakorlat főként a deltaizom első és oldalsó fejét stimulálja. Másodlagos terhelést kap a tricepsz.\r\nKiinduló helyzet\r\nÁllj vállszélességű terpeszállásba egyenes tartással. Fogj a kezeidbe egy-egy súlyzót úgy, hogy a súlyokat vállmagasságban az arcod előtt tartod. A tenyerek az arcod felé néznek.\r\nA mozdulat\r\nEmeld fel a súlyt a fejed fölé egyenes vonalban, miközben a tenyereidet kifelé fordítod. A súly a felső pozícióba úgy érkezik, hogy a tenyereid kifelé néznek. Ugyanezen az útvonalon engedd vissza a súlyt a kiinduló pozícióba.'), +(53, 'hu', 101, 'Oldalemelés hason fekve', 'Az oldalemelés hasonfekve elsősorban a vállizom hátsó fejét dolgoztatja meg,lényegében teljesen izoláltan dolgoztathatjuk meg ilyen módon a vállizom hátsó rosjtait szinte zéró vagy minimális csalással.\r\nKiinduló helyzet\r\nFeküdj egy magasabb padon hasra, és tarts a kezeidben egy-egy egykezes súlyzót kétoldalt lelógatva. Javasolt egy magasított padon végezni a gyakorlatot, hogy teljes mozgástartományban tudjunk dolgozni.\r\nA mozgás\r\nEmeld a karjaidat a vállad magasságában oldalra, majd lassan ereszd vissza a kiinduló pozícióba, hasonlóan a döntött törzsű oldalemeléshez.'), +(54, 'hu', 102, 'Oldalemelés ülve', 'Az oldalemelés ülve a gyakorlat a vállizom oldalsó fejét dolgoztatja meg, pontosan ugyanolyan módon, mint az állva végzendő oldalemelés, azonban ezzel a gyakorlattal sokkal izoláltabban terhelhetjük a deltaizmok oldalsó rostjait.\r\nKiinduló helyzet\r\nÜlj egy sima pad végére és támaszd meg lábaidat a padlón, mindkét kezedbe fogj egy-egy egykezes súlyzót. Ereszd le a karjaidat a tested mellé hüvelykujjakkal befelé fordítva.\r\nA mozgás\r\nBelégzés után hajlítsd be enyhén a könyöködet, majd kilégzés közben oldalt emeld félkörívben fel a súlyzókat valamivel vállmagasság fölé. Ebben a helyzetben tartsd meg pár pillanatig a súlyt, majd belégzés közben engedd lassan vissza a kiinduló helyzetbe.'), +(55, 'hu', 103, 'Egykezes oldalemelés állvá', 'Az oldalemelés állva az oldalsó deltaizmokat fejleszti elsősorban - ha helyesen hajtod végre.\r\nKiinduló helyzet\r\nÁllj kiegyenesedve, tarts hajlított könyökkel egy-egy egykezes súlyzót mindkét kezedben.\r\nA mozgás\r\nA súlyzókat egyszerre emeld ki oldalra a tested mellől addig, amíg vállmagasságnál egy kicsit fentebb nem kerül a súly. Engedd vissza lassan, és ismételd meg a gyakorlatot.'), +(56, 'hu', 104, 'Kábeles oldal emelés', 'Ez egy remek befejező illetve pumpáló gyakorlat a deltaizmok edzésének végére. Használjon két expandert (egyet-egyet a két láb alá aksztva), vagy alsó csigát ha jól felszerelt edzőteremben dolgozik. Emelje fel és engedje vissza karjait. Mozogjon egyenletes tempóban, szünet nélkül. Törzsét döntse enyhén előre, hogy a terhelés kizárólag az oldalsó fejet érje. A gyakorlatot állandó feszüléses mozdulatként hajtsa végre, úgy, hogy folyamatosan tartsa fenn a deltaizmok terhelését.'), +(57, 'hu', 105, 'Megtámasztott döntött törzsű oldal emelés', 'A megtámasztott döntött törzsű oldalemelés a deltaizom hátsó fejét és a hát felső részének izmait fejleszti. Másodlagos terhelést kap az oldalsó delta és a trapézizom is.\r\n\r\nKiinduló helyzet\r\n\r\nMint a döntött oldalemelésnél, vegyél egy-egy egykezes súlyzót a kezedbe. Hajolj előre és támaszd megh a fejedet pl. egy pad szélében, így keveseb terhelés éri majd a derekadat.\r\n\r\nA mozgás\r\n\r\nEmeld mindkét súlyzót oldalra. A mozgás legmagasabb pontjától engedd le a súlyzókat, és ismételd a gyakorlatot az előbbiek szerint.'), +(58, 'hu', 106, 'Döntött törzsű oldal emelés', 'A döntött törzsű oldalemelés a deltaizom hátsó fejét és a hát felső részének izmait fejleszti. Másodlagos terhelést kap az oldalsó delta és a trapézizom is.\r\nKiinduló helyzet\r\nMint az oldalemelésnél, vegyél egy-egy egykezes súlyzót a kezedbe. Hajolj előre egészen addig, amíg tested 90 fokban be nem hajlik. Kissé rogyasszad a térdedet, hogy hátadat mentesítsd a terhelés alól, amennyire lehetséges.\r\nA mozgás\r\nEmeld mindkét súlyzót oldalra. A mozgás legmagasabb pontjától engedd le a súlyzókat,és ismételd a gyakorlatot az előbbiek szerint.'), +(59, 'hu', 107, 'Döntött törzsű oldal emelés csigán', 'Döntött törzsű oldalemelés csigán a vállizom hátsó fejét stimulálja elsősorban.Másodlagos terhelést kap az oldalsó delta és a trapézizom is, azonban a terhelés a csigás ellenállásnak köszönheten folyamatosabb, mint a szabadsúlyos oldalemelések esetében.\r\nKiinduló helyzet\r\nÁllj a bal oldaladdal a csiga mellé, a jobb kezeddel fogd meg a csiga fogantyúját. Olyan távolságra állj, hogy a kiinduló pozícióban még érezd a súlyt. A felsőtested döntsd előre, hogy a padlóval majdnem párhuzamos helyzetet vegyél fel.\r\nA mozgás\r\nA kinyújtott karodat félkörívben távolítsd a géptől egészen vállmagasságig, a másik könyöködet szorítsd a testedhez. Lassan engedd vissza a súlyt. A gyakorlatot végezd el a másik kezeddel is.'), +(60, 'hu', 108, 'Egykezes oldal emelés', 'Ez a gyakorlat az oldalsó deltaizmokat fejleszti elsősorban.\r\nKiinduló helyzet\r\nBal kezedet tedd egy megfelelő támaszra (kb. 70-80 cm magasan). Legtöbben a súlytartó állványt vagy egy alacsony asztalt használnak erre a célra. Állj kis terpeszbe, és jobb kezedben fogj egy kézisúlyzót. Helyezkedj kényelmes testhelyzetbe úgy, hogy a törzsedet 70-80o-os szögben előredöntöd.\r\nA mozgás\r\nAz oldalemelés helyes végrehajtása nem olyan egyszerű, mint ahogyan az elsőre látszik, könnyű elhibázni a szabályos kivitelezést. Tenyeredet lefelé fordítva emeld ki oldalt a súlyt. Összpontosíts arra, hogy a súlyt a vállizmok emeljék (a kar legyen enyhén behajlítva). A mozdulatot ne indítsd túl gyorsan, nagy erővel, mert akkor a lendület fogja emelni a súlyt. Végezz el ugyanannyi ismétlést a másik karoddal is.'), +(61, 'hu', 109, 'Előre emelés', 'Álló helyzetben fogj a kezeidben egy pár kézisúlyzót. Egyik kezed emeld fel egyenesen magad előtt, amíg a súly magasabbra kerül a szemednél, majd miközben ezt a karodat leereszted, ezzel párhuzamosan emeld fel a másikat. Ezt a váltott karú mozgást folyamatosan végezd, egyik helyzetben se tarts szünetet.\r\nHatás\r\nEz a gyakorlat a a mellizom felső letapadásainak rosjtait és az elülső deltaizmokat fejleszti elsődlegesen, de járulékos terhelés éri a váll oldalsó rostjait is.\r\nKiinduló helyzet\r\nÁllj egyenesen, mindkét kezedben egy-egy egykezes súlyzót vagy egy egyenes rudat tartva kartávolságnyira, keresztben a combközépen.\r\nA mozgás\r\nEmeld a kézisúlyzókat szemmagasságig akár egyenként, akár együtt, könyöködet enyhén behajlítva. Lassan ereszd vissza és ismételj. Ugyanezt végezheted rúddal is.'), +(62, 'hu', 110, 'Állig húzás', 'Az állig húzás igénybe veszi a delta és a csuklyás izmot. Másodlagos terhelést kap a bicepsz és az alkar izomzata.\r\nKiinduló helyzet\r\nÁllj egyenesen, szűk fogást véve (a mutatóujjak kb. 15 cm-re legyenek egymástól a rúdon) a kétkezes súlyzó közepén, tenyerekkel a test felé. A mozgás elején a súlyzónak keresztbe kell feküdnie felső combodon, karod pedig legyen egyenes.\r\nA mozgás\r\nLassan húzd a súlyzót felfelé tested közelében egy vonal mentén, könyöködet felfelé emelve és mindig a kezed vonala fölött tartva. Amint a rúd nyakmagasságba ér, tarts szünetet, és ereszd le a súlyzót lassan ugyanezen vonalon, egészen addig, míg a combodhoz ér.Ismételd meg a gyakorlatot az előírt ismétlésszámban.'), +(63, 'hu', 111, 'Mellről nyomás állvá', 'Ez a gyakorlat a deltaizmot és a tricepszet fejleszti, másodlagos hatása van a mellizmokra, a csuklyás izomra és a hátra.\r\nKiinduló helyzet\r\nVállszélességű fogást vegyél fel a kétkezes súlyzón úgy, hogy a tenyered kifelé mutat, és a rúd keresztben fekszik vállad elülső részén.\r\nA mozgás\r\nNyomd egyenesen fel a súlyzót az arcod előtt, egészen addig, míg a karod kiegyenesedik, és a súlyzó közvetlenül a fejed fölött van. Lassan engedd vissza a kiinduló helyzetbe a súlyzót, és ismételd meg a mozgást az előírt ismétlésszámmal.'), +(64, 'hu', 112, 'Vállvonogatás', 'Ez a gyakorlat a vállöv izmait, köztük a csuklyás izmot, a nyak és a hát felső izmait dolgoztatja.\r\n\r\nKiinduló helyzet\r\n\r\nÁllj egyenesen és tarts két nehezebb kézisúlyzót (a gyakorlat rúddal is végezhető) a tested mellett, a tenyereid befelé nézzenek. Ha rúddal végzed a gyakorlatot, kartávolságra a tested előtt vegyél fel vállszélességű vagy kissé szűkebb fogást.\r\n\r\nA mozgás\r\n\r\nEmeld a válladat egyenesen felfelé, mintha a füledet szeretnéd megérinteni. Ne hajlítsd be könyöködet, és lassan ereszd vissza a rudat a kiinduló helyzetbe, majd ismételjen.'), +(65, 'hu', 113, 'Mellről nyomás ülve', 'Ez a gyakorlat elsődleges terhelést biztosít az elülső delták számára, de az oldalsó delta is beleszól a mozgásba - minél jobban kiforgatod oldalra a könyöködet, annál jobban terheled a vállizmod oldalsó rostjait is.\r\nKiinduló helyzet\r\nRagadd meg a kétkezes rudat, vállszélességben vagy picit széleesebb fogással. Emeld ki a villából és tarts a fejed fölött.\r\nA mozgás\r\nEngedd le a rudat az állad alá, majd nyomd ki a fejed fölé.'), +(66, 'hu', 65, 'Mellen áthúzás', ''), +(67, 'hu', 114, 'Cooper teszt', 'Hány métert tudsz teljesíteni 12 perc alatt'), +(68, 'hu', 115, 'Kábeles hatra húzás', 'Ez a gyakorlat elsődlegesen a vállizom hátsó fejét dolgoztatja meg, de másodlagos terhelést kap a hátizom felső része, a trapézizom és a bicepsz is.\r\nKiinduló helyzet\r\nRagadd meg a felső csigához erősített kötelet. Kissé dőlj hátra, hogy egyensúlyban legyen a tested. A szemed magasságában tartsd a kötelet magad előtt, nyújtott karokkal.\r\nA mozgás\r\nA könyöködet magasan tartva húzd hátra a kötelet, amennyire csak tudod, majd lassan engedd vissza.'), +(69, 'hu', 116, 'Csigás letolás', 'A csigás letolás az egyik legelterjedtebb tricepsz-fejlesztő gyakorlat, bár sokan megkérdőjelezik hatásosságát. Kiválóan képes hangsúlyozni a jellegzetes \"lópatkót\". Elsősorban izolációs gyakorlatként érdemes rá tekinteni.\r\nKiinduló helyzet\r\nKiinduláskor úgy fogd meg a készülék rúdját, hogy kezeid 5-20 cm-re legyenek egymástól.\r\nA mozgás\r\nNyomd le a rudat egészen addig, amíg a karjaid ki nem egyenesednek. Engedd vissza a súlyt, és ismételd meg a mozdulatot. A legtöbben e gyakorlat során a könyöküket szorosan az oldalukhoz szorítják, de néhányan viszont oldalt kinyomják és \"belehajolnak\" a mozdulatba. Fontos azonban, hogy a könyök mozdulatlan legyen.'), +(70, 'hu', 117, 'Csigás letolás Tricepsz kötéllel', 'A csigás letolás tricepsz kötéllel a rudas letolás módosított változata, amikor rúd helyett ún. tricepsz kötelet használunk. A kötéllel végzett mozgás kisebb súly, ám nagyobb mozgástartomány használatát feltételezi. Emellett a gyakorlat végpontján sokkal jobban rá tudsz feszíteni a tricepszedre.\r\nKiinduló helyzet\r\nÁllj meg egy felső csigával szemben, melyre egy tricepsz kötelet erősítesz. Fogd meg a kötél végeit és a könyöködet próbáld fixen tartani, ne mozogjon.\r\nA mozgás\r\nA gyakorlatot kétféle módon végezheted: vagy a tested mellé húzod le a kötél két végét, vagy pedig az egész gyakorlatot a tested előtt végzed, kifelé megfeszítve a kötél végeit. Mindkét variáció másféle érzetet kelt a tricepszedben, érdemes variálni őket! Nem kifejezetten sérülésveszélyes gyakorlat, ám ha rángatjuk a súlyt, és/vagy túl nagy terheléssel dolgozunk, akkor minden bizonnyal képesek lehetünk ezzel az egyébként teljesen biztonságos gyakorlattal is lesérülni :)'), +(71, 'hu', 118, 'Szűk nyomás', 'A szűknyomás elsődlegesen a mellizmokat (különösen belső részeit), a deltaizom elülső fejét és a háromfejű karizmot veszi igénybe.\r\nKiinduló helyzet\r\nKeskeny felső fogást alkalmazz a középnehéz súlyzó közepén (maximum vállszélességben, de inkább picit keskenyebb fogás lesz előnyös - amit a vállad enged). Feküdj a hátadra egy vízszintes gyakorlópadon úgy, hogy a lábad teljes talppal a padlóra támaszkodjon - a stabilitás érdekében -, és nyújtsd ki karodat vállból egyenesen felfelé.\r\nA mozgás\r\nHajlítsd be karodat, és lassan ereszd le a súlyzót egészen addig, amíg mellkasodat nem érinti. Nyomd lassan vissza a kiinduló pontra, és ismételd a mozgást az előírt számban.'), +(72, 'hu', 119, 'Tricepsz nyújtás fej fölött egykezes súlyzóval', 'A tricepsznyújtás fej fölött egykezes súlyzóval közvetlen veszi igénybe a felkar háromfejű izmait. Remekül megnyújtja a tricepsz hosszú fejét. Izolációs gyakorlat, nincs értelme csalva, nagy súllyal végezni, és sérülésveszélyes is lenne.\r\nKiinduló helyzet\r\nVegyél a bal kezedbe egy könnyű egykezes súlyzót, és ülj egy vízszintes gyakorlópad végére. A jobb kezedet tedd csípőre, és nyújtsd ki a bal karodat vállból egyenesen felfelé úgy, hogy tenyered előrenézzen a mozgás folyamán.\r\nA mozgás\r\nA felkarodat mozdulatlanul tartva engedd a súlyzót egy félköríven visszafelé mozogva, amennyire mély helyzetig csak lehet. A tricepszed erejét használva ugyanezen az íven mozgasd vissza a kiinduló helyzetbe. Egyforma számú sorozatot végezz mindkét karoddal.'), +(73, 'hu', 120, 'Tricepsz nyújtás ülve', 'A tricepsznyújtás ülve a tricepsz hosszú fejét stimulálja leginkább, de az egész tricepszet kemény terhelésnek teszi ki. Bár izolációs gyakorlat, mégis relatíve nagyobb súlyokkal is lehet végezni, így afféle határvonalon van a többízületes alapgyakorlatok és a kifejezetten izolációs gyakorlatok között.\r\nKiinduló helyzet\r\nTarts a fejed fölött két kézzel egy kézisúlyzót a tárcsák alatt fogva úgy, hogy a felkarjaid a lehető legközelebb legyenek a füledhez. Franciarúddal is végezheted a gyakorlatot.\r\nA mozgás\r\nEreszd hátra a súlyzót a hátad mögé, majd újra emeld vissza fel, a karod kinyújtott állapotáig. Felkarjaid eközben végig maradjanak függőleges helyzetben, mozdulatlanul.'), +(74, 'hu', 121, 'Tricepsz nyújtás ferde padon', 'A tricepsznyújtás ferde padon a háromfejű karizmot veszi igénybe. Izolációs gyakorlat ugyan, ám relatíve nagyobb terheléssel végezhető, mint egy hagyományos izolációs gyakorlat, ezért sokan alapgyakorlatként tekintenek rá. Valahol a kettő között lehet az igazság.\r\nKiinduló helyzet\r\nÜlj le egy ferde padra, a dőlésszög legyen kb 45 fokos. A könyöködet igyekezz minél szorosabban a fejed mellett mozdulatlanul tartani. Nyújtsd ki a karodat a fejed fölé.\r\nA mozgás\r\nInnen engedd vissza lassan, kontrolláltan le annyira, amennyire csak a tricepszed nyúlása engedi. Lent ne rugózz, hanem állítsd meg a súlyt, és robbanékonyan nyújtsd ki a karodat. A felső ponton feszíts rá a tricepszedre, majd ismételd a mozdulatot.'), +(75, 'hu', 122, 'Tricepsz nyújtás fekve', 'A tricepsznyújtás fekve a háromfejű karizmot (tricepszet) veszi igénybe. Mindhárom fej erős terhelést kap, de a legjobban a tricepsz hosszú feje (long head) dolgozik a gyakorlat közben.\r\nKiinduló helyzet\r\nVedd fel ugyanazt a kiinduló helyzetet, mint a fekvenyomásnál, azonban ennél közeli fogást alkalmazz (15 cm a mutatóujjak között) a kétkezes súlyzórúd közepén.\r\nA mozgás\r\nFelkarodat mozdulatlanul tartva, hajlítsd be könyöködet, és mozgasd a súlyzót félkörívben egészen addig, amíg a homlokodhoz nem ér, vagy a fejed felett túl nem megy a padon. Emeld vissza a súlyzót ugyanezen félkörív mentén a kiinduló helyzetbe, és ismételd meg a gyakorlatot az előírt számban.'), +(76, 'hu', 123, 'Tricepsz nyújtás állvá', 'A tricepsznyújtás állva az egész tricepszet keményen megdolgoztatja, kifejezetten jól megnyújtja a hosszú fejet, de az egész izomcsoportra nagy terhelést ró. Nem mellékesen, az álló pozíció stabilizálása során másodlagosan terhelést kapnak a core izmok is.\r\nKiinduló helyzet\r\nTarts egy egykezes súlyzót kinyújtott kézzel a fejed fölött, a tenyereddel a tárcsákon. Állj egyenesen, nagyon kis terpeszben.\r\nA mozgás\r\nFélkörívben engedd hátra a súlyzót addig, míg az alkarod a bicepszedet nem érinti, közben a könyöködet tartsd minél közelebb a fejedhez. Ugyanezen az íven emeld vissza a súlyt a kiinduló pozícióba.'), +(77, 'hu', 124, 'Egykezes Tricepsz nyújtás fekve', 'Az egykezes tricepsznyújtás fekve a tricepsz hosszú fejét stimulálja leginkább, valamint a csúcsösszehúzódás pillanatában a külső fej is kemény terhelést kap, főként ha pluszban ráfeszítesz a mozdulat végén.\r\nKiinduló helyzet\r\nFeküdj hanyatt egy padon, fogj meg egy kézisúlyzót az egyik kezedben.\r\nA mozgás\r\nA felkarod legyen függőleges, a súlyzót pedig engedd a füled mellé. Ebből a pozícióból nyújtsd ki a karodat, és a mozdulat végén keményen feszíts rá a tricepszedre.'), +(78, 'hu', 125, 'Lórúgás döntött törzzsel', 'A lórúgás csaknem kizárólag a háromfejű karizmot építi. Ízig-vérig izolációs gyakorlat, segédizmok gyakorlatilag nem kapcsolódnak be a mozgásba. Így nagy súlyokkal nem is lehet, és nem is célszerű végezni.\r\nKiinduló helyzet\r\nElőrehajolva támaszkodj egyik kezeddel egy pad végére és másik kezedben tarts egy egykezes súlyzót.\r\nA mozgás\r\nA könyöködet tartsd magasan, de stabilan, és egyenesítsd ki alkarodat. Csak az alkaroddal végezd a mozgást.'), +(79, 'hu', 126, 'Tolódzkodás', 'A tolódzkodás tricepszre egy remek tricepszgyakorlat, különösen, ha a tolódzkodóállvány fogantyúi viszonylag közel vannak egymáshoz. Az egymástól túl távol lévő rudak nagyobb mértékben mozgatják a mellizmot, bár azért a tricepsz munkája ebben az esetben sem megkerülhető.\r\nKiinduló helyzet\r\nAmikor a tricepszedet edzed a korláton, a lábaid legyenek a test alatt, álladat szegd le a melledre, könyökeidet tartsd magad mellett, és a test, amennyire lehet, legyen egyenes.\r\nA mozgás\r\nEngedd le magad olyan mélyre, amennyire csak bírod, a kinyomás végén pedig teljesen nyújtsd ki a karodat, és feszíts rá a tricepszedre a felső holtponton.'), +(80, 'hu', 127, 'Tolódzkodás feltámasztott lábakkal', 'Kezdőknek, amíg nem megy a teljes testsúllyal* való tolódzkodás kiválóan helyettesíti azt a tolódzkodás feltámasztott lábbal. Haladóbbaknak ez a gyakorlat inkább csak kiegészítésnek, izoláló jelleggel ajánlott.\r\nKiinduló helyzet\r\nTámaszkodj meg a hátad mögött egy padon, a lábadat pedig tedd fel egy másik padra magad előtt úgy, hogy le tudd magad engedni a két pad között.\r\nA mozgás\r\nEreszkedj le annyira, hogy a felkarod a padlóval párhuzamos legyen. A lábaidat tartsd egyenesen és a fejedet emeld fel gyakorlat közben.'), +(81, 'hu', 128, 'Bicepsz állva kétkezes rúddal', 'A bicepsz állva kétkezes rúddal a kétfejű karizmokat veszi igénybe, és másodlagos igénybevételt kap az alkar izomzata.\r\nKiinduló helyzet\r\nÁllj egyenesen, vállszélességű fogással a kétkezes súlyzón, a tenyerek előre néznek. A teljes mozgás folyamán a felkarod maradjon szorosan törzsed mellett. A mozgás kiinduló pozíciójában a kar egyenes, és a súlyzó keresztben fekszik a combodon.\r\nA mozgás\r\nCsak alkart mozgatva hajlítsd be a karodat, és mozgasd a súlyzót felfelé, félkörívben az állad irányába. Lassan ereszd vissza a súlyzót ugyanezen félkörív mentén a kiindulási ponthoz, majd ismételd a mozdulatot.'), +(82, 'hu', 129, 'Bicepsz ülve egykezes súlyzókkal', 'A bicepsz edzés egykezes súlyzóval egy kiváló bicepszgyakorlat, amely igénybe veszi az alkar hajlítóizmait is.\r\nKiinduló helyzet\r\nFogj egy-egy közepesen nehéz egykezes súlyzót mindkét kezedbe, és ülj lovaglóülésben egy vízszintes gyakorlópadon úgy, hogy talpad felfeküdjön a padlón. Lógasd oldalt lefelé karjaid a tenyereddel egymás felé. A felkart szorítsd a törzsedhez, és tartsd így a sorozat alatt.\r\nA mozgás\r\nA bal kezedben lévő súlyt hajlítással emeld felfelé, a csuklódat közben úgy forgatva, hogy tenyered a mozgás második felében felfelé nézzen. Végezd ugyanezt a mozgást visszafelé a súlyt leeresztve a kiinduló helyzetbe. Míg a bal kezedben lévő súly lefelé halad, a jobb kezedben lévő súlyt hajlítással emeld felfelé, csuklódat közben úgy forgatva, hogy tenyered felfelé nézzen a mozgás második felében.'), +(83, 'hu', 130, 'Bicepsz hanyatt fekve egykezes súlyzókkal', 'A bicepsz hanyattfekve egykezes súlyzókkal a bicepszet fejleszti, és remekül meg is nyújtja azt. \r\nKiinduló helyzet\r\nFeküdj hanyatt egy vízszintes padon, kezeidben egy-egy súlyzóval magad mellett, melyeket oldalra kifelé tartasz, tenyérrel felfelé.\r\nA mozgás\r\nEzt a gyakorlatot ugyanúgy kell végezni, mint a ferdepados változatot, csak itt a pad vízszintesen áll. Átlagos és átlag feletti, viszonylag magas padra van szükség, hogy a súlyzók ne érjenek le a padlóra az alsó holtponton, ezért ez a gyakorlat csak megfelelő felszerelés mellett végezhető.'), +(84, 'hu', 131, 'Bicepsz állvá váltott karral', 'A bicepsz állva váltott karral a kétfejű karizmokat és másodlagos terheléssel az alkar izmait dolgoztatja meg elsősorban.\r\nKiinduló helyzet\r\nÁllj egyenesen egy-egy egykezes súlyzóval a kézben, kis terpeszállásban. A hátadat és a fejedet tartsd egyenesen, a csípődet és a lábaidat tartsd mozdulatlanul. A kiinduló pozícióban a karjaid a tested mellett lógnak, a hüvelykujjakkal befelé fordítva, de végezheted végig kifordított hüvelykujjakkal is a gyakorlatot - mindkét módszernek megvan az előnye.\r\nA mozgás\r\nLélegezz be, majd kilégzés közepette kezdd el behajlítani a jobb karodat. A hüvelykujjadat, miután a súlyzó elhagyta a combodat, lassan forgasd felfelé és emeld fel egészen addig, míg az alkarod a bicepszedhez nem ér, ebben a pozícióban pár pillanatig próbáld meg megtartani a súlyt. Ez után lassan engedd vissza a súlyt, TÚL HOSZZZÚÚÚÚ'), +(85, 'hu', 132, 'Egyéb gyakorlat', ''), +(86, 'hu', 133, 'Bicepsz állva francia rúddal', 'A bicepsz állva francia rúddal hasonlóan terheli a bicepszedet, mint az egyenes rúddal végrehajtott bicepszhajlítás, de a csuklódat kevéssé terheli, valamint picivel nagyobb terhelést kap a brachioradialis izom.\r\nKiinduló helyzet\r\nFogd meg a franciarudat tetszőleges fogással az ujjaiddal felfelé, és tartsd a rudat a combod előtt kinyújtott karokkal. Szűkebb fogással a bicepsz külső feje kap nagyobb szerepet, szélesebb fogás esetén a belső fej kapja a terhelés nagyobbik részét.\r\nA mozgás\r\nFélkörívben emeld fel a rudat a karjaid behajlításával addig, míg a bicepszed el nem éri a csúcsösszehúzódás pontját. Figyelj rá hogy olyan pozícióban fejezd be a mozgást, amikor a bicepsz még dolgozik - ha túl magasra emeled a súlyt, azzal tehermentesítheted a célizmot. A könyöködet tartsd a testedhez minél közelebb, és lehetőleg mozdulatlanul.'), +(87, 'hu', 134, 'Bicepszgép', 'A bicepszgép segítségével végzett bicepszezés rendkívül koncentráltan edzi meg a célizmot, valamint az alkar izmai másodlagos terhelést kapnak.\r\nKiinduló helyzet\r\nHelyezkedj el a gépben, tartsd meg a rudat a tenyereddel, az ujjaidat felfelé fordítva. Igyekezz, hogy a felkarod minél kevésbé mozduljon el oldalra\r\nA mozgás\r\nA mozdulat felső pontján feszíts rá a bicepszedre, tartsd ki ezt a pozíciót 1-2 másodpercig, majd kontrollált mozdulattal engedd vissza súlyt.'), +(88, 'hu', 135, 'Bicepsz gép Scott padon', 'A bicepsz Scott-padon a hiedelem szerint nem képes \"megnyújtani\" a bicepszed, azaz közelebb hozni az alsó részt a könyékhajlathoz. Bár tény, hogy az alsó részt stimulálja leginkább, sajnos az izomtapadásokon nem tud változtatni, így hiú ábránd lenne azt hinni, hogy ezzel a gyakorlattal megváltoztathatjuk a genetikánk által ránk szabott formákat.\r\nKiinduló helyzet\r\nHelyezkedj el a Scott-pad (bicepsz-pad) mögött kényelmesen (ehhez a gyakorlathoz célszerű, ha van edzőpartner a közelben, hogy segíthessen a súlyt elvenni a gyakorlat végén).\r\nA mozgás\r\nMindkét karoddal egyszerre emeld fel a súlyt addig, míg az alkarod a bicepszedhez nem ér. Lassan engedd vissza a súlyokat, kihasználva a teljes mozgástartományt.'), +(89, 'hu', 35, 'Guggolás', ''), +(90, 'hu', 136, 'Kábeles egykezes bicepszezés', 'A kábeles egykezes bicepszezés koncentráltan dolgoztatja meg a bicepszet, és másodlagos terhelést nyújt az alkar számára.\r\nKiinduló helyzet\r\nÁllj olyan messzire a géptől, hogy a karod kinyújtott állapotában a súlyokat még mindig tarthasd, azaz érezd a terhelést.\r\nA mozgás\r\nA mozdulatot indítsd úgy, hogy a hüvelykujjad a combjaid felé mutatnak, majd amikor a karod elhagyta a combodat, fokozatosan fordítsd felfelé. A karodat annyira hajlítsd be, hogy az alkarod a bicepszedhez érjen. A mozgás teljes folyamata alatt tartsd a könyöködet szorosan a tested mellett. Az előírt ismétlés után végezd el a gyakorlatot a másik kezeddel is.'), +(91, 'hu', 137, 'Kábeles kétkezes bicepszezés', 'A kábeles kétkezes bicepszezés - avagy bicepsz alsó csigán - az egész bicepszet megterheli, a folyamatos terhelésnek köszönhetően a mozdulat egész ideje alatt.\r\nKiinduló helyzet\r\nÁllj egy alsó csigával szemben, melyhez egy kétkezes fogantyút erősítesz. Fogd meg a fogantyút alsó fogással.\r\nA mozgás\r\nLassan hajlítsd be a karodat, a könyék maradjon közben mozdulatlan. A felső ponton tartsd meg a rudat. Utána lassan engedd vissza.'), +(92, 'hu', 138, 'Kábeles kétkezes bicepszezes fekve', 'A kábeles kétkezes bicepszezés - avagy bicepsz alsó csigán - az egész bicepszet megterheli, a folyamatos terhelésnek köszönhetően a mozdulat egész ideje alatt.\r\nKiinduló helyzet\r\nÁllj egy alsó csigával szemben, melyhez egy kétkezes fogantyút erősítesz. Fogd meg a fogantyút alsó fogással.\r\nA mozgás\r\nLassan hajlítsd be a karodat, a könyék maradjon közben mozdulatlan. A felső ponton tartsd meg a rudat. Utána lassan engedd vissza.'), +(93, 'hu', 139, 'Bicepsz ferdepadon egykezes súlyzókkal', 'A bicepsz ferdepadon egykezes súlyzókkal a kétfejű karizmokat dolgoztatja meg leginkább, de másodlagos terhelést kapnak az alkar izmai is.\r\nKiinduló helyzet\r\nFeküdj háttal a padra, két egykezes súlyzót tartva.\r\nA mozgás\r\nTestedet a padhoz szorítva, lassan körívben emeld fel a súlyzókat alsó helyzetükből a válladhoz, majd engedd vissza őket kontrolláltan a kiinduló pozícióba.'), +(94, 'hu', 140, 'Koncentrált bicepszgyakorlat', 'A koncentrált bicepszgyakorlat a kétfejű karizmot fejleszti, annak is elsősorban a csúcsosságát lehet vele kihangsúlyozni - bár ez azért nagyrészt genetikai tényezőktől is függ.\r\nKiinduló helyzet\r\nÜlve vagy derékban előrehajolva szorítsd a karodat a belső combodhoz.\r\nA mozgás\r\nLassan hajlítsd alsó karodat mellkasod felé, de felkarod maradjon mozdulatlan belső combodhoz szorítva.'), +(95, 'hu', 141, 'Húzódzkodás szűk alsó fogassal', 'Ez egy remek bicepszfejlesztő gyakorlat azok számára is, akiknek nincs súlyzójuk, illetve a súlyzós edzés mellé kiváló az edzés változatosabbá tételére. Ahelyett, hogy a kar mozogna a testhez képest, a testet húzzuk a karhoz. Az egész bicepsz tömegének növelésére alkalmas, emellett erős másodlagos terhelést kapnak a hátizmok és az alkar izmai is.\r\nKiinduló helyzet\r\nKapaszkodj egy vízszintes rúdba a fejed fölött szűk (15-30 cm széles, de maximum vállszélességű) fogással.\r\nA mozgás\r\nTeljesen függő helyzetből kiindulva húzd fel magad, amíg az állad a rúd fölé nem kerül. Lassan ereszkedj vissza, és ismételd a gyakorlatot.'), +(96, 'hu', 142, 'Kalapács bicepsz gyakorlat', 'A kalapács-bicepsz gyakorlat a bicepsz alatt futó brachialis izmot és az alkar izmait dolgoztatja meg. A brachialis izom fejlesztésével javíthatod a bicepszed csúcsosságát.\r\nKiinduló helyzet\r\nRagadj meg mindkét kezedben egy-egy kézisúlyzót, és tartsd őket a tested mellett, a tenyereid nézzenek a tested irányába.\r\nA mozgás\r\nHa lehet, könyöködet egy helyben tartva, lassan és egyenletesen emeld az egyik súlyzót a válladhoz. Ereszd vissza, és a másik karral is ismételd a mozdulatot. Ügyelj rá, hogy a könyököd ne mozogjon ki oldalra. Végezheted egyszerre a két karoddal is a gyakorlatot.'); +INSERT INTO `exercise_type_translation` (`translation_id`, `language_code`, `exercise_type_id`, `name`, `description`) VALUES +(97, 'hu', 143, 'Guggolás', 'Ez a mozgás, egyike a legjobb gyakorlatoknak, mivel ez érinti a test fő izomcsoportjainak legtöbbjét. A guggolás megdolgoztatja a combizmokat, a csípő- és a farizmokat, a lábbicepszet és a hátizmok alsó részét. A hasi, a felső háti, a vádli- és a vállizmokat is igénybe veszi.\r\nKiinduló helyzet\r\nÁllj kiegyenesedve egy kétkezes súlyzó rúdját egyensúlyozva a nyakad mögött a hátadon keresztben, és a recézett rúdrészt a súlytárcsák közelében fogva. Tedd sarkaidat egymástól 30-50 cm-re úgy, hogy lábfejeid kissé kifelé mutassanak.\r\nA mozgás\r\nSzemeddel nézz egy pontra magad elé, szemmagasságnál kicsit feljebb, és tartsd tekintetedet azon a ponton az egész moNEMFER EL'), +(98, 'hu', 144, 'Guggolás mellső tartással', 'A mellső tartással történő guggolás nem engedi meg olyan nagy súly használatát mint a hagyományos guggolás, viszont jobban megdolgozza a kvadricepszet és a derék számára is biztonságosabb.\r\nKiinduló helyzet\r\nVedd a rudat a mellkasodra. Tarthatod keresztbe tett kezekkel is, vagy a súlylökésre emlékeztető fogással - kinek hogy válik be inkább. Amennyiben az utóbbi megoldást választod, egy gurtni sokat segíthet, hogy kényelmesen tudd tartani a rudat.\r\nA mozgás\r\nA hátadat végig egyenesen tartva, kissé felfelé (nem a plafonra!) nézve guggolj le amennyire csak tudsz. Figyelj rá, hogy a hátad ne görbüljön be, és ne is dőljön előre lehetőség szerint. Mikor a vízszintesnél mélyebbre guggoltál, állj fel a súllyal, de a felső ponton ne akaszd ki a térdedet.'), +(99, 'hu', 145, 'Guggolás hátsó tartással', 'A mellső tartással történő guggolással ellentétben a hátsó tartással történő guggolás helyesen végrehajtva jobban megdolgozza a combbicepszet. Ha állandó alkalmazása nem is, de időnkénti beiktatása az edzéstervbe hasznos lehet.\r\nKiinduló helyzet\r\nFogj meg egy rudat a hátad mögött. Ha merev a lábfejed, akkor tegyél egy-egy kisebb tárcsát a sarkaid alá.\r\nA mozgás\r\nGuggolj le úgy, hogy nyújtott karral végig a tested mögött tartod azt, majd állj fel. Ügyelj rá, hogy a hátad legyen teljesen egyenes.'), +(100, 'hu', 146, 'Hack-Squat', 'Ez a gyakorlat a comb középső és alsó részét stimulálja, emellett a terpesz szélességével is tudod irányítani a stimuláció helyét. Természetesen a négyfejű combizom egésze keményen bedurran a Hack guggolástól, azonban a fentebb említett területek nagyobb stimulációt kapnak.\r\nKiinduló helyzet\r\nHelyezkedj el a Hack-gépen, kb. vállszélességű terpeszt felvéve.\r\nA mozgás\r\nGuggolj le minimum addig, amíg a combod derékszöget nem zár be a lábszáraddal (de legjobb, ha teljesen leguggolsz), majd nyújtsd ki a lábadat, de figyelj rá, hogy a térdedet ne akasszad ki. A térd kiakasztásával, valamint az alsó ponton rugózással tudsz a legtöbbet ártani magadnak ennél a gyakorlatnál.'), +(101, 'hu', 147, 'Sissy guggolás', 'Ez egy igen specializált mozdulat, amely elsősorban a comb alsó részének az edzésére szolgál, megdolgoztatja a hajlító- és farizmokat is. Erősen javasolt azoknak, akik nehezen tudják izolálni a combfeszítők munkáját. Garantált, hogy ettől érezni fogod az izmok összehúzódását. \r\nKiinduló helyzet\r\nA gyakorlat végezhető speciális kerettel vagy anélkül. A keretes változatnál álljunk a keretbe úgy, hogy a vádlink a párnának feszül.\r\nA keret nélküli verziónál állj úgy, hogy lábaid mintegy 45 cm-re legyenek egymástól. \r\nA mozgás\r\nA keretben guggolj le koncentráltan, egyenes törzzsel addíg, míg a combjaid vízszintesek nem lesznek a talajjal, majd állj fel.\r\nA másik verziónál emelkedj lábujjhegyre, majd így guggolj le, miközben hátrahajolsz, amennyire csak bírsz. A dolog lényege az, hogy a comb és a törzs az egész gyakorlat alatt legyen egy síkban. Ha túl nehéznek érzed a mozdulatot, az egyensúly megőrzése érdekében kapaszkodj meg valamiben az egyik kezeddel.'), +(102, 'hu', 148, 'Guggolás felugrással', 'A guggolás felugrással kiválóan alkalmas a láb pumpálására. Saját testsúlyos gyakorlat gyanánt végezve is kiváló bedurranás érhető el. Emellett a robbanékonyság fejlesztésérre is kiválóan alkalmas. \r\nKiinduló helyzet\r\nÁllj meg kb vállszélességű terpeszben.\r\nA mozgás\r\nGuggolj le addig, míg a combjaid legalább párhuzamosak nem lesznek a padlóval, vagy még mélyebbre. Ebben az alsó pozícióban a tekintetedet szegezd előre, semmiképpen sem lefelé, a hátadat tartsd egyenesen, és a térdeidet enyhén fordítsd kifelé. Rugaszkodj el a padlótól minél magasabbra. A talajra érkezés után ereszkedj le újra guggolásba és ismételd a gyakorlatot.'), +(103, 'hu', 149, 'Láb hajlítás állva', 'Ez a gyakorlat remekül izolálja a combhajlító izmokat. Picit más jellegű terhelést jelent ez, mint a fekvő, vagy az ülő lábhajlítás.\r\nKiinduló helyzet\r\nÁllj bele a gépbe, támaszd ki a térdedet és tartsd is a párnához szorítva végig a gyakorlat ideje alatt. Akaszd be sarkad a görgőpárnák alá, és nyújtsd ki teljesen a lábad. Kapaszkodj bele a gépbe, és tartsd a térdedet a párnázott felülethez szorítva.\r\nA mozgás\r\nA láb kétfejű izmait használva hajlítsd be a lábadat, amennyire csak tudod. Tartsd ki ezt a leginkább összehúzott helyzetet 1-2 másodpercig, majd ereszkedj vissza a kiinduló pontig. Ismételd a mozgást az előírt számban.'), +(104, 'hu', 150, 'Láb hajlítás ülve', 'Ez a legjobb elkülönítő mozgás a kétfejű combizom igénybevételére. Hatására a comb oldalról nézve teltebb lesz, és szépen kidolgozható vele a comb hátsó íve. Emellett kiegyensúlyozottabb terhelésnek lesznek kitéve az ízületek is, hiszen kellő edzéssel a combhajlítók erőszintje egyensúlyba hozható a combfeszítőkével.\r\nKiinduló helyzet\r\nÜlj a gépbe, támaszd ki a hátadat és tartsd is a támlához szorítva végig a gyakorlat ideje alatt. Akaszd be sarkad a görgőpárnák alá, és nyújtsd ki teljesen a lábad. Fogd meg a pad széleit, és tartsd a csípődet a párnázott felülethez szorítva.\r\nA mozgás\r\nA láb kétfejű izmait használva hajlítsd be a lábadat, amennyire csak tudod. Tartsd ki ezt a leginkább összehúzott helyzetet 1-2 másodpercig, majd ereszkedj vissza a kiinduló pontig. Ismételd a mozgást az előírt számban.'), +(105, 'hu', 151, 'Láb nyújtás', 'Ez a legjobb izolációs gyakorlat a négyfejű combizom igénybevételére. Egyedül, önmagában nem alkalmas arra, hogy nagy combizmokat építsünk, azonban a részletek kidolgozására, valamint speciális edzéstechnikák kivitelezéséhez (előfárasztásos szuperszett, stb) kiválóan megfelel.\r\nKiinduló helyzet\r\nÜlj a lábgépbe úgy, hogy térdhajlatód a pad emelőkar felőli oldalának végéhez simuljon. Akaszd be lábfejedet a görgőpárna alá, és fogd meg a pad oldalát a kezeddel, egyenes helyzetben tartva felsőtestedet.\r\nA mozgás\r\nA quadricepsz erejét használva, lassan egyenesítsd ki lábadat. Tartsd ki a csúcsösszehúzódást 1-2 másodpercig, majd lassan engedd vissza a lábadat. Ismételd a mozgást az előírt számban.'), +(106, 'hu', 152, 'Láb tolás', 'Ez a gyakorlat egy fordított guggolásra emlékeztet, bár a legtöbb edzőteremben állítható támlájú 45o-os lábtológép van. Sok testépítő jobban kedveli ezt a gyakorlatot, mint a guggolást, mert lehetővé teszi, hogy teljes mértékben a láb mozgására összpontosítsanak, anélkül, hogy a csípő jelentősebb mértékben részt venne a mozdulatban. Sokkal kisebb a sérülés veszélye is mint a guggolás esetében, ezét kimondottan javasolt azoknak a sportolóknak, akik a súlyzós edzést valamilyen más sport mellet kiegészítésként végzik. Az elfogadott nézet szerint azonban a lábtolás nem építi olyan hatékonyan a combizmokat, mint a guggolás.\r\nKiinduló helyzet\r\nHelyezd a lábaidat egymástól mintegy harminc centiméterre a készülék taposólemeze alá.\r\nA mozgás\r\nNyomd ki a lábaidat, amíg a lábad ki nem egyenesedik, de a térdedet ne akaszd ki. Engedd vissza a súlyt, és ismételd a gyakorlatot.'), +(107, 'hu', 153, 'Kitörés', 'Ez a mozgás a combhajlítókat, a farizmokat és a négyfejű combizmot fejleszti. Miközben erőteljes izom-összehúzódás éri a combizmokat, ugyanakkor erőteljes nyújtó hatása is van a gyakorlatnak, ami ezáltal kiemelten hatékonnyá és komplexszé teszi. A kitörés helyesen végezve rendkívül intenzív, folyamatos terhelést biztosít, így mindenképpen érdemes beilleszteni a lábedzésedbe. \r\nKiinduló helyzet\r\nÁllj egyenesen. Egy nagy lépést lépj előre, és kinyújtott lábaddal lassan süllyedj guggolásba.\r\nA mozgás\r\nAmint leereszkedtél ebbe a helyzetbe, tégy egy újabb lépést előre a másik lábaddal, úgy, hogy közben kinyújtod az eddig behajlított lábadat, tehát fel-le ereszkedve lépegetsz előre, gyakorlatilag támadóállásban. A másik verzió, ha visszalépsz, és a másik lábaddal lépsz ki, majd azzal is vissza - így egy helyben kilépegetve, \"helytakarékosan\" tudod végezni a gyakorlatot.'), +(108, 'hu', 154, 'Kitörés egykezes súlyzókkal', 'A kitörés súllyal végezve a combhajlítókat, a farizmokat és a négyfejű combizmot fejleszti. Maximális izomösszehúzódás és megnyúlás egyaránt elérhető a gyakorlattal, ami kiemelten hatékonnyá teszi a combizmok fejlesztésére. Akkor érdemes bevetni, ha nincs lehetőségünk hosszabb \"úton\" kitöréseket végezni, de nem akarunk lemondani a sétálós kitörés perverz örömeiről. \r\nKiinduló helyzet\r\nÁllj egyenesen egy-egy súlyzóval a kezedben. Egy nagy lépést lépj előre, és kinyújtott lábaddal lassan süllyedj guggolásba.\r\nA mozgás\r\nAmint leereszkedtél ebbe a helyzetbe, tégy egy újabb lépést előre a másik lábaddal, úgy, hogy közben kinyújtod az eddig behajlított lábadat, tehát fel-le ereszkedve lépegetsz előre, gyakorlatilag támadóállásban.'), +(109, 'hu', 155, 'Merev lábú felhúzás', 'A gyakorlat kisebb súllyal helyesen végezve a comb-bicepszet és az alsó hátat erősíti. Az alsó mozgástartományban inkább dolgozik a combhajlító izom, de a törzs 45°-os pozícióján túljutva a felegyenesedés során már inkább a gerincmerevítő izmok végzik a munka javát.\r\nKiinduló helyzet\r\nTarts a kezedben egy kétkezes rudat, nem túl nagy súllyal felpakolva. Dobogóra vagy padra csak haladó szinten állj, ha teljesen kontroll alatt tudod tartani a testedet, de még ebben az esetben sem feltétlenül javasolt, és nem is feltétlenül szükséges.\r\nA mozgás\r\nA térdedet mozdulatlanul tartva, mereven tartva hajolj előre, miközben a csípőd NEMMMMMMELÉGAHELY'), +(110, 'hu', 156, 'Szamár vádli', 'Ez a gyakorlat a kétfejű lábikraizmot dolgoztatja meg.\r\nKiinduló helyzet\r\nVitathatatlan, hogy az az előredőlt testhelyzet, amit ehhez a gyakorlathoz fel kell venni valami egészen különlegeset tesz a lábszárral. Hajolj rá egy padra vagy asztalra, úgy, hogy a tested a padlóval párhuzamos helyzetben kényelmesen meg legyen támasztva. Egy edzőpartnered üljön fel a hátad alsó részére, a csípő környékére. \r\nA mozgás\r\nLábujjaidon emelkedj fel, majd ereszkedj vissza. Használj valamilyen magaslatot, lépcsőt, és a sarkadat engedd a lábujjaid alá miközben a lábujjaidon támaszkodsz, hogy a vádlid minél jobban megnyúljon.'), +(111, 'hu', 157, 'Ülő vádligép', 'Ezt a gyakorlatot is egy speciális gépen kell végezni. A végzett mozdulat inkább a talpemelő izmot (soleus) mozgatja meg.\r\nKiinduló helyzet\r\nÜlj be a gépbe, a térdedet szorítsd be a támasz alá úgy, hogy a vádlid megnyújtott állapotban legyen.\r\nA mozgás\r\nAkaszd ki a rögzítő kart. Emeld meg a vádlidat amennyire tudod, feszíts rá a felső ponton, majd lassan engedd vissza. Ügyelj rá, hogy ne rugózz az alsó ponton!'), +(112, 'hu', 158, 'Ülő vádligép', 'Ezt a gyakorlatot is egy speciális gépen kell végezni. A végzett mozdulat inkább a talpemelő izmot (soleus) mozgatja meg.\r\nKiinduló helyzet\r\nÜlj be a gépbe, a térdedet szorítsd be a támasz alá úgy, hogy a vádlid megnyújtott állapotban legyen.\r\nA mozgás\r\nAkaszd ki a rögzítő kart. Emeld meg a vádlidat amennyire tudod, feszíts rá a felső ponton, majd lassan engedd vissza. Ügyelj rá, hogy ne rugózz az alsó ponton!'), +(113, 'hu', 159, 'Kontroll', ''), +(114, 'hu', 160, 'Felhúzás', 'A felhúzás az erőemelés harmadik gyakorlata. Kétségtelenül a legnehezebb erőgyakorlat. A erő, a puszta fizikai erő igazi próbája. A guggolás mellett a leghatásosabb teljes testet megmozgató gyakorlat. Felállni egy képtelenül nagy súllyal, ez az igazi kihívás. A felhúzást kevesen csinálják, mert rosszul végezve igen sérülésveszélyes is lehet, ám jól kivitelezve az egyik leghatásosabb tömegnövelő alapgyakorlat.\r\n\r\nHatás\r\n\r\nA gyakorlat a hát alsó és középső részének izomzatát, a csípő izmait, a combizmokat és csuklyás izmot is stimulálja. A fogást is erősíti.\r\n\r\nKiinduló helyzet\r\nxxx'), +(115, 'hu', 161, 'Combközelítés lábgépen', 'Hatás\r\n\r\nA gyakorlat, a hiedelemmel ellentétben elsősorban a csípő izmait edzi meg, maguk a combizmok kis terhelést kapnak csupán. Tehát klasszikus értelemben ez nem is combközelítő izom gyakorlat, sajnos.\r\n\r\nKiinduló helyzet\r\n\r\nÜlj be a gépbe, és támaszd ki a hátadat.\r\n\r\nA mozgás\r\n\r\nÜlésben, széles terpeszből indulva a gép által biztosított ellenállással szemben zárd a lábaidat, majd lassan engedd őket vissza. (A gyakorlat során a derekadat nyomd a padnak és ülj egyenesen! Lassan és folyamatosan végezd a gyakorlatot, a súlyt a visszaengedéskor ne tedd le!)'), +(116, 'hu', 162, 'Méretek', ''), +(117, 'hu', 168, 'Faltámasz', ''), +(118, 'hu', 169, 'pop squat', ''), +(119, 'hu', 170, 'Kitörés kombináció hátra keresztezéssel', ''), +(120, 'hu', 171, 'Fekvőtámasz karhajlítással & nyújtott karemeléssel', ''), +(121, 'hu', 172, 'Gyorskorcsolyázó', ''), +(122, 'hu', 173, 'Jumping Jacks', ''), +(123, 'hu', 174, 'Crab Dance', ''), +(124, 'hu', 175, 'Kitörés oldalra terpeszállásban, talajérintéssel', ''), +(125, 'hu', 176, 'Ninja Squat Pulse', ''), +(126, 'hu', 177, 'Squat Jacks', ''), +(127, 'hu', 178, 'Hegymászó', ''), +(128, 'hu', 179, 'Sziklamászó', ''), +(129, 'hu', 180, 'Hip twister', ''), +(130, 'hu', 181, 'Biciklizés térd érintéssel', ''), +(131, 'hu', 182, 'Ugrás guggolásból', ''), +(132, 'hu', 183, 'Helyben futás', ''), +(133, 'hu', 184, 'T-Push Ups', ''), +(134, 'hu', 186, 'Burpees_v1', ''), +(135, 'hu', 187, 'Burpees_v2', ''), +(136, 'hu', 188, 'Skate Steps', ''), +(137, 'hu', 189, 'Kitörés talajérintéssel & előre rúgással', ''), +(138, 'hu', 190, 'Plank', ''), +(139, 'hu', 191, 'Hip Dip Plank', ''), +(140, 'hu', 192, 'Side Plank', ''), +(141, 'hu', 193, 'Plank Toe Taps', ''), +(142, 'hu', 194, 'Walking Plank', ''), +(143, 'hu', 195, 'Knee Drive Twister', ''), +(144, 'hu', 196, 'Bird-Dog Plank', ''), +(145, 'hu', 197, 'Side Bridge & Kick', ''), +(146, 'hu', 198, 'Warrior Lunge', ''), +(147, 'hu', 199, 'Warrior Lunge Combo', ''), +(148, 'hu', 200, 'Low Lunge', ''), +(149, 'hu', 201, 'Leg Drop', ''), +(150, 'hu', 202, 'Butterfly Twist', ''), +(151, 'hu', 203, 'Bear Kick Back', ''), +(152, 'hu', 204, 'Down Dog Crunch', ''), +(153, 'hu', 205, 'Warrior III. Flow', ''), +(154, 'hu', 206, 'Side Bridge & Lift', ''), +(155, 'hu', 207, 'Plank Leg Lift', ''), +(156, 'hu', 208, 'Side Plank', ''), +(157, 'hu', 209, 'Push Ups', ''), +(158, 'hu', 210, 'Plank & Tap', ''), +(159, 'hu', 211, 'Star Jumps', ''), +(160, 'hu', 212, 'Plank Stroke', ''), +(161, 'hu', 213, 'Dolphin Push Ups', ''), +(162, 'hu', 214, 'Super V Squeeze', ''), +(163, 'hu', 215, 'Féreg Jack', ''), +(164, 'hu', 216, 'Squat and Leg lift', ''), +(165, 'hu', 217, 'Lunge Leg', ''), +(166, 'hu', 218, '1-Leg Deadlift', ''), +(167, 'hu', 219, 'Deadlift', ''), +(168, 'hu', 220, 'In and out squat', ''), +(169, 'hu', 221, 'Side Lunge', ''), +(170, 'hu', 222, 'Prisoner Stand Ups', ''), +(171, 'hu', 223, 'Squat', ''), +(172, 'hu', 224, 'Sumo Squat', ''), +(173, 'hu', 225, 'Curtsey and Side Lift', ''), +(174, 'hu', 226, 'Wall Sit', ''), +(175, 'hu', 227, 'Booty Burn', ''), +(176, 'hu', 228, 'Shuffle Steps', ''), +(177, 'hu', 229, 'Rear Leg Lift', ''), +(178, 'hu', 230, 'Side Lift', ''), +(179, 'hu', 231, 'Curtsey', ''), +(180, 'hu', 232, 'Leg Lift', ''), +(181, 'hu', 233, 'Bridge & Kick', ''), +(182, 'hu', 234, 'In & Out Laydawn Heel Tuch', ''), +(183, 'hu', 235, 'Inner Leg Lift_v1', ''), +(184, 'hu', 236, 'Inner Leg Lift_v2', ''), +(185, 'hu', 237, 'Pinguin Crunch', ''), +(186, 'hu', 238, 'Riverse Tuck & Kick Out', ''), +(187, 'hu', 239, 'Bent Knee V-crunch', ''), +(188, 'hu', 240, 'Pike Kick', ''), +(189, 'hu', 241, 'Side Kick', ''), +(190, 'hu', 242, 'Riverse Crunch', ''), +(191, 'hu', 243, 'Scissor Kicks', ''), +(192, 'hu', 244, 'Scissor Kicks with Toe Touch', ''), +(193, 'hu', 245, 'Prayer Crunch', ''), +(194, 'hu', 246, 'Full Body Crunch', ''), +(195, 'hu', 247, 'Unicorn Crunch', ''), +(196, 'hu', 248, 'Rainbow „V”', ''), +(197, 'hu', 249, 'Butterfly Sit Up', ''), +(198, 'hu', 250, 'Russian Twist', ''), +(199, 'hu', 251, 'Tricep Press', ''), +(200, 'hu', 252, 'Robot Row Combo', ''), +(201, 'hu', 253, 'Side Bridge & Squeeze', ''), +(202, 'hu', 254, 'Underhand Row', ''), +(203, 'hu', 255, 'Tricep Kick Back', ''), +(204, 'hu', 256, 'Lateral Combo', ''), +(205, 'hu', 257, 'One Arm Raw', ''), +(206, 'hu', 258, 'Chest Press', ''), +(207, 'hu', 259, 'High Pull', ''), +(209, 'hu', 261, 'Testtömegindex', ''), +(210, 'hu', 262, 'Anyagcsere', ''); + +COMMIT; \ No newline at end of file diff --git a/asset/icon/icon.png b/asset/icon/icon.png index 08b76b4..6ba6e3a 100644 Binary files a/asset/icon/icon.png and b/asset/icon/icon.png differ diff --git a/asset/icon/icon0.png b/asset/icon/icon0.png new file mode 100644 index 0000000..08b76b4 Binary files /dev/null and b/asset/icon/icon0.png differ diff --git a/asset/icon/icon1.png b/asset/icon/icon1.png new file mode 100644 index 0000000..3e6e540 Binary files /dev/null and b/asset/icon/icon1.png differ diff --git a/asset/image/fb_registration.png b/asset/image/fb_registration.png new file mode 100644 index 0000000..279a37a Binary files /dev/null and b/asset/image/fb_registration.png differ diff --git a/asset/image/lock.png b/asset/image/lock.png index 2e8c552..edf3147 100644 Binary files a/asset/image/lock.png and b/asset/image/lock.png differ diff --git a/asset/image/merleg.png b/asset/image/merleg.png new file mode 100644 index 0000000..495e5c0 Binary files /dev/null and b/asset/image/merleg.png differ diff --git a/i18n/en.json b/i18n/en.json index 92392b3..48fd81d 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -11,6 +11,8 @@ "Change Language": "Change Language", "Password too short": "Password too short (at least 6 characters)", "Please type an email address": "Please type an email address", + "Exception: Please accept our data policy":"Please accept our data policy", + "Please accept our data protection policy. For more information please click on 'Privacy'":"Please accept our data protection policy. For more information please click on 'Privacy'", "SignUp": "SignUp", "Privacy": "Privacy", "Change App Language": "Change App Language", @@ -21,11 +23,10 @@ "Settings": "Settings", "Profile": "Profile", "Selected Language": "Selected Language", - "gdpr_text": "", - + "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", - "Customer exists": "The email address has been registered already", + "Exception: Customer exists": "The email address has been registered already", "There is an error: during registration:": "There is an error: during registration:", "Please select an exercise": "Please select an exercise", "Cardio": "Cardio", @@ -55,6 +56,9 @@ "Save": "Save", "Delete": "Delete", + "Endurance_desc":"", + "OneRepMax_desc":"", + "Name": "Name", "Exercise": "Exercise", "Quantity": "Quantity", @@ -113,20 +117,26 @@ "Endomorph": "Endomorph", "Mesomorph": "Mesomorph", + "Ectomorph_desc": "Ectomorf", + "Endomorph_desc":"Endomorf", + "Mesomorph_desc":"Mezomorf", + + "Description": "Description", "Make your first test": "Make your first test", "finished": "finished", - "Why do you need Exercise Control?" : "Why do you need Exercise Control?", + "Why do you need Exercise Control?" : "Why do you need Test Exercise?", - "Your 1RM:":"Your 1RM:", + "Your 1RM:":"Your One-Rep-Max:", "Your Real 1RM:":"Your Real 1RM:", "Check":"Check", - "Control Exercise:": "Control Exercise:", + "Control Exercise:": "Test Exercise:", + "controlexercise_desc":"", "Summary of your test":"Summary of your test", "Test":"Test", - "1st Control": "1st Control", - "2nd Control": "2nd Control", - "3rd Control": "3rd Control", + "1st Control": "1st Test Exercise", + "2nd Control": "2nd Test Exercise", + "3rd Control": "3rd Test Exercise", "My Development":"Development", "My Training Plan":"Training Plan", @@ -137,6 +147,7 @@ "Save The Exercise To The Exercise Plan": "Save The Exercise To The Exercise Plan", "The number of the serie done with":"The number of the serie done with", "The number of the repeats of one serie":"The number of the repeats of one serie", + "reps":"reps", "1. Chest": "1. Chest", "2. Biceps": "2. Biceps", @@ -165,7 +176,10 @@ "Here you see you development in the last period." : "Here you see your development in the last period.", "Sum Of Mass":"Sum Of Mass", "Percent": "Percent", - "One Max Rep": "One Max Rep", + "One Rep Max": "One Rep Max", + "OneRepMax": "One Rep Max", + "onerepmax_desc": "", + "Detailed": "Detailed", "Weekly": "Weekly", "Monthly": "Monthly", @@ -179,7 +193,7 @@ "Custom Exercise Plan": "Custom Exercise Plan", "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.": "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.", - "In this list you will find all your executed exercises grouped by the date.": "In this list you will find all your executed exercises grouped by the date.", + "In this list you will find all your executed exercises grouped by the date.": "In this list you can find all your completed exercises sorted by the date.", "Persistence!": "Persistence!", "Greetings!": "Greetings!", @@ -211,11 +225,19 @@ "I forgot the password":"I forgot the password", "Exception: Instance of 'NotFoundException'": "Customer with the email not found. Please register or reset your password", + "Customer does not exist or the password is wrong": "Customer does not exist or the password is wrong", + "The email does not exist or the password is wrong": "Customer does not exist or the password is wrong", + "Exception: You have a previous Facebook login operation in progress":"You have a previous Facebook login operation in progress", + "Exception: Facebook login was not successful":"Facebook login was not successful", + "Exception: Facebook login cancelled":"Facebook login cancelled", + "Exception: Facebook login failed":"Facebook login failed", + + "More »": "More »", "Done": "Done", "Height":"Height", - "Actual Height":"Actual Height", - "Actual Weight":"Actual Weight", + "Actual Height":"Height", + "Actual Weight":"Weight", "Based on your weight and height your goal for BMI and weight:":"Based on your weight and height your goal for BMI and weight:", "Body Mass Index":"Body Mass Index", "Basal Metabolic Rate":"Basal Metabolic Rate", @@ -263,7 +285,11 @@ "feature is reachable after you finished":"feature is reachable after you finished", "100% test circles":"100% test circles", - "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises." + "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.", + + "Please define your Exercise Plan":"Please define your Exercise Plan", + "Go to: 'Training Plan' - 'Edit My Custom Plan'":"Go to: 'Training Plan' - 'Edit My Custom Plan'", + "Jump there »":"Jump there »" } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index ec9c37b..79963ee 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -12,6 +12,8 @@ "Password too short": "A jelszó min. 6 karakterből álljon", "Please type an email address": "Kérlek írj be egy email címet", "SignUp": "Regisztráció", + "Exception: Please accept our data policy":"Kérlek fogadd el az adatvédelmi szabályzatunkat", + "Please accept our data protection policy. For more information please click on 'Privacy'":"Kérlek fogadd el az adatvédelmi szabályzatunkat. További információkért kattints az 'Adatkezelés' linkre.", "Privacy": "Adatkezelés", "Change App Language": "Nyelvválasztás", "English": "Angol", @@ -21,13 +23,19 @@ "Settings": "Beállítások", "Profile": "Személyes adatok", "Selected Language": "Választott nyelv", - "gdpr_text": "", "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.", + "Exception: Facebook login was not successful": "Facebook bejelentkezés sikertelen", + "Exception: You have a previous Facebook login operation in progress":"Az előző bejelentkezés még folyamatban van.", + "Exception: Facebook login cancelled":"Facebook bejelentkezés megszakítva ", + "Exception: Facebook login failed":"Facebook bejelentkezés sikertelen", + "Please select an exercise": "Válassz ki egy gyakorlatot", "There is an error: during registration:": "Hiba lépett fel a regisztráció során:", - "Customer exists": "Ez az email cím már regisztrálva van", + "Exception: Customer exists": "Ez az email cím már regisztrálva van", "Cardio": "Kardió", "400m": "400m", "300m": "300m", @@ -60,6 +68,9 @@ "Execute the": "Hajtsd végre a(z)", "set!":"sorozatot!", + "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": "Név", "Exercise": "Gyakorlat", "Quantity": "Mennyiség", @@ -113,16 +124,18 @@ "Endomorph":"Endomorf", "Mesomorph":"Mezomorf", + "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ó.

", + "Mesomorph_desc":"

A 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 személyre szabottság miatt. Előfordul, hogy egy mezomorf zsírfelesleggel is rendelkezik. Ekkor a csípőcsont/mellkas arány és az izomzat viselkedése a döntő szempont.

", + "Description": "Leírás", "Make your first test": "Végezd el az első tesztet", "finished": "végrehajtva", - "Why do you need Exercise Control?": "Miért szükséges a kontrollgyakorlat?", + "Why do you need Exercise Control?": "Miért szükséges a tesztgyakorlat?", "Your 1RM:":"Maxerőd:", "Your Real 1RM:":"Ellenőrzött maxerő:", "Check":"Ellenőrzés", - "1st Control Exercise:": "1. kontrollgyakorlat:", - "2nd Control Exercise:": "2. kontrollgyakorlat:", - "3rd Control Exercise:": "3. kontrollgyakorlat:", + "My Development":"Fejlődésem", "My Training Plan":"Edzéstervem", @@ -162,7 +175,10 @@ "Here you see you development in the last period." : "Itt az izomcsoportok fejlődését látod az elmúlt időszakban. A pontos képhez három diagram közül választhatsz: 'Gyakorlat össztömeg', 'Maxerő' és 'Százalékos fejlődés', illetv választhatsz 4 különböző időszaki bontásból is: 'Részletes', 'Heti', 'Havi', 'Éves", "Sum Of Mass":"Össztömeg", "Percent": "Százalék", - "One Max Rep": "Maxerő", + + "One Rep Max": "Maxerő", + "OneRepMax": "Maxerő", + "Detailed": "Részletes", "Weekly": "Heti", "Monthly": "Havi", @@ -202,11 +218,13 @@ "Are you sure to logout?": "Biztos, hogy kijelentkezel?", "hu_with": "-mal", - "Control Exercise:": "Gyakorlat végrehajtása:", + "Control Exercise:": "Tesztgyakorlat végrehajtása:", + "controlexercise_desc":"

Miért csináld meg a tesztgyakorlatokat?

Ha a leírtak szerint és szabályos végrehajtással végzed a tesztgyakorlatokat, akkor pontos képet ad az applikáció az izomerő és erőállóképesség állapotodról, ami alapján a későbbiekben testreszabottan tudod végezni a gyakorlatokat.

Ez mit jelent? Azt, hogy meghatározzuk számodra a célod eléréséhez megfelelő súlyt és a hozzátartozó ismétlésszámot, ami a siker kulcsa. Sőt! Az appon belül az egyéni edzésterv menüben össze is állíthatod magadnak a saját edzésnapodat.

Ne feledd! A teszt csak a jelen állapotodról ad visszaigazolást. Ha folyamatosan fejlődni szeretnél 3-6 hetente érdemes visszalátogatnod az 1RM vagy Erőállóképességi tesztekbe. Hajrá!

", + "Test":"Teszt", - "1st Control": "1. kontrollgyakorlat", - "2nd Control": "2. kontrollgyakorlat", - "3rd Control": "3. kontrollgyakorlat", + "1st Control": "1. tesztgyakorlat", + "2nd Control": "2. tesztgyakorlat", + "3rd Control": "3. tesztgyakorlat", "Summary of your test":"A teszt összefoglalása:", "Are you sure to delete this exercise?": "Biztos, hogy törlöd a gyakorlatot?", @@ -251,6 +269,7 @@ "Average BPM":"Átl pulzus", "Fatburn %":"Zsírégetés %", "Health Data Summary":"Egészségadatok összefoglalás", + "reps":"ism.", "Congratulation!":"Gratulálok!", "You have achieved to first 100% test-round!":"Teljesítetted az első 100%-os tesztköröd!", @@ -264,8 +283,10 @@ "feature is reachable after you finished":"funkció elérhető számodra, miután teljesítetted", "100% test circles":"100%-os teszt-köröd", - "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését" - + "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.":"Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését", + "Please define your Exercise Plan":"Kérlek készíts edzéstervet!", + "Go to: 'Training Plan' - 'Edit My Custom Plan'":"Menj a 'Edzéstervem' - 'Egyéni edzésterv' menübe", + "Jump there »":"Vigyél oda »" } \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b48f0cf..b3106f5 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,8 +1,16 @@ PODS: - - device_info (0.0.1): - - Flutter - devicelocale (0.0.1): - Flutter + - FBSDKCoreKit (8.2.0): + - FBSDKCoreKit/Basics (= 8.2.0) + - FBSDKCoreKit/Core (= 8.2.0) + - FBSDKCoreKit/Basics (8.2.0) + - FBSDKCoreKit/Core (8.2.0): + - FBSDKCoreKit/Basics + - FBSDKLoginKit (8.2.0): + - FBSDKLoginKit/Login (= 8.2.0) + - FBSDKLoginKit/Login (8.2.0): + - FBSDKCoreKit (~> 8.2.0) - Firebase/Auth (6.33.0): - Firebase/CoreOnly - FirebaseAuth (~> 6.9.2) @@ -61,6 +69,10 @@ PODS: - Flutter - Flurry-iOS-SDK/FlurrySDK (11.1.1) - Flutter (1.0.0) + - flutter_facebook_auth (1.0.0): + - FBSDKCoreKit (~> 8.2.0) + - FBSDKLoginKit (~> 8.2.0) + - Flutter - flutter_inapp_purchase (0.0.1): - Flutter - flutter_keyboard_visibility (0.0.1): @@ -88,8 +100,6 @@ PODS: - GoogleUtilities/UserDefaults (6.7.2): - GoogleUtilities/Logger - GTMSessionFetcher/Core (1.5.0) - - health (1.0.1): - - Flutter - nanopb (1.30906.0): - nanopb/decode (= 1.30906.0) - nanopb/encode (= 1.30906.0) @@ -104,24 +114,34 @@ PODS: - sqflite (0.0.2): - Flutter - FMDB (>= 2.7.5) + - video_player (0.0.1): + - Flutter + - wakelock (0.0.1): + - Flutter + - webview_flutter (0.0.1): + - Flutter DEPENDENCIES: - - device_info (from `.symlinks/plugins/device_info/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - flurry (from `.symlinks/plugins/flurry/ios`) - Flutter (from `Flutter`) + - flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`) - flutter_inapp_purchase (from `.symlinks/plugins/flutter_inapp_purchase/ios`) - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - - health (from `.symlinks/plugins/health/ios`) - path_provider (from `.symlinks/plugins/path_provider/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`) + - video_player (from `.symlinks/plugins/video_player/ios`) + - wakelock (from `.symlinks/plugins/wakelock/ios`) + - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`) SPEC REPOS: trunk: + - FBSDKCoreKit + - FBSDKLoginKit - Firebase - FirebaseAuth - FirebaseCore @@ -139,8 +159,6 @@ SPEC REPOS: - Protobuf EXTERNAL SOURCES: - device_info: - :path: ".symlinks/plugins/device_info/ios" devicelocale: :path: ".symlinks/plugins/devicelocale/ios" firebase_auth: @@ -153,22 +171,29 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flurry/ios" Flutter: :path: Flutter + flutter_facebook_auth: + :path: ".symlinks/plugins/flutter_facebook_auth/ios" flutter_inapp_purchase: :path: ".symlinks/plugins/flutter_inapp_purchase/ios" flutter_keyboard_visibility: :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" - health: - :path: ".symlinks/plugins/health/ios" path_provider: :path: ".symlinks/plugins/path_provider/ios" shared_preferences: :path: ".symlinks/plugins/shared_preferences/ios" sqflite: :path: ".symlinks/plugins/sqflite/ios" + video_player: + :path: ".symlinks/plugins/video_player/ios" + wakelock: + :path: ".symlinks/plugins/wakelock/ios" + webview_flutter: + :path: ".symlinks/plugins/webview_flutter/ios" SPEC CHECKSUMS: - device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00 + FBSDKCoreKit: 4afd6ff53d8133a433dbcda44451c9498f8c6ce4 + FBSDKLoginKit: 7181765f2524d7ebf82d9629066c8e6caafc99d0 Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5 firebase_auth: d5159db3873478d1ac839af7b10d2f831516136a firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659 @@ -182,19 +207,22 @@ SPEC CHECKSUMS: flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad Flurry-iOS-SDK: 8f3f7fce27177002f15f145eede88dc1b9ac0cd0 Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_facebook_auth: bad08a3d465e7b7ba9d8468a9dc7df3f69c136b8 flutter_inapp_purchase: 5c6a1ac3f11b11d0c8c0321c0c41c1f05805e4c8 flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833 GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52 - health: 44840ad4328aa5586e77bef289898bfed644a81c nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748 shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e + wakelock: bfc7955c418d0db797614075aabbc58a39ab5107 + webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96 PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index b8425b9..cdc9f4f 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -15,7 +15,6 @@ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; BB69292B2521AF45001FBA4C /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BB69292A2521AF45001FBA4C /* Launch Screen.storyboard */; }; BB81345024BB4BE10078D9A4 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB81344F24BB4BE10078D9A4 /* GoogleService-Info.plist */; }; - BBDBEBB825862170006762F6 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBDBEBB725862170006762F6 /* HealthKit.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -49,7 +48,6 @@ BB43773E2540715900D74BFA /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; BB69292A2521AF45001FBA4C /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; BB81344F24BB4BE10078D9A4 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - BBDBEBB725862170006762F6 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; D5EDDC52125075FB9E21AD35 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; F39E6E227EB942E5663A6086 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -60,7 +58,6 @@ buildActionMask = 2147483647; files = ( 42B6B159AF35AFB6DE777DFB /* Pods_Runner.framework in Frameworks */, - BBDBEBB825862170006762F6 /* HealthKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -80,7 +77,6 @@ 3ADC50290ED054951FAC1F56 /* Frameworks */ = { isa = PBXGroup; children = ( - BBDBEBB725862170006762F6 /* HealthKit.framework */, 09BD889296C5C90D989820C8 /* Pods_Runner.framework */, ); name = Frameworks; @@ -182,7 +178,7 @@ }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 10.0"; + compatibilityVersion = "Xcode 12.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -366,7 +362,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 42; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -383,7 +379,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.1.3; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -509,7 +505,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 42; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -526,7 +522,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.1.3; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -544,7 +540,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 42; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -561,7 +557,7 @@ "$(inherited)", "$(PROJECT_DIR)/Flutter", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.1.3; PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png index e0e21b7..17aee37 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png index 08b76b4..04e4f2f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png index 1a8fabd..d8728b2 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png index d51cca7..74dee32 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png new file mode 100644 index 0000000..13231ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png index 94d63c0..ac648a2 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png index 320c9e5..efd5c4a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png new file mode 100644 index 0000000..c478fa4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png index 513bacd..13b0f68 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png new file mode 100644 index 0000000..9cf86c6 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png index e4b1454..f5624f8 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png new file mode 100644 index 0000000..956942e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png index 50aa58a..89c9be2 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png new file mode 100644 index 0000000..062833a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png new file mode 100644 index 0000000..c39315e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png index 93f531d..9053baa 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png new file mode 100644 index 0000000..89023a5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png index 9b8c5d5..8beeb5e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png new file mode 100644 index 0000000..7e02091 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png index 75b74ab..8d3e043 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png new file mode 100644 index 0000000..48258df Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png new file mode 100644 index 0000000..602c954 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png index 27009dd..365cd47 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png index a662dd4..3ec51c6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png index d55c0f6..e7bb531 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png new file mode 100644 index 0000000..1611852 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png index 25fa4a7..47b270e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png index 0a1763c..5f0636e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png index 7aaff3f..374533b 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png index 15ee184..a5e9f7b 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png new file mode 100644 index 0000000..1497d47 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index 4fdf882..e138c0b 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,158 +1 @@ -{ - "images" : [ - { - "filename" : "40.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "60.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "29.png", - "idiom" : "iphone", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "58.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "87.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "80.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "120.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "57.png", - "idiom" : "iphone", - "scale" : "1x", - "size" : "57x57" - }, - { - "filename" : "114.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "57x57" - }, - { - "filename" : "120.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "180.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "20.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "40.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "29.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "58.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "40.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "80.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "50.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "50x50" - }, - { - "filename" : "100.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "50x50" - }, - { - "filename" : "72.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "72x72" - }, - { - "filename" : "144.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "72x72" - }, - { - "filename" : "76.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "152.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "167.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "1024.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"idiom":"watch","filename":"172.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"86x86","expected-size":"172","role":"quickLook"},{"idiom":"watch","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"40x40","expected-size":"80","role":"appLauncher"},{"idiom":"watch","filename":"88.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"40mm","scale":"2x","size":"44x44","expected-size":"88","role":"appLauncher"},{"idiom":"watch","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"50x50","expected-size":"100","role":"appLauncher"},{"idiom":"watch","filename":"196.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"98x98","expected-size":"196","role":"quickLook"},{"idiom":"watch","filename":"216.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"108x108","expected-size":"216","role":"quickLook"},{"idiom":"watch","filename":"48.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"24x24","expected-size":"48","role":"notificationCenter"},{"idiom":"watch","filename":"55.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"27.5x27.5","expected-size":"55","role":"notificationCenter"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"3x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"2x"},{"size":"1024x1024","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch-marketing","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 04f6f47..80c67d1 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -46,10 +46,6 @@ 10.0 LSRequiresIPhoneOS - NSHealthShareUsageDescription - We will sync your data with the Apple Health app to give you better insights - NSHealthUpdateUsageDescription - We will sync your data with the Apple Health app to give you better insights UIBackgroundModes fetch diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements index 57cd459..903def2 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner/Runner.entitlements @@ -4,11 +4,5 @@ aps-environment development - com.apple.developer.healthkit - - com.apple.developer.healthkit.access - - health-records - diff --git a/ios/Runner/appstore.png b/ios/Runner/appstore.png index 660df3d..04e4f2f 100644 Binary files a/ios/Runner/appstore.png and b/ios/Runner/appstore.png differ diff --git a/ios/Runner/playstore.png b/ios/Runner/playstore.png index f7c423a..da74533 100644 Binary files a/ios/Runner/playstore.png and b/ios/Runner/playstore.png differ diff --git a/lib/bloc/custom_exercise_form_bloc.dart b/lib/bloc/custom_exercise_form_bloc.dart index 0f2424f..c0755dd 100644 --- a/lib/bloc/custom_exercise_form_bloc.dart +++ b/lib/bloc/custom_exercise_form_bloc.dart @@ -4,6 +4,7 @@ import 'package:flutter_form_bloc/flutter_form_bloc.dart'; class CustomExerciseFormBloc extends FormBloc { final ExerciseRepository exerciseRepository; + bool loading = false; final quantityField = TextFieldBloc( validators: [ FieldBlocValidators.required, @@ -66,10 +67,12 @@ class CustomExerciseFormBloc extends FormBloc { @override void onSubmitting() async { try { + loading = true; emitLoading(progress: 30); // Emit either Loaded or Error emitSuccess(canSubmitAgain: false); + loading = false; } on Exception catch (ex) { emitFailure(failureResponse: ex.toString()); } diff --git a/lib/bloc/customer_change/customer_change_bloc.dart b/lib/bloc/customer_change/customer_change_bloc.dart index 6c6612b..104a41b 100644 --- a/lib/bloc/customer_change/customer_change_bloc.dart +++ b/lib/bloc/customer_change/customer_change_bloc.dart @@ -2,26 +2,30 @@ import 'dart:async'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:aitrainer_app/util/common.dart'; +import 'package:aitrainer_app/util/trans.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; part 'customer_change_event.dart'; part 'customer_change_state.dart'; -class CustomerChangeBloc extends Bloc { +class CustomerChangeBloc extends Bloc with Trans { final CustomerRepository customerRepository; + final BuildContext context; bool visiblePassword = false; int year = 1990; double weight = 60; double height = 170; - CustomerChangeBloc({this.customerRepository}) : super(CustomerChangeInitial()) { + CustomerChangeBloc({this.customerRepository, this.context}) : super(CustomerChangeInitial()) { year = this.customerRepository.customer.birthYear; if (year == 0) { year = 1990; } - weight = this.customerRepository.getWeight(); - height = this.customerRepository.getHeight(); + weight = this.customerRepository.getWeight() == 0 ? 60 : this.customerRepository.getWeight(); + height = this.customerRepository.getHeight() == 0 ? 170 : this.customerRepository.getHeight(); } @override @@ -98,21 +102,24 @@ class CustomerChangeBloc extends Bloc } String emailValidation(String email) { - bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email); - return emailValid ? null : "Please type an email address"; + String message = Common.emailValidation(email); + if (message != null) { + message = t(message); + } + return message; } String passwordValidation(String value) { - if (value == null || value.length == 0) { - return null; + String message = Common.passwordValidation(value); + if (message != null) { + message = t(message); } - bool valid = 8 < value.length; - return valid ? null : "Password too short"; + return message; } String nameValidation(String value) { if (value == null || value.length == 0) { - return "Name too short"; + return t("Name too short"); } return null; } diff --git a/lib/bloc/exercise_control/exercise_control_bloc.dart b/lib/bloc/exercise_control/exercise_control_bloc.dart index ce88cb4..9b49b80 100644 --- a/lib/bloc/exercise_control/exercise_control_bloc.dart +++ b/lib/bloc/exercise_control/exercise_control_bloc.dart @@ -13,7 +13,6 @@ class ExerciseControlBloc extends Bloc repeats = List(); double initialRM; double unitQuantity; @@ -27,17 +26,13 @@ class ExerciseControlBloc extends Bloc 0) { if (exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId) != null) { workoutTree.selected = true; + this.selectedNumber++; } } }); diff --git a/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart b/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart index c869a76..0b0ebe4 100644 --- a/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart +++ b/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart @@ -55,6 +55,7 @@ class ExerciseExecutePlanAddBloc extends Bloc { @override ExerciseLogBloc({this.exerciseRepository}) : super(ExerciseLogInitial()); - @override Stream mapEventToState(ExerciseLogEvent event) async* { try { if (event is ExerciseLogLoad) { yield ExerciseLogLoading(); + Flurry.logEvent("exerciseLog"); yield ExerciseLogReady(); - } else if ( event is ExerciseLogDelete ) { + } else if (event is ExerciseLogDelete) { yield ExerciseLogLoading(); exerciseRepository.exerciseList.remove(event.exercise); await exerciseRepository.deleteExercise(event.exercise); + Flurry.logEvent("exerciseDelete"); + yield ExerciseLogReady(); + } else if (event is ExerciseResult) { + yield ExerciseLogLoading(); + Flurry.logEvent("exerciseResult"); yield ExerciseLogReady(); } } on Exception catch (e) { diff --git a/lib/bloc/exercise_log/exercise_log_event.dart b/lib/bloc/exercise_log/exercise_log_event.dart index cf8fded..bce4fb5 100644 --- a/lib/bloc/exercise_log/exercise_log_event.dart +++ b/lib/bloc/exercise_log/exercise_log_event.dart @@ -18,5 +18,8 @@ class ExerciseLogDelete extends ExerciseLogEvent { @override List get props => [exercise]; - +} + +class ExerciseResult extends ExerciseLogEvent { + const ExerciseResult(); } diff --git a/lib/bloc/exercise_new/exercise_new_bloc.dart b/lib/bloc/exercise_new/exercise_new_bloc.dart index 8ed2914..83665aa 100644 --- a/lib/bloc/exercise_new/exercise_new_bloc.dart +++ b/lib/bloc/exercise_new/exercise_new_bloc.dart @@ -1,11 +1,13 @@ import 'dart:async'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/exercise_ability.dart'; import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; 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:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flurry/flurry.dart'; @@ -18,7 +20,7 @@ import 'package:stop_watch_timer/stop_watch_timer.dart'; part 'exercise_new_event.dart'; part 'exercise_new_state.dart'; -class ExerciseNewBloc extends Bloc { +class ExerciseNewBloc extends Bloc with Logging { final ExerciseRepository exerciseRepository; final CustomerRepository customerRepository; final MenuBloc menuBloc; @@ -45,6 +47,7 @@ class ExerciseNewBloc extends Bloc { double mediaWidth = 0; double mediaHeight = 0; bool isMan = true; + String exerciseTask = ""; final StopWatchTimer stopWatchTimer = StopWatchTimer( isLapHours: false, @@ -54,8 +57,8 @@ class ExerciseNewBloc extends Bloc { @override ExerciseNewBloc({this.exerciseRepository, this.menuBloc, this.customerRepository, ExerciseType exerciseType}) : super(ExerciseNewInitial()) { + exerciseRepository.exerciseType = exerciseType; exerciseRepository.setUnit(exerciseType.unit); - exerciseRepository.setQuantity(quantity); exerciseRepository.setUnitQuantity(unitQuantity); exerciseRepository.exercise.exercisePlanDetailId = 0; exerciseRepository.start = DateTime.now(); @@ -66,7 +69,38 @@ class ExerciseNewBloc extends Bloc { fitnessLevel = customerRepository.customer.fitnessLevel; this.isMan = (customerRepository.customer.sex == "m"); } - stopWatchTimer.rawTime.listen((value) => timerValue = value); + if (exerciseType.unit == "second") { + stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())}); + } + this.setExerciseTask(init: true); + } + + String setExerciseTask({bool init = false}) { + if (this.exerciseRepository.exerciseType == null) { + print("WTF, exerciseType is null"); + return ""; + } + if (this.exerciseRepository.exerciseType.unit != "second") { + if (menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) { + this.exerciseTask = "Please take a relative bigger weight and repeat 12-20 times"; + if (init) { + this.setQuantity(12); + } + } else if (this.exerciseRepository.exerciseType.isEndurance() && + menuBloc.ability.toString() == ExerciseAbility.endurance.toString() && + exerciseRepository.exerciseType.unitQuantity == "1") { + this.exerciseTask = "Please take a medium weight and repeat 20-30 times"; + if (init) { + this.setQuantity(20); + } + } + } + return this.exerciseTask; + } + + void setQuantity(double quantity) { + this.quantity = quantity; + exerciseRepository.setQuantity(quantity); } void setMediaDimensions(double width, double height) { @@ -213,6 +247,37 @@ class ExerciseNewBloc extends Bloc { } } + int getWeightCoordinate(isMan, {isTop = false, isLeft = false}) { + int value = 0; + this.manSizes.forEach((element) { + if (element.propertyName == "Weight") { + if (isTop == true) { + value = element.top; + } else if (isLeft == true) { + value = element.left; + } + } + }); + return value; + } + + Property getPropertyByName(String propertyName) { + Property property; + List sizes; + if (customerRepository.sex == "Man") { + sizes = this.manSizes; + } else { + sizes = this.womanSizes; + } + + sizes.forEach((element) { + if (element.propertyName == propertyName) { + property = element; + } + }); + return property; + } + void updateSizes(String propertyName, double value) { List sizes; if (customerRepository.sex == "Man") { @@ -236,8 +301,8 @@ class ExerciseNewBloc extends Bloc { yield ExerciseNewReady(); } else if (event is ExerciseNewQuantityChange) { yield ExerciseNewLoading(); - exerciseRepository.setQuantity(event.quantity); - quantity = event.quantity; + log("Event quantity " + event.quantity.toStringAsFixed(0)); + this.setQuantity(event.quantity); yield ExerciseNewReady(); } else if (event is ExerciseNewQuantityUnitChange) { yield ExerciseNewLoading(); @@ -288,6 +353,7 @@ class ExerciseNewBloc extends Bloc { menuBloc.add(MenuTreeDown(parent: 0)); Cache().initBadges(); Flurry.logEvent("newExercise"); + Flurry.logEvent("newExercise " + exerciseRepository.exerciseType.name); yield ExerciseNewReady(); } else if (event is ExerciseNewBMIAnimate) { yield ExerciseNewLoading(); @@ -342,19 +408,32 @@ class ExerciseNewBloc extends Bloc { getBMI(); } final double distortionWidth = mediaWidth / baseWidth; - final double distortionHeight = mediaHeight / baseHeight; + final double distortionHeight = distortionWidth - 0.02; //mediaHeight / baseHeight; + /* log("Width: " + + mediaWidth.toStringAsFixed(0) + + " Height: " + + mediaHeight.toStringAsFixed(0) + + " BaseW: " + + baseWidth.toStringAsFixed(0) + + " BaseH: " + + baseHeight.toStringAsFixed(0) + + " DistW: " + + distortionWidth.toStringAsFixed(2) + + " DistH: " + + distortionHeight.toStringAsFixed(2)); */ + this.bmiAngle = (bmi * 90 / 25) - 90; if (bmi < 18.5) { goalBMI = 19; this.bmiTop = 99 * distortionHeight; this.bmiLeft = 77 * distortionWidth; bmiAngle = -62; - } else if (bmi < 25 && 18.5 < bmi) { - goalBMI = 27; + } else if (bmi > 18.5 && bmi < 25) { + goalBMI = this.bmi; this.bmiTop = 48 * distortionHeight; this.bmiLeft = 130 * distortionWidth; bmiAngle = -23; - } else if (bmi < 30 && 24.9 < bmi) { + } else if (bmi < 30 && bmi > 24.9) { goalBMI = 24; this.bmiTop = 40.0 * distortionHeight; this.bmiLeft = 184.0 * distortionWidth; @@ -376,9 +455,4 @@ class ExerciseNewBloc extends Bloc { return goalBMI; } - - @override - void dispose() async { - await stopWatchTimer.dispose(); - } } diff --git a/lib/bloc/exercise_plan/exercise_plan_bloc.dart b/lib/bloc/exercise_plan/exercise_plan_bloc.dart index 9757c7b..9e8694e 100644 --- a/lib/bloc/exercise_plan/exercise_plan_bloc.dart +++ b/lib/bloc/exercise_plan/exercise_plan_bloc.dart @@ -7,6 +7,7 @@ import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flurry/flurry.dart'; +import 'package:flurry/flurry.dart'; import 'package:meta/meta.dart'; part 'exercise_plan_event.dart'; @@ -48,6 +49,7 @@ class ExercisePlanBloc extends Bloc { try { if (event is ExercisePlanLoad) { yield ExercisePlanLoading(); + Flurry.logEvent("exercisePlan"); await this.getData(); yield ExercisePlanReady(); } diff --git a/lib/bloc/login/login_bloc.dart b/lib/bloc/login/login_bloc.dart new file mode 100644 index 0000000..be8f5b4 --- /dev/null +++ b/lib/bloc/login/login_bloc.dart @@ -0,0 +1,108 @@ +import 'dart:async'; + +import 'package:aitrainer_app/bloc/account/account_bloc.dart'; +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/util/common.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'; +part 'login_state.dart'; + +class LoginBloc extends Bloc with Trans { + final AccountBloc accountBloc; + final UserRepository userRepository; + final CustomerRepository customerRepository = CustomerRepository(); + final BuildContext context; + final bool isRegistration; + bool dataPolicyAllowed = false; + LoginBloc({this.accountBloc, this.userRepository, this.context, this.isRegistration}) : super(LoginInitial()); + + @override + Stream mapEventToState( + LoginEvent event, + ) async* { + try { + if (event is LoginEmailChange) { + yield LoginLoading(); + final String email = event.email; + userRepository.setEmail(email); + yield LoginReady(); + } else if (event is LoginPasswordChange) { + yield LoginLoading(); + final String password = event.password; + userRepository.setPassword(password); + yield LoginReady(); + } else if (event is LoginSubmit) { + yield LoginLoading(); + await userRepository.getUser(); + accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + Flurry.logEvent("Login"); + yield LoginSuccess(); + } else if (event is LoginFB) { + yield LoginLoading(); + await userRepository.getUserByFB(); + accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + Flurry.logEvent("Login"); + Flurry.logEvent("LoginFB"); + yield LoginSuccess(); + } else if (event is RegistrationSubmit) { + yield LoginLoading(); + if (!this.dataPolicyAllowed) { + yield LoginError(); + throw Exception("Please accept our data policy"); + } + await userRepository.addUser(); + accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + await saveCustomer(); + Flurry.logEvent("Registration"); + + yield LoginSuccess(); + } else if (event is RegistrationFB) { + yield LoginLoading(); + if (!this.dataPolicyAllowed) { + yield LoginError(); + throw Exception("Please accept our data policy"); + } + await userRepository.addUserFB(); + accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + await saveCustomer(); + Flurry.logEvent("RegistrationFB"); + Flurry.logEvent("Registration"); + yield LoginSuccess(); + } else if (event is DataProtectionClicked) { + this.dataPolicyAllowed = event.marked; + yield LoginReady(); + } + } on Exception catch (e) { + yield LoginError(message: e.toString()); + } + } + + Future saveCustomer() async { + customerRepository.customer = Cache().userLoggedIn; + customerRepository.customer.dataPolicyAllowed = 1; + await customerRepository.saveCustomer(); + } + + String emailValidation(String email) { + String message = Common.emailValidation(email); + if (message != null) { + message = t(message); + } + return message; + } + + String passwordValidation(String value) { + String message = Common.passwordValidation(value); + if (message != null) { + message = t(message); + } + return message; + } +} diff --git a/lib/bloc/login/login_event.dart b/lib/bloc/login/login_event.dart new file mode 100644 index 0000000..c51f179 --- /dev/null +++ b/lib/bloc/login/login_event.dart @@ -0,0 +1,49 @@ +part of 'login_bloc.dart'; + +abstract class LoginEvent extends Equatable { + const LoginEvent(); + + @override + List get props => []; +} + +class LoginEmailChange extends LoginEvent { + final String email; + const LoginEmailChange({this.email}); + + @override + List get props => [email]; +} + +class LoginPasswordChange extends LoginEvent { + final String password; + const LoginPasswordChange({this.password}); + + @override + List get props => [password]; +} + +class LoginPasswordChangeObscure extends LoginEvent { + const LoginPasswordChangeObscure(); +} + +class LoginSubmit extends LoginEvent { + const LoginSubmit(); +} + +class LoginFB extends LoginEvent { + const LoginFB(); +} + +class DataProtectionClicked extends LoginEvent { + final bool marked; + const DataProtectionClicked({this.marked}); +} + +class RegistrationSubmit extends LoginEvent { + const RegistrationSubmit(); +} + +class RegistrationFB extends LoginEvent { + const RegistrationFB(); +} diff --git a/lib/bloc/login/login_state.dart b/lib/bloc/login/login_state.dart new file mode 100644 index 0000000..e075b3e --- /dev/null +++ b/lib/bloc/login/login_state.dart @@ -0,0 +1,36 @@ +part of 'login_bloc.dart'; + +abstract class LoginState extends Equatable { + const LoginState(); + + @override + List get props => []; +} + +class LoginInitial extends LoginState { + const LoginInitial(); +} + +class LoginLoading extends LoginState { + const LoginLoading(); +} + +class LoginReady extends LoginState { + const LoginReady(); +} + +class LoginSuccess extends LoginState { + const LoginSuccess(); +} + +class LoginError extends LoginState { + final String message; + const LoginError({this.message}); + + @override + List get props => [message]; +} + +class DataPolicyError extends LoginState { + const DataPolicyError(); +} diff --git a/lib/bloc/login_form_bloc.dart b/lib/bloc/login_form_bloc.dart deleted file mode 100644 index 38f4b75..0000000 --- a/lib/bloc/login_form_bloc.dart +++ /dev/null @@ -1,65 +0,0 @@ -import 'package:aitrainer_app/bloc/account/account_bloc.dart'; -import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/repository/exercise_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/property_service.dart'; -import 'package:aitrainer_app/util/common.dart'; -import 'package:flutter_form_bloc/flutter_form_bloc.dart'; - -class LoginFormBloc extends FormBloc with Common { - final AccountBloc accountBloc; - final UserRepository userRepository; - - final emailField = TextFieldBloc( - validators: [ - FieldBlocValidators.required, - ], - ); - final passwordField = TextFieldBloc(validators: [ - FieldBlocValidators.required, - ]); - - LoginFormBloc({this.userRepository, this.accountBloc}) { - addFieldBlocs(fieldBlocs: [emailField, passwordField]); - - emailField.onValueChanges(onData: (previous, current) async* { - userRepository.setEmail(current.value); - }); - - passwordField.onValueChanges(onData: (previous, current) async* { - userRepository.setPassword(current.value); - }); - } - - @override - void onSubmitting() async { - try { - emitLoading(progress: 30); - if (!validateEmail(userRepository)) { - emailField.addFieldError(EMAIL_ERROR, isPermanent: true); - - emitFailure(failureResponse: EMAIL_ERROR); - } else if (!validatePassword(userRepository)) { - passwordField.addFieldError(PASSWORD_ERROR, isPermanent: true); - emitFailure(failureResponse: PASSWORD_ERROR); - } else { - // Emit either Loaded or Error - await PropertyApi().getProperties(); - await userRepository.getUser(); - await ExerciseTypeApi().getExerciseTypes(); - await ExerciseTreeApi().getExerciseTree(); - if (Cache().userLoggedIn != null && Cache().userLoggedIn.customerId > 0) { - ExerciseRepository exerciseRepository = ExerciseRepository(); - await exerciseRepository.getExercisesByCustomer(Cache().userLoggedIn.customerId); - } - emitSuccess(canSubmitAgain: false); - accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); - Cache().initBadges(); - } - } on Exception catch (ex) { - emitFailure(failureResponse: ex.toString()); - } - } -} diff --git a/lib/bloc/registration_form_bloc.dart b/lib/bloc/registration_form_bloc.dart deleted file mode 100644 index dd443fa..0000000 --- a/lib/bloc/registration_form_bloc.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/repository/user_repository.dart'; -import 'package:aitrainer_app/util/common.dart'; -import 'package:flutter_form_bloc/flutter_form_bloc.dart'; -import 'account/account_bloc.dart'; - -class RegistrationFormBloc extends FormBloc with Common { - final AccountBloc accountBloc; - final emailField = TextFieldBloc( - validators: [ - FieldBlocValidators.required, - ], - ); - final passwordField = TextFieldBloc(validators: [ - FieldBlocValidators.required, - ]); - final UserRepository userRepository; - - RegistrationFormBloc({this.userRepository, this.accountBloc}) { - addFieldBlocs(fieldBlocs: [emailField, passwordField]); - - emailField.onValueChanges(onData: (previous, current) async* { - userRepository.setEmail(current.value); - }); - - passwordField.onValueChanges(onData: (previous, current) async* { - userRepository.setPassword(current.value); - }); - } - - @override - void onSubmitting() async { - try { - emitLoading(progress: 30); - if (!validateEmail(userRepository)) { - emailField.addFieldError(EMAIL_ERROR, isPermanent: true); - - emitFailure(failureResponse: EMAIL_ERROR); - } else if (!validatePassword(userRepository)) { - passwordField.addFieldError(PASSWORD_ERROR, isPermanent: true); - emitFailure(failureResponse: PASSWORD_ERROR); - } else { - // Emit either Loaded or Error - await userRepository.addUser(); - emitSuccess(canSubmitAgain: false); - accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); - Cache().initBadges(); - } - } on Exception catch (ex) { - emitFailure(failureResponse: ex.toString()); - } - } -} diff --git a/lib/bloc/reset_password_bloc.dart b/lib/bloc/reset_password_bloc.dart index 5a803f0..63b3025 100644 --- a/lib/bloc/reset_password_bloc.dart +++ b/lib/bloc/reset_password_bloc.dart @@ -1,10 +1,10 @@ - import 'package:aitrainer_app/repository/user_repository.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; class ResetPasswordFormBloc extends FormBloc with Common { final UserRepository userRepository; + bool loading = false; final emailField = TextFieldBloc( validators: [ @@ -13,9 +13,7 @@ class ResetPasswordFormBloc extends FormBloc with Common { ); ResetPasswordFormBloc({this.userRepository}) { - addFieldBlocs(fieldBlocs: [ - emailField - ]); + addFieldBlocs(fieldBlocs: [emailField]); emailField.onValueChanges(onData: (previous, current) async* { userRepository.setEmail(current.value); @@ -26,7 +24,8 @@ class ResetPasswordFormBloc extends FormBloc with Common { void onSubmitting() async { try { emitLoading(progress: 30); - if ( ! validateEmail(userRepository)) { + loading = true; + if (!validateEmail(userRepository)) { emailField.addFieldError(EMAIL_ERROR, isPermanent: true); emitFailure(failureResponse: EMAIL_ERROR); @@ -35,9 +34,9 @@ class ResetPasswordFormBloc extends FormBloc with Common { await userRepository.resetPassword(); emitSuccess(canSubmitAgain: false); } + loading = false; } on Exception catch (ex) { emitFailure(failureResponse: ex.toString()); - } } @@ -45,5 +44,4 @@ class ResetPasswordFormBloc extends FormBloc with Common { emailField.close(); return super.close(); } - -} \ No newline at end of file +} diff --git a/lib/bloc/result/result_bloc.dart b/lib/bloc/result/result_bloc.dart index b9b93d4..913fc49 100644 --- a/lib/bloc/result/result_bloc.dart +++ b/lib/bloc/result/result_bloc.dart @@ -5,21 +5,24 @@ import 'package:aitrainer_app/model/result.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_result_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; +import 'package:aitrainer_app/util/trans.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; -import 'package:health/health.dart'; +//import 'package:health/health.dart'; part 'result_event.dart'; part 'result_state.dart'; -class ResultBloc extends Bloc with Logging { +class ResultBloc extends Bloc with Logging, Trans { final ExerciseResultRepository resultRepository; final ExerciseRepository exerciseRepository; - List _healthDataList = List(); + final BuildContext context; + //List _healthDataList = List(); DateTime startTime; DateTime endTime; - final HealthFactory health = HealthFactory(); + /* final HealthFactory health = HealthFactory(); final List types = [ HealthDataType.ACTIVE_ENERGY_BURNED, HealthDataType.WATER, @@ -30,9 +33,9 @@ class ResultBloc extends Bloc with Logging { HealthDataType.HIGH_HEART_RATE_EVENT, HealthDataType.LOW_HEART_RATE_EVENT, HealthDataType.RESTING_HEART_RATE - ]; + ]; */ - ResultBloc({this.resultRepository, this.exerciseRepository}) : super(ResultInitial()) { + ResultBloc({this.resultRepository, this.exerciseRepository, this.context}) : super(ResultInitial()) { this.startTime = exerciseRepository.start; this.endTime = exerciseRepository.end; } @@ -45,7 +48,7 @@ class ResultBloc extends Bloc with Logging { if (event is ResultLoad) { yield ResultLoading(); - await _fetchHealthData(); + //await _fetchHealthData(); _matchExerciseData(); await resultRepository.saveExerciseResults(); yield ResultReady(); @@ -62,16 +65,16 @@ class ResultBloc extends Bloc with Logging { element.exerciseId = exerciseRepository.actualExerciseList[0].exerciseId; switch (element.item) { case ResultItem.bpm_avg: - element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE); + //element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE); break; case ResultItem.bpm_min: - element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE); + //element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE); break; case ResultItem.bpm_max: - element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE); + //element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE); break; case ResultItem.calorie: - element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED); + //element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED); break; case ResultItem.development_percent_bodypart: // TODO: Handle this case. @@ -82,7 +85,7 @@ class ResultBloc extends Bloc with Logging { } break; case ResultItem.fatburn_percent: - DateTime today = DateTime.now(); + /* DateTime today = DateTime.now(); int age = today.year - Cache().userLoggedIn.birthYear; double minBpm = (200 - age) * 0.6; double maxBpm = (200 - age) * 0.7; @@ -100,7 +103,7 @@ class ResultBloc extends Bloc with Logging { element.data = (burnCounter / counter * 100); } else { element.data = 0; - } + } */ break; case ResultItem.speed_max: // TODO: Handle this case. @@ -108,14 +111,14 @@ class ResultBloc extends Bloc with Logging { case ResultItem.reps_volume: if (exerciseRepository.exerciseType.unit == "repeat") { double value = 0; - exerciseRepository.actualExerciseList.forEach((element) { - value += element.quantity; + exerciseRepository.actualExerciseList.forEach((actual) { + value += actual.quantity; }); element.data = value; } break; case ResultItem.steps: - element.data = _gethHealthDataPointValueSum(HealthDataType.STEPS); + element.data = 0; //_gethHealthDataPointValueSum(HealthDataType.STEPS); break; /* case ResultItem.time: final Duration duration = this.endTime.difference(this.startTime); @@ -124,8 +127,8 @@ class ResultBloc extends Bloc with Logging { case ResultItem.weight_volume: if (exerciseRepository.exerciseType.unitQuantityUnit == "kilogram") { double value = 0; - exerciseRepository.actualExerciseList.forEach((element) { - value += element.quantity * element.unitQuantity; + exerciseRepository.actualExerciseList.forEach((actual) { + value += actual.quantity * actual.unitQuantity; }); element.data = value; } @@ -134,15 +137,31 @@ class ResultBloc extends Bloc with Logging { }); } - String _printDuration(Duration duration) { + String printDuration(Duration duration, {isText = false, isDecimal = false}) { String twoDigits(int n) => n.toString().padLeft(2, "0"); String twoDigitMinutes = twoDigits(duration.inMinutes); String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60)); String twoDigitMilliSeconds = duration.inMilliseconds.remainder(1000).toString(); - return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"'; + if (isText) { + if (isDecimal) { + return "$twoDigitMinutes" + t("min") + "$twoDigitSeconds" + t("sec") + ":$twoDigitMilliSeconds" + '"'; + } else { + return "$twoDigitMinutes" + t("min") + "$twoDigitSeconds" + t("sec"); + } + } else { + return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"'; + } } - double _gethHealthDataPointValueAvg(HealthDataType dataType) { + String printTime(double duration) { + String twoDigits(int n) => n.toString().padLeft(1, "0"); + String twoDigitMinutes = twoDigits((duration ~/ 60).toInt()); + String twoDigitSeconds = (duration % 60).toStringAsFixed(0); + + return "$twoDigitMinutes " + t("minutes") + " $twoDigitSeconds"; + } + + /* double _gethHealthDataPointValueAvg(HealthDataType dataType) { double value = 0; double counter = 0; _healthDataList.forEach((dataPoint) { @@ -193,9 +212,9 @@ class ResultBloc extends Bloc with Logging { min = 0; } return min; - } + } */ - Future _fetchHealthData() async { + /* Future _fetchHealthData() async { if (health == null) { return; } @@ -209,7 +228,7 @@ class ResultBloc extends Bloc with Logging { log("Caught exception in getHealthDataFromTypes: $e"); throw Exception(e); } - } + } */ double calculate1RM({double percent}) { if (exerciseRepository.exercise == null) { diff --git a/lib/bloc/sales/sales_bloc.dart b/lib/bloc/sales/sales_bloc.dart index eb6a834..8e26f1d 100644 --- a/lib/bloc/sales/sales_bloc.dart +++ b/lib/bloc/sales/sales_bloc.dart @@ -8,6 +8,7 @@ import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/service/product_test_service.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flurry/flurry.dart'; part 'sales_event.dart'; part 'sales_state.dart'; @@ -25,11 +26,13 @@ class SalesBloc extends Bloc with Logging { try { if (event is SalesLoad) { yield SalesLoading(); + Flurry.logEvent("SalesPageOpen"); this.getProductSet(); yield SalesReady(); } else if (event is SalesPurchase) { final int productId = event.productId; trace("Requesting purchase for" + productId.toString()); + Flurry.logEvent("PurchaseRequest"); //PlatformPurchaseApi().requestPurchase(null); } } on Exception catch (ex) { diff --git a/lib/bloc/session/session_bloc.dart b/lib/bloc/session/session_bloc.dart index 3a910f7..281a1be 100644 --- a/lib/bloc/session/session_bloc.dart +++ b/lib/bloc/session/session_bloc.dart @@ -7,6 +7,7 @@ import 'package:aitrainer_app/util/platform_purchase.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'; @@ -31,6 +32,7 @@ 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 f891807..7f2d6a5 100644 --- a/lib/bloc/settings/settings_bloc.dart +++ b/lib/bloc/settings/settings_bloc.dart @@ -7,7 +7,7 @@ import 'package:aitrainer_app/service/logging.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; -import 'package:health/health.dart'; +//import 'package:health/health.dart'; import 'package:meta/meta.dart'; part 'settings_event.dart'; @@ -50,17 +50,19 @@ class SettingsBloc extends Bloc with Logging { bool selectedHardwareBefore = await Cache().selectedHardwareBefore(); log("selectedBefore " + selectedHardwareBefore.toString()); - if (!selectedHardwareBefore) { - await _accessHealthData(); - } + final bool hasHardware = event.hasHardware; await Cache().setHardware(hasHardware); + if (hasHardware == true) { + await _accessHealthData(); + } + Cache().initBadges(); yield SettingsReady(_locale); } } Future _accessHealthData() async { - final List types = [ + /* final List types = [ HealthDataType.ACTIVE_ENERGY_BURNED, HealthDataType.WATER, HealthDataType.STEPS, @@ -71,10 +73,10 @@ class SettingsBloc extends Bloc with Logging { HealthDataType.LOW_HEART_RATE_EVENT, HealthDataType.RESTING_HEART_RATE ]; - final HealthFactory health = HealthFactory(); + final HealthFactory health = HealthFactory(); */ DateTime now = DateTime.now(); - List _healthDataList = await health.getHealthDataFromTypes(now.subtract(Duration(minutes: 5)), now, types); - log(_healthDataList.toString()); + //List _healthDataList = await health.getHealthDataFromTypes(now.subtract(Duration(minutes: 5)), now, types); + //log(_healthDataList.toString()); } Future _changeLang(String lang) async { @@ -94,6 +96,7 @@ class SettingsBloc extends Bloc with Logging { this.language = lang; AppLanguage().changeLanguage(_locale); await loadLang(); + await Cache().initBadges(); } Future loadLang() async { diff --git a/lib/localization/app_language.dart b/lib/localization/app_language.dart index 1fd196b..5ede331 100644 --- a/lib/localization/app_language.dart +++ b/lib/localization/app_language.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:aitrainer_app/service/logging.dart'; import 'package:flutter/cupertino.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -34,8 +36,14 @@ class AppLanguage with Logging { getLocale(SharedPreferences prefs) { String langCode = prefs.getString('language_code'); if (langCode == null) { - _appLocale = Locale('en'); - langCode = "en"; + final String localName = Platform.localeName; + if (localName.endsWith("HU")) { + _appLocale = Locale('hu'); + langCode = "hu"; + } else { + _appLocale = Locale('en'); + langCode = "en"; + } } _appLocale = Locale(langCode); log(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode"); diff --git a/lib/main.dart b/lib/main.dart index 5acb312..e57b2dd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:aitrainer_app/bloc/sales/sales_bloc.dart'; import 'package:aitrainer_app/push_notifications.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; @@ -21,7 +20,6 @@ import 'package:aitrainer_app/view/exercise_log_page.dart'; import 'package:aitrainer_app/view/exercise_plan_custom_page.dart'; import 'package:aitrainer_app/view/exercise_plan_custom_detail_add_page.dart'; import 'package:aitrainer_app/view/exercise_type_description.dart'; -import 'package:aitrainer_app/view/gdpr.dart'; import 'package:aitrainer_app/view/login.dart'; import 'package:aitrainer_app/view/exercise_new_page.dart'; import 'package:aitrainer_app/view/menu_page.dart'; @@ -209,7 +207,6 @@ class WorkoutTestApp extends StatelessWidget { 'login': (context) => LoginPage(), 'resetPassword': (context) => ResetPasswordPage(), 'registration': (context) => RegistrationPage(), - 'gdpr': (context) => Gdpr(), 'menu_page': (context) => MenuPage(), 'account': (context) => AccountPage(), 'settings': (context) => SettingsPage(), diff --git a/lib/model/cache.dart b/lib/model/cache.dart index b66fb70..f81821f 100644 --- a/lib/model/cache.dart +++ b/lib/model/cache.dart @@ -17,9 +17,11 @@ 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/util/env.dart'; import 'package:flurry/flurry.dart'; +import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; @@ -68,8 +70,11 @@ class Cache with Logging { static final String password = 'andio2009'; String authToken = ""; + AccessToken accessTokenFacebook; Customer userLoggedIn; String firebaseUid; + String facebookUid; + bool hasPurchased = false; bool firstLoad = true; @@ -196,7 +201,8 @@ class Cache with Logging { Future prefs = SharedPreferences.getInstance(); userLoggedIn = customer; - await setPreferences(prefs, SharePrefsChange.registration, customer.customerId, Cache().firebaseUid); + final String uid = Cache().firebaseUid == null ? Cache().facebookUid : Cache().firebaseUid; + await setPreferences(prefs, SharePrefsChange.registration, customer.customerId, uid); } afterLogin(Customer customer) async { @@ -211,7 +217,15 @@ class Cache with Logging { await setPreferences(prefs, SharePrefsChange.login, userLoggedIn.customerId, Cache().firebaseUid); } + afterFacebookLogin() async { + Future prefs = SharedPreferences.getInstance(); + await setPreferences(prefs, SharePrefsChange.login, userLoggedIn.customerId, Cache().facebookUid); + } + logout() async { + if (this.accessTokenFacebook != null) { + await FirebaseApi().logOutFacebook(); + } userLoggedIn = null; firebaseUid = null; authToken = ""; @@ -249,7 +263,7 @@ class Cache with Logging { sharedPreferences.setString(Cache.firebaseUidKey, null); sharedPreferences.setString(authTokenKey, ""); } - initBadges(); + await initBadges(); } void setExerciseTypes(List exerciseTypes) { @@ -374,7 +388,7 @@ class Cache with Logging { } } - void initBadges() { + Future initBadges() async { CustomerRepository customerRepository = CustomerRepository(); _badges = LinkedHashMap(); customerRepository.setCustomer(userLoggedIn); @@ -422,7 +436,7 @@ class Cache with Logging { Future initCustomer(int customerId) async { log(" *** initCustomer"); await CustomerApi().getCustomer(customerId); - Cache().startPage = "home"; + Flurry.setUserId(customerId.toString()); final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); Cache().setCustomerDevices(customerDevices); @@ -438,5 +452,12 @@ class Cache with Logging { await customerRepository.getProductTests(); this.hasPurchased = this._purchases.isNotEmpty; + Cache().startPage = "home"; } + + AccessToken get getAccessTokenFacebook => accessTokenFacebook; + set setAccessTokenFacebook(AccessToken accessTokenFacebook) => this.accessTokenFacebook = accessTokenFacebook; + + String get getFacebookUid => facebookUid; + set setFacebookUid(String facebookUid) => this.facebookUid = facebookUid; } diff --git a/lib/repository/customer_repository.dart b/lib/repository/customer_repository.dart index 450e873..87349f7 100644 --- a/lib/repository/customer_repository.dart +++ b/lib/repository/customer_repository.dart @@ -129,14 +129,14 @@ class CustomerRepository with Logging { } double getWeight() { - return getCustomerProperty("Weight"); + return getCustomerPropertyValue("Weight"); } double getHeight() { - return getCustomerProperty("Height"); + return getCustomerPropertyValue("Height"); } - double getCustomerProperty(String propertyName) { + double getCustomerPropertyValue(String propertyName) { if (this.customer.properties[propertyName] == null) { return 0.0; } else { @@ -144,6 +144,10 @@ class CustomerRepository with Logging { } } + CustomerProperty getCustomerProperty(String propertyName) { + return this.customer.properties[propertyName]; + } + setBirthYear(int birthYear) { this.customer.birthYear = birthYear; } diff --git a/lib/repository/exercise_repository.dart b/lib/repository/exercise_repository.dart index d524c19..1c88557 100644 --- a/lib/repository/exercise_repository.dart +++ b/lib/repository/exercise_repository.dart @@ -80,17 +80,32 @@ class ExerciseRepository { if (exerciseType.unitQuantity != "1") { modelExercise.unitQuantity = null; } - this.actualExerciseList.add(modelExercise); - int index = this.actualExerciseList.length - 1; + Exercise copy = modelExercise.copy(); + this.actualExerciseList.add(copy); + //final int index = this.actualExerciseList.length - 1; + //print("$index. actual exercise " + this.actualExerciseList[index].toJson().toString()); Exercise savedExercise = await ExerciseApi().addExercise(modelExercise); - this.actualExerciseList[index].exerciseId = savedExercise.exerciseId; + //this.actualExerciseList[index].exerciseId = savedExercise.exerciseId; if (customer.customerId == Cache().userLoggedIn.customerId) { Cache().addExercise(savedExercise); } else if (Cache().getTrainee() != null && customer.customerId == Cache().getTrainee().customerId) { Cache().addExerciseTrainee(savedExercise); } + +/* this.actualExerciseList.forEach((element) { + print("$index. actual: " + element.toJson().toString()); + }); */ + + this.createNew(); + this.exerciseType = exerciseType; + this.setUnit(exerciseType.unit); + exercise.exerciseTypeId = this.exerciseType.exerciseTypeId; + this.setQuantity(quantity); + this.setUnitQuantity(modelExercise.unitQuantity); + this.exercise.exercisePlanDetailId = 0; + this.start = DateTime.now(); } Future deleteExercise(Exercise exercise) async { @@ -274,7 +289,8 @@ class ExerciseRepository { } String delimiter = ""; if (prevCount > 0) delimiter = ", "; - summary += delimiter + exercise.quantity.toStringAsFixed(0); + double quantity = exercise.quantity == null ? 0 : exercise.quantity; + summary += delimiter + quantity.toStringAsFixed(0); ExerciseType exerciseType = Cache().getExercise(exercise.exerciseTypeId); if (exerciseType.unitQuantity == "1") { summary += "x" + exercise.unitQuantity.toStringAsFixed(0); @@ -286,6 +302,5 @@ class ExerciseRepository { prevExercise = exercise; prevCount++; } - ; } } diff --git a/lib/repository/exercise_result_repository.dart b/lib/repository/exercise_result_repository.dart index de814a7..2b5af13 100644 --- a/lib/repository/exercise_result_repository.dart +++ b/lib/repository/exercise_result_repository.dart @@ -42,15 +42,17 @@ class ExerciseResultRepository { List getResults() => this._results; Future saveExerciseResults() async { - this._results.forEach((result) async { - ExerciseResult exerciseResult = ExerciseResult(); - exerciseResult.customerId = Cache().userLoggedIn.customerId; - exerciseResult.exerciseId = result.exerciseId; - exerciseResult.dateFrom = result.dateFrom; - exerciseResult.dateTo = result.dateTo; - exerciseResult.resultType = result.itemString; - exerciseResult.value = result.data; - await ExerciseResultApi().saveExerciseResult(exerciseResult); - }); + if (this._results != null) { + this._results.forEach((result) async { + ExerciseResult exerciseResult = ExerciseResult(); + exerciseResult.customerId = Cache().userLoggedIn.customerId; + exerciseResult.exerciseId = result.exerciseId; + exerciseResult.dateFrom = result.dateFrom; + exerciseResult.dateTo = result.dateTo; + exerciseResult.resultType = result.itemString; + exerciseResult.value = result.data; + //await ExerciseResultApi().saveExerciseResult(exerciseResult); + }); + } } } diff --git a/lib/repository/user_repository.dart b/lib/repository/user_repository.dart index 6798955..3985b32 100644 --- a/lib/repository/user_repository.dart +++ b/lib/repository/user_repository.dart @@ -36,13 +36,33 @@ class UserRepository { } } + Future addUserFB() async { + final User modelUser = this.user; + + Map userData = await FirebaseApi().signInWithFacebook(); + if (userData != null) { + modelUser.email = userData['email']; + modelUser.password = "1234567"; + modelUser.firebaseUid = Cache().facebookUid; + await CustomerApi().addUser(modelUser); + } + } + + Future getUserByFB() async { + final User modelUser = this.user; + Map userData = await FirebaseApi().signInWithFacebook(); + modelUser.email = userData['email']; + await CustomerApi().getUserByEmail(modelUser.email); + await Cache().afterFacebookLogin(); + } + Future getUser() async { final User modelUser = this.user; String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password); if (rc == FirebaseApi.SIGN_IN_OK) { await CustomerApi().getUserByEmail(modelUser.email); - Cache().afterFirebaseLogin(); + await Cache().afterFirebaseLogin(); } else { print("Exception: user not found or password is wrong"); throw Exception("Customer does not exist or the password is wrong"); diff --git a/lib/service/customer_service.dart b/lib/service/customer_service.dart index 87a6209..e5cdb2f 100644 --- a/lib/service/customer_service.dart +++ b/lib/service/customer_service.dart @@ -47,7 +47,7 @@ class CustomerApi with Logging { throw new Exception(jsonDecode(responseBody)['error']); } else { customer = Customer.fromJson(jsonDecode(responseBody)); - Cache().afterRegistration(customer); + await Cache().afterRegistration(customer); } } on FormatException { throw new Exception(responseBody); diff --git a/lib/service/firebase_api.dart b/lib/service/firebase_api.dart index e285755..07669db 100644 --- a/lib/service/firebase_api.dart +++ b/lib/service/firebase_api.dart @@ -2,7 +2,7 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; -//import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; +import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; class FirebaseApi with Logging { static FirebaseApi _instance; @@ -75,16 +75,41 @@ class FirebaseApi with Logging { return rc; } - /*Future signInWithFacebook() async { - // Trigger the sign-in flow - final LoginResult result = await FacebookAuth.instance.login(); + Future> signInWithFacebook() async { + Map userData; + try { + // by default the login method has the next permissions ['email','public_profile'] + AccessToken accessToken = await FacebookAuth.instance.login(); + if (accessToken != null) { + log(accessToken.toJson().toString()); + Cache().accessTokenFacebook = accessToken; + // get the user data + userData = await FacebookAuth.instance.getUserData(); + Cache().facebookUid = userData['id']; + log(userData.toString()); + } else { + throw Exception("Facebook login was not successful"); + } + } on FacebookAuthException catch (e) { + switch (e.errorCode) { + case FacebookAuthErrorCode.OPERATION_IN_PROGRESS: + throw Exception("You have a previous Facebook login operation in progress"); + break; + case FacebookAuthErrorCode.CANCELLED: + throw Exception("Facebook login cancelled"); + break; + case FacebookAuthErrorCode.FAILED: + throw Exception("Facebook login failed"); + break; + } + } + return userData; + } - // Create a credential from the access token - final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.accessToken.token); - - // Once signed in, return the UserCredential - return await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential); - }*/ + Future logOutFacebook() async { + await FacebookAuth.instance.logOut(); + Cache().accessTokenFacebook = null; + } Future signOut() async { await FirebaseAuth.instance.signOut(); diff --git a/lib/util/common.dart b/lib/util/common.dart index 3519db6..6ffbd21 100644 --- a/lib/util/common.dart +++ b/lib/util/common.dart @@ -4,8 +4,9 @@ import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; -import 'package:aitrainer_app/util/env.dart'; +import 'package:badges/badges.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class DateRate { @@ -96,4 +97,37 @@ mixin Common { } return datePart; } + + static String emailValidation(String email) { + bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email); + return emailValid ? null : "Please type an email address"; + } + + static String passwordValidation(String value) { + if (value == null || value.length == 0) { + return null; + } + bool valid = 8 < value.length; + return valid ? null : "Password too short"; + } + + static Widget badgedIcon(Color color, IconData icon, String badgeKey) { + bool show = Cache().getBadges()[badgeKey] != null; + int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0; + return Badge( + position: BadgePosition.topEnd(top: -10, end: -10), + animationDuration: Duration(milliseconds: 500), + animationType: BadgeAnimationType.slide, + badgeColor: Colors.red, + showBadge: show, + badgeContent: Text( + counter.toString(), + style: TextStyle(color: Colors.white), + ), + child: Icon( + icon, + color: color, + ), + ); + } } diff --git a/lib/util/session.dart b/lib/util/session.dart index 1edd1fe..fcf6abc 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/service/api.dart'; @@ -17,7 +19,7 @@ class Session with Logging { fetchSessionAndNavigate() async { log(" -- Session: await prefs.."); _sharedPreferences = await _prefs; - + print("Platform: " + Platform.localeName); if (Cache().firstLoad) { log(" -- Session: fetch locale.."); await AppLanguage().getLocale(_sharedPreferences); diff --git a/lib/view/account.dart b/lib/view/account.dart index 82e76e5..3128562 100644 --- a/lib/view/account.dart +++ b/lib/view/account.dart @@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/account/account_bloc.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/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:badges/badges.dart'; @@ -58,7 +59,7 @@ class AccountPage extends StatelessWidget with Trans { ListView accountWidget(BuildContext context, String customerName, AccountBloc accountBloc) { return ListView(padding: EdgeInsets.only(top: 35), children: [ ListTile( - leading: badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity), + leading: Common.badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity), subtitle: Text(t("Profile")), title: FlatButton( child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -84,7 +85,7 @@ class AccountPage extends StatelessWidget with Trans { ListTile devices(BuildContext context, AccountBloc accountBloc) { ListTile element = ListTile(); element = ListTile( - leading: badgedIcon(Colors.grey, Icons.device_hub, "customerDevice"), + leading: Common.badgedIcon(Colors.grey, Icons.device_hub, "customerDevice"), title: FlatButton( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -226,24 +227,4 @@ class AccountPage extends StatelessWidget with Trans { ], )); } - - Widget badgedIcon(Color color, IconData icon, String badgeKey) { - bool show = Cache().getBadges()[badgeKey] != null; - int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0; - return Badge( - position: BadgePosition.topEnd(top: -10, end: -10), - animationDuration: Duration(milliseconds: 500), - animationType: BadgeAnimationType.slide, - badgeColor: Colors.red, - showBadge: show, - badgeContent: Text( - counter.toString(), - style: TextStyle(color: Colors.white), - ), - child: Icon( - icon, - color: color, - ), - ); - } } diff --git a/lib/view/custom_exercise_page.dart b/lib/view/custom_exercise_page.dart index 0f2624e..635305a 100644 --- a/lib/view/custom_exercise_page.dart +++ b/lib/view/custom_exercise_page.dart @@ -5,12 +5,12 @@ import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; -import 'package:aitrainer_app/widgets/splash.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; class CustomExercisePage extends StatefulWidget { _CustomExerciseNewPageState createState() => _CustomExerciseNewPageState(); @@ -50,17 +50,15 @@ class _CustomExerciseNewPageState extends State with Logging ), ), body: FormBlocListener( - onSubmitting: (context, state) { + /* onSubmitting: (context, state) { LoadingDialog.show(context); - }, - onSuccess: (context, state) { - LoadingDialog.hide(context); - }, - onFailure: (context, state) { - LoadingDialog.hide(context); - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, content: Text(state.failureResponse, style: TextStyle(color: Colors.white)))); - }, + }, */ + onSuccess: (context, state) {}, + onFailure: (context, state) { + Scaffold.of(context).showSnackBar(SnackBar( + backgroundColor: Colors.orange, content: Text(state.failureResponse, style: TextStyle(color: Colors.white)))); + }, + child: ModalProgressHUD( child: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, @@ -86,7 +84,13 @@ class _CustomExerciseNewPageState extends State with Logging ]), ), gridCalculation(exerciseBloc) - ])))); + ])), + inAsyncCall: exerciseBloc.loading == true, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ), + )); })); } diff --git a/lib/view/customer_bodytype_page.dart b/lib/view/customer_bodytype_page.dart index 7357b4b..fbd7378 100644 --- a/lib/view/customer_bodytype_page.dart +++ b/lib/view/customer_bodytype_page.dart @@ -1,6 +1,10 @@ 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/dialog_html.dart'; +import 'package:badges/badges.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -20,27 +24,16 @@ class BodyTypeItem { static String mesomorph = "mesomorph"; } -class _CustomerBodyTypePageState extends State { +class _CustomerBodyTypePageState extends State with Trans { String selected; @override Widget build(BuildContext context) { final CustomerRepository customerRepository = ModalRoute.of(context).settings.arguments; final double cWidth = MediaQuery.of(context).size.width * 0.75; + setContext(context); 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: AppBarMin(), body: Container( decoration: BoxDecoration( image: DecorationImage( @@ -64,78 +57,123 @@ class _CustomerBodyTypePageState extends State { alignment: WrapAlignment.center, children: [ Text( - AppLocalizations.of(context).translate("Your Body Type"), + t("Your Body Type"), textAlign: TextAlign.center, style: TextStyle(color: Colors.orange, fontSize: 42, fontFamily: 'Arial', fontWeight: FontWeight.w900), ) ]), Divider(), - FlatButton( - child: Container( - width: cWidth, - child: Column( - children: [ - Text(AppLocalizations.of(context).translate("Endomorph"), - textWidthBasis: TextWidthBasis.longestLine, - style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900)), - ], - )), - padding: EdgeInsets.all(10.0), - shape: getShape(customerRepository, BodyTypeItem.endomorph), - onPressed: () => { - setState(() { - selected = BodyTypeItem.endomorph; - changeBloc.add(CustomerBodyTypeChange(bodyType: selected)); - }), - }), - Divider(), - FlatButton( - child: Container( - width: cWidth, - child: Column( - children: [ - InkWell( - child: Text( - AppLocalizations.of(context).translate("Ectomorph"), - style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), - ), - highlightColor: Colors.white, - ), - ], - ), + Badge( + badgeColor: customerRepository.bodyType == BodyTypeItem.ectomorph ? Colors.orange[200] : Colors.blue[50], + badgeContent: GestureDetector( + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t("Ectomorph"), + htmlData: t("Ectomorph_desc"), + ); + }) + }, + child: Icon(Icons.info_outline_rounded), ), - padding: EdgeInsets.all(10.0), - shape: getShape(customerRepository, BodyTypeItem.ectomorph), - onPressed: () => { - setState(() { - selected = BodyTypeItem.ectomorph; - changeBloc.add(CustomerBodyTypeChange(bodyType: selected)); - }), - }), - Divider(), - FlatButton( - child: Container( - width: cWidth, - child: Column( - children: [ - InkWell( - child: Text( - AppLocalizations.of(context).translate("Mesomorph"), - style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), - ), - highlightColor: Colors.white, + child: FlatButton( + child: Container( + width: cWidth, + child: Column( + children: [ + InkWell( + child: Text( + t("Ectomorph"), + style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), + ), + highlightColor: Colors.white, + ), + ], ), - ], - ), + ), + padding: EdgeInsets.all(10.0), + shape: getShape(customerRepository, BodyTypeItem.ectomorph), + onPressed: () => { + setState(() { + selected = BodyTypeItem.ectomorph; + changeBloc.add(CustomerBodyTypeChange(bodyType: selected)); + }), + })), + Divider(), + Badge( + badgeColor: customerRepository.bodyType == BodyTypeItem.endomorph ? Colors.orange : Colors.blue[50], + badgeContent: GestureDetector( + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t("Endomorph"), + htmlData: t("Endomorph_desc"), + ); + }) + }, + child: Icon(Icons.info_outline_rounded)), + child: FlatButton( + child: Container( + width: cWidth, + child: Column( + children: [ + Text(t("Endomorph"), + textWidthBasis: TextWidthBasis.longestLine, + style: + TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900)), + ], + )), + padding: EdgeInsets.all(10.0), + shape: getShape(customerRepository, BodyTypeItem.endomorph), + onPressed: () => { + setState(() { + selected = BodyTypeItem.endomorph; + changeBloc.add(CustomerBodyTypeChange(bodyType: selected)); + }), + })), + Divider(), + Badge( + badgeColor: customerRepository.bodyType == BodyTypeItem.mesomorph ? Colors.orange[200] : Colors.blue[50], + badgeContent: GestureDetector( + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t("Mesomorph"), + htmlData: t("Mesomorph_desc"), + ); + }) + }, + child: Icon(Icons.info_outline_rounded), ), - padding: EdgeInsets.all(10.0), - shape: getShape(customerRepository, BodyTypeItem.mesomorph), - onPressed: () => { - setState(() { - selected = BodyTypeItem.mesomorph; - changeBloc.add(CustomerBodyTypeChange(bodyType: selected)); - }), - }), + child: FlatButton( + child: Container( + width: cWidth, + child: Column( + children: [ + InkWell( + child: Text( + t("Mesomorph"), + style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), + ), + highlightColor: Colors.white, + ), + ], + ), + ), + padding: EdgeInsets.all(10.0), + shape: getShape(customerRepository, BodyTypeItem.mesomorph), + onPressed: () => { + setState(() { + selected = BodyTypeItem.mesomorph; + changeBloc.add(CustomerBodyTypeChange(bodyType: selected)); + }), + })), Divider(), RaisedButton( color: Colors.orange, diff --git a/lib/view/customer_modify_page.dart b/lib/view/customer_modify_page.dart index 0c11c30..3107d4a 100644 --- a/lib/view/customer_modify_page.dart +++ b/lib/view/customer_modify_page.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; import 'package:toggle_switch/toggle_switch.dart'; @@ -23,7 +24,7 @@ class CustomerModifyPage extends StatelessWidget with Trans { final accountBloc = BlocProvider.of(context); return BlocProvider( - create: (context) => CustomerChangeBloc(customerRepository: accountBloc.customerRepository)..add(CustomerLoad()), + create: (context) => CustomerChangeBloc(customerRepository: accountBloc.customerRepository, context: context)..add(CustomerLoad()), child: Builder(builder: (context) { // ignore: close_sinks final customerBloc = BlocProvider.of(context); @@ -43,18 +44,26 @@ class CustomerModifyPage extends StatelessWidget with Trans { ), child: BlocConsumer( listener: (context, state) { - if (state is CustomerChangeLoading) { - //LoadingDialog(); - } else if (state is CustomerSaveError) { - //LoadingDialog.hide(context); - Scaffold.of(context).showSnackBar( - SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + if (state is CustomerSaveError) { + String message = t(state.message); + if (message == null) { + message = ""; + } else { + Scaffold.of(context).showSnackBar( + 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); } }, builder: (context, state) { - return loadForm(customerBloc); + return ModalProgressHUD( + child: loadForm(customerBloc), + inAsyncCall: state is CustomerChangeLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); }, ))); })); diff --git a/lib/view/evaluation.dart b/lib/view/evaluation.dart index 4231138..514d069 100644 --- a/lib/view/evaluation.dart +++ b/lib/view/evaluation.dart @@ -58,9 +58,10 @@ class EvaluationPage extends StatelessWidget with Trans { ), ), child: BlocProvider( - create: (context) => - ResultBloc(resultRepository: ExerciseResultRepository(resultType: resultType), exerciseRepository: exerciseRepository) - ..add(ResultLoad()), + create: (context) => ResultBloc( + resultRepository: ExerciseResultRepository(resultType: resultType), + exerciseRepository: exerciseRepository, + context: context), //..add(ResultLoad()) child: BlocConsumer(listener: (context, state) { if (state is ResultError) { Scaffold.of(context).showSnackBar( @@ -163,8 +164,8 @@ class EvaluationPage extends StatelessWidget with Trans { getSuggestionTitle(resultBloc), getSuggestion(resultBloc), emptySliver(), - getResultTitle(resultBloc), - getResults(resultBloc), + //getResultTitle(resultBloc), + //getResults(resultBloc), ])); } @@ -239,9 +240,9 @@ class EvaluationPage extends StatelessWidget with Trans { return SliverList( delegate: SliverChildListDelegate( [ - getSuggestionWidget(resultBloc, "Hypertrophy", "asset/image/pict_hypertrophy.png", "3x10-12", 0.9, "2"), + getSuggestionWidget(resultBloc, "Hypertrophy", "asset/image/pict_hypertrophy.png", "3x10-12", 0.75, "2"), Divider(color: Colors.transparent), - getSuggestionWidget(resultBloc, "Gain Strength", "asset/image/pict_weight_volumen_tonna.png", "3x10-12", 0.75, "3-5"), + getSuggestionWidget(resultBloc, "Gain Strength", "asset/image/pict_weight_volumen_tonna.png", "3x4-8", 0.95, "3-5"), Divider(color: Colors.transparent), getSuggestionWidget(resultBloc, "Endurance", "asset/image/pict_reps_volumen_db.png", "4x25-35", 0.50, "3"), ], @@ -381,11 +382,20 @@ class EvaluationPage extends StatelessWidget with Trans { Widget getSummary(ResultBloc bloc) { int index = 0; List resultList = List(); - bloc.exerciseRepository.actualExerciseList.forEach((exercise) { + /* for (int i = 0; i < bloc.exerciseRepository.actualExerciseList.length; i++) { + print("Q " + + bloc.exerciseRepository.actualExerciseList[i].quantity.toString() + + " Qu: " + + bloc.exerciseRepository.actualExerciseList[i].unitQuantity.toString()); + } */ + bloc.exerciseRepository.actualExerciseList.forEach((actual) { final String unit = t(bloc.exerciseRepository.exerciseType.unit); String exerciseElement = ""; - final String exerciseRepeats = exercise.quantity.toStringAsFixed(0); - final String exerciseUnitQuantity = exercise.unitQuantity != null ? "x" + exercise.unitQuantity.toStringAsFixed(0) : ""; + String exerciseRepeats = actual.quantity.toStringAsFixed(0); + if (bloc.exerciseRepository.exerciseType.unit == "second") { + exerciseRepeats = bloc.printTime(actual.quantity); + } + final String exerciseUnitQuantity = actual.unitQuantity != null ? "x" + actual.unitQuantity.toStringAsFixed(0) : ""; if (index == 0) { exerciseElement = t("Test") + ": "; } else if (index == 1) { @@ -477,7 +487,7 @@ class EvaluationPage extends StatelessWidget with Trans { Image.asset( element.getImage(), height: 80, - color: Colors.black54, + color: Colors.black.withOpacity(0.8), ), ]) : Image.asset( @@ -489,11 +499,11 @@ class EvaluationPage extends StatelessWidget with Trans { ), Text( element.data.toStringAsFixed(0), - style: GoogleFonts.archivoBlack(fontSize: 28, color: blur ? Colors.white30 : Colors.white), + style: GoogleFonts.archivoBlack(fontSize: 28, color: blur ? Colors.white12 : Colors.white), ), Text( t(element.getDescription()), - style: GoogleFonts.archivoBlack(fontSize: 14, color: blur ? Colors.white30 : Colors.white), + style: GoogleFonts.archivoBlack(fontSize: 14, color: blur ? Colors.white12 : Colors.white), textAlign: TextAlign.left, ), ], diff --git a/lib/view/exercise_control_page.dart b/lib/view/exercise_control_page.dart index 2e32dfb..120d5ec 100644 --- a/lib/view/exercise_control_page.dart +++ b/lib/view/exercise_control_page.dart @@ -1,25 +1,36 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_control/exercise_control_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/repository/exercise_repository.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_html.dart'; import 'package:aitrainer_app/widgets/number_picker.dart'; -import 'package:aitrainer_app/widgets/splash.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 ExerciseControlPage extends StatefulWidget { _ExerciseControlPage createState() => _ExerciseControlPage(); } class _ExerciseControlPage 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; @@ -35,22 +46,24 @@ class _ExerciseControlPage extends State with Trans { if (state is ExerciseControlError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); - } else if (state is ExerciseControlLoading) { - return LoadingDialog(); } }, builder: (context, state) { final exerciseBloc = BlocProvider.of(context); - if (state is ExerciseControlLoading) { - return LoadingDialog(); - } else if (state is ExerciseControlReady) { - return getControlForm(exerciseBloc); - } else { - return getControlForm(exerciseBloc); + if (state is ExerciseControlReady) { + _controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn); } + return ModalProgressHUD( + child: getControlForm(exerciseBloc), + inAsyncCall: state is ExerciseControlLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); })); } Form getControlForm(ExerciseControlBloc exerciseBloc) { + this.offset = exerciseBloc.scrollOffset; String exerciseName = AppLanguage().appLocal == Locale("en") ? exerciseBloc.exerciseRepository.exerciseType.name : exerciseBloc.exerciseRepository.exerciseType.nameTranslation; @@ -75,9 +88,7 @@ class _ExerciseControlPage extends State with Trans { padding: const EdgeInsets.only(top: 10, left: 25, right: 25), child: SingleChildScrollView( scrollDirection: Axis.vertical, - controller: ScrollController( - initialScrollOffset: exerciseBloc.scrollOffset, - ), + controller: _controller, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, @@ -86,7 +97,7 @@ class _ExerciseControlPage extends State with Trans { exerciseName, style: GoogleFonts.archivoBlack( fontWeight: FontWeight.bold, - fontSize: 20, + fontSize: 24, color: Colors.white, shadows: [ Shadow( @@ -115,27 +126,9 @@ class _ExerciseControlPage extends State with Trans { Divider( color: Colors.transparent, ), - /* FlatButton( - child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Icon( - Icons.info, - color: Colors.yellow[50], - ), - Flexible( - child: Text(t("Why do you need Exercise Control?"), - style: TextStyle(color: Colors.yellow[50], fontWeight: FontWeight.normal, fontSize: 14)), - ), - Icon( - Icons.arrow_forward_ios, - color: Colors.yellow[50], - ), - ]), - textColor: Colors.blueAccent, + Divider( color: Colors.transparent, - onPressed: () => { - //Navigator.of(context).pushNamed('exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository), - }, - ), */ + ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -143,17 +136,92 @@ class _ExerciseControlPage extends State with Trans { style: GoogleFonts.inter( color: Colors.yellow[300], fontSize: 18, + 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, + ), + ], )), Text( " " + exerciseBloc.initialRM.toStringAsFixed(0) + " " + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit, - style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold), + style: GoogleFonts.inter( + color: Colors.yellow[300], + fontSize: 18, + fontWeight: FontWeight.bold, + shadows: [ + Shadow( + offset: Offset(-2.0, -2.0), + blurRadius: 6.0, + color: Colors.black54, + ), + Shadow( + offset: Offset(-3.0, 3.0), + blurRadius: 6.0, + color: Colors.black54, + ), + ], + ), ), + SizedBox(width: 10), + GestureDetector( + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t("OneRepMax"), + htmlData: t("OneRepMax_desc"), + ); + }) + }, + child: Icon(CustomIcon.question, color: Colors.yellow[300])) ], ), Divider(), + Row(mainAxisAlignment: MainAxisAlignment.start, children: [ + Flexible( + child: Text(t("Why do you need Exercise Control?"), + style: GoogleFonts.inter( + color: Colors.yellow[300], + fontSize: 18, + 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, + ), + ], + ))), + SizedBox(width: 10), + GestureDetector( + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: t("Control Exercise:"), + htmlData: t("controlexercise_desc"), + ); + }) + }, + child: Icon(CustomIcon.question, color: Colors.yellow[300])) + ]), + Divider(), numberPickForm(exerciseBloc, 1), Divider(), numberPickForm(exerciseBloc, 2), @@ -166,6 +234,24 @@ class _ExerciseControlPage extends State with Trans { ); } + List getButton(int step, ExerciseControlBloc 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; + } + Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) { String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max."; String textInstruction = ""; @@ -211,7 +297,6 @@ class _ExerciseControlPage extends State with Trans { exerciseBloc.add(ExerciseControlSubmit(step: step)), if (step == 3) { - //confirmationDialog(exerciseBloc) Navigator.of(context).pop(), args['exerciseRepository'] = exerciseBloc.exerciseRepository, Navigator.of(context).pushNamed('evaluationPage', arguments: args) @@ -228,7 +313,10 @@ class _ExerciseControlPage extends State with Trans { ), ], ) - : Container()), + : Stack( + alignment: Alignment.center, + children: getButton(step, exerciseBloc), + )), ], ), ]; @@ -238,46 +326,4 @@ class _ExerciseControlPage extends State with Trans { children: listWidgets, ); } - - void confirmationDialog(ExerciseControlBloc bloc) { - String unit = t(bloc.exerciseRepository.exerciseType.unit); - LinkedHashMap args = LinkedHashMap(); - - showCupertinoDialog( - useRootNavigator: true, - context: context, - //barrierDismissible: false, - builder: (_) => CupertinoAlertDialog( - title: Text(t("Summary of your test")), - content: Column(children: [ - Text( - t("Test") + ": " + bloc.repeats[1].toStringAsFixed(0) + "x" + bloc.repeats[0].toStringAsFixed(0) + " " + unit, - style: (TextStyle(color: Colors.blue)), - ), - Divider(), - Text( - t("1st Control") + ": " + bloc.repeats[2].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit, - style: (TextStyle(color: Colors.blue)), - ), - Text( - t("2nd Control") + ": " + bloc.repeats[3].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit, - style: (TextStyle(color: Colors.blue)), - ), - Text( - t("3rd Control") + ": " + bloc.repeats[4].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit, - style: (TextStyle(color: Colors.blue)), - ), - ]), - actions: [ - FlatButton( - child: Text(t("OK")), - onPressed: () => { - Navigator.of(context).pop(), - args['exerciseRepository'] = bloc.exerciseRepository, - Navigator.of(context).pushNamed('evaluationPage', arguments: args) - }, - ) - ], - )); - } } diff --git a/lib/view/exercise_execute_page.dart b/lib/view/exercise_execute_page.dart index 82d80e0..b0b3c97 100644 --- a/lib/view/exercise_execute_page.dart +++ b/lib/view/exercise_execute_page.dart @@ -127,15 +127,43 @@ class _ExerciseExecutePage extends State with Trans { exerciseTypes.add(explanation); - bloc.menuTreeRepository.sortedTree.forEach((name, list) { + if (bloc.selectedNumber == 0) { exerciseTypes.add(Container( - margin: const EdgeInsets.only(left: 4.0), - child: TreeViewChild( - startExpanded: true, - parent: TreeviewParentWidget(text: name), - children: _getChildList(list, bloc), - ))); - }); + child: Center( + child: Text( + t("Please define your Exercise Plan"), + style: GoogleFonts.inter(color: Colors.white), + )))); + exerciseTypes.add(Container( + child: Center( + child: Text( + t("Go to: 'Training Plan' - 'Edit My Custom Plan'"), + style: GoogleFonts.inter(color: Colors.white), + )))); + exerciseTypes.add(Container( + child: Center( + child: InkWell( + onTap: () { + final LinkedHashMap args = LinkedHashMap(); + args['customerId'] = Cache().userLoggedIn.customerId; + Navigator.of(context).pop(); + Navigator.of(context).pushNamed('exercisePlanCustomPage', arguments: args); + }, + child: Text( + t("Jump there »"), + style: GoogleFonts.inter(color: Colors.blue[200], decorationStyle: TextDecorationStyle.solid), + ))))); + } else { + bloc.menuTreeRepository.sortedTree.forEach((name, list) { + exerciseTypes.add(Container( + margin: const EdgeInsets.only(left: 4.0), + child: TreeViewChild( + startExpanded: true, + parent: TreeviewParentWidget(text: name), + children: _getChildList(list, bloc), + ))); + }); + } return exerciseTypes; } diff --git a/lib/view/exercise_execute_plan_add_page.dart b/lib/view/exercise_execute_plan_add_page.dart index 27803b7..52c3b4c 100644 --- a/lib/view/exercise_execute_plan_add_page.dart +++ b/lib/view/exercise_execute_plan_add_page.dart @@ -7,12 +7,12 @@ 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/widgets/splash.dart'; import 'package:aitrainer_app/library/numberpicker.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:modal_progress_hud/modal_progress_hud.dart'; class ExerciseExecutePlanAddPage extends StatefulWidget { _ExerciseExecuteAddPage createState() => _ExerciseExecuteAddPage(); @@ -40,19 +40,18 @@ class _ExerciseExecuteAddPage extends State with Tra if (state is ExerciseExecutePlanAddError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); - } else if (state is ExerciseExecutePlanAddLoading) { - return LoadingDialog(); } }, builder: (context, state) { // ignore: close_sinks final exerciseBloc = BlocProvider.of(context); - if (state is ExerciseExecutePlanAddLoading) { - return LoadingDialog(); - } else if (state is ExerciseExecutePlanAddReady) { - return getControlForm(exerciseBloc); - } else { - return getControlForm(exerciseBloc); - } + + return ModalProgressHUD( + child: getControlForm(exerciseBloc), + inAsyncCall: state is ExerciseExecutePlanAddLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); })); } diff --git a/lib/view/exercise_log_page.dart b/lib/view/exercise_log_page.dart index 589e8ed..4f5cfdc 100644 --- a/lib/view/exercise_log_page.dart +++ b/lib/view/exercise_log_page.dart @@ -4,7 +4,6 @@ import 'package:aitrainer_app/library/custom_icon_icons.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/splash.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; @@ -18,6 +17,7 @@ import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/material.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; class ExerciseLogPage extends StatefulWidget { @override @@ -28,31 +28,25 @@ class _ExerciseLogPage extends State with Trans, Common { @override Widget build(BuildContext context) { LinkedHashMap arguments = ModalRoute.of(context).settings.arguments; - //final ExerciseRepository exerciseRepository = arguments['exerciseRepository']; final int customerId = arguments['customerId']; setContext(context); return BlocProvider( create: (context) => ExerciseLogBloc(exerciseRepository: ExerciseRepository())..add(ExerciseLogLoad()), child: BlocConsumer(listener: (context, state) { - if (state is ExerciseLogLoading) { - return LoadingDialog(); - } else if (state is ExerciseLogError) { - //LoadingDialog.hide(context); + if (state is ExerciseLogError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } }, builder: (context, state) { final exerciseBloc = BlocProvider.of(context); - if (state is ExerciseLogReady) { - //LoadingDialog.hide(context); - return getExerciseLog(customerId, exerciseBloc); - } else if (state is ExerciseLogLoading) { - return LoadingDialog(); - } else { - //LoadingDialog.hide(context); - return getExerciseLog(customerId, exerciseBloc); - } + return ModalProgressHUD( + child: getExerciseLog(customerId, exerciseBloc), + inAsyncCall: state is ExerciseLogLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); })); } diff --git a/lib/view/exercise_new_page.dart b/lib/view/exercise_new_page.dart index 5e69855..da9f039 100644 --- a/lib/view/exercise_new_page.dart +++ b/lib/view/exercise_new_page.dart @@ -23,6 +23,7 @@ import 'package:flutter_form_bloc/flutter_form_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:stop_watch_timer/stop_watch_timer.dart'; +import 'package:wakelock/wakelock.dart'; class ExerciseNewPage extends StatefulWidget { _ExerciseNewPageState createState() => _ExerciseNewPageState(); @@ -94,9 +95,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { child: BlocConsumer( listener: (context, state) { if (state is ExerciseNewLoading) { - //LoadingDialog.show(context); } else if (state is ExerciseNewError) { - //LoadingDialog.hide(context); Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } @@ -136,20 +135,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { return SizeWidget(exerciseBloc: exerciseBloc); } - bool isSecond = false; - String exerciseTask = ""; - if (exerciseBloc.exerciseRepository.exerciseType.unit != "second") { - if (exerciseBloc.exerciseRepository.exerciseType.is1RM() && menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) { - exerciseTask = "Please take a relative bigger weight and repeat 12-20 times"; - exerciseBloc.quantity = 12; - } else if (exerciseBloc.exerciseRepository.exerciseType.isEndurance() && - menuBloc.ability.toString() == ExerciseAbility.endurance.toString()) { - exerciseTask = "Please take a medium weight and repeat 20-30 times"; - exerciseBloc.quantity = 20; - } - } else { - isSecond = true; - } + final String exerciseTask = exerciseBloc.setExerciseTask(); return Form( child: Scaffold( @@ -205,7 +191,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { Text( exerciseDescription, style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[300]), - maxLines: 8, + maxLines: 4, overflow: TextOverflow.fade, softWrap: true, ), @@ -338,6 +324,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { //shape: const StadiumBorder(), onPressed: () async { bloc.stopWatchTimer.onExecute.add(StopWatchExecute.start); + Wakelock.enable(); // prevent sleep the phone }, icon: Icon(CustomIcon.play_1), iconSize: 40, @@ -352,6 +339,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { //shape: const StadiumBorder(), onPressed: () async { bloc.stopWatchTimer.onExecute.add(StopWatchExecute.stop); + Wakelock.disable(); }, icon: Icon(CustomIcon.stop), ), @@ -378,7 +366,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { Divider(), Text("Or type the time manually:", style: GoogleFonts.inter(color: Colors.white)), TimePickerWidget( - onChange: (value) => {bloc.add(ExerciseNewQuantityChange(quantity: value))}, + onChange: (value) => {print("timer"), bloc.add(ExerciseNewQuantityChange(quantity: value))}, ) ]); } @@ -410,6 +398,7 @@ class _ExerciseNewPageState extends State with Trans, Logging { void confirmationDialog(ExerciseNewBloc bloc, MenuBloc menuBloc) { LinkedHashMap args = LinkedHashMap(); + print("quantity: " + bloc.quantity.toString()); if (bloc.exerciseRepository.exercise.quantity == null) { return; } diff --git a/lib/view/gdpr.dart b/lib/view/gdpr.dart deleted file mode 100644 index 4d9f5bd..0000000 --- a/lib/view/gdpr.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:aitrainer_app/localization/app_localization.dart'; -import 'package:aitrainer_app/widgets/app_bar_min.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -class Gdpr extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBarMin( - back: true, - ), - body: Container( - padding: const EdgeInsets.only(left: 15, right: 15), - child: ListView( - children: [ - InkWell( - child: Text( - AppLocalizations.of(context).translate('gdpr_text'), - ), - customBorder: Border.all(color: Colors.orange, width: 1), - ), - ], - ))); - } -} diff --git a/lib/view/login.dart b/lib/view/login.dart index b76d6ce..2084b3e 100644 --- a/lib/view/login.dart +++ b/lib/view/login.dart @@ -1,67 +1,53 @@ -import 'package:aitrainer_app/bloc/login_form_bloc.dart'; import 'package:aitrainer_app/bloc/account/account_bloc.dart'; +import 'package:aitrainer_app/bloc/login/login_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; -import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; -import 'package:aitrainer_app/widgets/splash.dart'; +import 'package:aitrainer_app/widgets/dialog_long.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.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:modal_progress_hud/modal_progress_hud.dart'; import '../library_keys.dart'; -class LoginPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return LoginWidget(); - } -} - -class LoginWidget extends StatefulWidget { - LoginWidget(); - - @override - State createState() => _LoginWidget(); -} - -class _LoginWidget extends State with Common, Trans { +// ignore: must_be_immutable +class LoginPage extends StatelessWidget with Trans { final GlobalKey _scaffoldKey = new GlobalKey(); @override Widget build(BuildContext context) { final accountBloc = BlocProvider.of(context); setContext(context); - return BlocProvider( - create: (context) => LoginFormBloc(userRepository: UserRepository(), accountBloc: accountBloc), - child: Builder(builder: (context) { - final loginBloc = BlocProvider.of(context); - return Scaffold( - //key: _scaffoldKey, - appBar: AppBarMin(), - body: FormBlocListener( - onSubmitting: (context, state) { - LoadingDialog.show(context); - }, - onSuccess: (context, state) { - LoadingDialog.hide(context); - Navigator.of(context).pushNamed('home'); - }, - onFailure: (context, state) { - LoadingDialog.hide(context); - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, content: Text(t(state.failureResponse), style: TextStyle(color: Colors.white)))); - }, - onLoaded: (context, state) {}, - child: loadForm(loginBloc, accountBloc)), - ); - })); + return Scaffold( + appBar: AppBarMin(), + body: BlocProvider( + create: (context) => + LoginBloc(userRepository: UserRepository(), accountBloc: accountBloc, context: context, isRegistration: false), + child: BlocConsumer(listener: (context, state) { + if (state is LoginError) { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white)))); + } else if (state is LoginSuccess) { + Navigator.of(context).pushNamed('home'); + } + }, builder: (context, state) { + final loginBloc = BlocProvider.of(context); + + return ModalProgressHUD( + child: loadForm(loginBloc, accountBloc), + inAsyncCall: state is LoginLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); + }))); } - Widget loadForm(LoginFormBloc loginBloc, AccountBloc accountBloc) { + Widget loadForm(LoginBloc loginBloc, AccountBloc accountBloc) { return SafeArea( top: false, bottom: false, @@ -78,25 +64,20 @@ class _LoginWidget extends State with Common, Trans { ); } - Widget buildLoginForm(LoginFormBloc formBloc, AccountBloc accountBloc) { + Widget buildLoginForm(LoginBloc loginBloc, AccountBloc accountBloc) { return Form( key: _scaffoldKey, child: Container( padding: const EdgeInsets.only(left: 15, right: 50), - child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 150.0), children: [ - Divider(color: Colors.transparent), - /* FlatButton( - child: new Image.asset( - 'asset/image/login_fb.png', - width: cWidth * .85, - ), - onPressed: () => { - //_fbLogin(), - FirebaseApi().signInWithFacebook(), - print("Login with FB"), - }, - ), - Text(AppLocalizations.of(context).translate("OR")),*/ + child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 100.0), children: [ + FlatButton( + child: new Image.asset( + 'asset/image/login_fb.png', + width: MediaQuery.of(context).size.width * .85, + ), + onPressed: () => {loginBloc.add(LoginFB())}, + ), + Text(AppLocalizations.of(context).translate("OR")), Divider(), Row( mainAxisAlignment: MainAxisAlignment.start, @@ -107,28 +88,61 @@ class _LoginWidget extends State with Common, Trans { ), ], ), - Divider(), - TextFieldBlocBuilder( + Divider( + color: Colors.transparent, + ), + TextFormField( key: LibraryKeys.loginEmailField, - textFieldBloc: formBloc.emailField, decoration: InputDecoration( - fillColor: Colors.white, + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + labelText: t('Email'), + fillColor: Colors.white24, filled: true, - labelText: 'Email', + border: OutlineInputBorder( + gapPadding: 4.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), ), + initialValue: loginBloc.userRepository.user.email, + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: (val) { + return t(loginBloc.emailValidation(val)); + }, + onChanged: (value) => loginBloc.add(LoginEmailChange(email: value)), + keyboardType: TextInputType.emailAddress, + style: new TextStyle(fontSize: 16, color: Colors.indigo), ), Divider( color: Colors.transparent, ), - TextFieldBlocBuilder( + TextFormField( key: LibraryKeys.loginPasswordField, - textFieldBloc: formBloc.passwordField, + obscureText: true, decoration: InputDecoration( - fillColor: Colors.white, + labelStyle: TextStyle(fontSize: 14), + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + suffixIcon: IconButton( + onPressed: () => {loginBloc.add(LoginPasswordChangeObscure())}, + icon: Icon(Icons.remove_red_eye), + ), + labelText: t('Password'), + fillColor: Colors.white24, filled: true, - labelText: 'Password', + border: OutlineInputBorder( + gapPadding: 1.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), ), - suffixButton: SuffixButton.obscureText, + initialValue: loginBloc.userRepository.user.password, + autovalidateMode: AutovalidateMode.always, + validator: (val) { + return t(loginBloc.passwordValidation(val)); + }, + onChanged: (value) => loginBloc.add(LoginPasswordChange(password: value)), + keyboardType: TextInputType.visiblePassword, + style: new TextStyle(fontSize: 16, color: Colors.indigo), ), Divider( color: Colors.transparent, @@ -147,7 +161,7 @@ class _LoginWidget extends State with Common, Trans { ], ), //Image.asset('asset/icon/gomb_zold_b-1.png', width: 100, height: 100), - onPressed: () => {formBloc.add(SubmitFormBloc())}), + onPressed: () => {loginBloc.add(LoginSubmit())}), ]), Divider( color: Colors.transparent, @@ -164,9 +178,14 @@ class _LoginWidget extends State with Common, Trans { ), Spacer(flex: 2), InkWell( - child: Text(AppLocalizations.of(context).translate('Privacy')), - onTap: () => Navigator.of(context).pushNamed('gdpr'), - ), + child: Text(AppLocalizations.of(context).translate('Privacy')), + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogGDPR(); + }) + }), ]), ])), ); diff --git a/lib/view/mydevelopment_body_page.dart b/lib/view/mydevelopment_body_page.dart index 4b9e7ab..f896fcf 100644 --- a/lib/view/mydevelopment_body_page.dart +++ b/lib/view/mydevelopment_body_page.dart @@ -4,7 +4,7 @@ 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:aitrainer_app/widgets/splash.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'; @@ -12,6 +12,7 @@ import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:aitrainer_app/bloc/body_development/body_development_bloc.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; class MyDevelopmentBodyPage extends StatefulWidget { @override @@ -26,6 +27,7 @@ class _MyDevelopmentBodyPage extends State with Trans, Co @override void initState() { super.initState(); + Flurry.logEvent("myDevelopmentBody"); if (!Cache().hasPurchased) { Timer( Duration(milliseconds: 2000), @@ -74,16 +76,18 @@ class _MyDevelopmentBodyPage extends State with Trans, Co ), ), child: BlocConsumer( - listener: (context, state) { - if (state is BodyDevelopmentLoading) { - LoadingDialog(); - } - }, + listener: (context, state) {}, builder: (context, state) { if (state is BodyDevelopmentInitial) { return Container(); } else { - return developmentWidget(customerId); + return ModalProgressHUD( + child: developmentWidget(customerId), + inAsyncCall: state is BodyDevelopmentLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); } }, )), diff --git a/lib/view/mydevelopment_muscle_page.dart b/lib/view/mydevelopment_muscle_page.dart index 7a99219..63885e2 100644 --- a/lib/view/mydevelopment_muscle_page.dart +++ b/lib/view/mydevelopment_muscle_page.dart @@ -11,6 +11,7 @@ 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'; @@ -31,6 +32,7 @@ class _MyDevelopmentMuscleState extends State with Comm @override void initState() { super.initState(); + Flurry.logEvent("myDevelopmentMuscle"); if (!Cache().hasPurchased) { Timer( Duration(milliseconds: 2000), @@ -149,7 +151,7 @@ class _MyDevelopmentMuscleState extends State with Comm ), ChoiceChip( avatar: Icon(Icons.accessibility_new), - label: Text(t('One Max Rep')), + label: Text(t('One Rep Max')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.lightBlueAccent, selected: bloc.diagramType == DiagramType.oneRepMax, diff --git a/lib/view/mydevelopment_page.dart b/lib/view/mydevelopment_page.dart index fb78b56..43be52d 100644 --- a/lib/view/mydevelopment_page.dart +++ b/lib/view/mydevelopment_page.dart @@ -4,6 +4,7 @@ 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/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'; @@ -100,6 +101,7 @@ class _MyDevelopmentPage extends State with Trans { backgroundColor: Colors.black54.withOpacity(0.4))), image: "asset/image/predictions.jpg", onTap: () => { + Flurry.logEvent("Predictions"), showDialog( context: context, builder: (BuildContext context) { diff --git a/lib/view/myexcercise_plan_page.dart b/lib/view/myexcercise_plan_page.dart index e3cd832..bd56e75 100644 --- a/lib/view/myexcercise_plan_page.dart +++ b/lib/view/myexcercise_plan_page.dart @@ -7,6 +7,7 @@ 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'; @@ -40,25 +41,6 @@ class _MyExercisePlanPage extends State with Trans, Logging child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [ SliverGrid( delegate: SliverChildListDelegate([ - ImageButton( - width: imageWidth, - textAlignment: Alignment.topLeft, - text: t("Execute My Selected Training Plan"), - style: GoogleFonts.robotoMono( - textStyle: TextStyle( - fontSize: 14, - color: Colors.white, - fontWeight: FontWeight.bold, - backgroundColor: Colors.black54.withOpacity(0.4))), - image: "asset/image/exercise_plan_execute.jpg", - top: 130, - left: 5, - onTap: () => { - args['customerId'] = Cache().userLoggedIn.customerId, - Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) - }, - isLocked: false, - ), ImageButton( width: imageWidth, textAlignment: Alignment.topLeft, @@ -78,6 +60,25 @@ class _MyExercisePlanPage extends State with Trans, Logging }, isLocked: false, ), + ImageButton( + width: imageWidth, + textAlignment: Alignment.topLeft, + text: t("Execute My Selected Training Plan"), + style: GoogleFonts.robotoMono( + textStyle: TextStyle( + fontSize: 14, + color: Colors.white, + fontWeight: FontWeight.bold, + backgroundColor: Colors.black54.withOpacity(0.4))), + image: "asset/image/exercise_plan_execute.jpg", + top: 130, + left: 5, + onTap: () => { + args['customerId'] = Cache().userLoggedIn.customerId, + Navigator.of(context).pushNamed('exerciseExecutePlanPage', arguments: args) + }, + isLocked: false, + ), ImageButton( width: imageWidth, textAlignment: Alignment.topLeft, @@ -91,6 +92,7 @@ class _MyExercisePlanPage extends State with Trans, Logging image: "asset/image/exercise_plan_suggested.jpg", left: 2, onTap: () => { + Flurry.logEvent("SuggestedTrainingPlan"), showDialog( context: context, builder: (BuildContext context) { @@ -119,6 +121,7 @@ class _MyExercisePlanPage extends State with Trans, Logging image: "asset/image/exercise_plan_special.jpg", left: 5, onTap: () => { + Flurry.logEvent("SpecialTrainingPlan"), showDialog( context: context, builder: (BuildContext context) { @@ -147,6 +150,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) { diff --git a/lib/view/registration.dart b/lib/view/registration.dart index 0f87023..b66d3c8 100644 --- a/lib/view/registration.dart +++ b/lib/view/registration.dart @@ -1,175 +1,217 @@ import 'package:aitrainer_app/bloc/account/account_bloc.dart'; -import 'package:aitrainer_app/bloc/registration_form_bloc.dart'; +import 'package:aitrainer_app/bloc/login/login_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; -import 'package:aitrainer_app/util/common.dart'; -import 'package:aitrainer_app/repository/customer_repository.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/splash.dart'; +import 'package:aitrainer_app/widgets/dialog_long.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -//import 'package:flutter_facebook_login/flutter_facebook_login.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'; +import 'package:toggle_switch/toggle_switch.dart'; import '../library_keys.dart'; -class RegistrationPage extends StatelessWidget { - final UserRepository userRepository = UserRepository(); - final CustomerRepository customerRepository = CustomerRepository(); - - @override - Widget build(BuildContext context) { - return RegistrationWidget(userRepository: userRepository, customerRepository: customerRepository); - } -} - -class RegistrationWidget extends StatefulWidget { - final UserRepository userRepository; - final CustomerRepository customerRepository; - - RegistrationWidget({this.userRepository, this.customerRepository}); - - @override - State createState() => _RegistrationWidget(); -} - -class _RegistrationWidget extends State with Common, Trans { +// ignore: must_be_immutable +class RegistrationPage extends StatelessWidget with Trans { final GlobalKey _scaffoldKey = new GlobalKey(); @override Widget build(BuildContext context) { - setContext(context); - // ignore: close_sinks final accountBloc = BlocProvider.of(context); - return BlocProvider( - create: (context) => RegistrationFormBloc(userRepository: UserRepository(), accountBloc: accountBloc), - child: Builder(builder: (context) { - // ignore: close_sinks - final registrationBloc = BlocProvider.of(context); - - return Scaffold( - key: _scaffoldKey, - appBar: AppBarMin(), - body: FormBlocListener( - onSubmitting: (context, state) { - LoadingDialog.show(context); - }, - onSuccess: (context, state) { - LoadingDialog.hide(context); + setContext(context); + return Scaffold( + appBar: AppBarMin(), + body: BlocProvider( + create: (context) => + LoginBloc(userRepository: UserRepository(), accountBloc: accountBloc, context: context, isRegistration: true), + child: BlocConsumer(listener: (context, state) { + if (state is LoginError) { + String message = t(state.message); + if (message == null) { + message = ""; + } else { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(message, style: TextStyle(color: Colors.white)))); + } + } else if (state is LoginSuccess) { Navigator.of(context).pushNamed('customerModifyPage'); - }, - onFailure: (context, state) { - LoadingDialog.hide(context); - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, content: Text(t(state.failureResponse), style: TextStyle(color: Colors.white)))); - }, - child: SafeArea( - bottom: false, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_login.png'), - fit: BoxFit.cover, - //height: double.infinity, - //width: double.infinity, - alignment: Alignment.center, - ), - ), - child: Form( - child: Container( - padding: const EdgeInsets.only(left: 25, right: 50), - child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 150.0), - //mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Divider( - color: Colors.transparent, - ), - //Spacer(flex:4), + } + }, builder: (context, state) { + final loginBloc = BlocProvider.of(context); - /* FlatButton( - child: new Image.asset( - 'asset/image/login_fb.png', - width: cWidth * .85, - ), - onPressed: () => { - // _fbLogin(), - print("Login with FB"), - }, - ), - Text(AppLocalizations.of(context).translate("OR")),*/ - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - new InkWell( - child: new Text(AppLocalizations.of(context).translate('SignUp'), - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), - ), - ], - ), - Divider(), - TextFieldBlocBuilder( - key: LibraryKeys.loginEmailField, - textFieldBloc: registrationBloc.emailField, - decoration: InputDecoration( - fillColor: Colors.white, - filled: true, - labelText: 'Email', - ), - ), - Divider( - color: Colors.transparent, - ), - TextFieldBlocBuilder( - key: LibraryKeys.loginPasswordField, - textFieldBloc: registrationBloc.passwordField, - decoration: InputDecoration( - fillColor: Colors.white, - filled: true, - labelText: 'Password', - ), - suffixButton: SuffixButton.obscureText, - ), - Divider( - color: Colors.transparent, - ), - Row(mainAxisAlignment: MainAxisAlignment.end, children: [ - new FlatButton( - child: Stack( - alignment: Alignment.center, - children: [ - Image.asset('asset/icon/gomb_zold_a.png', width: 140, height: 60), - Text( - t("OK"), - style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.white), - ), - ], - ), - // Image.asset('asset/image/WT_OK.png', width: 100, height: 100), - onPressed: () => {registrationBloc.add(SubmitFormBloc())}), - ]), - Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - new InkWell( - child: new Text(AppLocalizations.of(context).translate('Login')), - onTap: () => Navigator.of(context).pushNamed('login'), - ), - Spacer(flex: 1), - new InkWell( - child: new Text(AppLocalizations.of(context).translate('Privacy')), - onTap: () => Navigator.of(context).pushNamed('gdpr'), - ), - Spacer(flex: 2), - ]), - //Spacer(flex:2), - ])), - ), + return ModalProgressHUD( + child: loadForm(loginBloc, accountBloc), + inAsyncCall: state is LoginLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); + }))); + } + + Widget loadForm(LoginBloc loginBloc, AccountBloc accountBloc) { + return SafeArea( + top: false, + bottom: false, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_login.png'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: buildLoginForm(loginBloc, accountBloc), + ), + ); + } + + Widget buildLoginForm(LoginBloc loginBloc, AccountBloc accountBloc) { + return Form( + key: _scaffoldKey, + child: Container( + padding: const EdgeInsets.only(left: 15, right: 50), + child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 150.0), children: [ + FlatButton( + child: Image.asset( + 'asset/image/fb_registration.png', + width: MediaQuery.of(context).size.width * .85, + ), + onPressed: () => {loginBloc.add(RegistrationFB())}, + ), + ListTile(title: Text(AppLocalizations.of(context).translate("OR"))), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + InkWell( + child: + Text(AppLocalizations.of(context).translate('SignUp'), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), + ), + ], + ), + Divider( + color: Colors.transparent, + ), + TextFormField( + key: LibraryKeys.loginEmailField, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + labelText: t('Email'), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 4.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), ), ), + initialValue: loginBloc.userRepository.user.email, + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: (val) { + return t(loginBloc.emailValidation(val)); + }, + onChanged: (value) => loginBloc.add(LoginEmailChange(email: value)), + keyboardType: TextInputType.emailAddress, + style: new TextStyle(fontSize: 16, color: Colors.indigo), ), - ); - })); + Divider( + color: Colors.transparent, + ), + TextFormField( + key: LibraryKeys.loginPasswordField, + obscureText: true, + decoration: InputDecoration( + labelStyle: TextStyle(fontSize: 14), + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + suffixIcon: IconButton( + onPressed: () => {loginBloc.add(LoginPasswordChangeObscure())}, + icon: Icon(Icons.remove_red_eye), + ), + labelText: t('Password'), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 1.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + initialValue: loginBloc.userRepository.user.password, + autovalidateMode: AutovalidateMode.always, + validator: (val) { + return t(loginBloc.passwordValidation(val)); + }, + onChanged: (value) => loginBloc.add(LoginPasswordChange(password: value)), + keyboardType: TextInputType.visiblePassword, + style: new TextStyle(fontSize: 16, color: Colors.indigo), + ), + Divider( + color: Colors.transparent, + ), + getDataProtection(loginBloc), + Row(mainAxisAlignment: MainAxisAlignment.start, children: [ + FlatButton( + key: LibraryKeys.loginOKButton, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_zold_a.png', width: 140, height: 60), + Text( + t("OK"), + style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.white), + ), + ], + ), + //Image.asset('asset/icon/gomb_zold_b-1.png', width: 100, height: 100), + onPressed: () => {loginBloc.add(RegistrationSubmit())}), + ]), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + InkWell( + child: Text(AppLocalizations.of(context).translate('Login')), + onTap: () => Navigator.of(context).pushNamed('login'), + ), + Spacer(flex: 2), + InkWell( + child: Text(AppLocalizations.of(context).translate('Privacy')), + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogGDPR(); + }) + }), + ]), + ])), + ); + } + + Widget getDataProtection(LoginBloc loginBloc) { + return ListTile( + subtitle: Text(t("Please accept our data protection policy. For more information please click on 'Privacy'")), + title: ToggleSwitch( + minWidth: 100.0, + minHeight: 30.0, + fontSize: 14.0, + initialLabelIndex: loginBloc.dataPolicyAllowed ? 0 : 1, + activeBgColor: Colors.indigo, + activeFgColor: Colors.white, + inactiveBgColor: Colors.white30, + inactiveFgColor: Colors.black, + labels: [t('Yes'), t('No')], + onToggle: (index) { + loginBloc.add(DataProtectionClicked(marked: index == 0)); + }, + ), + ); } } diff --git a/lib/view/reset_password.dart b/lib/view/reset_password.dart index 20eb9b6..6912bd4 100644 --- a/lib/view/reset_password.dart +++ b/lib/view/reset_password.dart @@ -3,12 +3,12 @@ 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/splash.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.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:modal_progress_hud/modal_progress_hud.dart'; import '../library_keys.dart'; @@ -30,15 +30,13 @@ class ResetPasswordPage extends StatelessWidget with Trans { key: _scaffoldKey, appBar: AppBarMin(), body: FormBlocListener( - onSubmitting: (context, state) { + /* onSubmitting: (context, state) { LoadingDialog.show(context); - }, + }, */ onSuccess: (context, state) { - LoadingDialog.hide(context); Navigator.of(context).pop(); }, onFailure: (context, state) { - LoadingDialog.hide(context); showInSnackBar(state.failureResponse); }, child: SafeArea( @@ -48,12 +46,16 @@ class ResetPasswordPage extends StatelessWidget with Trans { image: DecorationImage( image: AssetImage('asset/image/WT_login.png'), fit: BoxFit.cover, - //height: double.infinity, - //width: double.infinity, alignment: Alignment.center, ), ), - child: buildResetPasswordForm(loginBloc), + child: ModalProgressHUD( + child: buildResetPasswordForm(loginBloc), + inAsyncCall: loginBloc.loading == true, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ), ), ), ), diff --git a/lib/view/sales_page.dart b/lib/view/sales_page.dart index c8e7c19..ab73a98 100644 --- a/lib/view/sales_page.dart +++ b/lib/view/sales_page.dart @@ -2,10 +2,10 @@ import 'package:aitrainer_app/bloc/sales/sales_bloc.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:aitrainer_app/widgets/sales_button.dart'; -import 'package:aitrainer_app/widgets/splash.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:modal_progress_hud/modal_progress_hud.dart'; // ignore: must_be_immutable class SalesPage extends StatelessWidget with Trans { @@ -18,12 +18,16 @@ class SalesPage extends StatelessWidget with Trans { if (state is SalesError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); - } else if (state is SalesLoading) { - return LoadingDialog(); } }, builder: (context, state) { final salesBloc = BlocProvider.of(context); - return salesWidget(salesBloc); + return ModalProgressHUD( + child: salesWidget(salesBloc), + inAsyncCall: state is SalesLoading, + opacity: 0.5, + color: Colors.black54, + progressIndicator: CircularProgressIndicator(), + ); })); } diff --git a/lib/view/settings.dart b/lib/view/settings.dart index dd8a540..7e284b6 100644 --- a/lib/view/settings.dart +++ b/lib/view/settings.dart @@ -3,6 +3,7 @@ import 'package:aitrainer_app/bloc/settings/settings_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/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; @@ -72,7 +73,7 @@ class SettingsPage extends StatelessWidget with Trans { settingsBloc.add(SettingsChangeLanguage(language: lang)), })), getServer(settingsBloc), - getDevice(settingsBloc), + //getDevice(settingsBloc), ]); } @@ -109,7 +110,7 @@ class SettingsPage extends StatelessWidget with Trans { ListTile getDevice(SettingsBloc settingsBloc) { return ListTile( - leading: Icon(CustomIcon.cog), + leading: Common.badgedIcon(Colors.grey, CustomIcon.cog, "hardware"), subtitle: Text("Do you have Smart watch, or any device which collects the fit/health data?"), title: ToggleSwitch( minWidth: 120.0, diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart index b32baae..95ad802 100644 --- a/lib/widgets/bottom_nav.dart +++ b/lib/widgets/bottom_nav.dart @@ -1,6 +1,7 @@ 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/trans.dart'; import 'package:badges/badges.dart'; import 'package:flurry/flurry.dart'; @@ -40,8 +41,8 @@ class _NawDrawerWidget extends State with Trans, Logging { items: [ BottomNavigationBarItem( backgroundColor: bgrColor, - icon: badgedIcon(inactive, Icons.home, "home"), - activeIcon: badgedIcon(active, Icons.home, "home"), + icon: Common.badgedIcon(inactive, Icons.home, "home"), + activeIcon: Common.badgedIcon(active, Icons.home, "home"), title: new Text(t("Home"), style: TextStyle(fontSize: 12)), ), BottomNavigationBarItem( @@ -70,8 +71,8 @@ class _NawDrawerWidget extends State with Trans, Logging { ), BottomNavigationBarItem( backgroundColor: bgrColor, - icon: badgedIcon(inactive, Icons.person, "account"), - activeIcon: badgedIcon(active, Icons.person, "account"), + icon: Common.badgedIcon(inactive, Icons.person, "account"), + activeIcon: Common.badgedIcon(active, Icons.person, "account"), title: Text( AppLocalizations.of(context).translate("Account"), style: TextStyle(fontSize: 12), @@ -79,10 +80,7 @@ class _NawDrawerWidget extends State with Trans, Logging { BottomNavigationBarItem( backgroundColor: bgrColor, icon: Icon(Icons.settings, color: inactive), - activeIcon: new Icon( - Icons.settings, - color: active, - ), + activeIcon: Icon(Icons.settings, color: active), title: Text(t("Settings"), style: TextStyle(fontSize: 12))) ], onTap: (index) { @@ -122,24 +120,4 @@ class _NawDrawerWidget extends State with Trans, Logging { }); }); } - - Widget badgedIcon(Color color, IconData icon, String badgeKey) { - bool show = Cache().getBadges()[badgeKey] != null; - int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0; - return Badge( - position: BadgePosition.topEnd(top: -10, end: -10), - animationDuration: Duration(milliseconds: 500), - animationType: BadgeAnimationType.slide, - badgeColor: Colors.red, - showBadge: show, - badgeContent: Text( - counter.toString(), - style: TextStyle(color: Colors.white), - ), - child: Icon( - icon, - color: color, - ), - ); - } } diff --git a/lib/widgets/dialog_html.dart b/lib/widgets/dialog_html.dart new file mode 100644 index 0000000..c954bf2 --- /dev/null +++ b/lib/widgets/dialog_html.dart @@ -0,0 +1,97 @@ +import 'package:aitrainer_app/util/trans.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_html/style.dart'; +import 'package:google_fonts/google_fonts.dart'; + +// ignore: must_be_immutable +class DialogHTML extends StatefulWidget { + final String title; + final String htmlData; + DialogHTML({Key key, this.title, this.htmlData}) : super(key: key); + + @override + _DialogPremiumState createState() { + return _DialogPremiumState(); + } +} + +class _DialogPremiumState extends State with Trans { + bool isStart = true; + @override + Widget build(BuildContext context) { + setContext(context); + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(31), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + contentBox(context) { + return Stack(children: [ + Container( + padding: EdgeInsets.only(left: 10, top: 24, right: 10, 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_black_G_background.png'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: SingleChildScrollView( + child: Html( + data: '

' + widget.title + '

' + widget.htmlData, + //Optional parameters: + style: { + "p": Style( + color: Colors.white, + padding: const EdgeInsets.all(4), + ), + "li": Style( + color: Colors.white, + //padding: const EdgeInsets.all(4), + ), + "h2": Style( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: FontSize.larger, + //padding: const EdgeInsets.all(4), + ), + "h1": Style( + color: Colors.yellow[400], + fontWeight: FontWeight.bold, + fontSize: FontSize.larger, + alignment: Alignment.center, + padding: const EdgeInsets.all(4), + ), + }, + ), + ), + ), + GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: 28, + child: Text( + "X", + style: GoogleFonts.archivoBlack(fontSize: 32, color: Colors.white54), + ), + )), + ]); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/widgets/dialog_long.dart b/lib/widgets/dialog_long.dart new file mode 100644 index 0000000..dcfcee7 --- /dev/null +++ b/lib/widgets/dialog_long.dart @@ -0,0 +1,403 @@ +import 'package:aitrainer_app/util/trans.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_html/style.dart'; +import 'package:google_fonts/google_fonts.dart'; + +// ignore: must_be_immutable +class DialogGDPR extends StatefulWidget { + DialogGDPR({Key key}) : super(key: key); + + @override + _DialogPremiumState createState() { + return _DialogPremiumState(); + } +} + +const htmlData = """ + +

WorkoutTest Data Policy

+

Principle of anonymous data use

+In principle, our website can be used without providing personal data. The use of individual services and offers (Workout Test app, workouttest.com website) on our website and in our apps can entail divergent regulations which in this case are explained separately below. The legal basis for data protection can be found in the General Data Protection Regulation (GDPR). + +When you access our website or Apps, some information, such as IP address, is transferred. You are also providing information about the end device used (computer, smartphone, tablet etc.), the browser used (Internet Explorer, Safari, Firefox etc.), time of visit to the website, the so-called referrer and volume of data transferred. + +We cannot use this data to identify an individual user. We only use this information to determine how attractive our offers are and to improve their performance or content, if necessary, and make their design even more appealing to you. + +Please bear in mind, however, that in the case of a static + +IP address, personal identification is possible by RIPE query in individual cases, although we do not perform this. Nevertheless, this website is accessible for both static and dynamic IP addresses assigned. + +  +

Collection and processing of personal data

+We only collect personal data if you provide it to us, for example when you contact us, in particular by registering a Workout Test account, placing an order, requesting information or publishing personal data in our Workout Test in your profile or in the feed. + +We use the personal data you provide only to the extent that your data is necessary for rendering or processing our services. + +We store your data for as long as is necessary to achieve the intended purpose or until you delete your account or for as long as legal retention periods require data to be stored. Your data is subsequently deleted in accordance with legal requirements or processing is restricted. + +In the case of use purely for information, i.e. if you do not register or send us information another way, we only collect personal data which your browser transfers to our servers. If you want to view our website, we collect the following data, which we require for technical purposes in order to show you our content and guarantee stability and security (legal basis is a legitimate interest pursuant to Article 6 (1) (f) GDPR). + +In the context of the balance of interests in accordance with Article 6 (1) (f) GDPR, we have considered and weighed our interest in website and app provisioning and your interest in data protection compliant processing of your personal data. As the data below is technically required for the provision of our service in order to offer you our services and also guarantee stability and security, in particular protection against misuse, we have reached the conclusion that, with a state-of-the-art oriented data security guarantee, this data can be processed whereby appropriate consideration will be given to your interest in data protection compliant processing. + +  + +The collection of data for website provision and the storage of data in log files is imperative for website and operation. Consequently, users may not object to this. +

Registering a Workout Test Account

+Using our login system, you can create a Workout Test account for yourself that you can use to log in to all of our services (Workout Test, Workouttest.com). In the process, we use cookies – small files – on your browser in order to identify you. All data that you save to your account is stored at a database at the server of Contabo GmbH. Some of our services are only accessible if you have set up your Workout Test account. This includes Workout Test app. We will request the following data when registering (some of it is required). In addition, you must take note of our Data Protection Statement, as well as accept our General Terms and Conditions of Business and Withdrawal Policy. + +  +

Registering with Facebook or Google

+We also offer you the opportunity to create your Workout Test account using your Facebook or Google account, or to link your Workout Test account to your Facebook or Google account. You can register or log in to Workout Test using your Facebook or Google account if you simply use Facebook or Google instead of the other options while registering your Workout Test account. You will then be forwarded to Facebook or Google (where you must be logged in or require an account) and receive an explanation of which of your data we need from Facebook or Google, namely your public profile information such as first and last name, gender, and the email address you are using there. This information is required for identification purposes in order to create a secure Workout Test account for you. When you log in using your Facebook account, this allows us to show you which of your friends are already with Workout Test. Your Facebook or Google account and your Workout Test account will be permanently linked using your email address. We store your email information in-house and will send you information using this address as needed. We can also tell that you have logged in using Facebook or Google. As soon as you log in to Facebook or Google, you can log in to Workout Test. We will not submit any information on you to Facebook or Google without your consent. + +Important: We do not record your Facebook or Google login data in any way, and cannot post anything to your Facebook or Google profile without your having expressly consented to this. + +You can learn how Facebook handles privacy settings using Facebook's privacy policy and terms of use; these also include the applicable conditions for the previously specified option of logging in and registering to Workout Test. You can learn how Google handles privacy settings using Google's privacy policy and terms of use; these also include the applicable conditions for the previously specified option of logging in and registering to Workout Test. + +  +

Data collection, processing and use in the context of Workout Test Service

+

Community Profile

+You need a Workout Test account in order to use our Workout Test Apps. The data collected for this purpose has already been explained above. To provide you with the best Workout Test experience possible, our approach is partly based on publishing specific information relating to our users within the Workout Test community, i.e. even your information. We are going to introduce our program to you in more detail below so that you can decide for yourself whether and which data you want to publish. This introduction includes the following data in particular which is visible to other users: +
    +
  • public profile (photo, first name, surname, nickname, weight, height, personal measurement data, training location, motivation, Workout Test level)
  • +
  • fitness (progress, desired objective, skills)
  • +
  • training information (duration and type of training unit, total number of training sessions, notes, photo)
  • +
  • social media profile (Facebook, Twitter, Instagram)
  • +
  • food intake (meal type, notes, photo)
  • +
  • followed by/follows (persons who follow the user, persons followed by the user)
  • +
+You become visible in Workout Test Apps with the data in your public profile. This information helps other users to find you in Workout Test Apps. At the same time, other users can see your name and surname (if provided), your training location, your motivation and your profile photo and they can recognize you using this information if necessary. You have already agreed under our General Terms and Conditions of Business that upon beginning your Workout Test journey and provided that you make no changes to your privacy settings, all Workout Test users will be able to view your profile, your training data, your posts, your training spots, etc., without special consent. This is designed to make it easier to follow you and/or support you during your journey with comments and motivation. If you do not want this anymore, you can set your privacy settings to ‘private’ at any time, which only allows select athletes to access the information referred to above. + +Workout Test Apps save all your successfully completed training units or the meals you have consumed as well as related information such as self- uploaded photos or notes. Other users can see this data and can consider them as an incentive for themselves, leave comments or decide whether they want to follow you. + +Moreover, our Workout Test Apps also provide users with the option to be followed (‘followed by’) to support or encourage them in their training experiences, or to compete with one another. For this purpose, users can be searched for by the name registered in the public profile or, after linking a Workout Test account to a Facebook account, via their Friends list. You will be notified about new followers in the mobile app and by push notification where applicable. + +Consequently, some of your information is available to other users in Workout Test Apps. Our aim is that nobody is left alone with their training. Instead, users’ performance is appreciated and can become an incentive for new members. + +If you do not want to make it possible to link your performance to yourself, you are free to refrain from providing any personal data on your profile or training sessions and linking your account to Facebook. Moreover, you should not save any training photos or enter any notes in this case. For this reason, we have ensured that each user can change their personal information, which can be viewed by other users, and each user is free to use their own name or a fictitious name in their Workout Test Apps. + +  +

Analysis of location data

+Within the framework of our Workout Test Apps, in particular, Workout Test Running and Workout Test Training, it is possible to map runs. For this purpose, we need access to location data. This data allows us to calculate distances covered at the relevant time and thereby correctly determine the end for predefined distances or determine distances covered. + +Based on your location, you can also find training spots and users near you, as well as adjust your training plan to your current environment. At training spots, you can check-in after your workout and show the other users in your community where you exercised. To determine the parts of the world in which most users are based, we perform a statistical analysis of your location data. If you edit your saved training, you can remove the selected training spot later and therefore withdraw your consent. + +  +

Access rights

+We require these access options and information to ensure the technical function of our app and to provide the services offered with the app, in particular, to access your camera or your photos, to determine your running distances and your activity calories or to send you push-notifications to inform you about new followers or comments. During the installation procedure or before you use the app for the first time, we request permission to access individual functions and information. We will only access these functions with your approval. You can revoke access rights manually in the settings for each operating system. You can find out how this works in the manufacturer instructions for your mobile OS. However, please note that you can only use the app to a limited extent or you cannot use it at all without the relevant approval. + +Before you either use the app for the first time or use a function for the first time, we ask the user for the permissions for the purpose described below: + +  +

Contact form

+You have the option of contacting us via our e-mail address or the contact form. + +We will, of course, use the personal data transmitted to us only for the purpose for which you make it available by contacting us. + +The legal basis is in this respect our legitimate interest in accordance with Art. 6 para. 1 sent. 1(f) of the GDPR. If the aim of your request is to conclude a contract (e.g., purchasing a subscription), the legal basis for the processing of the communicated data is also the necessity for providing (pre-) contractual services, in accordance with Art. 6 para. 1 sent. 1(b) of the GDPR. + +If we request entries in our contact form that are required for establishing contact, we have marked them as compulsory (*). Any information without an asterisk is optional. We use this information to put your request into specific terms and handle your concern more effectively. Providing this information is entirely voluntary and with your consent. If the information in question refers to communication channels (for example, e-mail address or phone number), you also give consent for us to contact you via these communication channels to respond to your concern. + +You can, of course, withdraw your declarations of consent at any time with future effect. If you wish to withdraw your consent, please contact the office indicated at the end of this declaration. + +  +

Push notifications as part of the user experience

+We require your consent if you wish to receive our push notifications on your mobile iOS device even if the app is not open. Our app only uses push notifications if you have given your explicit consent to these. You can disable push notifications in settings at any time. If you use an Android device, push notifications are permitted automatically unless you disable this in your settings. + +  + +  +

Push notifications for marketing purposes

+We require your consent if you wish to receive our push notifications for marketing purposes on your mobile iOS device even if the app is not open. Our app only uses push notifications for marketing purposes if you have given your explicit consent to these. You can disable push-notifications in settings at any time. If you use an Android device, push notifications are permitted automatically unless you disable this in your settings. + +  +

Apple Health Kit

+We use the HealthKit framework from Apple (Apple Inc., 1 Infinite Loop, Cupertino, CA 95014, USA; “Apple”), which provides a central storage location for health and fitness data on the iPhone or Apple Watch and – with the express consent of the user – allows apps to communicate with the HealthKit store in order to access and share these data. + +With your express approval, we will process your heart rate (where appropriate) as well as information about your workout (start and end of training (date)), training duration, type of training, indoor or outdoor), which is obtained through the HealthKit framework in order to track and display your health and fitness activities. + +If you activate the HealthKit framework in your iPhone’s or Apple Watch settings, Workout Test is able to send, with your approval, the calories burned by the activity, route (walking and running), as well as your workouts (start and end of training [date], training duration, type of training, indoor or outdoor) to Apple, so that you can track and display your health and fitness activity. + +New data attributes can be added to the HealthKit framework, which are then displayed in the product and must be approved. You can prevent Apple from accessing your data at any time, and thus prevent it from being shared, by changing your mobile device settings. You can find more information about HealthKit here: [https://developer.apple.com/documentation/healthkit] https://developer.apple.com/documentation/healthkit + +  +

Google Fit

+We use Google Fit from Google (Google Ireland Limited, Gordon House, Barrow Street, Dublin 4, Ireland; “Google”), which provides a central storage location for health and fitness data on your Android phone and – with the express consent of the user – allows apps to communicate with Google Fit in order to access and share these data. + +With your express approval, we will send information about your workout (start and end of training (date), training duration, type of training, and name of the workout) to Google Fit, so that you can track and display your health and fitness activity. New data attributes can be added to Google Fit, which is then displayed in the product and must be approved. + +You can prevent Google from accessing your data at any time, and thus prevent it from being shared, by changing your mobile device settings. You can find more information about Google Fit here. + +  +

Cookies, tracking pixels and similar technologies

+To improve our web service and make your experience as comfortable as possible, we use cookies, tracking pixels, or similar technologies. Cookies are small text files saved on your computer when you visit our website. They help us recognize your browser as yours. Cookies save information such as your language settings or the duration of your visit to our website. They save data entries you make on the website, like when you log in, so you don’t need to enter your data each time you use our services. Cookies help us to recognize your preferences and adjust our website to your areas of interest. + +Every time our website loads, we record how often it is visited and clicked on by using tags on our website called tracking pixels. These tracking pixels do not interfere with your computer. + +Most browsers accept cookies automatically. If you want to prevent cookies from being saved, you can select the + +‘Accept no cookies’ option in your browser settings. To find out exactly how this works, you can consult your browser manufacturer’s instructions. You can delete cookies that have already been saved on your computer at any time. To find out exactly how this works, you can consult your browser manufacturer’s instructions. If you want to prevent performance cookies and advertising cookies from being saved, you can change your cookie preferences at any time by changing your cookie settings above. + +We use cookies and tracking pixels for different purposes, which also means they have different legal bases and storage periods. You will find more information about that in the following sections: +

Required and functional cookies

+Some cookies are required for the site to function and cannot be disabled. Without these cookies, you will not be able to view our site properly. We also use functional cookies, which help us to improve our website performance. + +- Analytical tools are used to analyze data based on your browser behaviour in order to improve the functionality and design of our site. + +- Quality assurance tools are used to measure errors presented on a website, to make sure we fix bugs or any issues promptly. + +- A/B testing tools or multivariate testing tools are used to ensure a consistent design of the website and a consistent user experience in the current and subsequent sessions. + +The legal basis is in this respect our legitimate interest in accordance with Art. 6 para. 1 sent. 1(f) GDPR +

Performance Cookies and Advertising Cookies

+These cookies allow us to analyze site usage so we can measure and improve performance. They are also used by advertising companies to serve ads that are relevant to your interests. These cookies contain a unique key to distinguish individual users’ browsing habits. We also use these cookies to limit the number of times a user sees a particular ad on a website and to measure the effectiveness of a particular campaign. The identifier stored by these cookies is provided by our partners. We cannot use the same identifier in our own systems. + +If you want to prevent performance cookies and advertising cookies from being saved, you can change your cookie preferences at any time by changing your cookie settings above. + +The legal basis for performance cookies and advertising cookies is consent in accordance with Art. 6 para. 1 sent. 1(a) GDPR. Obviously, you can withdraw your declarations of consent for the future at any time. If you no longer agree to us providing your data to the service providers mentioned in our privacy policy, you can opt- out in the cookie settings on our website or within your profile settings. + +Please note: it is possible that you can still see advertisements from Workout Test on third-party platforms even if you do not choose this functionality, but these advertisements are at random and won’t be personalized. +

Google Analytics

+We use the Google Analytics service from Google Ireland Limited (Gordon House, Barrow Street, Dublin 4, Ireland) to analyze our website visitors. Google uses cookies to track the use of the online product or service by users and the information is generally transferred to a Google server in the USA and stored there. + +Google will use this information on our behalf to evaluate the use of our online products and services by users, to compile reports on the activities within these online products and services and to provide us with further services associated with the use of these online products and services and the use of the internet. Pseudonymous user profiles can be created from the processed data. + +We use Google Analytics only with IP anonymization enabled. This means that Google will truncate the IP address of users within Member States of the European Union or in other states that are party to the Agreement + +on the European Economic Area. Only in exceptional cases will the full IP address be transmitted to a Google server in the USA and truncated there. The IP address transmitted by the user’s browser is not merged with other Google data. Users can prevent cookies from being stored by adjusting the settings to their browser software accordingly. We have made data protection friendly default settings. + +The legal basis for the use of this service is Art. 6 paragraph 1 sentence 1 letter f GDPR. Users can prevent the collection of data generated by cookies by downloading and installing the browser plug-in that is available here. As a guarantee pursuant of Art. 44ff of the General Data Protection Regulation (GDPR), Google has signed the EU standard contractual clauses. + +If you do not wish to be tracked by Google Analytics in the future, you can opt out at any time by writing an email to service@workouttest.com. +

+

Flurry

+We use Flurry (360 3rd Street, Suite 750, San Francisco, CA 94107, US) within our app in order to analyze your app usage behaviour. When you visit our website or app the information listed below is collected and analyzed by Flurry, which uses an identifier (ID) that allows analysis of your use of our services. + +On behalf of us, Flurry will use this information to evaluate your use of the app and to compile reports on the use of the website. This information may be used by us, if activated by you, to send you specific information (so-called push notifications or in-app messages) about Workout Test services or specific advertising. If you do not want to receive any in-app messages, please contact service@workouttest.com. For further information about push-notifications, see here. + +If Flurry transfers personal data to the USA, it does so on the basis of an agreement with the EU standard contractual clauses. The legal basis is Art. 6 para. 1 lit. f) DSGVO. If you do not wish to be tracked by Flurry in the future, you can opt-out at any time by writing an email to service@workouttest.com. + +  +

Google Marketing Services

+On our apps we use the marketing and re-marketing services of Google Ireland Limited (Gordon House, Barrow Street, Dublin 4, Ireland) that allow us to display advertisements in a more targeted manner in order to present advertisements of interest to users. Through (re- )marketing ads and products are displayed to users relating to an interest established by activity on other apps within the Google Network. For these purposes, a code is used by Google when our app is accessed and what are referred to as (re-)marketing tags are incorporated into the app. With their help, an individual cookie, i.e. a small file, is stored on the user’s device (comparable technologies may also be used instead of cookies). Cookies can be set by various domains. This file records which apps users have visited, which content they are interested in and which offers have been used. In addition, technical information about the browser and operating system, referring apps, the length of the visit as well as any additional data about the use of the online products and services are stored. The IP address of users is also recorded, although we would like inform you that within the framework of Google Analytics, IP addresses within Member States of the European Union or in other contracting states to the Agreement on the European Economic Area are truncated. + +All user data will only be processed as pseudonymous data. Google does not store any names or email addresses. All displayed ads are therefore not displayed specifically for a person, but for the owner of the cookie. This information is collected by Google and transmitted to and stored by servers in the USA. + +One of the Google marketing services we use is the online advertising program Google AdWords. In the case of Google AdWords, each AdWords customer receives a + +different conversion cookie. Cookies can therefore not be tracked through the apps of AdWords customers. The information collected by the cookie is used to generate conversion statistics for AdWords customers who have opted for conversion tracking. AdWords customers see the total number of users who clicked on their ad and were redirected to a page with a conversion tracking tag. However, they will not receive any information that personally identifies users. + +We may include third-party advertisements based on the Google Marketing Service called DoubleClick. DoubleClick uses cookies to enable Google and its partner apps to place ads based on users’ visits to this app or other apps on the Internet. + +Google services make use of Google’s Tag Manager. For more information about Google’s use of data for marketing purposes, please see the summary page, Google’s privacy policy is available here. + +The legal basis for the use of this service is Article Art. 6 paragraph 1 sentence 1 letter f GDPR. If you wish to object to interest-based advertising by Google marketing services, you can do so using the settings and opt-out options provided by Google. As a guarantee pursuant of Art. 44ff of the General Data Protection Regulation (GDPR), Google has signed the EU standard contractual clauses. + +There is another Google service we use called Google Audience, that allows us to show targeted messages to users within the Google Network (such as Gmail, YouTube, Google Feed, etc.). For this, we may provide Google with a customer list that includes the email address or other data such as the device ID you provide to us when you register. This allows Google to create a profile about your usage patterns in our app and on our website in order to display advertisements in a more targeted manner in order to present Workout Test advertisements of interest to users on other apps and websites within the Google Network. Please find more information about the Google Personalized Advertising Service here: https://support.google.com/adspolicy/answer/143465? hl=en + +The legal basis for our processing is Art. 6 Para. 1 Sentence 1 Letter a GDPR. We only actively provide Google with customer lists that include your email address or other personal data with your consent. Obviously, you can withdraw your declarations of consent for the future at any time. If you no longer agree to us providing your data to Google, you can opt-out in our app-settings. It is possible, that you can then still see advertisements from Workout Test even if you withdrew your consent or did not consent in the first place, but these advertisements on third party platforms are at random + +  +

Facebook Marketing Services

+We use the “visitor action pixels” from Facebook Inc. (Menlo Park, California) on our website so that user behavior can be tracked after users have been redirected to the provider’s website by clicking on a Facebook ad. This enables us to measure the effectiveness of Facebook ads for statistical and market research purposes. The data collected in this way is anonymous to us, i.e. we do not see the personal data of individual users. However, this data is stored and processed by Facebook, which is why we are informing you, based on our knowledge of the situation. Facebook may link this information to your Facebook account and also use it for its own promotional purposes, in accordance with Facebook’s Data Usage Policy. You can allow Facebook and its partners to place ads on and off Facebook. A cookie may also be stored on your computer for these purposes. You can object to the collection of your data by Facebook pixel, or to the use of your data for the purpose of displaying Facebook ads. + +We also use Facebook’s Software Development Kit (SDK) within our apps, in order to link various Facebook services with our apps. For example, this enables users to be able to use the Facebook SDK to share content from our apps within their Facebook timeline or to send messages to other Facebook users. Further information about the Facebook SDK within iOS can be found here: + +https://developers.facebook.com/docs/ios. For Android, please refer to: https://developers.facebook.com/docs/android. + +We use the Facebook App Events service though the Facebook SDK to track how many people our advertising campaigns reach, and the use of the Facebook SDK. Facebook merely provides us with an aggregated analysis of user behavior with our app. We have no influence beyond that on the information that will be processed through App Events by Facebook. In our app settings, you can opt out of using App Events for these purposes. + +As a guarantee pursuant of Art. 44ff of the General Data Protection Regulation (GDPR), Facebook has signed the EU standard contractual clauses. The legal basis for this processing is Art. 6 paragraph 1 sentence 1 letter f GDPR. + +If you do not wish to be tracked by Facebook in the future, you can opt out at any time by writing an email to service@workouttest.com. +

Facebook Custom Audience

+The product Custom Audiences from Facebook (Facebook Custom Audiences 1601 S. California Avenue, Palo Alto, CA, 94304) is also used on the website as part of the usage-based online advertising. Basically, a non- reversible and non-personal checksum (hash value) is generated from your usage data, which can be transmitted to Facebook for analysis and marketing purposes. This is done either by placing a pixel-code from Facebook on our website or by capturing your usage behavior in our app using the Facebook SDK (see section above for a detailed description of these two Facebook services). Alternatively, we may provide Facebook with a customer list that includes the email address you provided to us when you registered. It collects information about your activities on the website (e.g. surfing habits, sub-pages visited, etc.). This allows Facebook to create a profile about your usage patterns in our app and on our website. Your IP address is stored and used for the geographical control of advertising. + +As a guarantee pursuant of Art. 44ff of the General Data Protection Regulation (GDPR), Facebook has signed the EU standard contractual clauses. The legal basis for our processing is Art. 6 Para. 1 Sentence 1 Letter f GDPR. + +For registrations from June 2020: The legal basis for our processing is Art. 6 Para. 1 Sentence 1 Letter a GDPR. We only actively provide Facebook with customer lists that include your email address or other personal data with your consent. Obviously, you can withdraw your declarations of consent for the future at any time. + +If you no longer agree to us providing your data to Facebook, you can opt-out in our app-settings. + +In this context, please note that Facebook may also use + +the data we provide about your usage behavior and your e-mail address for its own purposes. Here you have the opportunity to object to targeting on Facebook. Alternatively, you can contact us directly by email at service@workouttest.com. + +Further information about the purpose and scope of the data collection and the further processing and use of the data, as well as the privacy settings can be found in the Facebook data protection guidelines. +

+

Firebase by Google

+We use the Firebase service from Google Ireland Limited (Gordon House, Barrow Street, Dublin 4, Ireland) in order to derive application behavioral analytics. We use that information to see how users interact with our website and app. + +Firebase is part of the Google Cloud Platform and offers numerous services for developers. Some Firebase services process personal data. In most cases, the personal data is limited to so-called "instance IDs", which are provided with a time stamp. These "Instance IDs" assigned by Firebase are unique and thus allow the linking of different events or processes. This data does not represent personally identifiable information for us, nor do we make any efforts to personalize it subsequently. We process these aggregated data to analyze and optimize usage behavior, for example by evaluating crash reports. + +Currently, we use the following Firebase services: + +Google Analytics for Firebase: Google Analytics uses the data to provide analytics and attribution information. The precise information collected can vary by the device and environment. Google Analytics retains ID-associated data for 60 days, and retains aggregate reporting and campaign data without automatic expiration, unless the Firebase customer changes their retention preference in their Analytics settings or deletes their project. For Analytics for Firebase, Google uses not only the "Instance ID" described above, but also the advertising ID of the end device. You can restrict the use of the advertising ID in the device settings of your mobile device. For Android: + +Settings > Google > Ads > Reset Ad ID For iOS: Settings > Privacy > Advertising > No ad tracking + +Firebase Remote Config: Remote Config uses Instance IDs to select configuration values to return to end-user devices. Firebase retains Instance IDs until the Firebase customer makes an API call to delete the ID. After the call, data is removed from live and backup systems within 180 days. + +Firebase Dynamic Links: Dynamic Links uses device specs on iOS to open newly-installed apps to a specific page or context. Dynamic Links only stores device specs temporarily, to provide the service. + +Firebase Cloud Messaging: Firebase Cloud Messaging is used to transmit push messages or so-called in-app messages (messages that are only displayed within the respective app). A pseudonymized push reference is assigned to the mobile device, which serves as a target for the push messages or in-app messages. The push messages can be deactivated and reactivated at any time in the settings of the mobile device. Firebase Cloud Messaging uses Instance IDs to determine which devices to deliver messages to. Firebase retains Instance IDs until the Firebase customer makes an API call to delete the ID. After the call, data is removed from live and backup systems within 180 days. + +Firebase will use this information on our behalf for the + +above mentioned reasons. + +The legal basis for the use of this service is Art. 6 paragraph 1 sentence 1 letter f GDPR. As a guarantee pursuant of Art. 44ff of the General Data Protection Regulation (GDPR), Google has signed the EU standard contractual clauses. + +  +

YouTube (extended data protection mode)

+We also use services from YouTube, LLC 901 Cherry Ave., 94066 San Bruno, CA, USA, a company of Google Inc., Amphitheatre Parkway, Mountain View, CA 94043, USA on our website. In so doing we use the option of “extended data protection mode” provided by YouTube. When you access a page containing an embedded YouTube video, a connection to the YouTube servers is established and the contents are displayed on the Internet page through a notification to your browser. Pursuant to YouTube specifications, in the “extended data protection mode” your data is sent to the YouTube servers only when you view the video. If you are simultaneously logged in to YouTube, this information is assigned to your YouTube member account. You may prevent this by logging out of your member account before visiting our website. + +For more information on data protection in connection with YouTube, please refer to this link. +

+

Quality assurance

+When using our website and apps, data is collected and stored which is used to generate information using pseudonymous usage profiles for purposes of web analysis. These usage profiles serve to analyze visitor behaviour and are evaluated to improve and design our services based on demand. In addition, we measure and analyze technical performance data (e.g. response and load times) and application data (hardware and software used) in order to improve the performance of our products. Cookies are used to do so. These are text files saved on your computer that allow us to analyze how you use our website. The pseudonymous usage profiles are not associated with personal data on the bearer of the pseudonym without the concerned party's express consent. You can object to future data collection and storage for the purpose of web analysis at any time by deactivating cookies in your browser settings. You can find the individual privacy notices for the providers here: + +Flurry, Sentry + +  + +  +

Social Plugins

+This website uses social plugins from providers: + +Facebook (Facebook Inc., 1601 S. California Ave, Palo Alto, CA 94304, USA) +Twitter (Twitter Inc., 795 Folsom St., Suite 600, San Francisco, CA 94107, USA) + +These plugins normally collect your data and transmit it to the server of the respective provider. + +After being activated, these plugins also record personal data, such as your IP address, and send this to the server of the respective provider where it is stored. Active social plugins also create a cookie with a unique identifier when accessing the respective website. This allows the provider to create profiles on your usage behavior. This also happens when you are not a member of the social network of the respective provider. If you are a member of the provider's social network, and if you are logged in to the social network while visiting this website, your data and visit information can be associated with your profile on the social network. We cannot influence the exact scope of the data collected on you by the respective provider. Please refer to the privacy policies of the respective social network providers for more detailed information on the scope, manner, and purpose of data processing, and on your rights and setting options to protect your privacy. These can be found in the table above. They are also available at the following addresses: + +Facebook, Twitter +

Social media fan pages

+Workout Test maintains so-called fan pages with social media providers like Instagram, Facebook (both: Facebook Inc. Menlo Park, California) and Twitter (Twitter Inc., 795 Folsom St., Suite 600, San Francisco, CA 94107, USA) in order to communicate with customers, interested parties, and users who are active there, and to inform them about our products, services, and events. In doing so, the users’ data can be processed outside of the EU. The above-mentioned US providers have signed the EU standard contractual clauses and thus guarantee the observance of European data protection laws. + +In the opinion of the European Court of Justice (ECJ), we are responsible, together with Facebook, for the processing of your personal data. You can find the decision of the ECJ dated June 5, 2018 here. + +A Joint Controller Agreement exists with Facebook Inc. pursuant to Art. 26 GDPR. Facebook Ireland pledges to assume the main responsibility in the context of the General Data Protection Regulation (GDPR) for the processing of Insights data and to fulfill all applicable obligations in the context of the GDPR with reference to the processing of Insights data (including, but not limited to Articles 12 and 13 GDPR, Articles 15 to 22 GDPR, and Articles 32 to 34 GDPR). Facebook Ireland will also make available the essential information of this Page Insights Addendum to the affected parties. Please contact Facebook to assume your rights as affected parties. The Data Policy of Facebook can be found here. + +When using the Facebook fan page, the following data will be collected from you for the purpose of user communication and target group advertising: +
    +
  • user interactions (posts, likes, etc.)
  • +
  • Facebook cookies
  • +
  • demographic data (e.g., based on information regarding age, place of residence, language, or gender)
  • +
  • statistical data on user interactions in aggregated form, that is, without the possibility to relate the information to any particular persons (e.g., page activities, page impressions, page previews, likes, recommendations, articles, videos, page subscriptions, incl. source, times of day)
  • +
+The usage of personal data for advertising purposes is of particular importance for Facebook. We use the statistics function to find out more about visitors to our fan page. The use of the function enables us to adapt our content to the respective target group. In this way we also use, for example, the demographic information about the users’ age and location, whereby it is not at all possible for us to relate this information to persons. + +In order to provide the social media service in the form of our Facebook fan page and to use the Insight function, Facebook generally saves cookies on the end device of the user. These include session cookies, which are deleted when the browser is closed, and persistent cookies that remain on the end device until they expire or are deleted by the user. + +We use the Facebook Insights function for statistical + +evaluation purposes. In this connection, we receive anonymized data concerning the users of our Facebook fan page. As a result, it is not possible for us to trace them back to your person. For more information, you can refer to the cookie guideline of Facebook. + +The personal data of users are processed on the basis of our justified interest in effectively providing information to users and maintaining communication with the users, as well as for the purposes of statistical evaluation pursuant to Art. 6(I) (f) GDPR. + +  +

Transfer of data to third parties

+We only pass your personal data on to third parties if: +
    +
  • you have given your explicit consent to this,
  • +
  • forwarding data is necessary for the assertion, exercise or defense of legal claims and there is no reason to assume you have an overriding legitimate interest in your data not being passed on,
  • +
  • in the event that we have a legal obligation to forward data, and
  • +
  • this is legally permissible and required for the performance of the contractual relationship with you.
  • +
+In the case of data transfer outside the European Union, the high European level of data protection essentially does not exist. It may be the case with a transfer that an EU Commission adequacy decision in accordance with Article 45 (1) (3) GDPR is not currently in place. This means the EU Commission has not yet decided that the level of data protection in the respective country corresponds to the level of protection in the European Union based on the GDPR. Consequently, we have put the appropriate guarantees referred to above in place. Potential risks, which cannot be ruled out completely in connection with data transfer, are in particular: +
    +
  • your personal data could be processed over and above the intended purpose.
  • +
  • Moreover, there is a possibility that you may not be able to exercise your rights in relation to data protection, for example your right of access, to rectification, erasure or data portability, on a consistent basis and enforce these.
  • +
  • It may also be highly likely that data is processed incorrectly and in quantitative and qualitative terms, the protection of personal data fails to meet the requirements of the GDPR in full.
  • +
+  +

Your rights

+

Information on the rights of data subjects

+Each data subject has the right of access in accordance with Article 15 GDPR, the right to rectification in accordance with Article 16 GDPR, the right to erasure in accordance with Article 17 GDPR, the right to restriction of processing in accordance with Article 18 GDPR, the right to object in Article 21 GDPR and the right to data portability in Article 20 GDPR. The limitations according to Articles 34 and 35 BDSG apply to the right of access and to the right to erasure. + +  +

+

Information on right the to object in the case of balance of interests

+If we process your personal data based on a balance of interests, you can object to such processing. If you exercise this right to object, please state the reasons why we should not process your data as we have described. If your objection is justified, we will review the situation and either stop or adjust data processing or explain our compelling legitimate reasons for processing to you. + +  + +Information on withdrawal of consent + +You can withdraw your consent with us to process personal data at any time. This also applies to withdrawals of a declaration of consent that were given to us before the General Data Protection Regulation came into effect, i.e. before May 25, 2018. Please note that this withdrawal will only apply prospectively. This does not affect processing that took place prior to a withdrawal. + +  +

Information on right the to object in the case of balance of interests

+If we process your personal data based on a balance of interests, you can object to such processing. If you exercise this right to object, please state the reasons why we should not process your data as we have described. If your objection is justified, we will review the situation and either stop or adjust data processing or explain our compelling legitimate reasons for processing to you. + +"""; + +class _DialogPremiumState extends State with Trans { + bool isStart = true; + @override + Widget build(BuildContext context) { + setContext(context); + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(31), + ), + elevation: 0, + backgroundColor: Colors.transparent, + child: contentBox(context), + ); + } + + contentBox(context) { + return Stack(children: [ + SingleChildScrollView( + padding: EdgeInsets.only(top: 15), + child: 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_light_background.png'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: Html(data: htmlData, + //Optional parameters: + style: { + "html": Style( + backgroundColor: Colors.transparent, + ), + }), + ), + ), + Align( + alignment: Alignment.centerRight, + child: FloatingActionButton( + backgroundColor: Colors.orange, + onPressed: () => Navigator.of(context).pop(), + child: Text("OK"), + )), + GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: CircleAvatar( + backgroundColor: Colors.transparent, + radius: 28, + child: Text( + "X", + style: GoogleFonts.archivoBlack(fontSize: 32, color: Colors.grey[400]), + ), + )), + ]); + } + + @override + void dispose() { + super.dispose(); + } +} diff --git a/lib/widgets/image_button.dart b/lib/widgets/image_button.dart index 0c73ce7..f34dbdd 100644 --- a/lib/widgets/image_button.dart +++ b/lib/widgets/image_button.dart @@ -53,36 +53,55 @@ class ImageButton extends StatelessWidget { top = height - (style.fontSize - 5) * text.length - 2 * left < 0 ? height - 2 * style.fontSize - 22 : height - style.fontSize - 37; //print("Top: " + top.toStringAsFixed(0) + " length: " + ((style.fontSize - 5) * text.length).toString()); } - return Stack( - //alignment: textAlignment, - fit: StackFit.passthrough, - overflow: Overflow.clip, - children: [ - FlatButton( - child: image == null - ? _getButtonImage("asset/image/WT_menu_dark.png") - : isMarked - ? Stack( - children: [ - _getButtonImage(image), - Container( - width: width, - height: height, - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1), - child: Container( - color: Colors.black.withOpacity(0.3), - ), - ), - ) - ], + return Stack(alignment: AlignmentDirectional.bottomStart, children: [ + FlatButton( + child: image == null + ? _getButtonImage("asset/image/WT_menu_dark.png") + : isMarked + ? Stack( + children: [ + _getButtonImage(image), + Container( + width: width, + height: height, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1), + child: Container( + color: Colors.black.withOpacity(0.3), + ), + ), ) - : _getButtonImage(image), - padding: EdgeInsets.only(left: 0.0, bottom: 0), - shape: getShape(isShape), - onPressed: onTap ?? onTap, - ), - Positioned( + ], + ) + : _getButtonImage(image), + padding: EdgeInsets.only(left: 0.0, bottom: 0), + shape: getShape(isShape), + onPressed: onTap ?? onTap, + ), + Container( + padding: EdgeInsets.all(4), + child: InkWell( + onTap: onTap ?? onTap, + child: Text(text, + maxLines: 2, + style: GoogleFonts.archivoBlack( + fontSize: 16, + color: Colors.white, + 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, + ), + ], + )), + )), + /* Positioned( top: top, left: left, child: Container( @@ -98,35 +117,35 @@ class ImageButton extends StatelessWidget { ), color: Colors.transparent, ), - ), - Cache().hasPurchased - ? Offstage() - : Stack(alignment: Alignment.topLeft, children: [ - Positioned( - top: height / 2 - 30, - left: width / 2 - 30, - child: this.isLocked + ), */ + Cache().hasPurchased + ? Offstage() + : Stack(alignment: Alignment.topCenter, children: [ + Positioned( + top: 20, + left: 20, + child: this.isLocked + ? GestureDetector( + child: Image.asset( + 'asset/image/lock.png', + height: 150, + width: 150, + ), + onTap: onTap ?? onTap, + ) + : isMarked ? GestureDetector( child: Image.asset( - 'asset/image/lock.png', - height: 60, - width: 60, + '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(), - ) - ]), - ] + : Container(), + ) + ]), + ] //) // ) ); diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index ccbbcf2..bc12ebb 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -17,6 +17,7 @@ import 'package:flutter/painting.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'dialog_html.dart'; import 'menu_info_widget.dart'; // ignore: must_be_immutable @@ -103,24 +104,41 @@ class _MenuPageWidgetState extends State with Trans, Logging { color: Colors.white, fontSize: 12, )), - child: Stack(alignment: Alignment.bottomLeft, children: [ - FlatButton( - child: badgedIcon(workoutTree, cWidth, cHeight), - padding: EdgeInsets.only(left: 0.0, bottom: 0), - onPressed: () => menuClick(workoutTree, menuBloc, context), - ), - Container( - padding: EdgeInsets.only(left: 15, bottom: 15, right: 15), - child: GestureDetector( - onTap: () => menuClick(workoutTree, menuBloc, context), - child: Text( - workoutTree.name, - maxLines: 4, - style: GoogleFonts.archivoBlack(color: workoutTree.color, fontSize: workoutTree.fontSize, height: 1.1), + child: Badge( + showBadge: workoutTree.nameEnglish == "One Rep Max" || workoutTree.nameEnglish == "Endurance", + animationDuration: Duration(milliseconds: 800), + animationType: BadgeAnimationType.fade, + badgeColor: Colors.blue[100], + badgeContent: GestureDetector( + onTap: () => { + showDialog( + context: context, + builder: (BuildContext context) { + return DialogHTML( + title: workoutTree.name, + htmlData: workoutTree.nameEnglish == "Endurance" ? t("Endurance_desc") : t("OneRepMax_desc"), + ); + }) + }, + child: Icon(Icons.info_outline_rounded)), + child: Stack(alignment: Alignment.bottomLeft, children: [ + FlatButton( + child: badgedIcon(workoutTree, cWidth, cHeight), + padding: EdgeInsets.only(left: 0.0, bottom: 0), + onPressed: () => menuClick(workoutTree, menuBloc, context), ), - ), - ), - ])))); + Container( + padding: EdgeInsets.only(left: 15, bottom: 15, right: 15), + child: GestureDetector( + onTap: () => menuClick(workoutTree, menuBloc, context), + child: Text( + workoutTree.name, + maxLines: 4, + style: GoogleFonts.archivoBlack(color: workoutTree.color, fontSize: workoutTree.fontSize, height: 1.1), + ), + ), + ), + ]))))); }); } @@ -285,7 +303,6 @@ class _MenuPageWidgetState extends State with Trans, Logging { } void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) { - print("Hi!, Menu clicked " + workoutTree.id.toString()); if (workoutTree.child == false) { menuBloc.add(MenuTreeDown(item: workoutTree, parent: workoutTree.id)); } else { @@ -321,13 +338,13 @@ class _MenuPageWidgetState extends State with Trans, Logging { borderRadius: BorderRadius.circular(24), child: Image.asset( workoutTree.imageName, - height: cHeight, + height: 210, errorBuilder: (context, error, stackTrace) { String url = Cache.mediaUrl + 'images/' + workoutTree.imageName.substring(11); Widget image = FadeInImage.assetNetwork( placeholder: 'asset/image/dots.gif', image: url, - height: 180, + height: 210, ); return image; }, @@ -337,7 +354,7 @@ class _MenuPageWidgetState extends State with Trans, Logging { image = FadeInImage.assetNetwork( placeholder: 'asset/image/dots.gif', image: url, - height: 180, + height: 210, ); } diff --git a/lib/widgets/size_widget.dart b/lib/widgets/size_widget.dart index f6ca8e6..1567cf7 100644 --- a/lib/widgets/size_widget.dart +++ b/lib/widgets/size_widget.dart @@ -75,6 +75,18 @@ class _SizeState extends State with Trans { width: mediaWidth, ), ); + list.add(Positioned( + top: widget.exerciseBloc.getWeightCoordinate(widget.exerciseBloc.isMan, isTop: true).toDouble(), + left: widget.exerciseBloc.getWeightCoordinate(widget.exerciseBloc.isMan, isTop: false, isLeft: true).toDouble() - 45, + child: GestureDetector( + onTap: () => onPressed(widget.exerciseBloc.getPropertyByName("Weight")), + child: Image.asset( + "asset/image/merleg.png", + height: 120, + width: 120, + color: Colors.blue, + )), + )); list.addAll(getSizeElements()); list.add( @@ -110,6 +122,7 @@ class _SizeState extends State with Trans { ], )), ); + return list; } diff --git a/lib/widgets/splash.dart b/lib/widgets/splash.dart deleted file mode 100644 index 99f2cc2..0000000 --- a/lib/widgets/splash.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/material.dart'; - -class LoadingDialog extends StatelessWidget { - static void show(BuildContext context, {Key key}) => showDialog( - context: context, - useRootNavigator: false, - barrierDismissible: false, - builder: (_) => LoadingDialog(key: key), - ).then((_) => FocusScope.of(context).requestFocus(FocusNode())); - - static void hide(BuildContext context) => Navigator.pop(context); - - LoadingDialog({Key key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async => false, - child: Center( - child: Card( - child: Container( - width: 80, - height: 80, - padding: EdgeInsets.all(12.0), - child: CircularProgressIndicator(backgroundColor: Colors.transparent,), - color: Colors.transparent, - ), - ), - ), - ); - } -} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index e6a2d46..67b11f2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -148,6 +148,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + chewie: + dependency: transitive + description: + name: chewie + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.1+1" + chewie_audio: + dependency: transitive + description: + name: chewie_audio + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" cli_util: dependency: transitive description: @@ -197,6 +211,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.5" + css_colors: + dependency: transitive + description: + name: css_colors + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.2" cupertino_icons: dependency: "direct main" description: @@ -211,20 +239,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.10" - device_info: - dependency: transitive - description: - name: device_info - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.2+10" - device_info_platform_interface: - dependency: transitive - description: - name: device_info_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" devicelocale: dependency: "direct main" description: @@ -329,7 +343,7 @@ packages: name: fl_chart url: "https://pub.dartlang.org" source: hosted - version: "0.12.1" + version: "0.12.2" flurry: dependency: "direct main" description: @@ -349,6 +363,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.1" + flutter_facebook_auth: + dependency: "direct main" + description: + name: flutter_facebook_auth + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2+2" flutter_form_bloc: dependency: "direct main" description: @@ -356,6 +377,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.19.0" + flutter_html: + dependency: "direct main" + description: + name: flutter_html + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" flutter_inapp_purchase: dependency: "direct main" description: @@ -382,6 +410,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + url: "https://pub.dartlang.org" + source: hosted + version: "0.19.1" flutter_test: dependency: "direct dev" description: flutter @@ -441,13 +476,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0" - health: - dependency: "direct main" + html: + dependency: transitive description: - name: health + name: html url: "https://pub.dartlang.org" source: hosted - version: "2.0.9" + version: "0.14.0+4" http: dependency: "direct dev" description: @@ -476,6 +511,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.19" + import_js_library: + dependency: transitive + description: + name: import_js_library + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" infinite_listview: dependency: "direct main" description: @@ -553,6 +595,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.1.3" + modal_progress_hud: + dependency: "direct main" + description: + name: modal_progress_hud + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" nested: dependency: transitive description: @@ -985,6 +1034,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0-nullsafety.3" + video_player: + dependency: transitive + description: + name: video_player + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4+1" vm_service: dependency: transitive description: @@ -992,6 +1062,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.5.0" + wakelock: + dependency: "direct main" + description: + name: wakelock + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1+1" + wakelock_platform_interface: + dependency: transitive + description: + name: wakelock_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+1" + wakelock_web: + dependency: transitive + description: + name: wakelock_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+3" watcher: dependency: transitive description: @@ -1013,6 +1104,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.7.4" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.7" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2e61281..597b0e1 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.2+42 +version: 1.1.3 environment: sdk: ">=2.7.0 <3.0.0" @@ -42,17 +42,20 @@ dependencies: keyboard_actions: ^3.3.1+1 dropdown_search: ^0.4.8 badges: ^1.1.4 - health: ^2.0.9 + #health: ^3.0.0 stop_watch_timer: ^0.6.0+1 #geolocator: ^6.1.13 flutter_inapp_purchase: ^3.0.1 + modal_progress_hud: ^0.1.3 + flutter_html: ^1.1.1 + wakelock: ^0.2.1+1 firebase_core: ^0.5.2 #firebase_analytics: ^6.2.0 firebase_messaging: ^7.0.3 firebase_auth: ^0.18.3 - #flutter_facebook_auth: ^1.0.1 + flutter_facebook_auth: ^1.0.2+2 flurry: ^0.0.7 animated_widgets: ^1.0.6 @@ -85,6 +88,7 @@ flutter_icons: android: "launcher_icon" image_path: "asset/icon/icon.png" + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -102,6 +106,8 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - asset/icon/gomb_kek_a-2.png + - asset/icon/gomb_kek_b.png + - asset/icon/gomb_lila_b.png - asset/icon/gomb_orange_a.png - asset/icon/gomb_orange_c.png - asset/icon/gomb_pink_a.png @@ -131,6 +137,7 @@ flutter: - asset/image/WT_Results_for_female.png - asset/image/WT_Results_for_men.png - asset/image/login_fb.png + - asset/image/fb_registration.png - asset/image/lock.png - asset/image/Congrats_N1.jpg - asset/image/testemfejl400x400.jpg @@ -144,6 +151,7 @@ flutter: - asset/image/predictions.jpg - asset/image/man_sizes.png - asset/image/woman_sizes.png + - asset/image/merleg.png - asset/image/BMI_diagram_b.png - asset/image/BMI_graph_c.png - asset/image/BMI_mutato.png diff --git a/test/widget_test.db.dart b/test/widget_test.db.dart index 49fabf5..383d8d8 100644 --- a/test/widget_test.db.dart +++ b/test/widget_test.db.dart @@ -5,7 +5,7 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:aitrainer_app/bloc/login_form_bloc.dart'; +//import 'package:aitrainer_app/bloc/login_form_bloc.dart'; import 'package:aitrainer_app/helper/database.dart'; import 'package:aitrainer_app/library_keys.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; @@ -26,7 +26,7 @@ void main() { await DB().initDb(); }); - tearDown(() async{ + tearDown(() async { await DB().closeDb(); }); @@ -36,7 +36,5 @@ void main() { {'col1': 2, 'col2': 2} ]); }); - - }); } diff --git a/test/widget_test.login.dart b/test/widget_test.login.dart index c658ba3..18b0607 100644 --- a/test/widget_test.login.dart +++ b/test/widget_test.login.dart @@ -5,7 +5,8 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:aitrainer_app/bloc/login_form_bloc.dart'; +//import 'package:aitrainer_app/bloc/login_form_bloc.dart'; +import 'package:aitrainer_app/bloc/login/login_bloc.dart'; import 'package:aitrainer_app/helper/database.dart'; import 'package:aitrainer_app/library_keys.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; @@ -40,7 +41,7 @@ class MockUserRepository extends Mock implements UserRepository { } } -class MockLoginBloc extends MockBloc implements LoginFormBloc {} +class MockLoginBloc extends MockBloc implements LoginBloc {} class MockCommon with Common { String getEmailError() {