Skip to content

Commit

Permalink
add welcome page
Browse files Browse the repository at this point in the history
  • Loading branch information
nknapp committed Feb 4, 2024
1 parent b950b1d commit 734daf9
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 110 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@types/node": "^20.11.7",
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"@types/react-router": "^5.1.20",
"bootstrap": "5.3.2",
"handtrackjs": "^0.1.5",
"i18next": "^23.7.20",
Expand All @@ -21,7 +20,7 @@
"react-bootstrap-icons": "^1.10.3",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.1",
"react-router": "^6.21.3",
"react-router-dom": "^6.22.0",
"typescript": "^5.3.3",
"web-vitals": "^3.5.2"
},
Expand Down
55 changes: 14 additions & 41 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,20 @@
import React, { useState } from "react";
import React from "react";
import { RouterProvider, createHashRouter } from "react-router-dom";
import "src/assets/styles/styles.scss";
import { DefaultLayout } from "./layout/DefaultLayout";
import { Reader } from "./components/Reader/Reader";
import { CreateExamButton } from "./components/ExamTableChooser/CreateExamButton";
import { NoTechniquesChosen } from "./components/Reader/NoTechniquesChosen";
import css from "./components/Reader/Reader.module.scss";
import { ShowExamTable } from "./components/ShowExamTable/ShowExamTable";
import { Button } from "react-bootstrap";
import { Printer } from "react-bootstrap-icons";
import { TechniqueList } from "./model/TechniqueList";

export const router = createHashRouter([
{
path: "/",
lazy: () => import("src/pages"),
},
{
path: "/chooser",
lazy: () => import("src/pages/chooser"),
},
]);

function App(): JSX.Element {
const [techniques, setTechniques] = useState<TechniqueList>(new TechniqueList());
const [currentTechniqueIndex, setCurrentTechniqueIndex] = useState(-1);
return (
<DefaultLayout
navbuttons={
techniques.length > 0 && (
<>
<CreateExamButton onChoice={setTechniques} />
<Button className={"ms-2"} variant={"outline-secondary"} onClick={() => window.print()}>
<Printer /> Print
</Button>
</>
)
}
>
<div className={"mt-1"}>
{techniques.length === 0 ? (
<NoTechniquesChosen className={css.techniqueDisplay} onTechniqueChoice={setTechniques} />
) : (
<>
<div className={"no-print"}>
<Reader techniques={techniques.techniques} nextTechniqueChanged={setCurrentTechniqueIndex} />
</div>
<div className={"mt-4"}>
<ShowExamTable techniques={techniques} currentTechnique={techniques.at(currentTechniqueIndex)} />
</div>
</>
)}
</div>
</DefaultLayout>
);
return <RouterProvider router={router} />;
}

export default App;
16 changes: 16 additions & 0 deletions src/assets/styles/styles-include.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/mixins";

$primary: #55aa77;
$info: #66bb33;
$theme-colors: (
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark,
);
17 changes: 1 addition & 16 deletions src/assets/styles/styles.scss
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";

$primary: #55aa77;
$info: #66bb33;
$theme-colors: (
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark,
);

@import "./styles-include.scss";
@import "bootstrap";

$hightlighTechniqueBg: change-color($primary, $alpha: 0.3);
Expand Down
5 changes: 5 additions & 0 deletions src/components/logo/Logo.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

.logo {
width: 10rem;
height: 10rem;
}
7 changes: 7 additions & 0 deletions src/components/logo/Logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from "react";
import css from "./Logo.module.scss";
import logo from "src/assets/logo.svg";

export const Logo: React.FC<{ className?: string }> = ({ className = "" }) => {
return <img src={logo} className={`${className} ${css.logo}`} alt="Logo" />;
};
25 changes: 11 additions & 14 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import React from "react";
import ReactDOM from "react-dom";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { initI18Next } from "./i18n/i18n";
import i18n from "i18next";
import { initCurrentDojo } from "./exam-tables";

async function initialize() {
await initI18Next();
await initCurrentDojo();
}
await initI18Next();
document.title = i18n.t("app.title");

