Yuriy Evdokimov 2023-10-13 23:55:39 +05:00
parent dff64780f5
commit 55537aa02f
5 changed files with 37 additions and 32 deletions

View File

@ -2,24 +2,20 @@ import { useState } from 'react'
import './App.css'
import { Badge, Button, ListGroup } from 'react-bootstrap';
import { initials, finales } from './data';
import { BtnColor, Tone } from './types';
import { BtnColor, Status, Tone } from './types';
import { strings } from './strings';
import { useStateContext } from './store';
import { Params } from './params';
import { ActionType, ToggleType } from './reducer';
import { ButtonSet } from './buttons';
enum Status {params, plaing, plaied, showlist}
function App() {
const { state, dispatch } = useStateContext();
//---------------- to found state
const isFound = ():boolean => state.foundSyllables!.length > 0
const [plaingNo, setPlaingNo ] = useState(0)
const [ status, setStatus ] = useState(Status.params)
const setStatus = (status: Status) => { dispatch({ type: ActionType.setStatus, payload: status}) }
const beginDictation = (): void => {
dispatch({ type: ActionType.refreshPlayList })
@ -36,7 +32,7 @@ const playDictation2 = (randomTones: Tone[]) => {
if ( audios.length == 0 ) return
for(let x=0; x<audios.length-1;x++)
{
audios[x].onended = () => setTimeout( () => {
audios[x].onended = () => setTimeout( () => {
let pno = x+2
setPlaingNo(pno)
audios[x+1].play()
@ -61,40 +57,44 @@ const refresh = () => {
<>
<h1>Диктант pīnyīn</h1>
<ListGroup>
<ListGroup.Item disabled={status != Status.params}>
<ListGroup.Item disabled={state.status != Status.params}>
<h2>{strings.selectInitiales}</h2>
<ButtonSet source={initials} color={BtnColor.blue} toggle={ToggleType.init}/>
</ListGroup.Item>
<ListGroup.Item disabled={status != Status.params}>
<ListGroup.Item disabled={state.status != Status.params}>
<h2>{strings.selectFinales}</h2>
<ButtonSet source={finales} color={BtnColor.green} toggle={ToggleType.fin}/>
</ListGroup.Item>
<ListGroup.Item disabled={status != Status.params}>
<ListGroup.Item disabled={state.status != Status.params}>
<h2>{strings.params}</h2>
<Params/>
</ListGroup.Item>
<ListGroup.Item>
{ status == Status.params &&
{ state.status == Status.params &&
<>
Выбрано {state.initiales!.length} инициалей, {state.finales!.length} финалей, найдено {state.foundSyllables!.length} слогов, { state.foundTones!.length } тонов ,
<br/>
<Button variant={isFound() ? "success" : "secondary"} size="lg" onClick={()=>beginDictation()} disabled={!isFound()}>
{isFound() ? "Начать диктант!" : "Выберите инициали и финали" }
<Button
variant={state.isFound!() ? "success" : "secondary"}
size="lg"
onClick={()=>beginDictation()}
disabled={!state.isFound!()}>
{state.isFound!() ? "Начать диктант!" : "Выберите инициали и финали" }
</Button>
</>
}
{
status == Status.plaing &&
state.status == Status.plaing &&
<h1>Воспроизводится...{plaingNo}</h1>
}
{
status == Status.plaied &&
state.status == Status.plaied &&
<Button variant="success" onClick={()=>setStatus(Status.showlist)}>Показать слоги</Button>
}
{
status == Status.showlist &&
state.status == Status.showlist &&
<>
<div>{renderRandomTones2()}</div>
<br/>

View File

@ -3,5 +3,6 @@ export const strings = {
selectFinales: 'Выберите финали',
selectAll: 'Выбрать все',
unselectAll: 'Снять все',
params: 'Параметры'
params: 'Параметры',
sylCount: 'Количество слогов'
}

View File

@ -17,12 +17,13 @@ export const ButtonSet = (props: IBtnSerProps) => {
return <>
<Button variant={ state.allEnabled!(toggle) ? color : Outlined(color) }
onClick= {()=>dispatch({type: ActionType.toggleAll, payload: toggle})}>
{state.allInitiales ? strings.unselectAll : strings.selectAll}
{state.allEnabled!(toggle) ? strings.unselectAll : strings.selectAll}
</Button>
{ source.map( (part, i) => <Button
{ source.map( (part, i) => <Button
variant={ state.isEnabled!(toggle, part.index) ? color : Outlined(color) }
key={i} onClick={()=>dispatch({
type: ActionType.toggleOne,
key={i}
onClick={()=>dispatch({
type: ActionType.toggleOne,
payload: { type: toggle, part: part }
})}>
{part.caption}

View File

@ -8,14 +8,13 @@ export const Params = (): ReactElement => {
const { state, dispatch } = useStateContext();
const pausedispatcher = (e: React.ChangeEvent<HTMLInputElement>) =>
const pausedispatcher = (e: React.ChangeEvent<HTMLInputElement>) =>
dispatch({ type: ActionType.setPause, payload: Number(e.target.value)})
const countdispatcher = (e: React.ChangeEvent<HTMLInputElement>) =>
const countdispatcher = (e: React.ChangeEvent<HTMLInputElement>) =>
dispatch({ type: ActionType.setCount, payload: Number(e.target.value)})
return <>
<h2>{strings.params}</h2>
<Form.Label>Количество слогов {state.sylCount}</Form.Label>
<Form.Label>{strings.sylCount} {state.sylCount}</Form.Label>
<Form.Range value={state.sylCount} min={5} max={50} step={5} onChange={countdispatcher}/>
<Form.Label>Пауза между слогами {state.sylPause} секунд</Form.Label>
<Form.Range value={state.sylPause} min={1} max={10} step={1} onChange={pausedispatcher}/>

View File

@ -1,6 +1,6 @@
import { Context, createContext, Dispatch, ReactElement, useContext, useReducer } from "react";
import { reducer, Action, ToggleType } from "./reducer"
import { Syllable, SylPart, Tone } from "./types";
import { Status, Syllable, SylPart, Tone } from "./types";
import { isEnabled } from "./utils";
export interface IState {
@ -14,7 +14,9 @@ export interface IState {
foundTones: Tone[],
randomTones: Tone[],
allEnabled: (type: ToggleType) => false,
isEnabled: (type: ToggleType, index: string) => false
isEnabled: (type: ToggleType, index: string) => false,
isFound: () => false,
status: Status
}
export interface IStore {
@ -37,11 +39,13 @@ export const defaultState:Object = {
if ( type === ToggleType.fin ) return (this as IState).allfinales
return false
},
isEnabled: function(type: ToggleType, index: string) {
if ( type === ToggleType.init ) return isEnabled((this as IState).initiales!, index)
isEnabled: function(type: ToggleType, index: string) {
if ( type === ToggleType.init ) return isEnabled((this as IState).initiales!, index)
if ( type === ToggleType.fin ) return isEnabled((this as IState).finales!, index)
return false
}
return false
},
isFound: function():boolean { return (this as IState).foundSyllables!.length > 0 },
status: Status.params
}
export const AppContext:Context<IStore> = createContext<IStore>({ state: defaultState as IState, dispatch: () => null })