From b193a970b83b953789fe001928c39e0d2ee8fc63 Mon Sep 17 00:00:00 2001 From: Jeremy Guiselin <jeremy.guiselin@student.ecp.fr> Date: Wed, 11 Jan 2017 14:48:48 +0100 Subject: [PATCH] Remains purchase, score, etc... --- .gitignore | 2 + bower.json | 3 +- config.xml | 108 +++++++++++--------- package.json | 4 +- scss/common.scss | 10 ++ scss/header-bar.scss | 2 +- scss/info.scss | 2 +- scss/prediction.scss | 8 +- scss/variables.scss | 1 + www/index.html | 1 - www/js/app.js | 59 ++++++++--- www/js/modules/config/config.js | 70 ++++++++----- www/js/modules/notification/service.js | 68 ++++++++++++ www/js/modules/purchase/service.js | 46 +++++++++ www/js/pages/football/controller.js | 121 ++++++++++++++++------ www/js/pages/football/template.html | 4 +- www/js/pages/info/template.html | 22 ++-- www/js/pages/notifications/controller.js | 72 ++++++++++--- www/js/pages/notifications/template.html | 8 +- www/js/pages/tennis/controller.js | 125 +++++++++++++++++------ www/js/pages/tennis/template.html | 57 +---------- www/manifest.json | 4 + www/partials/prediction.html | 36 +++++++ www/partials/sport-index.html | 23 +++++ 24 files changed, 615 insertions(+), 241 deletions(-) create mode 100644 www/js/modules/notification/service.js create mode 100644 www/js/modules/purchase/service.js create mode 100644 www/manifest.json create mode 100644 www/partials/prediction.html create mode 100644 www/partials/sport-index.html diff --git a/.gitignore b/.gitignore index 01b4ff7..4049a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ node_modules/ platforms/ plugins/ www/lib +www/css +www/dist resources/android resources/ios .idea/ diff --git a/bower.json b/bower.json index 7d75990..84b6527 100644 --- a/bower.json +++ b/bower.json @@ -10,7 +10,8 @@ "ionic": "1.3.1", "ngCordova": "*", "angular-translate": "^2.13.1", - "angular-translate-loader-static-files": "^2.13.1" + "angular-translate-loader-static-files": "^2.13.1", + "ionic-img-cache": "^1.1.1" }, "devDependencies": { "platform.js": "platform#^1.3.1", diff --git a/config.xml b/config.xml index f945800..37f931e 100644 --- a/config.xml +++ b/config.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <widget id="com.jeremyguiselin.betskills" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> - <name>betskills</name> + <name>Betskills</name> <description> - An Ionic Framework and Cordova project. + Betskills app to see predictions of football and tennis games. </description> - <author email="hi@betskills.com" href="http://ionicframework.com/"> + <author email="contact@betskills.com" href=""> Betskills team </author> <content src="index.html"/> @@ -23,68 +23,74 @@ <feature name="StatusBar"> <param name="ios-package" onload="true" value="CDVStatusBar"/> </feature> - <plugin name="cordova-plugin-device" spec="~1.1.2"/> <plugin name="cordova-plugin-console" spec="~1.0.3"/> <plugin name="cordova-plugin-whitelist" spec="~1.2.2"/> <plugin name="cordova-plugin-splashscreen" spec="~3.2.2"/> <plugin name="cordova-plugin-statusbar" spec="~2.1.3"/> <plugin name="ionic-plugin-keyboard" spec="~2.2.1"/> - <plugin name="cordova-plugin-firebase" spec="~0.1.17"/> + <plugin name="cordova-plugin-firebase" spec="~0.1.18"/> + <plugin name="cordova-plugin-device" spec="~1.1.3"/> + <plugin name="cordova-plugin-file-transfer" spec="~1.6.1"/> + <plugin name="cordova-plugin-inapppurchase" spec="~1.1.0"/> <platform name="ios"> <preference name="FadeSplashScreen" value="false"/> <preference name="FadeSplashScreenDuration" value="1000"/> - <splash src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" height="1136"/> - <splash src="resources/ios/splash/Default-667h.png" width="750" height="1334"/> - <splash src="resources/ios/splash/Default-736h.png" width="1242" height="2208"/> - <splash src="resources/ios/splash/Default-Landscape-736h.png" width="2208" height="1242"/> - <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" height="1536"/> - <splash src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" height="768"/> - <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" height="2048"/> - <splash src="resources/ios/splash/Default-Portrait~ipad.png" width="768" height="1024"/> - <splash src="resources/ios/splash/Default@2x~iphone.png" width="640" height="960"/> - <splash src="resources/ios/splash/Default~iphone.png" width="320" height="480"/> - <icon src="resources/ios/icon/icon.png" width="57" height="57"/> - <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/> - <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/> - <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/> - <icon src="resources/ios/icon/icon-40@3x.png" width="120" height="120"/> - <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/> - <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/> - <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/> - <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/> - <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/> - <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/> - <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/> - <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/> - <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/> - <icon src="resources/ios/icon/icon-83.5@2x.png" width="167" height="167"/> - <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/> - <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/> - <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/> + <preference name="iosPersistentFileLocation" value="Library"/> + <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640"/> + <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750"/> + <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242"/> + <splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208"/> + <splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048"/> + <splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024"/> + <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536"/> + <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768"/> + <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640"/> + <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320"/> + <icon height="57" src="resources/ios/icon/icon.png" width="57"/> + <icon height="114" src="resources/ios/icon/icon@2x.png" width="114"/> + <icon height="40" src="resources/ios/icon/icon-40.png" width="40"/> + <icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80"/> + <icon height="120" src="resources/ios/icon/icon-40@3x.png" width="120"/> + <icon height="50" src="resources/ios/icon/icon-50.png" width="50"/> + <icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100"/> + <icon height="60" src="resources/ios/icon/icon-60.png" width="60"/> + <icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120"/> + <icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180"/> + <icon height="72" src="resources/ios/icon/icon-72.png" width="72"/> + <icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144"/> + <icon height="76" src="resources/ios/icon/icon-76.png" width="76"/> + <icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152"/> + <icon height="167" src="resources/ios/icon/icon-83.5@2x.png" width="167"/> + <icon height="29" src="resources/ios/icon/icon-small.png" width="29"/> + <icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58"/> + <icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87"/> </platform> <platform name="android"> <preference name="android-minSdkVersion" value="22"/> <preference name="android-targetSdkVersion" value="22"/> <preference name="SplashMaintainAspectRatio" value="true"/> <preference name="SplashShowOnlyFirstTime" value="false"/> - <splash src="resources/android/splash/drawable-land-ldpi-screen.png" density="land-ldpi"/> - <splash src="resources/android/splash/drawable-land-mdpi-screen.png" density="land-mdpi"/> - <splash src="resources/android/splash/drawable-land-hdpi-screen.png" density="land-hdpi"/> - <splash src="resources/android/splash/drawable-land-xhdpi-screen.png" density="land-xhdpi"/> - <splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" density="land-xxhdpi"/> - <splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" density="land-xxxhdpi"/> - <splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/> - <splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/> - <splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/> - <splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/> - <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/> - <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/> - <icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/> - <icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/> - <icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/> - <icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/> - <icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/> - <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/> + <preference name="AndroidPersistentFileLocation" value="Compatibility"/> + <splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png"/> + <splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png"/> + <splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png"/> + <splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png"/> + <splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png"/> + <splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png"/> + <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png"/> + <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png"/> + <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png"/> + <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png"/> + <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png"/> + <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png"/> + <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png"/> + <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png"/> + <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png"/> + <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png"/> + <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png"/> + <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png"/> + <access origin="cdvfile://*"/> + <allow-intent href="cdvfile://*"/> </platform> <icon src="resources/android/icon/drawable-xhdpi-icon.png"/> </widget> \ No newline at end of file diff --git a/package.json b/package.json index 72a81ff..84d3176 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,10 @@ "description": "betskills: An Ionic project", "dependencies": { "gulp": "^3.5.6", - "gulp-sass": "^2.0.4", "gulp-concat": "^2.2.0", "gulp-minify-css": "^0.3.0", - "gulp-rename": "^1.2.0" + "gulp-rename": "^1.2.0", + "gulp-sass": "^2.0.4" }, "devDependencies": { "bower": "^1.3.3", diff --git a/scss/common.scss b/scss/common.scss index 9d8bc75..646efed 100644 --- a/scss/common.scss +++ b/scss/common.scss @@ -15,3 +15,13 @@ color: #000; border-color: #000; } + +.spinner svg { + width: 19% !important; + height: 85px !important; + fill: transparent !important; +} + +.loading-container .loading { + background-color: transparent !important; +} diff --git a/scss/header-bar.scss b/scss/header-bar.scss index 327e12b..3b4ff58 100644 --- a/scss/header-bar.scss +++ b/scss/header-bar.scss @@ -10,7 +10,7 @@ ion-header-bar.bar.bar-header { border-bottom: 1px solid $bar-border; div { - font-size: 35px; + font-size: 35px !important; font-family: "OspDin"; } } diff --git a/scss/info.scss b/scss/info.scss index 3c87599..928f057 100644 --- a/scss/info.scss +++ b/scss/info.scss @@ -30,7 +30,7 @@ font-family: "SF-UI-Display"; font-size: 17px; color: $blackColor; - text-align: left; + text-align: justify; padding: 0 10px; } } diff --git a/scss/prediction.scss b/scss/prediction.scss index 400860a..14b50d7 100644 --- a/scss/prediction.scss +++ b/scss/prediction.scss @@ -32,18 +32,22 @@ width: 33%; color: #7F7F7E; font-family: "OspDin"; - font-size: 40px; + font-size: 30px; color: #000; .percent { font-family: "Impact"; - font-size: 33px; + font-size: 28px; } } .main-prediction { color: $greenColor; } + + .second-prediction { + color: $orangeColor; + } } .title { diff --git a/scss/variables.scss b/scss/variables.scss index ad885f2..e0b2688 100644 --- a/scss/variables.scss +++ b/scss/variables.scss @@ -30,3 +30,4 @@ $blackColor: black; $darkGreyColor: #4c4b4b; $whiteColor: #fff; $greenColor: #15AC72; +$orangeColor: #eb7c38; diff --git a/www/index.html b/www/index.html index ea20130..04fa107 100644 --- a/www/index.html +++ b/www/index.html @@ -17,7 +17,6 @@ <!-- project js --> <script src="dist/templates.js"></script> <script src="dist/project.js"></script> - </head> <body ng-app="starter"> <ion-nav-bar></ion-nav-bar> diff --git a/www/js/app.js b/www/js/app.js index 87c4cf9..7616ebc 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -6,13 +6,19 @@ "info_title_1": "How to stay connected ?", "info_title_2": "What is Betskills ?", "info_title_3": "How to use Betskills ?", - "info_title_4": "General terms of use", - "who_we_are": "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?", - "how_to_use": "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?", - "legal_terms": "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or pursues or desires to obtain pain of itself, because it is pain, but because occasionally circumstances occur in which toil and pain can procure him some great pleasure. To take a trivial example, which of us ever undertakes laborious physical exercise, except to obtain some advantage from it? But who has any right to find fault with a man who chooses to enjoy a pleasure that has no annoying consequences, or one who avoids a pain that produces no resultant pleasure?", - "facebook_link": "https://www.facebook.com/betskillsuk", + "who_we_are_1": "Betskills aims at combining mathematics and statistical analysis with sport. Our team has developed a powerful algorithm which analyses data from previous games. We are currently focused on Football and Tennis.", + "who_we_are_2": "Regarding football, we provide 6 major European championships per week but also Champions League, a selection of Europa League games and some « exotic » championships or international major tournaments (World Cup, Euro…) during summer.", + "who_we_are_3": "For Tennis, we provide Grand Slams and all the ATP Masters 1000.", + "who_we_are_4": "Our statistics are updated up to 24 hours after the last game.", + "who_we_are_5": "A dozen of parameters are taken into account to proceed our calculations regarding soccer’s outcomes as home/away forms, goals scored/conceded, possession, free kicks... For tennis, we analyse data such as 1st/2nd serve %, winning forehands and backhands, surface, winning returns…", + "how_to_use_1": "We will never provide any winner or draw for any games. Our job is mainly focused on giving tips to our users on the possible game’s outcomes.", + "how_to_use_2": "In order to increase your chances of winning, we advise our users to favour « draw no bet » and double chance ( the 2 highest percentages). Also, we do not suggest you to make combinations of multiple games.", + "how_to_use_3": "When a 2 green ticks are displayed, it means that our prediction was accurate (the final score matches with the highest percentage.", + "how_to_use_4": "When a orange tick is displayed, it means that our prediction was accurate in double chance (the final score matches with the 2 highest percentages).", + "how_to_use_5": "When a red cross is displayed, it means the final score matches with the lowest percentage.", + "facebook_link": "https://facebook.com/betskillsuk", "twitter_link": "https://twitter.com/betskills", - "instagram_link": "https://www.instagram.com/betskills", + "instagram_link": "https://instagram.com/betskills", "daily_predictions": "Daily Predictions", "all_predictions": "All the predictions", "unlock": "Unlock", @@ -22,13 +28,19 @@ "info_title_1": "Comment resté connecté ?", "info_title_2": "Qui sommes-nous ?", "info_title_3": "Comment utiliser Betskills ?", - "info_title_4": "Conditions générales d'utilisation", - "who_we_are": "Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker.", - "how_to_use": "Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker.", - "legal_terms": "Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un peintre anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker.", - "facebook_link": "https://www.facebook.com/betskillsfrance", + "who_we_are_1": "Betskills a pour vocation d’allier les mathématiques et l’analyse statistique au sport. Nous avons développé un algorithme mathématique complexe qui analyse les données des dernières rencontres sportives. Notre activité se concentre principalement aujourd’hui sur le football ainsi que le tennis.", + "who_we_are_2": "Pour le football, nous proposons, chaque week-end et au minimum, 6 championnats majeurs Européens. Mais également l’intégralité de la Ligue des champions, une sélection en Europa League ainsi que certains championnats « exotiques » ou des compétitions internationales majeures (Coupe du monde, Euro…) pendant l’été.", + "who_we_are_3": "Pour le Tennis, nous couvrons l’ensemble des grands chelems ainsi que les ATP masters 1000.", + "who_we_are_4": "Nos statistiques sont mises à jours au maximum 24h après la dernière rencontre du championnat ou de la journée.", + "who_we_are_5": "Notre algorithme prend en compte une douzaine de paramètres pour le football (comme la forme domicile/exterieur, les buts marqués, les buts encaissés, la possession, les coups de pied arrêtés…) et l’ensemble des paramètres disponibles pour le tennis (% de service 1ere et 2eme balles, coups droits gagnants, revers gagnants, la surface, % de retours gagnants…).", + "how_to_use_1": "Nous ne communiquons jamais sur le possible vainqueur d’une rencontre. Nous nous efforçons cependant de conseiller et d’éclairer au maximum nos utilisateurs sur le possible dénouement d’un match. Notre activité s’oriente sur du conseil et de la prédiction plutôt que sur du pronostique.", + "how_to_use_2": "Nous conseillons à l’ensemble de nos utilisateurs de privilégier le « draw no bet » ou la double chance qui consiste à prendre en compte les 2 pourcentages les plus élevés (1 ou N, 2 ou N ou 1 et 1 ou 2). Nous déconseillons également de combiner un trop grand nombre de matchs.", + "how_to_use_3": "Lorsque qu’une rencontre est marquée de 2 ticks verts, cela signifie que notre prédiction est validée (le score finale concorde avec le pourcentage le plus élevé).", + "how_to_use_4": "Lorsqu’une rencontre est marquée d’un tick orange, cela signifie que notre prédiction est validée en double chance (le score finale concorde avec le 2ème pourcentage le plus élevé).", + "how_to_use_5": "Lorsqu’une rencontre est marquée d’une croix rouge, cela signifie que le score concorde avec le pourcentage le plus faible.", + "facebook_link": "https://facebook.com/betskillsfrance", "twitter_link": "https://twitter.com/betskills_fr", - "instagram_link": "https://www.instagram.com/betskills_fr", + "instagram_link": "https://instagram.com/betskills_fr", "daily_predictions": "Prédictions gratuites", "all_predictions": "Toutes les prédictions", "unlock": "Dévérouiller", @@ -39,8 +51,9 @@ /** * @ngInject */ - function setupRun($ionicPlatform) { + function setupRun($ionicPlatform, NotificationService) { $ionicPlatform.ready(function () { + // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard // for form inputs) if (window.cordova && window.cordova.plugins.Keyboard) { @@ -51,6 +64,10 @@ StatusBar.styleDefault(); } }); + + ionic.Platform.ready(function () { + NotificationService.registerDevice(); + }); } function nativeScrolling($ionicConfigProvider) { @@ -78,10 +95,18 @@ 'templatescache', 'ngCordova', 'Config', - 'pascalprecht.translate' + 'pascalprecht.translate', + 'ionicImgCache' ]) .run(setupRun) .config(setupRoutes) + .config(function(ionicImgCacheProvider) { + // Enable imgCache debugging. + ionicImgCacheProvider.debug(true); + + // Set storage size quota to 100 MB. + ionicImgCacheProvider.quota(100); + }) .config(function($ionicConfigProvider, $stateProvider, $urlRouterProvider, $translateProvider) { $ionicConfigProvider.views.maxCache(5); @@ -90,7 +115,11 @@ Object.keys(translations).forEach(function (key) { $translateProvider.translations(key, translations[key]); }); - $translateProvider.preferredLanguage('fr'); + var locale = window.navigator.language.split('-')[0]; + if (locale !== 'fr' && locale !== 'en') { + locale = 'en'; + } + $translateProvider.use(locale); $translateProvider.useSanitizeValueStrategy('escape'); }) diff --git a/www/js/modules/config/config.js b/www/js/modules/config/config.js index cec852f..923db7d 100644 --- a/www/js/modules/config/config.js +++ b/www/js/modules/config/config.js @@ -4,30 +4,54 @@ (function (angular){ "use strict"; - angular.module('Config') - .constant("constantConfig", { - "apiClient": "betskills", - "appStaging": "development", - "apiUrl": "http://betskills.dev/api/", - "imgUrl": "http://betskills.dev/img/application/" - }); - angular.module('Config') - .constant("notificationConfig",{ - 'core': { - 'app_id': 'com.jeremyguiselin.betskills' - }, - 'push': { - 'sender_id': '1006878207346', - 'pluginConfig': { - 'ios': { - 'badge': true, - 'sound': true - }, - 'android': { - 'iconColor': '#343434' - } + + var module = angular.module('Config'); + + module.constant("constantConfig", { + "apiClient": "betskills", + "appStaging": "production", + "apiUrl": "http://backend.betskills.com/api/", + "imgUrl": "http://backend.betskills.com/img/application/" + }); + module.constant("notificationConfig",{ + 'core': { + 'app_id': 'com.jeremyguiselin.betskills' + }, + 'push': { + 'sender_id': '1006878207346', + 'pluginConfig': { + 'ios': { + 'badge': true, + 'sound': true + }, + 'android': { + 'iconColor': '#343434' } } - }); + } + }); + module.constant('purchaseConfig', { + 'tennis': [ + 'tennis', + 'tennis-full-1', + 'tennis-full-2', + 'tennis-full-3', + 'tennis-full-4', + 'tennis-full-5' + ], + 'football': [ + 'ligue-1', + 'premiere-league', + 'bundesliga', + 'liga-bbva', + 'liga-nos', + 'serie-a', + 'champions-league', + 'football-full-3', + 'football-full-4', + 'football-full-5', + 'football-full-6' + ] + }) })(angular); diff --git a/www/js/modules/notification/service.js b/www/js/modules/notification/service.js new file mode 100644 index 0000000..ff61f3b --- /dev/null +++ b/www/js/modules/notification/service.js @@ -0,0 +1,68 @@ +(function (angular) { + "use strict"; + /** + * @ngdoc service + * @name starter.NotificationService + * + * @description + * + * A service for receive notifications and register device. + * + * @ngInject + */ + function NotificationService($http, constantConfig) { + var service = { + + registerDevice: function () { + + var locale = window.navigator.language.split('-')[0]; + if (locale !== 'fr' && locale !== 'en' ) { + locale = 'en'; + } + + ionic.Platform.ready(function () { + var deviceData = {}; + if (window.cordova) { + var device = ionic.Platform.device(); + deviceData = device; + var tokenAlreadyCreated = false; + window.FirebasePlugin.getToken(function (token) { + deviceData = Object.assign(device, {'locale': locale, 'token': token}); + tokenAlreadyCreated = true; + }, function (error) { + }); + + if (!tokenAlreadyCreated) { + window.FirebasePlugin.onTokenRefresh(function (token) { + deviceData = Object.assign(device, {'locale': locale, 'token': token}); + }, function (error) { + }); + } + + } else { + //Mock deviceData + deviceData = { + platform: 'Android', + version: '6.0.1', + model: 'AquarisE5', + uuid: '7f4a6a40e5c87157', + locale: locale, + token: 'cNgyx3ZgOX4:APA91bF5eigDuJLjj8wI8SC4l5KIHATuxi-2G5whpWI1n1jWpWWwRAwbEXec4fQ2S7HW8EdUPaREXJ5fVd_TZV8rZq_eIJIEhEadeH9wpsbYmUUM7E8H8Y0Qst9KmBuHWodCFFJPJ0vh' + } + } + $http.post(constantConfig.apiUrl + 'devices/register', deviceData) + .then(function successCallback() { + }, function errorCallback() { + }); + }); + } + }; + + return service; + + } + + angular.module('starter') + .service('NotificationService', NotificationService) + ; +})(angular); diff --git a/www/js/modules/purchase/service.js b/www/js/modules/purchase/service.js new file mode 100644 index 0000000..beb65c7 --- /dev/null +++ b/www/js/modules/purchase/service.js @@ -0,0 +1,46 @@ +(function (angular) { + "use strict"; + /** + * @ngdoc service + * @name starter.PurchaseService + * + * @description + * + * A service for purchasing products + * + * @ngInject + */ + function PurchaseService($http, $cordovaToast, constantConfig, purchaseConfig) { + var service = { + + getProducts: function (sport) { + if (window.cordova) { + var products = []; + inAppPurchase + .getProducts(purchaseConfig[sport]) + .then(function (storeProducts) { + products = storeProducts; + }) + .catch(function (err) { + $cordovaToast + .showLongBottom(err) + .then(function(success) { + // success + }, function (error) { + console.log(error); + }); + }); + } + + return []; + } + }; + + return service; + + } + + angular.module('starter') + .service('PurchaseService', PurchaseService) + ; +})(angular); diff --git a/www/js/pages/football/controller.js b/www/js/pages/football/controller.js index c43f010..4576181 100644 --- a/www/js/pages/football/controller.js +++ b/www/js/pages/football/controller.js @@ -7,10 +7,10 @@ /** * @ngdoc controller - * @name ChoiceController + * @name FootballController * * @description - * Controller for the choice of sport page. + * Controller for the football page. * * @ngInject */ @@ -18,17 +18,82 @@ $ionicHistory, $scope, $http, + $q, + $ionicLoading, constantConfig ) { + /** + Static variables + **/ + var deregistrationCallbackList = []; + /** + End Controller variables + **/ + + /** + Scope variables + **/ + + $scope.pictureUrl = constantConfig.imgUrl; + $scope.locale = window.navigator.language.split('-')[0]; + $scope.selected = []; + $scope.price = 0; + + /** + End Scope variables + **/ + + /** + Scope functions + **/ + + $scope.isBought = function (id) { + return null; + } + + $scope.isSelected = function (league) { + return $scope.selected.indexOf(league) !== -1; + } + + $scope.select = function (league) { + if ($scope.isBought(league.id) === null) { + if ($scope.selected.indexOf(league) !== -1) { + $scope.selected.splice($scope.selected.indexOf(league), 1); + } else { + $scope.selected.push(league); + } + } + } + + $scope.getPredictionClass = function (prediction, value) { + var percentages = [prediction.prediction_win_first, prediction.prediction_win_second, prediction.prediction_draw]; + percentages.sort(); + if (percentages.indexOf(value) === 2) { + return "main-prediction"; + } else if (percentages.indexOf(value) === 1) { + return "second-prediction"; + } + + return ''; + } + + /** + End Scope functions + **/ + + /** + Scope events + **/ + deregistrationCallbackList.push( $scope.$on('$ionicView.afterEnter', function(){ $ionicHistory.clearHistory(); }) ); - // cleanup + $scope.$on('$destroy', function(){ angular.forEach(deregistrationCallbackList, function(deregistrationCallback){ deregistrationCallback(); @@ -36,38 +101,28 @@ deregistrationCallbackList = null; }); - var deviceData = {}; - - ionic.Platform.ready(function () { - if (window.cordova) { - var device = ionic.Platform.device(); - window.FirebasePlugin.getToken(function (token) { - deviceData = Object.assign(device, {'token': token}); - }, function (error) { - $scope.deviceData = error; - }); - window.FirebasePlugin.onTokenRefresh(function (token) { - deviceData = Object.assign(device, {'token': token}); - }, function (error) { - $scope.deviceData = error; - }); - } else { - //Mock deviceData - deviceData = { - platform: 'Android', - version: '6.0.1', - model: 'AquarisE5', - uuid: '7f4a6a40e5c87158', - token: 'cNgyx3ZgOX4:APA91bF5eigDuJLjj8wI8SC4l5KIHATuxi-2G5whpWI1n1jWpWWwRAwbEXec4fQ2S7HW8EdUPaREXJ5fVd_TZV8rZq_eIJIEhEadeH9wpsbYmUUM7E8H8Y0Qst9KmBuHWodCFFJPJ0vh' - } - } - $http.post(constantConfig.apiUrl + 'devices/register', deviceData) - .then(function successCallback() { - $state.go('tabs.football'); - }, function errorCallback() { - }); + + $scope.$on("$ionicView.beforeEnter", function(event, data){ + $ionicLoading.show({ + template: '<ion-spinner icon="ripple" class="spinner-assertive"></ion-spinner>', + animation: 'fade-in', + showBackdrop: true, + }); + + var freePredictionsPromise = $http.get(constantConfig.apiUrl + 'predictions/football/free'); + var leaguesPromise = $http.get(constantConfig.apiUrl + 'leagues/football'); + + $q.all([freePredictionsPromise, leaguesPromise]).then(function (data) { + $scope.freePredictions = data[0]['data']; + $scope.leagues = data[1]['data']; + }).finally(function () { + $ionicLoading.hide(); + }); }); + /** + End Scope event + **/ } angular.module('starter') diff --git a/www/js/pages/football/template.html b/www/js/pages/football/template.html index d1dd4ae..f06d442 100644 --- a/www/js/pages/football/template.html +++ b/www/js/pages/football/template.html @@ -1,8 +1,8 @@ -<ion-view cache-view="false" title="Football"> +<ion-view cache-view="true" title="Football"> <ion-nav-buttons side="right"> <img ui-sref="info" class="info-icon" src="img/info.png" alt="info"> </ion-nav-buttons> <ion-content class="has-header"> - <h1>Football</h1> + <div ng-include src="'partials/sport-index.html'"></div> </ion-content> </ion-view> diff --git a/www/js/pages/info/template.html b/www/js/pages/info/template.html index af0d011..a029b9b 100644 --- a/www/js/pages/info/template.html +++ b/www/js/pages/info/template.html @@ -1,28 +1,34 @@ -<ion-view cache-view="false" title="Info"> +<ion-view cache-view="true" can-swipe-back="true" title="Info"> <ion-nav-buttons side="left"> <img class="info-icon" ng-click="myGoBack()" src="img/back.png" alt=""> </ion-nav-buttons> <ion-content class="has-header info"> <h3 class="title-section" translate="info_title_1"></h3> <div class="social-networks"> - <a target="_system" href='{{"instagram_link"|translate}}'> + <a ng-href='{{"instagram_link"|translate}}' onclick="window.open(this.href, '_system', 'location=yes'); return false;"> <img src="img/instagram.png"> <p>Instagram</p> </a> - <a target="_system" href='{{"facebook_link"|translate}}'> + <a ng-href='{{"facebook_link"|translate}}' onclick="window.open(this.href, '_system', 'location=yes'); return false;"> <img src="img/facebook.png"> <p>Facebook</p> </a> - <a target="_system" href='{{"twitter_link"|translate}}'> + <a ng-href='{{"twitter_link"|translate}}' onclick="window.open(this.href, '_system', 'location=yes'); return false;"> <img src="img/twitter.png"> <p>Twitter</p> </a> </div> <h3 class="title-section" translate="info_title_2"></h3> - <p class="content" translate="who_we_are"></p> + <p class="content" translate="who_we_are_1"></p> + <p class="content" translate="who_we_are_2"></p> + <p class="content" translate="who_we_are_3"></p> + <p class="content" translate="who_we_are_4"></p> + <p class="content" translate="who_we_are_5"></p> <h3 class="title-section" translate="info_title_3"></h3> - <p class="content" translate="how_to_use"></p> - <h3 class="title-section" translate="info_title_4"></h3> - <p class="content" translate="legal_terms"></p> + <p class="content" translate="how_to_use_1"></p> + <p class="content" translate="how_to_use_2"></p> + <p class="content" translate="how_to_use_3"></p> + <p class="content" translate="how_to_use_4"></p> + <p class="content" translate="how_to_use_5"></p> </ion-content> </ion-view> diff --git a/www/js/pages/notifications/controller.js b/www/js/pages/notifications/controller.js index 1cfe01d..62e386e 100644 --- a/www/js/pages/notifications/controller.js +++ b/www/js/pages/notifications/controller.js @@ -18,20 +18,45 @@ constantConfig, $ionicHistory, $scope, + $ionicLoading, $http ) { + /** + Scope variables + **/ + + $scope.locale = window.navigator.language.split('-')[0]; + + /** + End Scope variables + **/ + + /** + Controller variables + **/ + this.status = []; + + /** + End Controller variables + **/ + + /** + Static variables + **/ + var self = this; var deregistrationCallbackList = []; + var uuid = window.cordova ? ionic.Platform.device().uuid : '7f4a6a40e5c87157'; - var uuid = ''; + /** + End Static variables + **/ - if (window.cordova) { - uuid = ionic.Platform.device().uuid; - } else { - uuid = '7f4a6a40e5c87158'; - } + /** + Controller functions + **/ this.findNotificationStatus = function(id) { var notificationStatus = 'read'; @@ -43,6 +68,14 @@ return notificationStatus; }; + /** + End Controller functions + **/ + + /** + Scope events + **/ + deregistrationCallbackList.push( $scope.$on('$ionicView.afterEnter', function(){ $ionicHistory.clearHistory(); @@ -60,14 +93,27 @@ deregistrationCallbackList = null; }); - $http - .get(constantConfig.apiUrl + 'notifications/' + uuid) - .then(function successCallback(response) { - self.status = response['data']['status']; - $scope.notifications = response['data']['notifications']; - }, function errorCallback() { - $scope.notifications = []; + $scope.$on("$ionicView.beforeEnter", function(event, data){ + $ionicLoading.show({ + template: '<ion-spinner icon="ripple" class="spinner-assertive"></ion-spinner>', + animation: 'fade-in', + showBackdrop: true, }); + $http + .get(constantConfig.apiUrl + 'notifications/' + uuid) + .then(function successCallback(response) { + self.status = response['data']['status']; + $scope.notifications = response['data']['notifications']; + }, function errorCallback() { + $scope.notifications = []; + }).finally(function () { + $ionicLoading.hide(); + }); + }); + + /** + End Scope events + **/ } angular.module('starter') diff --git a/www/js/pages/notifications/template.html b/www/js/pages/notifications/template.html index fafb9f5..f9c2cf2 100644 --- a/www/js/pages/notifications/template.html +++ b/www/js/pages/notifications/template.html @@ -1,4 +1,4 @@ -<ion-view cache-view="false" title="Notifications"> +<ion-view cache-view="true" title="Notifications"> <ion-nav-buttons side="right"> <img ui-sref="info" class="info-icon" src="img/info.png" alt="info"> </ion-nav-buttons> @@ -7,10 +7,10 @@ <ion-item ng-repeat="notification in notifications" class="notification-item"> <div class="title"> <div ng-hide="notificationCtrl.findNotificationStatus(notification.id) == 'read'" class="green-circle"></div> - {{ notification.title }} + {{ locale === 'fr' ? notification.french_title : notification.english_title }} </div> - <div class="date">{{notification.date | date: 'shortDate'}}</div> - <div class="content">{{ notification.content}}</div> + <div class="date">{{locale === 'fr' ? (notification.date | date: "dd/MM/yy") : (notification.date | date: "MM/dd/yy")}}</div> + <div class="content">{{ locale === 'fr' ? notification.french_content : notification.english_content}}</div> </ion-item> </ion-list> </ion-content> diff --git a/www/js/pages/tennis/controller.js b/www/js/pages/tennis/controller.js index ccb61bc..8732fd9 100644 --- a/www/js/pages/tennis/controller.js +++ b/www/js/pages/tennis/controller.js @@ -18,49 +18,45 @@ $ionicHistory, $scope, $http, + $q, + $ionicLoading, + PurchaseService, constantConfig ) { + + /** + Static variables + **/ + var deregistrationCallbackList = []; + var products = PurchaseService.getProducts('tennis'); - deregistrationCallbackList.push( - $scope.$on('$ionicView.afterEnter', function(){ - $ionicHistory.clearHistory(); - }) - ); + /** + End Controller variables + **/ - // cleanup - $scope.$on('$destroy', function(){ - angular.forEach(deregistrationCallbackList, function(deregistrationCallback){ - deregistrationCallback(); - }); - deregistrationCallbackList = null; - }); + /** + Scope variables + **/ $scope.pictureUrl = constantConfig.imgUrl; + $scope.locale = window.navigator.language.split('-')[0]; + $scope.selected = []; + $scope.price = 0; + $scope.predictionsNumber = 0; - $http - .get(constantConfig.apiUrl + 'predictions/tennis/free') - .then(function successCallback(response) { - $scope.freePredictions = response['data']; - }, function errorCallback() { - $scope.freePredictions = []; - }); + /** + End Scope variables + **/ - $http - .get(constantConfig.apiUrl + 'leagues/tennis') - .then(function successCallback(response) { - $scope.leagues = response['data']; - }, function errorCallback() { - $scope.leagues = []; - }); + /** + Scope functions + **/ $scope.isBought = function (id) { return null; } - $scope.selected = []; - $scope.price = 0; - $scope.isSelected = function (league) { return $scope.selected.indexOf(league) !== -1; } @@ -69,11 +65,82 @@ if ($scope.isBought(league.id) === null) { if ($scope.selected.indexOf(league) !== -1) { $scope.selected.splice($scope.selected.indexOf(league), 1); + $scope.predictionsNumber -= league.predictionsNumber; } else { $scope.selected.push(league); + $scope.predictionsNumber += league.predictionsNumber; } } } + + $scope.getPredictionClass = function (prediction, value) { + var percentages = [ + prediction.prediction_win_first, + prediction.prediction_win_second, + prediction.prediction_draw + ]; + percentages.sort(); + if (percentages.indexOf(value) === 1) { + return "main-prediction"; + } + + return ''; + } + + $scope.buyContent = function () { + var selectedPack = ''; + if ($scope.selected.length === 1) { + selectedPack = 'tennis'; + } else if($scope.selected.length > 1) { + selectedPack = 'tennis-full-'+ $scope.selected.length; + } + } + + /** + End Scope functions + **/ + + /** + Scope events + **/ + + deregistrationCallbackList.push( + $scope.$on('$ionicView.afterEnter', function(){ + $ionicHistory.clearHistory(); + }) + ); + + + $scope.$on('$destroy', function(){ + angular.forEach(deregistrationCallbackList, function(deregistrationCallback){ + deregistrationCallback(); + }); + deregistrationCallbackList = null; + }); + + + $scope.$on("$ionicView.beforeEnter", function(event, data){ + $ionicLoading.show({ + template: '<ion-spinner icon="ripple" class="spinner-assertive"></ion-spinner>', + animation: 'fade-in', + showBackdrop: true, + }); + + var freePredictionsPromise = $http.get(constantConfig.apiUrl + 'predictions/tennis/free'); + var leaguesPromise = $http.get(constantConfig.apiUrl + 'leagues/tennis'); + + $q.all([freePredictionsPromise, leaguesPromise]).then(function (data) { + $scope.freePredictions = data[0]['data']; + $scope.leagues = data[1]['data']; + }).finally(function () { + $ionicLoading.hide(); + }); + }); + + /** + End Scope event + **/ + } angular.module('starter') diff --git a/www/js/pages/tennis/template.html b/www/js/pages/tennis/template.html index d74bd61..20b227c 100644 --- a/www/js/pages/tennis/template.html +++ b/www/js/pages/tennis/template.html @@ -1,61 +1,8 @@ -<ion-view cache-view="false" title="Tennis"> +<ion-view cache-view="true" title="Tennis"> <ion-nav-buttons side="right"> <img ui-sref="info" class="info-icon" src="img/info.png" alt="info"> </ion-nav-buttons> <ion-content class="has-header"> - <h3 class="title-section" translate="daily_predictions"></h3> - <ion-list> - <ion-item ng-repeat="freePrediction in freePredictions" class="prediction"> - <div class="team"> - <img src="{{pictureUrl}}team/{{getPicturePath(freePrediction.first_team.name)}}.png" /> - <div class="name">{{freePrediction.first_team.name}}</div> - </div> - <div class="center"> - <div class="title"> - {{ freePrediction.league.name }} - <span class="date">{{freePrediction.date | date: 'shortDate'}}</span> - </div> - <div class="figures"> - <div class="figure">1</div> - <div class="figure"></div> - <div class="figure">2</div> - </div> - <div class="prediction_figures"> - <div - class="prediction_figure" - ng-class="freePrediction.prediction_win_first > freePrediction.prediction_win_second ? 'main-prediction' : ''"> - {{freePrediction.prediction_win_first}}<span class="percent">%</span> - </div> - <div class="prediction_figure"></div> - <div - class="prediction_figure" - ng-class="freePrediction.prediction_win_second > freePrediction.prediction_win_first ? 'main-prediction' : ''"> - {{freePrediction.prediction_win_second}}<span class="percent">%</span> - </div> - </div> - </div> - <div class="team"> - <img src="{{pictureUrl}}{{getPicturePath(freePrediction.second_team.name)}}.png" /> - <div class="name">{{freePrediction.second_team.name}}</div> - </div> - </ion-item> - </ion-list> - <h3 class="title-section" translate="all_predictions"></h3> - <ion-list> - <ion-item ng-repeat="league in leagues" class="pack-item"> - <a ui-sref="{{isBought(league.id)}}" ng-click="select(league)"> - <div class="selected-pack" ng-class="{active : isSelected(league)}" > - <img src="img/white-check.png" /> - </div> - <div class="pack-background" style="background-image: url('league.picture_path')"> - <div class="title">{{league.name}}</div> - </div> - </a> - </ion-item> - </ion-list> - <div class="unlock" ng-class="{active : selected.length > 0}"> - <a ui-sref="" class="content"> - {{"unlock" | translate}} {{"predictions" | translate}} <span>{{price / 100}}€</span> - </div> - </div> + <div ng-include src="'partials/sport-index.html'"></div> </ion-content> </ion-view> diff --git a/www/manifest.json b/www/manifest.json new file mode 100644 index 0000000..f7f0137 --- /dev/null +++ b/www/manifest.json @@ -0,0 +1,4 @@ +{ + "play_store_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs06saHKaKvyRbwiZOtg9sTM0nn8q3cjoQbVJK0jOEDDG9q4cB852cYYROBYDFwUCM0Yz2oSOZ0SBEVBpUxDcMu9tasH9EekLbjBSC15bLJIx44mqsWL1CkOo/Z19B81IITJ7v7Hz3adst5PAvi5OgZiJSrlEMJlKPrQwSFy9do6NeVwixxbdWlzbf8fcLL2RTiQgJVt7+SGzgjgaiGjGGZRN1sYKhIk8k6vgj7pgV1vRM5crVGnnQKf6AIBfkymsfMQTcoUF/StSEBuMOEjHZs/dmYI1GFrdUbFQK/EsLDv6PDUaMYvGKvr8lqdkcEYiKp/BQ7Db7UMuiWUUjtl4QwIDAQAB +" +} diff --git a/www/partials/prediction.html b/www/partials/prediction.html new file mode 100644 index 0000000..918ad32 --- /dev/null +++ b/www/partials/prediction.html @@ -0,0 +1,36 @@ +<div class="team"> + <img ion-img-cache ng-src="{{pictureUrl}}team/{{freePrediction.first_team.picture}}" /> + <div class="name">{{freePrediction.first_team.name}}</div> +</div> +<div class="center"> + <div class="title"> + {{ freePrediction.league.name }} - <span class="date">{{locale === 'fr' ? (freePrediction.date | date: "dd/MM/yy") : (notification.date | date: "MM/dd/yy")}}</span> + </div> + <div class="figures"> + <div class="figure">1</div> + <div class="figure">{{freePrediction.league.sport === "football" ? 'N' : '' }}</div> + <div class="figure">2</div> + </div> + <div class="prediction_figures"> + <div + class="prediction_figure" + ng-class="getPredictionClass(freePrediction, freePrediction.prediction_win_first)"> + {{freePrediction.prediction_win_first}}<span class="percent">%</span> + </div> + <div + class="prediction_figure" + ng-class="getPredictionClass(freePrediction, freePrediction.prediction_draw)" + style="{{!freePrediction.prediction_draw ? 'opacity: 0' : ''}}"> + {{freePrediction.prediction_draw}}<span class="percent">%</span> + </div> + <div + class="prediction_figure" + ng-class="getPredictionClass(freePrediction, freePrediction.prediction_win_second)"> + {{freePrediction.prediction_win_second}}<span class="percent">%</span> + </div> + </div> +</div> +<div class="team"> + <img ion-img-cache ng-src="{{pictureUrl}}team/{{freePrediction.second_team.picture}}" /> + <div class="name">{{freePrediction.second_team.name}}</div> +</div> diff --git a/www/partials/sport-index.html b/www/partials/sport-index.html new file mode 100644 index 0000000..463fd42 --- /dev/null +++ b/www/partials/sport-index.html @@ -0,0 +1,23 @@ +<h3 class="title-section" translate="daily_predictions"></h3> +<ion-list> + <ion-item ng-include src="'partials/prediction.html'" ng-repeat="freePrediction in freePredictions track by freePrediction.id" class="prediction"> + </ion-item> +</ion-list> +<h3 class="title-section" translate="all_predictions"></h3> +<ion-list> + <ion-item ng-repeat="league in leagues track by league.id" class="pack-item"> + <a ng-click="select(league)"> + <div class="selected-pack" ng-class="{active : isSelected(league)}" > + <img src="img/white-check.png" /> + </div> + <div ion-img-cache-bg class="pack-background" ng-style="{'background-image':'url({{pictureUrl}}league/{{league.picture}})'}"> + <div class="title">{{league.name}}</div> + </div> + </a> + </ion-item> +</ion-list> +<div class="unlock" ng-class="{active : selected.length > 0}"> + <a class="content" ng-click="buyContent()"> + {{"unlock" | translate}} {{predictions}} {{"predictions" | translate}} <span>{{price / 100}}€</span> + </div> +</div> -- GitLab