From 512cebe1c938b2ff68ef1c926525e3ce44891de0 Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Wed, 10 Apr 2019 23:48:42 +0200 Subject: [PATCH 1/7] Adapt types --- api/app/UserFeedbackQuestion.php | 27 ++++----- ...2019_03_27_134609_adapt_user_feedbacks.php | 59 +++++++++++++++++++ .../src/stores/userFeedbackQuestionStore.ts | 6 ++ frontend/src/types.ts | 17 ++++++ 4 files changed, 95 insertions(+), 14 deletions(-) create mode 100644 api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php create mode 100644 frontend/src/stores/userFeedbackQuestionStore.ts diff --git a/api/app/UserFeedbackQuestion.php b/api/app/UserFeedbackQuestion.php index f59d9cc4..cfa0aed0 100644 --- a/api/app/UserFeedbackQuestion.php +++ b/api/app/UserFeedbackQuestion.php @@ -9,22 +9,21 @@ class UserFeedbackQuestion extends Model public $timestamps = false; protected $fillable = [ - 'id', - 'question', - 'new_page', - 'type', - 'required', - 'custom_info', - 'opt1', - 'opt2', - 'opt3', - 'pos', - 'active', - ]; + 'id', + 'question', + 'page', + 'type', + 'required', + 'custom_info', + 'opt1', + 'opt2', + 'opt3', + 'pos', + 'active' + ]; protected $casts = [ - 'new_page' => 'boolean', - 'required' => 'boolean', + 'required' => 'boolean' ]; public function userFeedbacks() diff --git a/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php b/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php new file mode 100644 index 00000000..5ade6e4e --- /dev/null +++ b/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php @@ -0,0 +1,59 @@ +addColumn('integer', 'page')->after('new_page'); + }); + + $feedbacks = DB::table('user_feedback_questions') + ->select('id', 'new_page') + ->orderBy('pos') + ->get(); + + $current_page = 1; + $feedbacks->each(function($feedback) use (&$current_page) { + $current_page += $feedback->new_page; + + DB::table('user_feedback_questions')->where('id', $feedback->id) + ->update(['page' => $current_page]); + }); + + Schema::table('user_feedback_questions', function (Blueprint $table) { + $table->dropColumn('new_page'); + }); + + DB::table('user_feedback_questions')->where('type', 3)->update(['type' => 1]); + DB::table('user_feedback_questions')->where('type', 4)->update(['type' => 3]); + DB::table('user_feedback_questions')->where('type', 5)->update(['type' => 4]); + DB::table('user_feedback_questions')->where('type', 6)->update(['type' => 5]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('user_feedback_questions', function (Blueprint $table) { + $table->dropColumn('page'); + $table->addColumn('integer', 'new_page')->default(0); + }); + DB::table('user_feedback_questions')->where('type', 5)->update(['type' => 6]); + DB::table('user_feedback_questions')->where('type', 4)->update(['type' => 5]); + DB::table('user_feedback_questions')->where('type', 3)->update(['type' => 4]); + } +} diff --git a/frontend/src/stores/userFeedbackQuestionStore.ts b/frontend/src/stores/userFeedbackQuestionStore.ts new file mode 100644 index 00000000..676e031f --- /dev/null +++ b/frontend/src/stores/userFeedbackQuestionStore.ts @@ -0,0 +1,6 @@ +import { UserFeedback, UserFeedbackQuestion } from '../types'; +import { DomainStore } from './domainStore'; + +export class UserFeedbackQuestionStore extends DomainStore { + +} diff --git a/frontend/src/types.ts b/frontend/src/types.ts index bc85711f..78295a41 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -172,6 +172,23 @@ export interface UserFeedback { id?: number; } +export enum UserFeedbackQuestionType { + LikertScale = 1, + SectionTitle = 2, + FreeText = 3, + YesOrNo = 4, + MultipleChoice = 5, +} + +export interface UserFeedbackQuestion { + id?: number; + question: string; + page: number; + type: number; + custom_info: string; + options: string[]; +} + export interface UserQuestionWithAnswers { id?: number; answers: UserQuestionAnswers; From 5342d3ad704db66f5f686b72495fbe018ad62ef4 Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Thu, 11 Apr 2019 11:16:32 +0200 Subject: [PATCH 2/7] Fixed linting issues --- api/app/UserFeedbackQuestion.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/api/app/UserFeedbackQuestion.php b/api/app/UserFeedbackQuestion.php index cfa0aed0..780463a9 100644 --- a/api/app/UserFeedbackQuestion.php +++ b/api/app/UserFeedbackQuestion.php @@ -9,21 +9,21 @@ class UserFeedbackQuestion extends Model public $timestamps = false; protected $fillable = [ - 'id', - 'question', - 'page', - 'type', - 'required', - 'custom_info', - 'opt1', - 'opt2', - 'opt3', - 'pos', - 'active' - ]; + 'id', + 'question', + 'page', + 'type', + 'required', + 'custom_info', + 'opt1', + 'opt2', + 'opt3', + 'pos', + 'active', + ]; protected $casts = [ - 'required' => 'boolean' + 'required' => 'boolean', ]; public function userFeedbacks() From cc014b197abc557a0470945b5c56f87234832619 Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Thu, 11 Apr 2019 11:41:22 +0200 Subject: [PATCH 3/7] Implement user feedback question store --- api/app/Console/Commands/.gitkeep | 0 api/database/migrations/.gitkeep | 0 api/resources/views/.gitkeep | 0 .../src/stores/userFeedbackQuestionStore.ts | 42 ++++++++++++++++++- frontend/src/utilities/StoreProvider.tsx | 5 ++- 5 files changed, 44 insertions(+), 3 deletions(-) delete mode 100755 api/app/Console/Commands/.gitkeep delete mode 100755 api/database/migrations/.gitkeep delete mode 100755 api/resources/views/.gitkeep diff --git a/api/app/Console/Commands/.gitkeep b/api/app/Console/Commands/.gitkeep deleted file mode 100755 index e69de29b..00000000 diff --git a/api/database/migrations/.gitkeep b/api/database/migrations/.gitkeep deleted file mode 100755 index e69de29b..00000000 diff --git a/api/resources/views/.gitkeep b/api/resources/views/.gitkeep deleted file mode 100755 index e69de29b..00000000 diff --git a/frontend/src/stores/userFeedbackQuestionStore.ts b/frontend/src/stores/userFeedbackQuestionStore.ts index 676e031f..10420075 100644 --- a/frontend/src/stores/userFeedbackQuestionStore.ts +++ b/frontend/src/stores/userFeedbackQuestionStore.ts @@ -1,6 +1,44 @@ -import { UserFeedback, UserFeedbackQuestion } from '../types'; +import { computed, observable } from 'mobx'; +import { UserFeedbackQuestion } from '../types'; import { DomainStore } from './domainStore'; -export class UserFeedbackQuestionStore extends DomainStore { +interface RawUserFeedbackQuestion extends UserFeedbackQuestion { + opt1: string; + opt2: string; + opt3: string; +} + +export class UserFeedbackQuestionStore extends DomainStore { + @computed + get entities(): UserFeedbackQuestion[] { + return this.userFeedbackQuestions; + } + + @computed + get pages(): UserFeedbackQuestion[][] { + const pages: UserFeedbackQuestion[][] = []; + this.userFeedbackQuestions.forEach(question => { + const currentPage = pages[question.page - 1]; + currentPage ? currentPage.push(question) : pages[question.page - 1] = []; + }); + + return pages; + } + + static formatServerResponse(data: RawUserFeedbackQuestion[]): UserFeedbackQuestion[] { + return data.map(userFeedbackQuestion => { + return { + options: [userFeedbackQuestion.opt1, userFeedbackQuestion.opt2, userFeedbackQuestion.opt3], + ...userFeedbackQuestion, + }; + }); + } + + @observable + private userFeedbackQuestions: UserFeedbackQuestion[] = []; + protected async doFetchAll(params: object = {}): Promise { + const response = await this.mainStore.api.get('/user_feedback_questions', { params }); + this.userFeedbackQuestions = UserFeedbackQuestionStore.formatServerResponse(response.data); + } } diff --git a/frontend/src/utilities/StoreProvider.tsx b/frontend/src/utilities/StoreProvider.tsx index a12e5599..33fb0ff5 100644 --- a/frontend/src/utilities/StoreProvider.tsx +++ b/frontend/src/utilities/StoreProvider.tsx @@ -8,6 +8,7 @@ import { MissionStore } from '../stores/missionStore'; import { PaymentStore } from '../stores/paymentStore'; import { ReportSheetStore } from '../stores/reportSheetStore'; import { SpecificationStore } from '../stores/specificationStore'; +import { UserFeedbackQuestionStore } from '../stores/userFeedbackQuestionStore'; import { UserFeedbackStore } from '../stores/userFeedbackStore'; import { UserStore } from '../stores/userStore'; import { Formatter } from './formatter'; @@ -17,7 +18,7 @@ interface Props { } export class StoreProvider extends React.Component { - private stores: { + private readonly stores: { apiStore: ApiStore; mainStore: MainStore; holidayStore: HolidayStore; @@ -27,6 +28,7 @@ export class StoreProvider extends React.Component { userStore: UserStore; missionStore: MissionStore; specificationStore: SpecificationStore; + userFeedbackQuestionStore: UserFeedbackQuestionStore; }; constructor(props: Props) { @@ -46,6 +48,7 @@ export class StoreProvider extends React.Component { userStore: new UserStore(mainStore), missionStore: new MissionStore(mainStore), specificationStore: new SpecificationStore(mainStore), + userFeedbackQuestionStore: new UserFeedbackQuestionStore(mainStore), }; } render() { From 614b05721040c6fea48ea0a482684f58a9be4102 Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Thu, 11 Apr 2019 15:14:07 +0200 Subject: [PATCH 4/7] Adapt feedback page --- frontend/src/App.tsx | 2 +- .../users/mission_feedback/FeedbackPage.tsx | 8 +++-- .../mission_feedback/MissionFeedback.tsx | 34 ++++++++++++++----- .../mission_subform/MissionOverviewTable.tsx | 2 +- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 186e662c..75e8e9b0 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -43,7 +43,7 @@ class App extends React.Component { - + diff --git a/frontend/src/views/users/mission_feedback/FeedbackPage.tsx b/frontend/src/views/users/mission_feedback/FeedbackPage.tsx index 9a3229be..492b7255 100644 --- a/frontend/src/views/users/mission_feedback/FeedbackPage.tsx +++ b/frontend/src/views/users/mission_feedback/FeedbackPage.tsx @@ -1,7 +1,11 @@ import * as React from 'react'; -export class FeedbackPage extends React.Component { +interface FeedbackPageProps { + page: number; +} + +export class FeedbackPage extends React.Component { render() { - return
page
; + return
Page {this.props.page}
; } } diff --git a/frontend/src/views/users/mission_feedback/MissionFeedback.tsx b/frontend/src/views/users/mission_feedback/MissionFeedback.tsx index 7ac3fddd..eb67be59 100644 --- a/frontend/src/views/users/mission_feedback/MissionFeedback.tsx +++ b/frontend/src/views/users/mission_feedback/MissionFeedback.tsx @@ -3,31 +3,49 @@ import * as React from 'react'; import { RouteComponentProps } from 'react-router'; import { Progress } from 'reactstrap'; import IziviContent from '../../../layout/IziviContent'; -import { UserFeedbackStore } from '../../../stores/userFeedbackStore'; +import { UserFeedbackQuestionStore } from '../../../stores/userFeedbackQuestionStore'; import { FeedbackPage } from './FeedbackPage'; -interface MissionFeedbackProps extends RouteComponentProps<{ id?: string }> { - userFeedbackStore?: UserFeedbackStore; +interface MissionFeedbackProps extends RouteComponentProps<{ id: string, page: string }> { + userFeedbackQuestionStore?: UserFeedbackQuestionStore; } -@inject('missionStore') -export class MissionFeedback extends React.Component { +interface MissionFeedbackState { + loading: boolean; +} + +@inject('userFeedbackQuestionStore') +export class MissionFeedback extends React.Component { + get currentPage() { + return parseInt(this.props.match.params.page, 10); + } + constructor(props: MissionFeedbackProps) { super(props); + + this.state = { + loading: true, + }; + + props.userFeedbackQuestionStore!.fetchAll().then(this.handleUserFeedbackQuestions.bind(this)); + } + + handleUserFeedbackQuestions() { + this.setState({ loading: false }); } render() { return ( - +
Hinweis: Alle Fragen, welche mit (*) enden, sind erforderlich und müssen ausgefüllt werden. - +
- +
); } diff --git a/frontend/src/views/users/mission_subform/MissionOverviewTable.tsx b/frontend/src/views/users/mission_subform/MissionOverviewTable.tsx index 2e6eed76..2bb41ff7 100644 --- a/frontend/src/views/users/mission_subform/MissionOverviewTable.tsx +++ b/frontend/src/views/users/mission_subform/MissionOverviewTable.tsx @@ -49,7 +49,7 @@ function renderFeedbackButton(mission: Mission) { } return ( - + From cd7ab608ecc125aa2657b8be65bbef781ca50213 Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Thu, 11 Apr 2019 15:14:33 +0200 Subject: [PATCH 5/7] Only return relevant data --- api/app/Http/Controllers/api/FeedbackController.php | 3 ++- .../migrations/2019_03_27_134609_adapt_user_feedbacks.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/api/app/Http/Controllers/api/FeedbackController.php b/api/app/Http/Controllers/api/FeedbackController.php index 28e64bc2..2d15c54d 100644 --- a/api/app/Http/Controllers/api/FeedbackController.php +++ b/api/app/Http/Controllers/api/FeedbackController.php @@ -32,7 +32,8 @@ class FeedbackController extends Controller public function index() { - return UserFeedbackQuestion::all(); + return UserFeedbackQuestion::orderBy('pos') + ->get(['id', 'question', 'type', 'page', 'custom_info', 'opt1', 'opt2', 'opt3']); } public function postFeedback() diff --git a/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php b/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php index 5ade6e4e..57866037 100644 --- a/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php +++ b/api/database/migrations/2019_03_27_134609_adapt_user_feedbacks.php @@ -23,7 +23,7 @@ public function up() ->orderBy('pos') ->get(); - $current_page = 1; + $current_page = 0; $feedbacks->each(function($feedback) use (&$current_page) { $current_page += $feedback->new_page; From b6614d422c685a92cc687c56db5c392f71f9bc04 Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Fri, 12 Apr 2019 16:11:48 +0200 Subject: [PATCH 6/7] Implement survey types --- frontend/src/types.ts | 4 +-- .../users/mission_feedback/FeedbackPage.tsx | 26 +++++++++++++-- .../questions/FeedbackQuestion.tsx | 19 +++++++++++ .../questions/FeedbackQuestionProps.ts | 5 +++ .../questions/types/LikertScale.tsx | 33 +++++++++++++++++++ .../questions/types/MultipleChoice.tsx | 29 ++++++++++++++++ .../questions/types/SectionTitle.tsx | 4 +++ 7 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 frontend/src/views/users/mission_feedback/questions/FeedbackQuestion.tsx create mode 100644 frontend/src/views/users/mission_feedback/questions/FeedbackQuestionProps.ts create mode 100644 frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx create mode 100644 frontend/src/views/users/mission_feedback/questions/types/MultipleChoice.tsx create mode 100644 frontend/src/views/users/mission_feedback/questions/types/SectionTitle.tsx diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 78295a41..529aa8b2 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -181,10 +181,10 @@ export enum UserFeedbackQuestionType { } export interface UserFeedbackQuestion { - id?: number; + id: number; question: string; page: number; - type: number; + type: UserFeedbackQuestionType; custom_info: string; options: string[]; } diff --git a/frontend/src/views/users/mission_feedback/FeedbackPage.tsx b/frontend/src/views/users/mission_feedback/FeedbackPage.tsx index 492b7255..54dac260 100644 --- a/frontend/src/views/users/mission_feedback/FeedbackPage.tsx +++ b/frontend/src/views/users/mission_feedback/FeedbackPage.tsx @@ -1,11 +1,33 @@ +import { inject } from 'mobx-react'; import * as React from 'react'; +import { UserFeedbackQuestionStore } from '../../../stores/userFeedbackQuestionStore'; +import { UserFeedbackQuestion } from '../../../types'; +import FeedbackQuestion from './questions/FeedbackQuestion'; interface FeedbackPageProps { page: number; + userFeedbackQuestionStore?: UserFeedbackQuestionStore; } -export class FeedbackPage extends React.Component { +interface FeedbackPageState { + currentQuestions: UserFeedbackQuestion[]; +} + +@inject('userFeedbackQuestionStore') +export class FeedbackPage extends React.Component { + constructor(props: FeedbackPageProps) { + super(props); + + this.state = { + currentQuestions: props.userFeedbackQuestionStore!.pages[props.page - 1], + }; + } + render() { - return
Page {this.props.page}
; + return ( +
+ {this.state.currentQuestions.map(question => )} +
+ ); } } diff --git a/frontend/src/views/users/mission_feedback/questions/FeedbackQuestion.tsx b/frontend/src/views/users/mission_feedback/questions/FeedbackQuestion.tsx new file mode 100644 index 00000000..d30c1aef --- /dev/null +++ b/frontend/src/views/users/mission_feedback/questions/FeedbackQuestion.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import { UserFeedbackQuestionType } from '../../../../types'; +import { FeedbackQuestionProps } from './FeedbackQuestionProps'; +import LikertScale from './types/LikertScale'; +import MultipleChoice from './types/MultipleChoice'; +import SectionTitle from './types/SectionTitle'; + +export default (props: FeedbackQuestionProps) => { + switch (props.question.type) { + case UserFeedbackQuestionType.SectionTitle: + return ; + case UserFeedbackQuestionType.LikertScale: + return ; + case UserFeedbackQuestionType.MultipleChoice: + return ; + default: + return <>; + } +}; diff --git a/frontend/src/views/users/mission_feedback/questions/FeedbackQuestionProps.ts b/frontend/src/views/users/mission_feedback/questions/FeedbackQuestionProps.ts new file mode 100644 index 00000000..23710678 --- /dev/null +++ b/frontend/src/views/users/mission_feedback/questions/FeedbackQuestionProps.ts @@ -0,0 +1,5 @@ +import { UserFeedbackQuestion } from '../../../../types'; + +export interface FeedbackQuestionProps { + question: UserFeedbackQuestion; +} diff --git a/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx b/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx new file mode 100644 index 00000000..ef2ba142 --- /dev/null +++ b/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx @@ -0,0 +1,33 @@ +import { useState } from 'react'; +import * as React from 'react'; +import { Button, ButtonGroup } from 'reactstrap'; +import { FeedbackQuestionProps } from '../FeedbackQuestionProps'; + +function renderButton(index: number, activeIndex: number, setActiveIndex: React.Dispatch>) { + return ( + + ); +} + +export default ({ question }: FeedbackQuestionProps) => { + const [activeIndex, setActiveIndex] = useState(0); + + return ( +
+

{question.question}

+ + { + [...(Array(4).keys() as any)] + .map(index => renderButton(index, activeIndex, setActiveIndex)) + } + +
+ ); +}; diff --git a/frontend/src/views/users/mission_feedback/questions/types/MultipleChoice.tsx b/frontend/src/views/users/mission_feedback/questions/types/MultipleChoice.tsx new file mode 100644 index 00000000..367299c0 --- /dev/null +++ b/frontend/src/views/users/mission_feedback/questions/types/MultipleChoice.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { Form, FormGroup, Label } from 'reactstrap'; +import { FeedbackQuestionProps } from '../FeedbackQuestionProps'; + +function renderOption(option: any) { + const optionId = `opt-${option.value}`; + + return ( +
+ + +
+ ); +} + +export default ({ question }: FeedbackQuestionProps) => { + const options = JSON.parse(question.custom_info).choices; + + return ( +
+

{question.question}

+
+ + {options.map((option: any) => renderOption(option))} + +
+
+ ); +}; diff --git a/frontend/src/views/users/mission_feedback/questions/types/SectionTitle.tsx b/frontend/src/views/users/mission_feedback/questions/types/SectionTitle.tsx new file mode 100644 index 00000000..d8ddb271 --- /dev/null +++ b/frontend/src/views/users/mission_feedback/questions/types/SectionTitle.tsx @@ -0,0 +1,4 @@ +import * as React from 'react'; +import { FeedbackQuestionProps } from '../FeedbackQuestionProps'; + +export default ({ question }: FeedbackQuestionProps) =>

{question.question}

; From 5cdb02fd54c432df2df1ff5debae15daa05a8bce Mon Sep 17 00:00:00 2001 From: Lukas Bischof Date: Fri, 12 Apr 2019 17:52:59 +0200 Subject: [PATCH 7/7] Implement navigation --- .../users/mission_feedback/FeedbackPage.tsx | 30 +++++++------ .../FeedbackPageNavigation.tsx | 30 +++++++++++++ .../mission_feedback/MissionFeedback.tsx | 6 ++- .../questions/FeedbackQuestionContainer.tsx | 10 +++++ .../questions/types/LikertScale.tsx | 33 ++++++++------ .../questions/types/MultipleChoice.tsx | 44 ++++++++++++++----- .../questions/types/SectionTitle.tsx | 13 +++++- 7 files changed, 125 insertions(+), 41 deletions(-) create mode 100644 frontend/src/views/users/mission_feedback/FeedbackPageNavigation.tsx create mode 100644 frontend/src/views/users/mission_feedback/questions/FeedbackQuestionContainer.tsx diff --git a/frontend/src/views/users/mission_feedback/FeedbackPage.tsx b/frontend/src/views/users/mission_feedback/FeedbackPage.tsx index 54dac260..ddcabaf3 100644 --- a/frontend/src/views/users/mission_feedback/FeedbackPage.tsx +++ b/frontend/src/views/users/mission_feedback/FeedbackPage.tsx @@ -1,33 +1,35 @@ import { inject } from 'mobx-react'; import * as React from 'react'; +import { Container } from 'reactstrap'; import { UserFeedbackQuestionStore } from '../../../stores/userFeedbackQuestionStore'; -import { UserFeedbackQuestion } from '../../../types'; +import FeedbackPageNavigation from './FeedbackPageNavigation'; import FeedbackQuestion from './questions/FeedbackQuestion'; interface FeedbackPageProps { page: number; + missionId: number; userFeedbackQuestionStore?: UserFeedbackQuestionStore; } -interface FeedbackPageState { - currentQuestions: UserFeedbackQuestion[]; -} - @inject('userFeedbackQuestionStore') -export class FeedbackPage extends React.Component { - constructor(props: FeedbackPageProps) { - super(props); +export class FeedbackPage extends React.Component { + get currentQuestions() { + return this.props.userFeedbackQuestionStore!.pages[this.props.page - 1]; + } - this.state = { - currentQuestions: props.userFeedbackQuestionStore!.pages[props.page - 1], - }; + get totalPages() { + return this.props.userFeedbackQuestionStore!.pages.length; } render() { return ( -
- {this.state.currentQuestions.map(question => )} -
+ + + + {this.currentQuestions.map(question => )} + + + ); } } diff --git a/frontend/src/views/users/mission_feedback/FeedbackPageNavigation.tsx b/frontend/src/views/users/mission_feedback/FeedbackPageNavigation.tsx new file mode 100644 index 00000000..59147a89 --- /dev/null +++ b/frontend/src/views/users/mission_feedback/FeedbackPageNavigation.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { Link } from 'react-router-dom'; +import { Button, ButtonGroup } from 'reactstrap'; + +interface FeedbackPageNavigationProps { + missionId: number; + page: number; + totalPages: number; +} + +function previousLink(missionId: number, page: number) { + return `/mission/${missionId}/feedback/${Math.max(page - 1, 0)}`; +} + +function nextLink(missionId: number, page: number, totalPages: number) { + return `/mission/${missionId}/feedback/${Math.min(page + 1, totalPages)}`; +} + +export default ({ missionId, page, totalPages }: FeedbackPageNavigationProps) => { + return ( + + + + + + + + + ); +}; diff --git a/frontend/src/views/users/mission_feedback/MissionFeedback.tsx b/frontend/src/views/users/mission_feedback/MissionFeedback.tsx index eb67be59..0fd4b6c9 100644 --- a/frontend/src/views/users/mission_feedback/MissionFeedback.tsx +++ b/frontend/src/views/users/mission_feedback/MissionFeedback.tsx @@ -20,6 +20,10 @@ export class MissionFeedback extends React.Component - +
); } diff --git a/frontend/src/views/users/mission_feedback/questions/FeedbackQuestionContainer.tsx b/frontend/src/views/users/mission_feedback/questions/FeedbackQuestionContainer.tsx new file mode 100644 index 00000000..d129e687 --- /dev/null +++ b/frontend/src/views/users/mission_feedback/questions/FeedbackQuestionContainer.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; +import Row from 'reactstrap/lib/Row'; + +export default ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; diff --git a/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx b/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx index ef2ba142..d118deb7 100644 --- a/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx +++ b/frontend/src/views/users/mission_feedback/questions/types/LikertScale.tsx @@ -1,14 +1,17 @@ -import { useState } from 'react'; import * as React from 'react'; import { Button, ButtonGroup } from 'reactstrap'; +import Col from 'reactstrap/lib/Col'; +import FeedbackQuestionContainer from '../FeedbackQuestionContainer'; import { FeedbackQuestionProps } from '../FeedbackQuestionProps'; function renderButton(index: number, activeIndex: number, setActiveIndex: React.Dispatch>) { + const isActive = activeIndex === index; + return (