add servant and king explanations

This commit is contained in:
lingdocs 2022-04-14 12:12:49 +05:00
parent 9b5e19f39e
commit d9c0ed9630
3 changed files with 109 additions and 28 deletions

View File

@ -1,12 +1,37 @@
import * as T from "../types";
import Select from "react-select";
import { StyleHTMLAttributes } from "react";
import Select, { StylesConfig } from "react-select";
import AsyncSelect from "react-select/async";
import {
makeSelectOption,
makeVerbSelectOption,
zIndexProps,
} from "./np-picker/picker-tools";
const customStyles: StylesConfig = {
menuPortal: (base) => ({
...base,
zIndex: 99999,
}),
menu: (base) => ({
...base,
zIndex: 999999,
}),
option: (provided, state) => ({
...provided,
padding: "10px 5px",
}),
input: (base) => ({
...base,
padding: 0,
}),
singleValue: (provided, state) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = 'opacity 300ms';
return { ...provided, opacity, transition };
}
}
function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({
entries: E[]
} | {
@ -18,9 +43,10 @@ function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({
name: string | undefined,
isVerbSelect?: boolean,
opts: T.TextOptions,
style?: StyleHTMLAttributes<HTMLDivElement>,
}) {
const divStyle = props.style || { width: "13rem" };
const placeholder = "entries" in props ? "Select…" : "Search Pashto";
const minWidth = "9rem";
function makeOption(e: E | T.DictionaryEntry) {
if ("entry" in e) {
return (props.isVerbSelect ? makeVerbSelectOption : makeSelectOption)(e, props.opts);
@ -42,16 +68,17 @@ function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({
if (!s) return;
props.onChange(s);
}
return <div style={{ minWidth }}>
return <div style={divStyle}>
<AsyncSelect
styles={customStyles}
isSearchable={true}
className="mb-2"
value={value}
// @ts-ignore
onChange={onChange}
defaultOptions={[]}
loadOptions={options}
placeholder={placeholder}
{...zIndexProps}
/>
</div>;
}
@ -76,15 +103,16 @@ function EntrySelect<E extends T.DictionaryEntry | T.VerbEntry>(props: ({
if (!s) return;
props.onChange(s);
}
return <div style={{ minWidth }}>
return <div style={divStyle}>
<Select
styles={customStyles}
isSearchable={true}
value={value}
// @ts-ignore
onChange={onChange}
className="mb-2"
options={options}
placeholder={placeholder}
{...zIndexProps}
/>
</div>
}

View File

@ -56,7 +56,7 @@ function NPPicker(props: {
const clearButton = !props.cantClear
? <button className="btn btn-sm btn-light mb-2" onClick={handleClear}>X</button>
: <div></div>;
return <div>
return <div style={{ minWidth: "9rem" }}>
{!npType && <div className="text-center mt-3">
<div className="h6 mr-3">
Choose NP

View File

@ -3,7 +3,7 @@ import VerbPicker from "./VerbPicker";
import TensePicker from "./TensePicker";
import VPDisplay from "./VPDisplay";
import ButtonSelect from "../ButtonSelect";
import { Modal } from "react-bootstrap";
import {
isInvalidSubjObjCombo,
} from "../../lib/phrase-building/vp-tools";
@ -11,15 +11,14 @@ import * as T from "../../types";
import ChartDisplay from "./ChartDisplay";
import useStickyState from "../../lib/useStickyState";
import { makeVPSelectionState } from "./verb-selection";
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { getKingAndServant } from "../../lib/phrase-building/render-vp";
import { isPastTense } from "../../lib/phrase-building/vp-tools";
import VPExplorerQuiz from "./VPExplorerQuiz";
import { switchSubjObj } from "../../lib/phrase-building/vp-tools"
const kingEmoji = "👑";
const servantEmoji = "🙇‍♂️";
import { switchSubjObj } from "../../lib/phrase-building/vp-tools";
const kingIcon = <i className="mx-1 fas fa-crown" />;
const servantIcon = <i className="mx-1 fas fa-male" />;
// TODO: make answerFeedback emojis appear at random translate angles a little bit
// add energy drinks?
@ -61,7 +60,9 @@ export function VPExplorer(props: {
},
"verbExplorerMode",
);
const [showingKingExplanation, setShowingKingExplanation] = useState<"subject" | "object" | false>(false);
const [showingServantExplanation, setShowingServantExplanation] = useState<"subject" | "object" | false>(false);
const roles = getKingAndServant(isPastTense(vps.verb.tense), vps.verb.transitivity !== "intransitive");
useEffect(() => {
setVps(oldVps => {
if (mode === "quiz") {
@ -139,7 +140,9 @@ export function VPExplorer(props: {
{mode !== "quiz" && <div className="d-flex flex-row justify-content-around flex-wrap" style={{ marginLeft: "-0.5rem", marginRight: "-0.5rem" }}>
{mode === "phrases" && <>
<div className="my-2">
<div className="h5 text-center">Subject {showRole(vps, "subject")}</div>
{roles.king === "subject"
? <div className="h5 text-center clickable" onClick={() => setShowingKingExplanation("subject")}>Subject {kingIcon}</div>
: <div className="h5 text-center clickable" onClick={() => setShowingKingExplanation("subject")}>Subject {servantIcon}</div>}
<NPPicker
{..."getNounByTs" in props ? {
getNounByTs: props.getNounByTs,
@ -157,7 +160,9 @@ export function VPExplorer(props: {
/>
</div>
{vps.verb && (vps.verb.object !== "none") && <div className="my-2">
<div className="h5 text-center">Object {showRole(vps, "object")}</div>
{roles.king === "object"
? <div className="h5 text-center clickable" onClick={() => setShowingKingExplanation("object")}>Object {kingIcon}</div>
: <div className="h5 text-center clickable" onClick={() => setShowingServantExplanation("object")}>Object {servantIcon}</div>}
{(typeof vps.verb.object === "number")
? <div className="text-muted">Unspoken 3rd Pers. Masc. Plur.</div>
: <NPPicker
@ -189,6 +194,64 @@ export function VPExplorer(props: {
{mode === "phrases" && <VPDisplay VP={vps} opts={props.opts} />}
{mode === "charts" && <ChartDisplay VS={vps.verb} opts={props.opts} />}
{mode === "quiz" && <VPExplorerQuiz opts={props.opts} vps={vps} />}
<Modal show={!!showingKingExplanation} onHide={() => setShowingKingExplanation(false)}>
<Modal.Header closeButton>
<Modal.Title>About the King {kingIcon}</Modal.Title>
</Modal.Header>
<Modal.Body>
In this tense/form, the {showingKingExplanation} is the <strong>king</strong> {kingIcon} of the phrase. That means that:
<ul className="mt-2">
<li>
<div>It controls the verb conjugation. The verb agrees with the gender and number of the king.</div>
</li>
<li>
<div>👍 It <strong>can</strong> be removed / left out from the phrase.</div>
<div className="text-muted">(You can kill the king)</div>
</li>
<li>
<div>🙅 It <strong>cannot be</strong> shrunk it into a <a target="_blank" rel="noreferrer" href="https://grammar.lingdocs.com/pronouns/pronouns-mini/">mini-pronoun</a>. 👶</div>
<div className="text-muted">(You can't shrink the king)</div>
</li>
</ul>
<p>Mnemonic for shortening phrases:</p>
<p className="text-muted">"🚫 Kill the king 👶 Shrink the servant"</p>
</Modal.Body>
<Modal.Footer>
<button type="button" className="btn btn-primary clb" onClick={() => setShowingKingExplanation(false)}>
Close
</button>
</Modal.Footer>
</Modal>
<Modal show={!!showingServantExplanation} onHide={() => setShowingServantExplanation(false)}>
<Modal.Header closeButton>
<Modal.Title>About the Servant {servantIcon}</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
In this tense/form, the {showingServantExplanation} is the <strong>servant</strong> {servantIcon} of the phrase. That means that:
</p>
<ul>
<li>
It does not affect the conjugation of the verb. That's the king's job.
</li>
<li>
<div>👍 It <strong>can</strong> shrink it into a <a target="_blank" rel="noreferrer" href="https://grammar.lingdocs.com/pronouns/pronouns-mini/">mini-pronoun</a>. 👶</div>
<div className="text-muted">(You can <strong>shrink the servant</strong>)</div>
</li>
<li>
<div>🙅 It <strong>cannot</strong> be removed / left out of the phrase</div>
<div className="text-muted">(You can't kill the servant)</div>
</li>
</ul>
<p>Mnemonic for shortening phrases:</p>
<p className="text-muted">"🚫 Kill the king 👶 Shrink the servant"</p>
</Modal.Body>
<Modal.Footer>
<button type="button" className="btn btn-primary clb" onClick={() => setShowingServantExplanation(false)}>
Close
</button>
</Modal.Footer>
</Modal>
</div>
}
@ -201,14 +264,4 @@ function hasPronounConflict(subject: T.NPSelection | undefined, object: undefine
return isInvalidSubjObjCombo(subjPronoun.person, objPronoun.person);
}
function showRole(VP: T.VPSelection, member: "subject" | "object") {
const roles = getKingAndServant(
isPastTense(VP.verb.tense),
VP.verb.transitivity !== "intransitive",
);
return VP
? <span className="ml-2">
{(roles.king === member ? kingEmoji : roles.servant === member ? servantEmoji : "")}
</span>
: "";
}