still doesn't work

This commit is contained in:
Michael Zhang 2023-06-07 18:03:50 -05:00
parent db3ef039c7
commit 4cbdc7c142
19 changed files with 136 additions and 96 deletions

2
.prettierignore Normal file
View file

@ -0,0 +1,2 @@
node_modules
src-tauri

View file

@ -4,4 +4,4 @@
singleQuote: false,
trailingComma: "all",
printWidth: 100,
}
}

View file

@ -3,4 +3,4 @@ export default {
tailwindcss: {},
autoprefixer: {},
},
}
};

View file

@ -1,4 +1,4 @@
use sqlx::{Row, SqlitePool};
use sqlx::{sqlite::SqliteRow, Row, SqlitePool};
use tauri::State;
pub struct KanjiDb(pub SqlitePool);
@ -6,9 +6,7 @@ pub struct KanjiDb(pub SqlitePool);
#[derive(Debug, Derivative, Serialize, Deserialize)]
#[derivative(Default)]
pub struct GetKanjiOptions {
/// For looking up an existing one
character: Option<String>,
#[serde(default)]
#[derivative(Default(value = "10"))]
how_many: u32,
}
@ -26,47 +24,68 @@ pub struct GetKanjiResult {
kanji: Vec<Kanji>,
}
fn build_kanji(row: SqliteRow) -> Kanji {
let character = row.get("Character");
let meaning = row.get("Meaning");
let most_used_rank = row.get("MostUsedRank");
Kanji {
character,
meaning,
most_used_rank,
}
}
#[tauri::command]
pub async fn get_kanji(
state: State<'_, KanjiDb>,
db: State<'_, KanjiDb>,
options: Option<GetKanjiOptions>,
) -> Result<GetKanjiResult, ()> {
let opts = options.unwrap_or_default();
let result = sqlx::query(
r#"
SELECT * FROM KanjiSet
LEFT JOIN KanjiMeaningSet ON KanjiSet.ID = KanjiMeaningSet.Kanji_ID
GROUP BY KanjiSet.ID
HAVING MostUsedRank IS NOT NULL
ORDER BY MostUsedRank
LIMIT ?
SELECT * FROM KanjiSet
LEFT JOIN KanjiMeaningSet ON KanjiSet.ID = KanjiMeaningSet.Kanji_ID
GROUP BY KanjiSet.ID
HAVING MostUsedRank IS NOT NULL
ORDER BY MostUsedRank
LIMIT ?
"#,
)
.bind(opts.how_many)
.fetch_all(&state.0)
.fetch_all(&db.0)
.await
.map_err(|_| ())?;
let kanji = result
.into_iter()
.map(|row| {
let character = row.get("Character");
let meaning = row.get("Meaning");
let most_used_rank = row.get("MostUsedRank");
Kanji {
character,
meaning,
most_used_rank,
}
})
.collect();
let kanji = result.into_iter().map(build_kanji).collect();
let count = sqlx::query("SELECT COUNT(*) FROM KanjiSet")
.fetch_one(&state.0)
.fetch_one(&db.0)
.await
.map_err(|_| ())?;
let count = count.try_get(0).map_err(|_| ())?;
Ok(GetKanjiResult { kanji, count })
}
#[tauri::command]
pub async fn get_single_kanji(
db: State<'_, KanjiDb>,
character: String,
) -> Result<Option<Kanji>, ()> {
let result = sqlx::query(
r#"
SELECT * FROM KanjiSet
LEFT JOIN KanjiMeaningSet ON KanjiSet.ID = KanjiMeaningSet.Kanji_ID
GROUP BY KanjiSet.ID
HAVING MostUsedRank IS NOT NULL
AND Kanji.Character = ?
"#,
)
.bind(character)
.fetch_one(&db.0)
.await
.map_err(|_| ())?;
Ok(Some(build_kanji(result)))
}

View file

@ -41,7 +41,11 @@ async fn main() -> Result<()> {
tauri::Builder::default()
.manage(KanjiDb(kanji_pool))
.system_tray(tray)
.invoke_handler(tauri::generate_handler![greet, kanji::get_kanji])
.invoke_handler(tauri::generate_handler![
greet,
kanji::get_kanji,
kanji::get_single_kanji
])
.run(tauri::generate_context!())
.context("error while running tauri application")?;

View file

@ -15,9 +15,8 @@ main.main {
flex-grow: 1;
display: inline-block;
padding: 12px;
}
.link-active {
background-color: skyblue;
}
}

View file

@ -1,10 +1,10 @@
import { Link, RouterProvider, createHashRouter } from "react-router-dom";
import KanjiPane from "./panes/KanjiPane";
import classNames from "classnames";
import { ChakraProvider } from '@chakra-ui/react'
import { ChakraProvider } from "@chakra-ui/react";
import HomePane from "./panes/HomePane";
import { createBrowserRouter } from "react-router-dom";
import { Outlet, Route, createRoutesFromElements, useLocation } from "react-router";
import { Outlet, Route, createRoutesFromElements, matchPath, useLocation } from "react-router";
import SrsPane from "./panes/SrsPane";
import VocabPane from "./panes/VocabPane";
import SettingsPane from "./panes/SettingsPane";
@ -20,11 +20,15 @@ function Layout() {
<ul className={styles.header}>
{routes.map((route) => {
if (!route.title) return undefined;
const active = route.path == location.pathname;
const className = classNames(styles.link, active && styles['link-active']);
return <li key={route.path}>
<Link to={route.path} className={className}>{route.title}</Link>
</li>
const active = matchPath({ path: route.path }, location.pathname);
const className = classNames(styles.link, active && styles["link-active"]);
return (
<li key={route.path}>
<Link to={route.path} className={className}>
{route.title}
</Link>
</li>
);
})}
</ul>
@ -38,22 +42,19 @@ export default function App() {
createRoutesFromElements(
<Route path="/" element={<Layout />}>
{routes.map((route, idx) => (
<Route
key={route.path}
index={idx === 0}
path={route.path}
element={route.element}
/>
<Route key={route.path} index={idx === 0} path={route.path} element={route.element} />
))}
</Route>
)
</Route>,
),
);
return <StrictMode>
<ChakraProvider>
<RouterProvider router={router} />
</ChakraProvider>
</StrictMode>
return (
<StrictMode>
<ChakraProvider>
<RouterProvider router={router} />
</ChakraProvider>
</StrictMode>
);
}
const routes = [

View file

@ -7,4 +7,4 @@ $kanjiDisplaySize: 80px;
font-size: $kanjiDisplaySize * 0.8;
text-align: center;
vertical-align: middle;
}
}

