Skip to content

Commit

Permalink
[Minor] Dashboard Renovation 2/3
Browse files Browse the repository at this point in the history
  • Loading branch information
heypoom committed Jan 19, 2017
1 parent b71d363 commit 6d0e94e
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 67 deletions.
24 changes: 16 additions & 8 deletions src/components/ContentEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const ContentEditor = props => ({
<Remove r={props.remove} />
</div>
<Quill
placeholder="Try writing something here! You're welcome."
value={props.content}
onChange={v => props.set("content", v)}
theme="bubble"
Expand Down Expand Up @@ -116,18 +117,25 @@ const ContentEditor = props => ({
</div>
),
quiz: (
<div>
<div className={s.rightmost}>
<Remove r={props.remove} />
</div>
<Shadow depth="z-1">
<QuizCreator {...props} />
</Shadow>
</div>
<QuizCreator {...props} />
),
embed: (
<div>
<div className={s.left} style={{zIndex: 3}}>
<Full e={props.set} f={props.full} />
</div>
<div className={s.right} style={{zIndex: 3}}>
<Remove r={props.remove} />
</div>
<Content {...props} />
<div style={{padding: "0em 2em 0.5em 2em"}}>
<TextField
style={{width: "100%"}}
floatingLabelText="กรุณาวางลิงค์ของ Embed"
value={props.src}
onChange={v => props.set("src", getYouTubeID(v.target.value))}
/>
</div>
</div>
),
gist: (
Expand Down
53 changes: 53 additions & 0 deletions src/components/Quiz/Quiz.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import "../variables.scss";

$quiz: $blue;
$error: #ff5454;

.card {
background: white;
Expand Down Expand Up @@ -29,3 +30,55 @@ $quiz: $blue;
font-weight: $font-weight-base;
line-height: 1.4em;
}

.show.correct {
color: $white;
background: $green;
box-shadow: $zCard;
}

.show:not(.correct) {
color: $error;
}

.show.mine:not(.correct) {
color: $white;
background: $error;
box-shadow: $zCard;
}

.ripple {
@extend .resetBtn;
background: transparent;
width: 100%;
margin: 0;
padding: 0;
}

.loading {
display: flex;
flex-direction: column;

height: 15.5em;
padding: 1.5em;

& > img {
flex: 1;
align-self: center;

width: 8.5em;
}

& > h2 {
text-align: center;
font-weight: $font-weight-base;
}

& > h4 {
margin: 0;
color: grey;
text-align: center;
font-weight: 300;
line-height: 1.2em;
}
}
135 changes: 124 additions & 11 deletions src/components/Quiz/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,55 @@ import Grid from "../Grid"
import Button from "../Button"

import {services} from "../../client/api"
import {setSnackbar} from "../../actions/app"

import s from "./Quiz.scss"

const QuizCard = withStyles(s)(({q = {choices: []}}) => (
let shuffled = {}

/* eslint no-param-reassign: 0 */
const shuffle = (array, id) => {
if (!shuffled[id]) {
let currentIndex = array.length
let temporaryValue
let randomIndex

// While there remain elements to shuffle...
while (currentIndex !== 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex)
currentIndex -= 1

// And swap it with the current element.
temporaryValue = array[currentIndex]
array[currentIndex] = array[randomIndex]
array[randomIndex] = temporaryValue
}

shuffled[id] = array

return array
}
return shuffled[id]
}

const QuizCard = withStyles(s)(({send, show, mine, q = {choices: []}}) => (
<div className={s.card}>
<div className={s.question}>
{q.question}
</div>
<div className={s.choices}>
<Grid r>
{q.choices.map((item, i) => (
{shuffle(q.choices, q._id).map((item, i) => (
<Grid xs={12} sm={6} key={i}>
<Button className={c(s.choice, item.correct && s.correct)}>
<Button
className={c(
s.choice, show && s.show,
i === mine && s.mine, item.correct && s.correct
)}
onClick={() => send(item.correct, i)}
disabled={show}
>
{item.text}
</Button>
</Grid>
Expand All @@ -29,12 +65,41 @@ const QuizCard = withStyles(s)(({q = {choices: []}}) => (
</div>
))

const LoadingCard = withStyles(s)(props => (
<div className={s.card}>
<Button className={s.ripple} onClick={props.init}>
<div className={s.loading}>
<img src="/images/fdesk2.svg" role="presentation" />
<h2>Quiz is loading, Please Wait.</h2>
<h4>Tap anywhere to load the quiz.</h4>
</div>
</Button>
</div>
))

const ReportCard = withStyles(s)(props => (
<div className={s.card}>
<Button className={s.ripple} onClick={props.reset}>
<div className={s.loading}>
<img src="/images/fdesk3.svg" role="presentation" />
<h2>
Your Score is {props.score}. Congratulations!
</h2>
<h4>
Tap anywhere to reset.
</h4>
</div>
</Button>
</div>
))

const mapStateToProps = state => ({
quiz: state.quizzes.data || {questions: []}
quiz: state.quizzes.data || {}
})

const mapDispatchToProps = (dispatch, props) => ({
init: () => dispatch(services.quizzes.get(props.id || "57af2356b2cf16503933f5da"))
init: () => dispatch(services.quizzes.get(props.id)),
gj: () => dispatch(setSnackbar("Good Job!"))
})

@withStyles(s)
Expand All @@ -43,17 +108,65 @@ export default class Quiz extends Component {

constructor(props) {
super(props)
this.state = {index: 0}
this.state = {
score: 0,
curr: 0,
mine: 0,
show: false,
done: false
}
}

componentDidMount() {
this.props.init()
}

render = () => (
<div>
<QuizCard q={this.props.quiz.questions[this.state.index]} />
</div>
)
next = () => {
if (this.state.curr < this.props.quiz.questions.length - 1) {
this.setState({curr: this.state.curr + 1})
} else {
this.setState({done: true})
}
}

prev = () => {
if (this.state.curr > 0)
this.setState({curr: this.state.curr - 1})
}

reset = () => {
shuffled = {}
this.setState({score: 0, curr: 0, mine: 0, show: false, done: false})
}

send = (correct, i) => {
if (correct) {
this.props.gj()
this.setState({score: this.state.score + 1})
}

this.setState({show: true, mine: i})
setTimeout(() => {
this.setState({show: false, mine: 0})
this.next()
}, 2000)
}

render = () => {
if (this.props.quiz.questions) {
if (this.state.done) {
return <ReportCard score={this.state.score} reset={this.reset} />
}
return (
<QuizCard
q={this.props.quiz.questions[this.state.curr]}
show={this.state.show}
mine={this.state.mine}
send={this.send}
/>
)
}
return <LoadingCard init={this.props.init} />
}

}
69 changes: 58 additions & 11 deletions src/components/QuizEditor/QuizCreator.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,67 @@
import React from "react"
import {connect} from "react-redux"
import {Link} from "react-router"
import {push} from "connected-react-router"
import withStyles from "isomorphic-style-loader/lib/withStyles"

import Fab from "material-ui/FloatingActionButton"
import DeleteIcon from "material-ui/svg-icons/action/delete"

import Button from "../Button"

import {services} from "../../client/api"

import s from "./QuizCreator.scss"

const QuizCreator = props => (
<div className={s.creator}>
<p>
Quiz Creator
</p>
<p>
<Link to="/quiz/57af2356b2cf16503933f5da">
Edit Quiz
</Link>
</p>
const QuizCreator = ({id, add, del, set}) => (
<div>
<div className={s.rightmost}>
<Fab data-tip="ลบ" onClick={del} mini>
<DeleteIcon />
</Fab>
</div>
<div className={s.creator}>
<img src="/images/fdesk3.svg" role="presentation" />
<h2>Quiz Creator</h2>
<div className={s.cta}>
{id ? (
<Link to={`/quiz/${id}`} className={s.link}>
<Button className={s.button}>
แก้ไขคำถาม
</Button>
</Link>
) : (
<Button className={s.button} onClick={add}>
เพิ่มคำถามใหม่
</Button>
)}
</div>
<div>
<small>รหัสเชิงเทคนิค: {id}</small>
</div>
</div>
</div>
)

export default withStyles(s)(QuizCreator)
const mapDispatchToProps = (dispatch, props) => ({
add: () => {
dispatch(services.quizzes.create({name: "My Quiz"})).then(({value}) => {
console.log("Added new Quiz:", value)
props.set("id", value._id)
props.save()
dispatch(push(`/quiz/${value._id}`))
})
},
del: () => {
dispatch(services.quizzes.remove(props.id)).then(item => {
console.log("Removed Quiz Safely:", item)
props.remove()
props.save()
}).catch(err => {
console.error(`Unable to remove ${props.id} safely:`, err)
props.remove(err)
})
}
})

export default connect(null, mapDispatchToProps)(withStyles(s)(QuizCreator))
Loading

0 comments on commit 6d0e94e

Please sign in to comment.