study links on browser and formatting fix on phonetics viewer
This commit is contained in:
parent
a0b1c04d1d
commit
32dc0518a2
|
@ -23,6 +23,7 @@
|
|||
"react-countdown-circle-timer": "^2.5.4",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-ga": "^3.3.0",
|
||||
"react-media": "^1.10.0",
|
||||
"react-rewards": "^1.1.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-router-hash-link": "^2.3.1",
|
||||
|
|
|
@ -37,8 +37,6 @@ if (prod) {
|
|||
function App(props: RouteComponentProps) {
|
||||
const [navOpen, setNavOpen] = useState(false);
|
||||
const { user } = useUser();
|
||||
// TODO: seperate function for getUserInfo with useUser and fetch
|
||||
// then set cronjob to call that - also do signin flox
|
||||
useEffect(() => {
|
||||
ReactGA.pageview(window.location.pathname);
|
||||
}, []);
|
||||
|
|
|
@ -12,7 +12,7 @@ const isObject = x => (
|
|||
function Table({ headRow, children, opts, wide }) {
|
||||
return (
|
||||
<div style={{ overflowX: "auto", marginBottom: "1em" }}>
|
||||
<table class="table" style={wide ? { minWidth: "635px" } : {}}>
|
||||
<table className="table" style={wide ? { minWidth: "635px" } : {}}>
|
||||
{headRow && <thead>
|
||||
<tr>
|
||||
{headRow.map((h, i) => (
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from "./phonemes";
|
||||
import playAudio from "../../lib/play-audio";
|
||||
import views from "./views";
|
||||
import Media from "react-media";
|
||||
|
||||
export type ViewOptions = "all" | "shortVowel" | "longVowel" | "fiveYs" | "specialConsonant";
|
||||
|
||||
|
@ -42,74 +43,80 @@ class PhoneticsViewer extends React.Component<any, IAppState> {
|
|||
}
|
||||
return <>
|
||||
<div className="text-center mt-4">
|
||||
<div className="btn-group mb-3">
|
||||
{views.map(({ label, value }) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
className={classNames("btn", "btn-outline-secondary", {
|
||||
active: this.state.view === value,
|
||||
})}
|
||||
onClick={() => this.setState({ view: value })}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<Media queries={{ small: "(max-width: 599px)" }}>
|
||||
{matches => (
|
||||
<div className={`btn-group${matches.small ? "-vertical" : ""} mb-3`}>
|
||||
{views.map(({ label, value }) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
className={classNames("btn", "btn-outline-secondary", {
|
||||
active: this.state.view === value,
|
||||
})}
|
||||
onClick={() => this.setState({ view: value })}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Media>
|
||||
<div className="small mb-2"><i className="fas fa-volume-down"></i> click the phonetic letter or examples to hear - not all sounds are available</div>
|
||||
</div>
|
||||
<table className="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Phonetic Letter</th>
|
||||
{/* <th>IPA Letter</th> */}
|
||||
<th>Short Explanation</th>
|
||||
<th>Example</th>
|
||||
<th>Pashto Letter(s)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{phonemesShowing.map((phoneme) => (
|
||||
<tr key={phoneme.phoneme}>
|
||||
<td onClick={generatePlayerFunction(phoneme)}>
|
||||
{phoneme.phoneme}
|
||||
</td>
|
||||
{/* <td>{phoneme.ipa.letter} </td> */}
|
||||
<td>
|
||||
{phoneme.quickExplanation}{" "}
|
||||
{phoneme.ipa.video && (
|
||||
<a href={phoneme.ipa.video} target="_blank" rel="noopener noreferrer">
|
||||
<i className="fa fa-video" />
|
||||
</a>
|
||||
)}
|
||||
</td>
|
||||
<td onClick={generatePlayerFunction(phoneme.examples[0])}>
|
||||
{highlightExample(
|
||||
phoneme.examples[0].f,
|
||||
phoneme.examples[0].fHighlight
|
||||
)}
|
||||
{` - `}
|
||||
{highlightExample(
|
||||
phoneme.examples[0].p,
|
||||
phoneme.examples[0].pHighlight
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{phoneme.possibleLetters
|
||||
? phoneme.possibleLetters.reduce(
|
||||
(s, l) =>
|
||||
`${s}${l.letter} ${
|
||||
l.alternate ? ` (${l.alternate}) ` : ""
|
||||
}`,
|
||||
""
|
||||
)
|
||||
: ""}
|
||||
{/* phoneme.diacritic && `(diacritic ◌${phoneme.diacritic})` */}
|
||||
</td>
|
||||
<div style={{ overflowX: "auto", marginBottom: "1em" }}>
|
||||
<table className="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Phonetic Letter</th>
|
||||
{/* <th>IPA Letter</th> */}
|
||||
<th>Short Explanation</th>
|
||||
<th>Example</th>
|
||||
<th>Pashto Letter(s)</th>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
{phonemesShowing.map((phoneme) => (
|
||||
<tr key={phoneme.phoneme}>
|
||||
<td onClick={generatePlayerFunction(phoneme)}>
|
||||
{phoneme.phoneme}
|
||||
</td>
|
||||
{/* <td>{phoneme.ipa.letter} </td> */}
|
||||
<td>
|
||||
{phoneme.quickExplanation}{" "}
|
||||
{phoneme.ipa.video && (
|
||||
<a href={phoneme.ipa.video} target="_blank" rel="noopener noreferrer">
|
||||
<i className="fa fa-video" />
|
||||
</a>
|
||||
)}
|
||||
</td>
|
||||
<td onClick={generatePlayerFunction(phoneme.examples[0])}>
|
||||
{highlightExample(
|
||||
phoneme.examples[0].f,
|
||||
phoneme.examples[0].fHighlight
|
||||
)}
|
||||
{` - `}
|
||||
{highlightExample(
|
||||
phoneme.examples[0].p,
|
||||
phoneme.examples[0].pHighlight
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{phoneme.possibleLetters
|
||||
? phoneme.possibleLetters.reduce(
|
||||
(s, l) =>
|
||||
`${s}${l.letter} ${
|
||||
l.alternate ? ` (${l.alternate}) ` : ""
|
||||
}`,
|
||||
""
|
||||
)
|
||||
: ""}
|
||||
{/* phoneme.diacritic && `(diacritic ◌${phoneme.diacritic})` */}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{selectedOption?.notes && <div>
|
||||
<p><strong>Notes about {selectedOption.label.toLowerCase()}:</strong></p>
|
||||
{selectedOption.notes}
|
||||
|
|
|
@ -4,7 +4,7 @@ title: Games 🎮
|
|||
|
||||
import Link from "../components/Link";
|
||||
|
||||
There are little games/quizzes scattered throughout this book. Here you can see them all listed below. If you are <Link to="/account">logged in</Link>, when you successfully complete a game you will see a ✅ beside it. Try to master them all! 🤓🏆
|
||||
There are little games/quizzes scattered throughout this book. Here you can see them all listed below. If you are <Link to="/account">logged in</Link>, when you successfully complete a game you will see a ✅ beside it. To study for a game, click on the 📚 on the right. Try to master them all! 🤓🏆
|
||||
|
||||
There currently just a few games available. Keep checking back as over time there will be lots of games covering all the aspects of grammar.
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import games from "./games";
|
||||
import { useUser } from "../user-context";
|
||||
import Link from "../components/Link";
|
||||
import SmoothCollapse from "react-smooth-collapse";
|
||||
|
||||
function GamesBrowser() {
|
||||
|
@ -15,7 +16,7 @@ function GamesBrowser() {
|
|||
{games.map((chapter) => (
|
||||
<>
|
||||
<h3 key={chapter.chapter}>{chapter.chapter}</h3>
|
||||
{chapter.items.map(({ id, title, Game }) => {
|
||||
{chapter.items.map(({ id, title, Game, studyLink }) => {
|
||||
const done = user && user.tests.some(t => t.id === id);
|
||||
const open = opened === id;
|
||||
return <div key={id}>
|
||||
|
@ -23,10 +24,16 @@ function GamesBrowser() {
|
|||
<div>
|
||||
<h4 className="my-4 clickable" onClick={() => handleTitleClick(id)}>
|
||||
<i className={`fas fa-caret-${open ? "down" : "right"}`}></i> {title}
|
||||
{` `}
|
||||
</h4>
|
||||
</div>
|
||||
<div>
|
||||
<h4>{done ? "✅" : ""}</h4>
|
||||
<h4>
|
||||
{done ? "✅"
|
||||
:
|
||||
<Link to={studyLink}>{"📚"}</Link>
|
||||
}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<SmoothCollapse expanded={open}>
|
||||
|
|
|
@ -2,28 +2,37 @@ import React from "react";
|
|||
import GenderGame from "./sub-cores/GenderGame";
|
||||
import UnisexNounGame from "./sub-cores/UnisexNounGame";
|
||||
|
||||
function makeGameRecord(title: string, id: string, game: (id: string) => (() => JSX.Element)): GameRecord {
|
||||
function makeGameRecord(
|
||||
title: string,
|
||||
id: string,
|
||||
studyLink: string,
|
||||
game: (id: string, link: string) => (() => JSX.Element),
|
||||
): GameRecord {
|
||||
return {
|
||||
title,
|
||||
studyLink,
|
||||
id,
|
||||
Game: game(id),
|
||||
Game: game(id, studyLink),
|
||||
}
|
||||
}
|
||||
|
||||
export const nounGenderGame1 = makeGameRecord(
|
||||
"Identify Noun Genders - Level 1",
|
||||
"gender-nouns-1",
|
||||
(id) => () => <GenderGame id={id} level={1} />,
|
||||
"/nouns/nouns-gender#gender-by-ending",
|
||||
(id, link) => () => <GenderGame id={id} level={1} link={link} />,
|
||||
);
|
||||
export const nounGenderGame2 = makeGameRecord(
|
||||
"Identify Noun Genders - Level 2",
|
||||
"gender-nouns-2",
|
||||
(id) => () => <GenderGame id={id} level={2} />,
|
||||
"/nouns/nouns-gender#exceptions",
|
||||
(id, link) => () => <GenderGame id={id} level={2} link={link} />,
|
||||
);
|
||||
export const unisexNounGame = makeGameRecord(
|
||||
"Changing genders on unisex nouns",
|
||||
"unisex-nouns-1",
|
||||
(id) => () => <UnisexNounGame id={id} />,
|
||||
"/nouns/nouns-unisex/",
|
||||
(id, link) => () => <UnisexNounGame id={id} link={link} />,
|
||||
);
|
||||
|
||||
const games: { chapter: string, items: GameRecord[] }[] = [
|
||||
|
|
|
@ -50,7 +50,7 @@ const exceptions: Record<string, CategorySet> = {
|
|||
|
||||
const amount = 35;
|
||||
|
||||
export default function({level, id}: { level: 1 | 2, id: string}) {
|
||||
export default function({level, id, link}: { level: 1 | 2, id: string, link: string }) {
|
||||
function* questions () {
|
||||
const wordPool = {...types};
|
||||
const exceptionsPool = {...exceptions};
|
||||
|
@ -101,7 +101,7 @@ export default function({level, id}: { level: 1 | 2, id: string}) {
|
|||
}
|
||||
|
||||
return <GameCore
|
||||
studyLink={level === 1 ? "/nouns/nouns-gender#gender-by-ending" : "/nouns/nouns-gender#exceptions"}
|
||||
studyLink={link}
|
||||
questions={questions}
|
||||
id={id}
|
||||
Display={Display}
|
||||
|
|
|
@ -34,7 +34,7 @@ const amount = 20;
|
|||
|
||||
type Question = { entry: T.DictionaryEntry, gender: T.Gender };
|
||||
|
||||
export default function({ id }: { id: string }) {
|
||||
export default function({ id, link }: { id: string, link: string }) {
|
||||
function* questions (): Generator<Current<Question>> {
|
||||
let pool = [...nouns];
|
||||
for (let i = 0; i < amount; i++) {
|
||||
|
@ -127,7 +127,7 @@ export default function({ id }: { id: string }) {
|
|||
}
|
||||
|
||||
return <GameCore
|
||||
studyLink="/nouns/nouns-unisex#"
|
||||
studyLink={link}
|
||||
questions={questions}
|
||||
id={id}
|
||||
Display={Display}
|
||||
|
|
|
@ -18,5 +18,6 @@ type QuestionDisplayProps<T> = {
|
|||
type GameRecord = {
|
||||
title: string,
|
||||
id: string,
|
||||
studyLink: string,
|
||||
Game: () => JSX.Element,
|
||||
};
|
29
yarn.lock
29
yarn.lock
|
@ -1223,6 +1223,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.2.0":
|
||||
version "7.15.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
|
||||
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
|
||||
|
@ -7225,6 +7232,13 @@ json-stringify-safe@~5.0.1:
|
|||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||
|
||||
json2mq@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/json2mq/-/json2mq-0.2.0.tgz#b637bd3ba9eabe122c83e9720483aeb10d2c904a"
|
||||
integrity sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=
|
||||
dependencies:
|
||||
string-convert "^0.2.0"
|
||||
|
||||
json3@^3.3.2:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
|
||||
|
@ -10031,6 +10045,16 @@ react-lifecycles-compat@^3.0.4:
|
|||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-media@^1.10.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/react-media/-/react-media-1.10.0.tgz#7b0c5fe8ac55a53ce31b5249db3aaf8a22ff7703"
|
||||
integrity sha512-FjgYmFoaPTImST06jqotuu0Mk8LOXiGYS/fIyiXuLnf20l3DPniBwtrxi604/HxxjqvmHS3oz5rAwnqdvosV4A==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.2.0"
|
||||
invariant "^2.2.2"
|
||||
json2mq "^0.2.0"
|
||||
prop-types "^15.5.10"
|
||||
|
||||
react-overlays@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-5.0.0.tgz#b50351de194dda0706b40f9632d261c9f0011c4c"
|
||||
|
@ -11387,6 +11411,11 @@ strict-uri-encode@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
|
||||
|
||||
string-convert@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
|
||||
integrity sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c=
|
||||
|
||||
string-length@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
|
||||
|
|
Loading…
Reference in New Issue