Last active
June 30, 2018 13:14
-
-
Save adash333/03b6c66e7a219fb7dcbfdd33ed0c5b43 to your computer and use it in GitHub Desktop.
ionic3-firebase-quiz-ranking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app.module.ts | |
import { BrowserModule } from '@angular/platform-browser'; | |
import { ErrorHandler, NgModule } from '@angular/core'; | |
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; | |
import { SplashScreen } from '@ionic-native/splash-screen'; | |
import { StatusBar } from '@ionic-native/status-bar'; | |
import { HttpClientModule } from '@angular/common/http'; | |
// import AF2 modules | |
import { AngularFireModule } from 'angularfire2'; | |
import { AngularFireDatabaseModule } from 'angularfire2/database'; | |
import { environment } from '../environments/environment'; | |
import { MyApp } from './app.component'; | |
import { HomePage } from '../pages/home/home'; | |
import { DataProvider } from '../providers/data/data'; | |
//import { FlashCardComponent } from '../components/flash-card/flash-card'; | |
import { ComponentsModule } from '../components/components.module'; | |
@NgModule({ | |
declarations: [ | |
MyApp, | |
HomePage, | |
//FlashCardComponent | |
], | |
imports: [ | |
BrowserModule, | |
IonicModule.forRoot(MyApp), | |
HttpClientModule, | |
ComponentsModule, | |
AngularFireModule.initializeApp(environment.firebase), | |
AngularFireDatabaseModule | |
], | |
bootstrap: [IonicApp], | |
entryComponents: [ | |
MyApp, | |
HomePage | |
], | |
providers: [ | |
StatusBar, | |
SplashScreen, | |
{provide: ErrorHandler, useClass: IonicErrorHandler}, | |
DataProvider | |
] | |
}) | |
export class AppModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"questions": [ | |
{ | |
"flashCardFront": "<img src='assets/imgs/helicopter.png' />", | |
"flashCardBack": "ヘリコプター", | |
"flashCardFlipped": false, | |
"questionText": "これはなに?", | |
"answers": [ | |
{"answer": "ヘリコプター", "correct": true, "selected": false}, | |
{"answer": "ひこうき", "correct": false, "selected": false}, | |
{"answer": "トラック", "correct": false, "selected": false} | |
] | |
}, | |
{ | |
"flashCardFront": "<img src='assets/imgs/plane.png' />", | |
"flashCardBack": "ひこうき", | |
"flashCardFlipped": false, | |
"questionText": "これはなに?", | |
"answers": [ | |
{"answer": "スポーツカー", "correct": false, "selected": false}, | |
{"answer": "ひこうき", "correct": true, "selected": false}, | |
{"answer": "オートバイ", "correct": false, "selected": false} | |
] | |
}, | |
{ | |
"flashCardFront": "<img src='assets/imgs/truck.png' />", | |
"flashCardBack": "トラック", | |
"flashCardFlipped": false, | |
"questionText": "これはなに?", | |
"answers": [ | |
{"answer": "ふね", "correct": false, "selected": false}, | |
{"answer": "でんしゃ", "correct": false, "selected": false}, | |
{"answer": "トラック", "correct": true, "selected": false} | |
] | |
} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-content> | |
<ion-slides #slides> | |
<ion-slide class="start-slide"> | |
<h3>Ionic3-kids-quiz</h3> | |
<form (ngSubmit)="nextSlide()"> | |
<ion-list> | |
<ion-item> | |
<ion-label floating>Enter your Nickname</ion-label> | |
<ion-input type="text" [(ngModel)]="data.user" name="user" required="" ></ion-input> | |
</ion-item> | |
<ion-item> | |
<button ion-button color="primary" full>Start!</button> | |
</ion-item> | |
</ion-list> | |
</form> | |
<br><br> | |
<button ion-button color="secondary" outline [navPush]="'RankingPage'">ランキング</button> | |
</ion-slide> | |
<ion-slide *ngFor="let question of questions; let i = index;"> | |
<h3>Question {{i+1}}</h3> | |
<ion-item no-lines> | |
<flash-card [isFlipped]="question.flashCardFlipped"> | |
<div class="flash-card-front" [innerHTML]="question.flashCardFront"></div> | |
<div class="flash-card-back" [innerHTML]="question.flashCardBack"></div> | |
</flash-card> | |
</ion-item> | |
<h3>{{question.questionText}}</h3> | |
<ion-list no-lines radio-group> | |
<ion-item *ngFor="let answer of question.answers; let i = index"> | |
<ion-label>{{i+1}}.{{answer.answer}} </ion-label> | |
<ion-radio (click)="selectAnswer(answer, question)" [checked]="answer.selected" [disabled]="hasAnswered"></ion-radio> | |
</ion-item> | |
</ion-list> | |
</ion-slide> | |
<ion-slide> | |
<h2>{{data.user}}さんのスコア:{{score}}</h2> | |
<button (click)="saveScore()" ion-button full color="secondary">スコアを保存</button> | |
<br><br> | |
<button ion-button color="secondary" outline [navPush]="'RankingPage'">ランキング</button> | |
<br><br> | |
<button (click)="restartQuiz()" ion-button full color="primary">クイズに再チャレンジ | |
</button> | |
</ion-slide> | |
</ion-slides> | |
</ion-content> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
page-home { | |
ion-slide { | |
align-items: flex-start; | |
} | |
ion-item { | |
margin-bottom: 5px; | |
font-size: 1.2em; | |
background-color: map-get($colors, primary); | |
} | |
flash-card { | |
color: #000; | |
img { | |
width: 70%; | |
height: auto; | |
} | |
} | |
.start-slide { | |
justify-content: center; | |
align-items: center; | |
button { | |
font-size: 1.3em; | |
font-weight: bold; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, ViewChild } from '@angular/core'; | |
import { NavController, AlertController } from 'ionic-angular'; | |
import { DataProvider } from '../../providers/data/data'; | |
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database'; | |
//import { QuizScore } from '../../models/quizScore'; | |
import * as firebase from 'Firebase'; | |
@Component({ | |
selector: 'page-home', | |
templateUrl: 'home.html' | |
}) | |
export class HomePage { | |
data = { user:"", score:"" }; | |
public quizScores: AngularFireList<{}>; | |
//public quizScore: QuizScore; | |
@ViewChild('slides') slides: any; | |
hasAnswered: boolean = false; | |
user: string; | |
score: number = 0; | |
slideOptions: any; | |
//flashCardFlipped: boolean = false; | |
questions: any; | |
constructor( | |
public navCtrl: NavController, | |
public dataService: DataProvider, | |
db: AngularFireDatabase, | |
private alertCtrl: AlertController | |
) { | |
this.quizScores = db.list('quizScores'); | |
} | |
ionViewDidLoad() { | |
this.slides.lockSwipes(true); | |
this.dataService.load().then((data) => { | |
data.map((question) => { | |
let originalOrder = question.answers; | |
question.answers = this.randomizeAnswers(originalOrder); | |
return question; | |
}); | |
this.questions = data; | |
}); | |
} | |
nextSlide() { | |
this.slides.lockSwipes(false); | |
this.slides.slideNext(); | |
this.slides.lockSwipes(true); | |
} | |
selectAnswer(answer, question) { | |
this.hasAnswered = true; | |
answer.selected = true; | |
question.flashCardFlipped = true; | |
if(answer.correct) { | |
this.score++; | |
} | |
setTimeout(() => { | |
this.hasAnswered = false; | |
this.nextSlide(); | |
answer.selected = false; | |
question.flashCardFlipped = false; | |
}, 3000); | |
} | |
randomizeAnswers(rawAnswers: any[]): any[] { | |
for(let i = rawAnswers.length -1; i > 0; i--) { | |
let j = Math.floor(Math.random() * (i + 1)); | |
let temp = rawAnswers[i]; | |
rawAnswers[i] = rawAnswers[j]; | |
rawAnswers[j] = temp; | |
} | |
return rawAnswers; | |
} | |
restartQuiz() { | |
this.score = 0; | |
this.slides.lockSwipes(false); | |
this.slides.slideTo(1, 1000); | |
this.slides.lockSwipes(true); | |
} | |
//firebaseへのデータ保存 | |
saveScore() { | |
let newData = firebase.database().ref('quizscores').push(); | |
newData.set({ | |
user:this.data.user, | |
score:this.score, | |
date:Date() | |
}) | |
let alert = this.alertCtrl.create({ | |
title: 'スコアを保存しました', | |
buttons: ['OK'] | |
}); | |
alert.present(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class QuizScore { | |
user: string; | |
score: number; | |
//date: number; | |
constructor(user: string, score: number) { | |
this.user = user; | |
this.score = score; | |
//this.date = Date.now(); | |
} | |
// 取得した日付を反映 | |
//setData(date: number): QuizScore { | |
// this.date = date; | |
// return this; | |
//} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HttpClient } from '@angular/common/http'; | |
import { Injectable } from '@angular/core'; | |
import 'rxjs/add/operator/map'; | |
//import { Observable } from 'rxjs/observable'; | |
@Injectable() | |
export class DataProvider { | |
data: any; | |
constructor(public http: HttpClient) { | |
console.log('Hello DataProvider Provider'); | |
} | |
load() { | |
if(this.data) { | |
return Promise.resolve(this.data); | |
} | |
return new Promise(resolve => { | |
this.http.get('assets/data/questions.json').subscribe(data => { | |
this.data = data["questions"]; | |
resolve(this.data); | |
}); | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-header> | |
<ion-navbar color="primary"> | |
<ion-title> | |
ランキング | |
</ion-title> | |
</ion-navbar> | |
</ion-header> | |
<ion-content padding> | |
<ion-grid> | |
<ion-row text-center nowrap class="top"> | |
<ion-col col-2> | |
<div>順位</div> | |
</ion-col> | |
<ion-col col-8> | |
<div>お名前</div> | |
</ion-col> | |
<ion-col col-2> | |
<div>記録</div> | |
</ion-col> | |
</ion-row> | |
<ion-row *ngFor="let item of quizScores; index as i"> | |
<ion-col col-2> | |
<div>{{i + 1}}位</div> | |
</ion-col> | |
<ion-col col-8> | |
<div>{{item.user}}</div> | |
</ion-col> | |
<ion-col col-2> | |
<div>{{item.score}}点</div> | |
</ion-col> | |
</ion-row> | |
</ion-grid> | |
</ion-content> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
page-ranking { | |
ion-grid ion-row { | |
background-color: white; | |
border: 0px solid #e6e9ee; | |
//border-radius: 2px; | |
padding: 5px; | |
text-align: center; | |
//border-bottom: solid 1px black; | |
} | |
ion-grid .top { | |
border-bottom: solid 2px orange; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from '@angular/core'; | |
import { IonicPage, NavController, NavParams } from 'ionic-angular'; | |
import { AngularFireDatabase, AngularFireList} from 'angularfire2/database'; | |
import { QuizScore } from '../../models/quizScore'; | |
@IonicPage() | |
@Component({ | |
selector: 'page-ranking', | |
templateUrl: 'ranking.html', | |
}) | |
export class RankingPage { | |
public FB_quizScores: AngularFireList<{}>; | |
public quizScores: QuizScore[] = []; | |
constructor( | |
public navCtrl: NavController, | |
public navParams: NavParams, | |
public db: AngularFireDatabase | |
) { | |
this.FB_quizScores = db.list('/quizscores'); | |
this.FB_quizScores.snapshotChanges().subscribe((actions: any[]) => { | |
this.quizScores = []; | |
actions.forEach((action: any) => { | |
// 取得したデータを反映 | |
const val = action.payload.val() | |
this.quizScores.push(new QuizScore(val.user, val.score)); | |
}); | |
this.quizScores.sort( function(a, b) { | |
return a.score > b.score ? -1 : 1; | |
}); | |
}); | |
} | |
ionViewDidLoad() { | |
console.log('ionViewDidLoad RankingPage'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment