done selectors for initiales and finales
parent
ea9747edc5
commit
5876aed345
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<title>Pinyin dictation</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
|
|
@ -40,3 +40,7 @@
|
|||
.read-the-docs {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
70
src/App.tsx
70
src/App.tsx
|
|
@ -1,23 +1,61 @@
|
|||
import { useState } from 'react'
|
||||
import reactLogo from './assets/react.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import './App.css'
|
||||
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() {
|
||||
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 (
|
||||
<>
|
||||
<div>
|
||||
<a href="https://vitejs.dev" target="_blank">
|
||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://react.dev" target="_blank">
|
||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + React</h1>
|
||||
<h1>Диктант pīnyīn</h1>
|
||||
<Accordion defaultActiveKey="0">
|
||||
<Accordion.Item eventKey="0">
|
||||
<Accordion.Header>Выберите инициали</Accordion.Header>
|
||||
<Accordion.Body>
|
||||
<Btn type="primary" text="Выбрать все" altText="Снять все"/>
|
||||
{initials.map( (text) => <BtnSimple
|
||||
type="primary"
|
||||
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">
|
||||
<Button variant="success" onClick={() => setCount((count) => count + 1)}>
|
||||
count is {count}
|
||||
|
|
@ -29,14 +67,6 @@ function App() {
|
|||
<p className="read-the-docs">
|
||||
Click on the Vite and React logos to learn more
|
||||
</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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
{' '}
|
||||
</>
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
]
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export type proc = (caption: String) => void;
|
||||
export type justproc = () => void;
|
||||
|
|
@ -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]
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@
|
|||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"moduleResolution": "Node",
|
||||
// "allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
|
|
|
|||
Loading…
Reference in New Issue