From 78f7046e9be8113813edfe8966fc88927a2bae29 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Tue, 27 Aug 2024 11:51:50 +0200 Subject: [PATCH] refactor(Block): Properly type the child components of `Block.tsx` --- frontend/src/components/Block/Block.tsx | 118 +++++++----------- .../src/components/Explainer/Explainer.tsx | 2 +- frontend/src/components/Final/Final.tsx | 2 +- frontend/src/components/Info/Info.tsx | 2 +- frontend/src/components/Loading/Loading.tsx | 2 +- frontend/src/components/Playlist/Playlist.tsx | 2 +- frontend/src/components/Redirect/Redirect.tsx | 2 +- frontend/src/components/Score/Score.tsx | 2 +- frontend/src/components/Trial/Trial.tsx | 2 +- 9 files changed, 50 insertions(+), 84 deletions(-) diff --git a/frontend/src/components/Block/Block.tsx b/frontend/src/components/Block/Block.tsx index 0bbcc18a0..fb040c940 100644 --- a/frontend/src/components/Block/Block.tsx +++ b/frontend/src/components/Block/Block.tsx @@ -5,87 +5,43 @@ import classNames from "classnames"; import useBoundStore from "@/util/stores"; import { getNextRound, useBlock } from "@/API"; -import Consent from "@/components/Consent/Consent"; +import Consent, { ConsentProps } from "@/components/Consent/Consent"; import DefaultPage from "@/components/Page/DefaultPage"; -import Explainer from "@/components/Explainer/Explainer"; -import Final from "@/components/Final/Final"; -import Loading from "@/components/Loading/Loading"; -import Playlist from "@/components/Playlist/Playlist"; -import Score from "@/components/Score/Score"; -import Trial, { IFeedbackForm } from "@/components/Trial/Trial"; -import Info from "@/components/Info/Info"; +import Explainer, { ExplainerProps } from "@/components/Explainer/Explainer"; +import Final, { FinalProps } from "@/components/Final/Final"; +import Loading, { LoadingProps } from "@/components/Loading/Loading"; +import Playlist, { PlaylistProps } from "@/components/Playlist/Playlist"; +import Score, { ScoreProps } from "@/components/Score/Score"; +import Trial, { TrialProps } from "@/components/Trial/Trial"; +import Info, { InfoProps } from "@/components/Info/Info"; import FloatingActionButton from "@/components/FloatingActionButton/FloatingActionButton"; import UserFeedback from "@/components/UserFeedback/UserFeedback"; import FontLoader from "@/components/FontLoader/FontLoader"; import useResultHandler from "@/hooks/useResultHandler"; import Session from "@/types/Session"; -import { PlaybackArgs, PlaybackView } from "@/types/Playback"; -import { FeedbackInfo, Step } from "@/types/Block"; -import { TrialConfig } from "@/types/Trial"; -import Social from "@/types/Social"; +import { PlaybackView } from "@/types/Playback"; +import { RedirectProps } from "../Redirect/Redirect"; type BlockView = PlaybackView | "TRIAL_VIEW" | "EXPLAINER" | "SCORE" | "FINAL" | "PLAYLIST" | "LOADING" | "CONSENT" | "INFO" | "REDIRECT"; -interface ActionProps { - - view: BlockView; +interface SharedActionProps { title?: string; - url?: string; - next_round?: any[]; - - // Some views require additional data - button_label?: string; - instruction?: string; - timer?: number; - steps: Step[]; - body?: string; - html?: string; - feedback_form?: IFeedbackForm; - playback?: PlaybackArgs; - config?: TrialConfig; - - // TODO: Think about how to properly handle the typing of different views - - // Score-related - score?: number; - score_message?: string; - texts?: { - score: string; - next: string; - listen_explainer: string; - }; - feedback?: string; - icon?: string; - - // Final related - feedback_info?: FeedbackInfo; - rank?: string; - button?: { - text: string; - link: string; - }; - final_text?: string | TrustedHTML; - show_participant_link?: boolean; - participant_id_only?: boolean; - show_profile_link?: boolean; - action_texts?: { - all_experiments: string; - profile: string; - play_again: string; - } - points?: string; - social?: Social; - logo?: { - image: string; - link: string; - }; - - // Consent related - text?: string; - confirm?: string; - deny?: string; + config?: object; + style?: object; } +type ActionProps = SharedActionProps & + ( + | { view: "CONSENT" } & ConsentProps + | { view: "EXPLAINER" } & ExplainerProps + | { view: "INFO" } & InfoProps + | { view: "TRIAL_VIEW" } & TrialProps + | { view: 'SCORE' } & ScoreProps + | { view: 'FINAL' } & FinalProps + | { view: 'PLAYLIST' } & PlaylistProps + | { view: 'REDIRECT' } & RedirectProps + | { view: "LOADING" } & LoadingProps + ) // Block handles the main (experiment) block flow: // - Loads the block and participant @@ -239,11 +195,20 @@ const Block = () => { }); // Render block state - const render = (view: BlockView) => { + const render = () => { + + if (!state) { + return ( +
+ No valid state +
+ ); + } + // Default attributes for every view const attrs = { - block, - participant, + block: block!, + participant: participant!, loadingText, onResult, onNext, @@ -252,7 +217,7 @@ const Block = () => { }; // Show view, based on the unique view ID: - switch (view) { + switch (attrs.view) { // Block views // ------------------------- case "TRIAL_VIEW": @@ -261,7 +226,7 @@ const Block = () => { // Information & Scoring // ------------------------- case "EXPLAINER": - return ; + return ; case "SCORE": return ; case "FINAL": @@ -278,7 +243,8 @@ const Block = () => { case "INFO": return ; case "REDIRECT": - return window.location.replace(state.url); + window.location.replace(state.url); + return null; default: return ( @@ -326,7 +292,7 @@ const Block = () => { } className={className} > - {render(view)} + {render()} {block?.feedback_info?.show_float_button && ( diff --git a/frontend/src/components/Explainer/Explainer.tsx b/frontend/src/components/Explainer/Explainer.tsx index 8137f6f79..d4a0ff7c1 100644 --- a/frontend/src/components/Explainer/Explainer.tsx +++ b/frontend/src/components/Explainer/Explainer.tsx @@ -6,7 +6,7 @@ interface ExplainerStep { description: string; } -interface ExplainerProps { +export interface ExplainerProps { instruction: string; button_label: string; steps?: Array; diff --git a/frontend/src/components/Final/Final.tsx b/frontend/src/components/Final/Final.tsx index fb3f7679d..c6104a1c2 100644 --- a/frontend/src/components/Final/Final.tsx +++ b/frontend/src/components/Final/Final.tsx @@ -14,7 +14,7 @@ import ISocial from "@/types/Social"; import Block, { FeedbackInfo } from "@/types/Block"; import Participant from "@/types/Participant"; -interface FinalProps { +export interface FinalProps { block: Block; participant: Participant; score: number; diff --git a/frontend/src/components/Info/Info.tsx b/frontend/src/components/Info/Info.tsx index b8de15166..b25affc2b 100644 --- a/frontend/src/components/Info/Info.tsx +++ b/frontend/src/components/Info/Info.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import Button from "../Button/Button"; -interface InfoProps { +export interface InfoProps { heading?: string; body: string | TrustedHTML; button_label?: string; diff --git a/frontend/src/components/Loading/Loading.tsx b/frontend/src/components/Loading/Loading.tsx index df448691f..cdfbabbd6 100644 --- a/frontend/src/components/Loading/Loading.tsx +++ b/frontend/src/components/Loading/Loading.tsx @@ -1,6 +1,6 @@ import Circle from "../Circle/Circle"; -interface LoadingProps { +export interface LoadingProps { duration?: number; loadingText?: string; } diff --git a/frontend/src/components/Playlist/Playlist.tsx b/frontend/src/components/Playlist/Playlist.tsx index 5dab5120d..d62e3befe 100644 --- a/frontend/src/components/Playlist/Playlist.tsx +++ b/frontend/src/components/Playlist/Playlist.tsx @@ -1,7 +1,7 @@ import { ExtendedBlock } from "@/types/Block"; import { MutableRefObject, useEffect } from "react"; -interface PlaylistProps { +export interface PlaylistProps { block: ExtendedBlock; instruction: string; onNext: () => void; diff --git a/frontend/src/components/Redirect/Redirect.tsx b/frontend/src/components/Redirect/Redirect.tsx index f3e929d23..2300dd696 100644 --- a/frontend/src/components/Redirect/Redirect.tsx +++ b/frontend/src/components/Redirect/Redirect.tsx @@ -1,7 +1,7 @@ import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; -interface RedirectProps { +export interface RedirectProps { to: string; } diff --git a/frontend/src/components/Score/Score.tsx b/frontend/src/components/Score/Score.tsx index d78c5caa5..49467b0ad 100644 --- a/frontend/src/components/Score/Score.tsx +++ b/frontend/src/components/Score/Score.tsx @@ -3,7 +3,7 @@ import classNames from "classnames"; import Circle from "../Circle/Circle"; import Button from "../Button/Button"; -interface ScoreProps { +export interface ScoreProps { last_song?: string; score: number; score_message: string; diff --git a/frontend/src/components/Trial/Trial.tsx b/frontend/src/components/Trial/Trial.tsx index a4d717d7a..c0183aa3f 100644 --- a/frontend/src/components/Trial/Trial.tsx +++ b/frontend/src/components/Trial/Trial.tsx @@ -17,7 +17,7 @@ export interface IFeedbackForm { is_skippable: boolean; } -interface TrialProps { +export interface TrialProps { playback: any; html: { body: string | TrustedHTML }; feedback_form: IFeedbackForm;