View file

@ -1,7 +1,7 @@
import { invoke } from "@tauri-apps/api/tauri";
import { GetKanjiResult } from "../panes/KanjiPane";
import { Kanji } from "../types/Kanji"
import styles from "./KanjiDisplay.module.scss"
import { Kanji } from "../types/Kanji";
import styles from "./KanjiDisplay.module.scss";
import useSWR from "swr";
interface KanjiDisplayProps {
@ -9,11 +9,23 @@ interface KanjiDisplayProps {
}
export default function KanjiDisplay({ kanjiCharacter }: KanjiDisplayProps) {
const { data, error, isLoading } = useSWR(["get_kanji", kanjiCharacter], invoke<GetKanjiResult>);
const { data, error, isLoading } = useSWR(["get_single_kanji", kanjiCharacter], ([command, character]) => invoke<GetKanjiResult>(command, { character }));
return <>
<div className={styles.display}>
{kanjiCharacter}
</div>
</>
}
return (
<>
<div className={styles.display}>{kanjiCharacter}</div>
{JSON.stringify(isLoading)}
<p>
data:
{JSON.stringify(data)}
</p>
<p>
error:
{JSON.stringify(error)}
</p>
</>
);
}

View file

@ -7,5 +7,5 @@ import "./styles.css";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App />
</React.StrictMode>
</React.StrictMode>,
);

View file

@ -1,5 +1,3 @@
export default function HomePane() {
return <>
hellosu
</>
}
return <>hellosu</>;
}

View file

@ -7,4 +7,4 @@
.kanji-link {
padding: 4px 8px;
border: 1px solid lightgray;
}
}

View file

@ -14,24 +14,30 @@ export interface GetKanjiResult {
interface KanjiListProps {
data: GetKanjiResult;
selectedCharacter: string;
selectedCharacter?: string;
}
function KanjiList({ data, selectedCharacter }: KanjiListProps) {
return <>
Displaying {data.kanji.length} of {data.count} results.
{data.kanji.map(kanji => <Link key={kanji.character} className={styles['kanji-link']} to={`/kanji/${kanji.character}`}>
<Grid
templateRows='repeat(2, 1fr)'
templateColumns='1fr 3fr'>
<GridItem rowSpan={2} style={{ fontSize: '24px', textAlign: 'center' }}>{kanji.character}</GridItem>
<GridItem>{kanji.meaning}</GridItem>
<GridItem>#{kanji.most_used_rank} most used</GridItem>
</Grid>
</Link>)}
</>
return (
<>
Displaying {data.kanji.length} of {data.count} results.
{data.kanji.map((kanji) => (
<Link
key={kanji.character}
className={styles["kanji-link"]}
to={`/kanji/${kanji.character}`}
>
<Grid templateRows="repeat(2, 1fr)" templateColumns="1fr 3fr">
<GridItem rowSpan={2} style={{ fontSize: "24px", textAlign: "center" }}>
{kanji.character}
</GridItem>
<GridItem>{kanji.meaning}</GridItem>
<GridItem>#{kanji.most_used_rank} most used</GridItem>
</Grid>
</Link>
))}
</>
);
}
export default function KanjiPane() {
@ -43,15 +49,15 @@ export default function KanjiPane() {
{JSON.stringify(error)}
{JSON.stringify(selectedKanji)}
<Stack spacing={7} direction='row'>
<Box p={2} className={styles['kanji-list']}>
<Stack spacing={7} direction="row">
<Box p={2} className={styles["kanji-list"]}>
{data && <KanjiList data={data} selectedCharacter={selectedKanji} />}
</Box>
<Box p={5}>
{selectedKanji ? <KanjiDisplay kanjiCharacter={selectedKanji} /> : "nothing selected"}
</Box>
</Stack >
</Stack>
</>
);
}

View file

@ -1,3 +1,3 @@
export default function SettingsPane() {
return <></>
}
return <></>;
}

View file

@ -1,3 +1,3 @@
export default function SrsPane() {
return <></>
}
return <></>;
}

View file

@ -1,3 +1,3 @@
export default function VocabPane() {
return <></>
}
return <></>;
}

View file

@ -1,3 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind utilities;

View file

@ -2,4 +2,4 @@ export interface Kanji {
character: string;
meaning: string;
most_used_rank: number;
}
}

View file

@ -1,11 +1,10 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{html,js,jsx,ts,tsx}",
"./node_modules/flowbite/**/*.js"],
content: ["./src/**/*.{html,js,jsx,ts,tsx}", "./node_modules/flowbite/**/*.js"],
theme: {
extend: {},
},
plugins: [require("flowbite/plugin")],
};
};