initialize().then(() => {
document.title = i18n.t("app.title");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
});
await initCurrentDojo();

const root = createRoot(document.getElementById("root")!);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
Expand Down
37 changes: 22 additions & 15 deletions src/layout/DefaultLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import logo from "src/assets/logo.svg";
import { Square } from "react-bootstrap-icons";
import { Impress } from "src/components/Impress/Imress";

export const DefaultLayout: React.FC<{ navbuttons: ReactNode; children: ReactNode }> = ({ children, navbuttons }) => {
export const DefaultLayout: React.FC<{ hideNavbar?: boolean; navbuttons?: ReactNode; children: ReactNode }> = ({
children,
navbuttons,
hideNavbar = false,
}) => {
const { t } = useTranslation();

return (
Expand All @@ -16,18 +20,20 @@ export const DefaultLayout: React.FC<{ navbuttons: ReactNode; children: ReactNod
<div>{document.location.origin}</div>
</div>
</div>
<Navbar expand="md" className={"no-print"}>
<Container>
<Navbar.Brand>
<img width="30" height="30" src={logo} alt={t("app.title")} /> {t("app.title")}
</Navbar.Brand>
<Navbar.Toggle aria-controls="navbar-nav" />
<Navbar.Collapse id="navbar-nav">
<Form className={"form-inline ms-auto"}>{navbuttons}</Form>
<Navbar.Text className={"ms-auto"}>© Nils Knappmeier (2021)</Navbar.Text>
</Navbar.Collapse>
</Container>
</Navbar>
{!hideNavbar && (
<Navbar expand="md" className={"no-print"}>
<Container>
<Navbar.Brand href="/">
<img width="30" height="30" src={logo} alt={t("app.title")} /> {t("app.title")}
</Navbar.Brand>
<Navbar.Toggle aria-controls="navbar-nav" />
<Navbar.Collapse id="navbar-nav">
<Form className={"form-inline ms-auto"}>{navbuttons}</Form>
<Navbar.Text className={"ms-auto"}>© Nils Knappmeier (2021)</Navbar.Text>
</Navbar.Collapse>
</Container>
</Navbar>
)}
<Container>
{children}

Expand All @@ -38,8 +44,9 @@ export const DefaultLayout: React.FC<{ navbuttons: ReactNode; children: ReactNod
<a href={"https://www.aikido-foederation.de/wp-content/uploads/AFD-Pruefungsordnung-052014.pdf"}>
Prüfungsprogramm
</a>{" "}
der <a href={"https://www.aikido-foederation.de/"}>Aikido-Föderation Deutschland</a>. Ich übernehme keine
Garantie für die Richtigkeit und Aktualität der Daten. Fehler könnt ihr mir gerne über{" "}
der <a href={"https://www.aikido-foederation.de/"}>Aikido-Föderation Deutschland</a> und des{" "}
<a href="https://aikidodarmstadt.de">Aikido-Dojo Darmnstadt</a> Ich übernehme keine Garantie für die
Richtigkeit und Aktualität der Daten. Fehler könnt ihr mir gerne über{" "}
<a href={"https://github.com/nknapp/aikido-exam/issues"}>Github-Issues</a> oder per Mail schicken (siehe{" "}
<a href="https://github.com/nknapp">Github-Profil</a>)
</p>
Expand Down
46 changes: 46 additions & 0 deletions src/pages/chooser/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useState } from "react";
import { Button } from "react-bootstrap";
import { Printer } from "react-bootstrap-icons";
import { CreateExamButton } from "src/components/ExamTableChooser/CreateExamButton";
import { NoTechniquesChosen } from "src/components/Reader/NoTechniquesChosen";
import { Reader } from "src/components/Reader/Reader";
import { ShowExamTable } from "src/components/ShowExamTable/ShowExamTable";
import { DefaultLayout } from "src/layout/DefaultLayout";
import { TechniqueList } from "src/model/TechniqueList";
import css from "src/components/Reader/Reader.module.scss";

export const Component: React.FC = () => {
const [techniques, setTechniques] = useState<TechniqueList>(new TechniqueList());
const [currentTechniqueIndex, setCurrentTechniqueIndex] = useState(-1);

return (
<DefaultLayout
hideNavbar={location.pathname === "/"}
navbuttons={
techniques.length > 0 && (
<>
<CreateExamButton onChoice={setTechniques} />
<Button className={"ms-2"} variant={"outline-secondary"} onClick={() => window.print()}>
<Printer /> Print
</Button>
</>
)
}
>
<div className={"mt-1"}>
{techniques.length === 0 ? (
<NoTechniquesChosen className={css.techniqueDisplay} onTechniqueChoice={setTechniques} />
) : (
<>
<div className={"no-print"}>
<Reader techniques={techniques.techniques} nextTechniqueChanged={setCurrentTechniqueIndex} />
</div>
<div className={"mt-4"}>
<ShowExamTable techniques={techniques} currentTechnique={techniques.at(currentTechniqueIndex)} />
</div>
</>
)}
</div>
</DefaultLayout>
);
};
58 changes: 58 additions & 0 deletions src/pages/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@import "src/assets/styles/styles-include.scss";

.homepage {
margin-top: 3rem;
margin-left: auto;
margin-right: auto;
max-width: 100vh;
@include media-breakpoint-up(lg) {
max-width: 800px;
}
}

.subheader {
text-align: center;
font-size: 1.5rem;
}
.header {
text-align: center;
}

.logo {
text-align: center;
margin: 1rem;
}

.teaser {
// inline style in component
// --columns: ...;
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
@include media-breakpoint-up(lg) {
grid-template-columns: repeat(var(--columns), 1fr);
}
}

.action {
text-align: center;
margin: 2rem;
}
.actionButton {
border: 2px solid lighten($warning, 30%);
padding: 0.5rem;
color: darken($warning, 30%);
background-color: lighten($warning, 40%);
font-weight: bold;
text-decoration: none;
transition: background-color 0.2s ease-in-out;
&:hover {
background-color: lighten($warning, 10%);
}
}

.teaserItem {
background-color: lighten($primary, 40%);
padding: 1rem;
min-height: 200px;
}
53 changes: 53 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from "react";
import { Link } from "react-router-dom";
import { Logo } from "src/components/logo/Logo";
import css from "./index.module.scss";
import { DefaultLayout } from "src/layout/DefaultLayout";

function cssVar(name: string, value: string | number): React.CSSProperties {
return {
[name]: value,
} as React.CSSProperties;
}

export const Component = () => {
return (
<DefaultLayout hideNavbar={location.pathname === "/"}>
<div className={css.homepage}>
<p className={css.subheader}>Besser vorbereitet auf deine</p>
<h1 className={css.header}>Aikido-Prüfung</h1>

<div className={css.logo}>
<Logo />
</div>
<div className={css.reason}></div>
<div className={css.action}>
<Link className={css.actionButton} to={"/chooser"}>
Gleich anfangen
</Link>
</div>
<div className={css.teaser} style={{ ...cssVar("--columns", 3) }}>
<div className={css.teaserItem}>
<p>
Im Training üben wir Techniken und Prinzipien. Die Techniken werden in der Prüfung abgefragt. Dabei muss
es manchmal schnell gehen. Du musst sofort wissen, welche Technik du machst. Das kann man üben:
</p>
</div>
<div className={css.teaserItem}>
<h4>Prüfungslisten erzeugen</h4>
<p>
Mit <b>Aikido-Prüfung</b> kannst du dir zufällige Listen aus deinen Prüfungen erzeugen. Damit kannst du
dich beim freien Training abfragen lassen.
</p>
</div>
<div className={css.teaserItem}>
<h4>Vorlesen lassen</h4>
<p>
<b>Aikido-Prüfung</b> kann die Techniken vorlesen, die ausgewählt hast. Du musst nur auf "Play" drücken.
</p>
</div>
</div>
</div>
</DefaultLayout>
);
};
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 734daf9

Please sign in to comment.