Mock data and add expression set selection page
This commit is contained in:
parent
79ba58bb36
commit
47ea97adaf
@ -17,7 +17,6 @@ const Template: ComponentStory<typeof ExpressionSetCard> = (args) => (
|
||||
|
||||
export const Daily = Template.bind({});
|
||||
Daily.args = {
|
||||
id: 1,
|
||||
name: "Daily",
|
||||
description: "Words for daily practice",
|
||||
word_count: 11,
|
||||
|
@ -1,12 +1,10 @@
|
||||
export interface ExpressionSetCardProps {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
word_count: number;
|
||||
}
|
||||
|
||||
export function ExpressionSetCard({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
word_count,
|
||||
|
@ -7,7 +7,7 @@ export function Navigation() {
|
||||
<NavigationItem
|
||||
text="practice"
|
||||
iconUrl="/icons/calendar.svg"
|
||||
href="/practice"
|
||||
href="/expression-sets"
|
||||
/>
|
||||
<NavigationItem
|
||||
text="settings"
|
||||
|
14
src/hooks/useExpressionData.ts
Normal file
14
src/hooks/useExpressionData.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { useState } from "react";
|
||||
import { MockData } from "../mock";
|
||||
|
||||
export function useExpressionData() {
|
||||
const [state] = useState(MockData);
|
||||
|
||||
return {
|
||||
catefories: state.categories,
|
||||
expressions: state.expressions,
|
||||
expression_sets: state.expression_sets,
|
||||
expression_to_category: state.expression_to_category,
|
||||
expression_to_expression_set: state.expression_to_expression_set,
|
||||
};
|
||||
}
|
1
src/mock/index.ts
Normal file
1
src/mock/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from "./mock-data";
|
127
src/mock/mock-data.ts
Normal file
127
src/mock/mock-data.ts
Normal file
@ -0,0 +1,127 @@
|
||||
import {
|
||||
Category,
|
||||
Expression,
|
||||
ExpressionSet,
|
||||
ExpressionToCategory,
|
||||
ExpressionToExpressionSet,
|
||||
} from "../model";
|
||||
|
||||
interface RawExpressionDataItem {
|
||||
prompt: string;
|
||||
description: string;
|
||||
category: string;
|
||||
expression_set: string;
|
||||
}
|
||||
|
||||
interface RawExpressionSetItem {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const RawExpressionData: RawExpressionDataItem[] = [
|
||||
["koira", "noun", "daily", "dog, dog paddle (swimming stroke)"],
|
||||
["liite", "noun", "daily", "attachment, appendix, affix, supplement"],
|
||||
["havaita", "verb", "daily", "to observe, to detect, to perceive"],
|
||||
["tukea", "verb", "daily", "to support, finance, sponsor, substantiate"],
|
||||
].map(([prompt, category, expression_set, description]) => ({
|
||||
prompt,
|
||||
description,
|
||||
category,
|
||||
expression_set,
|
||||
}));
|
||||
|
||||
const RawExpressionSetData: RawExpressionSetItem[] = [
|
||||
["daily", "New expressions and poorly remembered expressions"],
|
||||
["weekly", "Expressions to be reviewed at the end of the week"],
|
||||
["monthly", "Expressions to be reviewed at the end of the month"],
|
||||
["yearly", "Expressions to be reviewed at the end of the year"],
|
||||
["ancient", "Expressions here should be memorized by now"],
|
||||
].map(([name, description]) => ({ name, description }));
|
||||
|
||||
interface MockData {
|
||||
// Tables
|
||||
categories: Category[];
|
||||
expressions: Expression[];
|
||||
expression_sets: ExpressionSet[];
|
||||
|
||||
// Relationships
|
||||
expression_to_category: ExpressionToCategory[];
|
||||
expression_to_expression_set: ExpressionToExpressionSet[];
|
||||
}
|
||||
|
||||
export function parseRawData(
|
||||
raw_expression_data: RawExpressionDataItem[],
|
||||
raw_expression_set_data: RawExpressionSetItem[]
|
||||
): MockData {
|
||||
const category_names = new Set(
|
||||
raw_expression_data.map((item) => item.category)
|
||||
);
|
||||
const categories: Category[] = Array.from(category_names).map(
|
||||
(name, index) => ({
|
||||
id: index + 1,
|
||||
name,
|
||||
description: name,
|
||||
})
|
||||
);
|
||||
|
||||
const expressions: Expression[] = raw_expression_data.map(
|
||||
({ prompt, description }, index) => ({
|
||||
id: index + 1,
|
||||
prompt,
|
||||
description,
|
||||
})
|
||||
);
|
||||
|
||||
const expression_sets: ExpressionSet[] = raw_expression_set_data.map(
|
||||
({ name, description }, index) => ({
|
||||
id: index + 1,
|
||||
name,
|
||||
description,
|
||||
})
|
||||
);
|
||||
|
||||
const expression_to_category: ExpressionToCategory[] =
|
||||
raw_expression_data.map((item, index) =>
|
||||
matchExpressionAndCategory(index + 1, item, categories)
|
||||
);
|
||||
|
||||
const expression_to_expression_set: ExpressionToExpressionSet[] =
|
||||
raw_expression_data.map((item, index) =>
|
||||
matchExpressionAndExpressionSet(index + 1, item, expression_sets)
|
||||
);
|
||||
|
||||
return {
|
||||
expressions,
|
||||
expression_sets,
|
||||
categories,
|
||||
expression_to_category,
|
||||
expression_to_expression_set,
|
||||
};
|
||||
}
|
||||
|
||||
function matchExpressionAndCategory(
|
||||
expression_id: number,
|
||||
{ category }: RawExpressionDataItem,
|
||||
categories: Category[]
|
||||
): ExpressionToCategory {
|
||||
const category_id = categories.find(({ name }) => name === category)?.id || 0;
|
||||
return {
|
||||
category_id,
|
||||
expression_id,
|
||||
};
|
||||
}
|
||||
|
||||
function matchExpressionAndExpressionSet(
|
||||
expression_id: number,
|
||||
{ expression_set }: RawExpressionDataItem,
|
||||
expression_sets: ExpressionSet[]
|
||||
): ExpressionToExpressionSet {
|
||||
const expression_set_id =
|
||||
expression_sets.find(({ name }) => name === expression_set)?.id || 0;
|
||||
return {
|
||||
expression_id,
|
||||
expression_set_id,
|
||||
};
|
||||
}
|
||||
|
||||
export const MockData = parseRawData(RawExpressionData, RawExpressionSetData);
|
7
src/model/Category.ts
Normal file
7
src/model/Category.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export type CategoryId = number;
|
||||
|
||||
export type Category = {
|
||||
id: CategoryId;
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
7
src/model/Expression.ts
Normal file
7
src/model/Expression.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export type ExpressionId = number;
|
||||
|
||||
export type Expression = {
|
||||
id: ExpressionId;
|
||||
prompt: string;
|
||||
description: string;
|
||||
};
|
7
src/model/ExpressionSet.ts
Normal file
7
src/model/ExpressionSet.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export type ExpressionSetId = number;
|
||||
|
||||
export type ExpressionSet = {
|
||||
id: ExpressionSetId;
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
13
src/model/Relationships.ts
Normal file
13
src/model/Relationships.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { CategoryId } from "./Category";
|
||||
import { ExpressionId } from "./Expression";
|
||||
import { ExpressionSetId } from "./ExpressionSet";
|
||||
|
||||
export type ExpressionToCategory = {
|
||||
expression_id: ExpressionId;
|
||||
category_id: CategoryId;
|
||||
};
|
||||
|
||||
export type ExpressionToExpressionSet = {
|
||||
expression_id: ExpressionId;
|
||||
expression_set_id: ExpressionSetId;
|
||||
};
|
4
src/model/index.ts
Normal file
4
src/model/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from "./Category";
|
||||
export * from "./Expression";
|
||||
export * from "./ExpressionSet";
|
||||
export * from "./Relationships";
|
37
src/pages/expression-sets.tsx
Normal file
37
src/pages/expression-sets.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import type { NextPage } from "next";
|
||||
import Link from "next/link";
|
||||
import { ExpressionSetCard } from "../components/ExpressionSetCard";
|
||||
import { Page } from "../components/Page";
|
||||
import { useExpressionData } from "../hooks/useExpressionData";
|
||||
|
||||
const ExpressionSetsPage: NextPage = () => {
|
||||
const { expression_sets, expression_to_expression_set } = useExpressionData();
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<div className="content-list">
|
||||
{expression_sets.map(({ id, name, description }) => (
|
||||
<Link
|
||||
key={id}
|
||||
href={{ pathname: "/practice", query: { "set-id": id } }}
|
||||
passHref
|
||||
>
|
||||
<a>
|
||||
<ExpressionSetCard
|
||||
name={name}
|
||||
description={description}
|
||||
word_count={
|
||||
expression_to_expression_set.filter(
|
||||
(item) => item.expression_set_id === id
|
||||
).length
|
||||
}
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExpressionSetsPage;
|
@ -19,6 +19,16 @@
|
||||
display: block;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
/* Will it conflict with overlays? Move elsewhere? */
|
||||
padding: 16px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.content-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-gap: 16px;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
|
Loading…
Reference in New Issue
Block a user