diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index 64ffd4a..a8bd7ac 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -14,6 +14,7 @@ dependencies { implementation project(':capacitor-filesystem') implementation project(':capacitor-haptics') implementation project(':capacitor-keyboard') + implementation project(':capacitor-splash-screen') implementation project(':capacitor-status-bar') implementation project(':capacitor-storage') diff --git a/android/app/src/main/assets/capacitor.config.json b/android/app/src/main/assets/capacitor.config.json index 8b46e6b..9899f21 100644 --- a/android/app/src/main/assets/capacitor.config.json +++ b/android/app/src/main/assets/capacitor.config.json @@ -2,5 +2,22 @@ "appId": "com.linnettchristopher.apneaelearning", "appName": "ApneaElearning", "webDir": "www", - "bundledWebRuntime": false + "bundledWebRuntime": false, + "plugins": { + "SplashScreen": { + "launchShowDuration": 3000, + "launchAutoHide": true, + "backgroundColor": "#ffffffff", + "androidSplashResourceName": "splash", + "androidScaleType": "CENTER_CROP", + "showSpinner": true, + "androidSpinnerStyle": "large", + "iosSpinnerStyle": "small", + "spinnerColor": "#999999", + "splashFullScreen": true, + "splashImmersive": true, + "layoutName": "launch_screen", + "useDialog": true + } + } } diff --git a/android/app/src/main/assets/capacitor.plugins.json b/android/app/src/main/assets/capacitor.plugins.json index 9b7f5b4..f72ad89 100644 --- a/android/app/src/main/assets/capacitor.plugins.json +++ b/android/app/src/main/assets/capacitor.plugins.json @@ -19,6 +19,10 @@ "pkg": "@capacitor/keyboard", "classpath": "com.capacitorjs.plugins.keyboard.KeyboardPlugin" }, + { + "pkg": "@capacitor/splash-screen", + "classpath": "com.capacitorjs.plugins.splashscreen.SplashScreenPlugin" + }, { "pkg": "@capacitor/status-bar", "classpath": "com.capacitorjs.plugins.statusbar.StatusBarPlugin" diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index b3cb0c1..82bcec6 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -17,6 +17,9 @@ project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/ include ':capacitor-keyboard' project(':capacitor-keyboard').projectDir = new File('../node_modules/@capacitor/keyboard/android') +include ':capacitor-splash-screen' +project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android') + include ':capacitor-status-bar' project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') diff --git a/capacitor.config.ts b/capacitor.config.ts index 4267aa0..9d027da 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -4,7 +4,24 @@ const config: CapacitorConfig = { appId: 'com.linnettchristopher.apneaelearning', appName: 'ApneaElearning', webDir: 'www', - bundledWebRuntime: false + bundledWebRuntime: false, + plugins: { + SplashScreen: { + launchShowDuration: 3000, + launchAutoHide: true, + backgroundColor: "#ffffffff", + androidSplashResourceName: "splash", + androidScaleType: "CENTER_CROP", + showSpinner: true, + androidSpinnerStyle: "large", + iosSpinnerStyle: "small", + spinnerColor: "#999999", + splashFullScreen: true, + splashImmersive: true, + layoutName: "launch_screen", + useDialog: true, + }, + }, }; export default config; diff --git a/ios/App/Podfile b/ios/App/Podfile index 8ba5807..f4f8eeb 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -9,13 +9,14 @@ install! 'cocoapods', :disable_input_output_paths => true def capacitor_pods pod 'Capacitor', :path => '../../node_modules/@capacitor/ios' pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios' - pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app' - pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera' - pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem' - pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics' - pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard' - pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar' - pod 'CapacitorStorage', :path => '../../node_modules/@capacitor/storage' + pod 'CapacitorApp', :path => '..\..\node_modules\@capacitor\app' + pod 'CapacitorCamera', :path => '..\..\node_modules\@capacitor\camera' + pod 'CapacitorFilesystem', :path => '..\..\node_modules\@capacitor\filesystem' + pod 'CapacitorHaptics', :path => '..\..\node_modules\@capacitor\haptics' + pod 'CapacitorKeyboard', :path => '..\..\node_modules\@capacitor\keyboard' + pod 'CapacitorSplashScreen', :path => '..\..\node_modules\@capacitor\splash-screen' + pod 'CapacitorStatusBar', :path => '..\..\node_modules\@capacitor\status-bar' + pod 'CapacitorStorage', :path => '..\..\node_modules\@capacitor\storage' end target 'App' do diff --git a/package-lock.json b/package-lock.json index e003ed5..c52709f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@capacitor/haptics": "1.1.4", "@capacitor/ios": "3.5.0", "@capacitor/keyboard": "1.2.2", + "@capacitor/splash-screen": "^1.2.2", "@capacitor/status-bar": "1.0.8", "@capacitor/storage": "^1.2.5", "@ionic/angular": "^6.0.0", @@ -2421,6 +2422,14 @@ "@capacitor/core": "^3.0.0" } }, + "node_modules/@capacitor/splash-screen": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-1.2.2.tgz", + "integrity": "sha512-iGh9gc0rdS3R+Wr+bD/+tJl3qbmJZ5xVQAP5UsD6U6Y3ydCBo9KpA8DEqxaBZVsCDaLt67009hK5nxKBwjRn7Q==", + "peerDependencies": { + "@capacitor/core": "^3.0.0" + } + }, "node_modules/@capacitor/status-bar": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-1.0.8.tgz", @@ -18188,6 +18197,12 @@ "integrity": "sha512-dOZSXJTY/tTbRQ+Neiny72BIXN2Hvf/2AgPpMdTErDfaQM7C2MMgtJrm+Mi+YUeT6AnJFmt68nHJGImAL4lzmA==", "requires": {} }, + "@capacitor/splash-screen": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-1.2.2.tgz", + "integrity": "sha512-iGh9gc0rdS3R+Wr+bD/+tJl3qbmJZ5xVQAP5UsD6U6Y3ydCBo9KpA8DEqxaBZVsCDaLt67009hK5nxKBwjRn7Q==", + "requires": {} + }, "@capacitor/status-bar": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-1.0.8.tgz", diff --git a/package.json b/package.json index f3e4146..2c279e8 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@capacitor/haptics": "1.1.4", "@capacitor/ios": "3.5.0", "@capacitor/keyboard": "1.2.2", + "@capacitor/splash-screen": "^1.2.2", "@capacitor/status-bar": "1.0.8", "@capacitor/storage": "^1.2.5", "@ionic/angular": "^6.0.0", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 5e26e95..975616e 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -13,11 +13,6 @@ const routes: Routes = [ loadChildren: () => import('./users/login/login.module').then((m) => m.LoginPageModule), }, - { - path: 'quizlanding', - loadChildren: () => - import('./quiz/landing/landing.module').then((m) => m.LandingPageModule), - }, { path: 'in-progress', loadChildren: () => diff --git a/src/app/app.component.ts b/src/app/app.component.ts index f8cc37a..751e774 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,6 +2,8 @@ import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { ModalController } from '@ionic/angular'; import { LoginPage } from './users/login/login.page'; import { UserService } from './users/user.service'; +import { SplashScreen } from '@capacitor/splash-screen'; + @Component({ selector: 'app-root', templateUrl: 'app.component.html', @@ -13,7 +15,10 @@ export class AppComponent implements OnInit { private userService: UserService ) {} - ngOnInit(): void { - } + async ngOnInit(): Promise { + await SplashScreen.show({ + autoHide: true + }); +} } diff --git a/src/app/course-landing/course-landing.page.html b/src/app/course-landing/course-landing.page.html index 4f429a1..594b747 100644 --- a/src/app/course-landing/course-landing.page.html +++ b/src/app/course-landing/course-landing.page.html @@ -2,14 +2,9 @@ {{thisCourse.title}} Course - + + + @@ -37,18 +32,35 @@ - Chapter Selection + Review - - - Chapter {{chapter+1}} - - +
+ + + + Chapter Selection + + + + Chapter {{chapter+1}} + + + + + + Available Quizzes + + + + Chapter {{quizNo + 1}} Quiz + + + + +
- {{thisCourse.unlockedChapters.length > 1 ? "Continue Course" : "Start Course"}} - - Quiz - - + + {{thisCourse.unlockedChapters.length > 1 ? "Continue Course" : "Start Course"}} + \ No newline at end of file diff --git a/src/app/course-landing/course-landing.page.ts b/src/app/course-landing/course-landing.page.ts index dfcd646..e695d19 100644 --- a/src/app/course-landing/course-landing.page.ts +++ b/src/app/course-landing/course-landing.page.ts @@ -27,6 +27,15 @@ export class CourseLandingPage implements OnInit { this.thisAvailableChapters = this.thisCourse.unlockedChapters } + async launchModuleQuiz(moduleNo){ + this.currentModuleService.currentModuleIndex = moduleNo + const quizmodal = await this.modalController.create({ + component: InProgressPage, + cssClass: 'my-custom-class' + }); + return await quizmodal.present(); + } + ngOnInit() { console.log(this.thisCourse) @@ -46,10 +55,6 @@ export class CourseLandingPage implements OnInit { modal.onDidDismiss().then(() => {}); return modal.present(); } - - launchQuiz() { - this.router.navigate(['/app-landing']); //move to quiz in progress page - } async showUserOptions() { //logs out user diff --git a/src/app/quiz/in-progress/in-progress.page.ts b/src/app/quiz/in-progress/in-progress.page.ts index 20ef109..755c569 100644 --- a/src/app/quiz/in-progress/in-progress.page.ts +++ b/src/app/quiz/in-progress/in-progress.page.ts @@ -3,7 +3,7 @@ import { Answer, Question } from '../question'; import SwiperCore, { EffectCoverflow } from 'swiper'; import { ViewChild } from '@angular/core'; import { SwiperComponent } from 'swiper/angular'; -import { IonRadioGroup, ModalController } from '@ionic/angular'; +import { AlertController, IonRadioGroup, ModalController } from '@ionic/angular'; import { AfterContentChecked } from '@angular/core'; import { CurrentModuleService } from "../../content/detail-content/current-module.service" import { CourseService } from 'src/app/course-landing/course.service'; @@ -34,7 +34,7 @@ export class InProgressPage implements OnInit{ * created to keep track of the current module that the user is on. * @param {CourseService} courseService - This is a service that contains the course object. */ - constructor(private modalController:ModalController ,private dataStorageService: DatastorageService, private currentModuleService: CurrentModuleService, private courseService:CourseService, private userService: UserService) { + constructor(private alertController: AlertController, private modalController:ModalController ,private dataStorageService: DatastorageService, private currentModuleService: CurrentModuleService, private courseService:CourseService, private userService: UserService) { this.chapterIndex = this.currentModuleService.currentModuleIndex this.course = courseService.getCourse() } @@ -97,14 +97,32 @@ export class InProgressPage implements OnInit{ } } if (userScore/correctAnswers.length > 0.75){ + if (!this.userService.user.availableCourses[`${this.course.courseID}`].unlockedChapters.includes(this.chapterIndex+1)){ this.userService.user.availableCourses[`${this.course.courseID}`].unlockedChapters.push(this.chapterIndex+1) var allUsers = await this.dataStorageService.lookup('users') allUsers[`${this.userService.user.email}`] = this.userService.user await this.dataStorageService.save('users',allUsers) - this.modalController.dismiss() + } + await this.finishedQuiz(true) + } else { + await this.finishedQuiz(false) } + this.modalController.dismiss() + } + async finishedQuiz(success: boolean) { + const alert = await this.alertController.create({ + cssClass: 'my-custom-class', + header: 'Quiz Completed', + subHeader: success ? 'Nice Work' : 'sorry, that did not go as planned', + message: success ? 'You successfully completed the quiz, you have unlocked the next chapter' : 'Please review this chapter, and retry the quiz from there', + buttons: ['OK'] + }); + + await alert.present(); } + + /** * For each question in the quiz, if the question has been answered and the answer is correct, add an * object to the results array with a property of correct set to true. Otherwise, add an object to @@ -119,7 +137,4 @@ export class InProgressPage implements OnInit{ } this.allQuestionsAnswered = true } - - ngAfterContentChanged() { - } } diff --git a/src/app/quiz/landing/landing-routing.module.ts b/src/app/quiz/landing/landing-routing.module.ts deleted file mode 100644 index ad48ed3..0000000 --- a/src/app/quiz/landing/landing-routing.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; - -import { LandingPage } from './landing.page'; - -const routes: Routes = [ - { - path: '', - component: LandingPage, - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class LandingPageRoutingModule {} diff --git a/src/app/quiz/landing/landing.module.ts b/src/app/quiz/landing/landing.module.ts deleted file mode 100644 index 14c0527..0000000 --- a/src/app/quiz/landing/landing.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -import { IonicModule } from '@ionic/angular'; - -import { LandingPageRoutingModule } from './landing-routing.module'; - -import { LandingPage } from './landing.page'; - -@NgModule({ - imports: [CommonModule, FormsModule, IonicModule, LandingPageRoutingModule], - declarations: [LandingPage], -}) -export class LandingPageModule {} diff --git a/src/app/quiz/landing/landing.page.html b/src/app/quiz/landing/landing.page.html deleted file mode 100644 index f329509..0000000 --- a/src/app/quiz/landing/landing.page.html +++ /dev/null @@ -1,7 +0,0 @@ - - - landing - - - - diff --git a/src/app/quiz/landing/landing.page.scss b/src/app/quiz/landing/landing.page.scss deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/quiz/landing/landing.page.spec.ts b/src/app/quiz/landing/landing.page.spec.ts deleted file mode 100644 index d9578e5..0000000 --- a/src/app/quiz/landing/landing.page.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { IonicModule } from '@ionic/angular'; - -import { LandingPage } from './landing.page'; - -describe('LandingPage', () => { - let component: LandingPage; - let fixture: ComponentFixture; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [LandingPage], - imports: [IonicModule.forRoot()], - }).compileComponents(); - - fixture = TestBed.createComponent(LandingPage); - component = fixture.componentInstance; - fixture.detectChanges(); - })); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/quiz/landing/landing.page.ts b/src/app/quiz/landing/landing.page.ts deleted file mode 100644 index 896a693..0000000 --- a/src/app/quiz/landing/landing.page.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Component, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-landing', - templateUrl: './landing.page.html', - styleUrls: ['./landing.page.scss'], -}) -export class LandingPage implements OnInit { - constructor() {} - - ngOnInit() {} -}