Index.jsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import { h, render, Component } from 'preact'; // eslint-disable-line no-unused-vars
  2. // Content
  3. import content from '../content/module.json';
  4. import questions from '../content/questions.json';
  5. import data from '../content/offline';
  6. // Configuration
  7. import config from '../config';
  8. // Services
  9. import api from '../utilities/api';
  10. // Views
  11. import TitleScreen from './TitleScreen.jsx';
  12. import FinalScreen from './FinalScreen.jsx';
  13. import ChartScreen from './ChartScreen.jsx';
  14. /**
  15. * titlescreen -> chartscreen (*n) -> finalscreen
  16. */
  17. export default class App extends Component {
  18. // Initialize functions
  19. constructor (props) {
  20. super(props);
  21. this.state = {
  22. route: 'titlescreen', // Current screen
  23. currentQuestion: 0, // Current question
  24. currentStep: 0, // Current graph task
  25. chartMode: 'interaction', // Mode for graph 'interaction', 'presentation' or 'comparison'
  26. questions: [], // Wrapper for all questions
  27. data: [], // Global data wrapper
  28. interactionData: [], // Wrapper for interaction data
  29. comparisonData: [], // Wrapper for comparison data
  30. isFetching: false, // Currently performing XHR?
  31. userId: null, // Current user id for posting
  32. token: null // Current access token
  33. };
  34. // Context binding
  35. this.navigate = this.navigate.bind(this);
  36. this.toNextStep = this.toNextStep.bind(this);
  37. this.setup = this.setup.bind(this);
  38. this.setData = this.setData.bind(this);
  39. }
  40. // Initial setup, get accesToken and userId
  41. setup () {
  42. this.setState({ questions });
  43. if (this.props.isOffline) {
  44. this.setState({ data });
  45. } else {
  46. this.setState({ isFetching: true });
  47. api.getToken().then(accessToken => {
  48. this.setState({ token: accessToken });
  49. // Create user
  50. api.createUser(accessToken)
  51. .then(user => {
  52. this.setState({
  53. userId: user.userId,
  54. isFetching: false
  55. });
  56. // Draw first question
  57. this.drawQuestions();
  58. });
  59. });
  60. }
  61. }
  62. // Navigate to specific route
  63. navigate (route) {
  64. if (route !== 'titlescreen') {
  65. this.setState({ route });
  66. } else {
  67. location.reload();
  68. }
  69. }
  70. // Set data
  71. setData (newData) {
  72. this.setState({ interactionData: newData });
  73. }
  74. // Get number of questions
  75. getNumberQuestions () {
  76. let sum = 0;
  77. for (let i = 0; i < this.state.questions.length; i += 1) {
  78. sum += this.state.questions[i].length;
  79. }
  80. return sum;
  81. }
  82. // Get question set from api
  83. drawQuestions () {
  84. let newData = [ ...this.state.data ];
  85. api.get(config.api.lists.a)
  86. .then(json => {
  87. newData[0] = json;
  88. // })
  89. // .then(() => api.get(config.api.lists.b))
  90. // .then(json => {
  91. // newData[1] = json;
  92. this.setState({ data: newData });
  93. })
  94. .catch(error => {
  95. console.error(error); // eslint-disable-line
  96. });
  97. }
  98. // Update state depending on chart mode and current question
  99. toNextStep () {
  100. const nextQuestion = this.state.currentQuestion < this.state.questions.length - 1;
  101. const nextStep = this.state.currentStep < this.state.questions[this.state.currentQuestion].texts.length - 1;
  102. if (this.state.chartMode === 'interaction') { // If in interaction mode, go to presentation mode
  103. if (!this.props.isOffline) {
  104. api.post(
  105. this.state.currentQuestion === 0 ? config.api.creates.a : config.api.creates.b,
  106. {
  107. userId: this.state.userId,
  108. kontext: this.state.questions[this.state.currentQuestion].yKeys[this.state.currentStep],
  109. punkte: this.state.interactionData
  110. },
  111. this.state.token
  112. )
  113. .then(() => {
  114. this.setState({ chartMode: 'presentation' });
  115. });
  116. } else {
  117. this.setState({ chartMode: 'presentation' });
  118. }
  119. } else if (this.state.chartMode === 'presentation' && !this.props.isOffline) { // If 'online' and in presentation mode, go to comparison mode
  120. api.get(
  121. this.state.currentQuestion === 0 ? config.api.proportions.a : config.api.proportions.b,
  122. { kontext: this.state.questions[this.state.currentQuestion].yKeys[this.state.currentStep] })
  123. .then(json => {
  124. this.setState({ chartMode: 'comparison', comparisonData: json });
  125. });
  126. } else if (nextStep) {
  127. this.setState({
  128. chartMode: 'interaction',
  129. currentStep: this.state.currentStep + 1,
  130. interactionData: [],
  131. comparisonData: []
  132. });
  133. } else if (nextQuestion) {
  134. this.setState({
  135. chartMode: 'interaction',
  136. currentQuestion: this.state.currentQuestion + 1,
  137. currentStep: 0,
  138. interactionData: [],
  139. comparisonData: []
  140. });
  141. } else {
  142. // Go to finalscreen
  143. this.setState({ route: 'finalscreen' });
  144. }
  145. }
  146. // LIFECYCLE
  147. componentDidMount () {
  148. this.setup();
  149. }
  150. // RENDER
  151. render () {
  152. let outputContent;
  153. switch (this.state.route) {
  154. case 'question':
  155. outputContent = <ChartScreen
  156. {...content}
  157. data={this.state.data}
  158. comparisonData={this.state.comparisonData}
  159. interactionData={this.state.mode === 'interaction' ? [] : this.state.interactionData}
  160. mode={this.state.chartMode}
  161. route={this.state.route}
  162. questions={this.state.questions}
  163. currentQuestion={this.state.currentQuestion}
  164. currentStep={this.state.currentStep}
  165. setData={this.setData}
  166. toNextStep={this.toNextStep} />;
  167. break;
  168. case 'finalscreen':
  169. outputContent = <FinalScreen
  170. {...content}
  171. navigate={this.navigate}
  172. isFetching={this.state.isFetching} />;
  173. break;
  174. case 'titlescreen':
  175. default:
  176. outputContent = <TitleScreen
  177. {...content}
  178. navigate={ this.navigate }
  179. navigateTo='question'
  180. isFetching={this.state.isFetching} />;
  181. break;
  182. }
  183. return outputContent;
  184. }
  185. }