done selectors for initiales and finales

main
Yuriy Evdokimov 2023-09-27 23:11:26 +05:00
parent ea9747edc5
commit 5876aed345
9 changed files with 145 additions and 23 deletions

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title> <title>Pinyin dictation</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@ -40,3 +40,7 @@
.read-the-docs { .read-the-docs {
color: #888; color: #888;
} }
.btn {
margin-bottom: 5px;
}

View File

@ -1,23 +1,61 @@
import { useState } from 'react' import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css' import './App.css'
import { Button } from 'react-bootstrap'; import { Button } from 'react-bootstrap';
import Accordion from 'react-bootstrap/Accordion';
import Form from 'react-bootstrap/Form';
import { initials, finales } from './Data';
import { Btn, BtnSimple } from './Btn';
import { isEnabled, toggle } from './Utils';
function App() { function App() {
const [count, setCount] = useState(0)
const [count, setCount] = useState(10)
const [pause, setPause] = useState(3)
const [ enabledInitials, setInitialsState ] = useState([] as String[])
const toggleInitialsState = (caption: String) => setInitialsState(toggle(enabledInitials,caption))
const [ enabledFinals, setFinalsState ] = useState([] as String[])
const toggleFinalsState = (caption: String) => setFinalsState(toggle(enabledFinals,caption))
return ( return (
<> <>
<div> <h1>Диктант pīnyīn</h1>
<a href="https://vitejs.dev" target="_blank"> <Accordion defaultActiveKey="0">
<img src={viteLogo} className="logo" alt="Vite logo" /> <Accordion.Item eventKey="0">
</a> <Accordion.Header>Выберите инициали</Accordion.Header>
<a href="https://react.dev" target="_blank"> <Accordion.Body>
<img src={reactLogo} className="logo react" alt="React logo" /> <Btn type="primary" text="Выбрать все" altText="Снять все"/>
</a> {initials.map( (text) => <BtnSimple
</div> type="primary"
<h1>Vite + React</h1> text={text}
enabled={isEnabled(enabledInitials, text)}
onclick={toggleInitialsState}/>
)}
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="1">
<Accordion.Header>Выберите финали</Accordion.Header>
<Accordion.Body>
<Btn type="success" text="Выбрать все" altText="Снять все"/>
{finales.map( (text) => <BtnSimple
type="success"
text={text}
enabled={isEnabled(enabledFinals, text)}
onclick={toggleFinalsState}/>
)}
</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="2">
<Accordion.Header>Параметры</Accordion.Header>
<Accordion.Body>
<Form.Label>Количество слогов {count}</Form.Label>
<Form.Range defaultValue={10} min={5} max={50} step={5}/>
<Form.Label>Пауза между слогами {pause} секунд</Form.Label>
<Form.Range defaultValue={3} min={1} max={10} step={1}/>
</Accordion.Body>
</Accordion.Item>
</Accordion>
<div className="card"> <div className="card">
<Button variant="success" onClick={() => setCount((count) => count + 1)}> <Button variant="success" onClick={() => setCount((count) => count + 1)}>
count is {count} count is {count}
@ -29,14 +67,6 @@ function App() {
<p className="read-the-docs"> <p className="read-the-docs">
Click on the Vite and React logos to learn more Click on the Vite and React logos to learn more
</p> </p>
<Button variant="primary">Primary</Button>{' '}
<Button variant="secondary">Secondary</Button>{' '}
<Button variant="success">Success</Button>{' '}
<Button variant="warning">Warning</Button>{' '}
<Button variant="danger">Danger</Button>{' '}
<Button variant="info">Info</Button>{' '}
<Button variant="light">Light</Button>{' '}
<Button variant="dark">Dark</Button> <Button variant="link">Link</Button>
</> </>
) )
} }

39
src/Btn.tsx Normal file
View File

@ -0,0 +1,39 @@
import { ReactElement, useState } from 'react'
import { Button } from 'react-bootstrap';
import { justproc, proc } from './Types';
interface IBtnProps {
type: String,
text: String,
altText?: String
onclick?: justproc
}
interface IBtnSimpleProps {
type: String,
text: String,
enabled: Boolean,
onclick?: proc
}
export function Btn ({ type, text, altText, onclick }: IBtnProps): ReactElement {
const [enabled, toggleState] = useState(false)
const alttext = altText ?? text;
const onclicklocal = () => {
toggleState(!enabled)
if (onclick) onclick!()
}
return <><Button
variant={`${enabled ? "" : "outline-"}${type}`}
onClick={ onclicklocal }>{enabled ? alttext : text}
</Button>{' '}</>
}
export function BtnSimple ({ type, text, enabled, onclick }: IBtnSimpleProps): ReactElement {
const onclickdefault: proc = (caption: String) => {console.log(caption)}
const onclickinternal: proc = onclick ?? onclickdefault
return <>
<Button variant={`${enabled ? "" : "outline-"}${type}`} onClick={()=>onclickinternal(text)}>{text}</Button>
{' '}
</>
}

28
src/BtnSet.tsx Normal file
View File

@ -0,0 +1,28 @@
import { ReactElement, useState } from 'react'
import { Btn, BtnSimple } from './Btn'
import { isEnabled, toggle } from './Utils'
function BtnSet(captions: String[], type: String): ReactElement {
const [ enabledButtons, setButtonsState ] = useState([] as String[])
const [ selectedAll, toggleSelectAll ] = useState(false)
const toggleState = (caption: String) => setButtonsState(toggle(enabledButtons,caption))
const toggleAll = () => {
toggleSelectAll( !selectedAll )
if (!selectedAll) setButtonsState([... captions])
else setButtonsState([])
}
return <>
<Btn type={type} text="Выбрать все" altText="Снять все" onclick={toggleAll}/>
{captions.map( (text) => <BtnSimple
type={type}
text={text}
enabled={isEnabled(enabledButtons, text)}
onclick={toggleState}/>
)}
</>
}
export default BtnSet

11
src/Data.ts Normal file
View File

@ -0,0 +1,11 @@
export const initials = [
'b', 'p', 'm', 'f', 'd', 't', 'n', 'l', 'g', 'k',
'h', 'j', 'q', 'x', 'zh', 'ch', 'sh', 'r', 'z', 'c', 's'
]
export const finales = [
'a', 'ai', 'an', 'ang', 'ao', 'e', 'ei', 'en', 'eng', 'er',
'i', 'ia', 'ian', 'iang', 'iao', 'ie', 'in', 'ing', 'io', 'iong', 'iu',
'o', 'ong', 'ou', 'u', 'ua', 'uai', 'uan', 'uang', 'ui', 'un', 'uo',
'ü', 'üan', 'üe', 'ün'
]

2
src/Types.ts Normal file
View File

@ -0,0 +1,2 @@
export type proc = (caption: String) => void;
export type justproc = () => void;

8
src/Utils.ts Normal file
View File

@ -0,0 +1,8 @@
export const isEnabled = (arr: String[], caption: String): Boolean => arr.some((btn) => btn==caption)
export const toggle = ( arr: String[], caption: String ):String[] => {
if ( arr.some((btn) => btn==caption) )
return arr.filter((el)=>el!==caption)
else
return [ ...arr, caption]
}

View File

@ -7,8 +7,8 @@
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */
"moduleResolution": "bundler", "moduleResolution": "Node",
"allowImportingTsExtensions": true, // "allowImportingTsExtensions": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,