Fix top nagivation flickering, add 404 page
This commit is contained in:
parent
ae30e8d4a8
commit
b43abafa1c
@ -1,17 +1,17 @@
|
||||
import Head from "next/head";
|
||||
import { PropsWithChildren } from "react";
|
||||
import { Navigation } from "../Navigation";
|
||||
|
||||
export interface PageProps {
|
||||
className?: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export function Page({ className, children }: PropsWithChildren<PageProps>) {
|
||||
export function Page({ title, children }: PropsWithChildren<PageProps>) {
|
||||
return (
|
||||
<div className="page">
|
||||
<header>
|
||||
<Navigation />
|
||||
</header>
|
||||
<main className={className}>{children}</main>
|
||||
</div>
|
||||
<>
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
</Head>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
10
src/pages/404.tsx
Normal file
10
src/pages/404.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import type { NextPage } from "next";
|
||||
import { PageWithError } from "../views/PageWithError";
|
||||
|
||||
const PageTitle = "Flash Card App - 404";
|
||||
|
||||
const Page404: NextPage = () => {
|
||||
return <PageWithError title={PageTitle} message="404 - content not found" />;
|
||||
};
|
||||
|
||||
export default Page404;
|
@ -1,7 +1,17 @@
|
||||
import "../styles/globals.css";
|
||||
import "../styles/components.css";
|
||||
import type { AppProps } from "next/app";
|
||||
import { Navigation } from "../components";
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />;
|
||||
return (
|
||||
<div className="page">
|
||||
<header>
|
||||
<Navigation />
|
||||
</header>
|
||||
<main>
|
||||
<Component {...pageProps} />
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,10 @@ import { useExpressionSetQueryId } from "../../hooks/useExpressionSetQueryId";
|
||||
import { useExpressionsInSet } from "../../hooks/useExpressionsInSet";
|
||||
import { PageWithError } from "../../views/PageWithError/PageWithError";
|
||||
|
||||
function pageTitle(name?: string) {
|
||||
return `Flash Card App - ${name || "Sets"}`;
|
||||
}
|
||||
|
||||
const ExpressionSetDetailsPage: NextPage = () => {
|
||||
const expression_set_id = useExpressionSetQueryId();
|
||||
const expression_set = useExpressionSet(expression_set_id);
|
||||
@ -15,13 +19,15 @@ const ExpressionSetDetailsPage: NextPage = () => {
|
||||
|
||||
// Fallback for expression set not found
|
||||
if (!expression_set) {
|
||||
return <PageWithError message="Expression set not found" />;
|
||||
return (
|
||||
<PageWithError title={pageTitle()} message="Expression set not found" />
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback for expression set empty
|
||||
if (expressions.length === 0)
|
||||
return (
|
||||
<Page>
|
||||
<Page title={pageTitle(expression_set.name)}>
|
||||
<div className="page-with-padding scroll">
|
||||
<ExpressionSetInfo
|
||||
id={expression_set.id!}
|
||||
@ -35,7 +41,7 @@ const ExpressionSetDetailsPage: NextPage = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Page title={pageTitle(expression_set.name)}>
|
||||
<div className="page-with-bottom-navigation">
|
||||
<section className="padding-small scroll">
|
||||
<ExpressionSetInfo
|
||||
|
@ -8,15 +8,19 @@ import { useExpressionsInSet } from "../../hooks/useExpressionsInSet";
|
||||
import { IndexedExpressionSet } from "../../model";
|
||||
import { PageWithError } from "../../views/PageWithError";
|
||||
|
||||
const PageTitle = "Flash Card App - Sets";
|
||||
|
||||
const ExpressionSetListPage: NextPage = () => {
|
||||
const expression_sets = useExpressionSets();
|
||||
|
||||
if (!expression_sets?.length) {
|
||||
return <PageWithError message="No expression sets found" />;
|
||||
return (
|
||||
<PageWithError title={PageTitle} message="No expression sets found" />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Page title={PageTitle}>
|
||||
<div className="page-with-padding content-list scroll">
|
||||
{expression_sets.map(({ id, name, description }) => (
|
||||
<ExpressionSetLink
|
||||
|
@ -16,6 +16,8 @@ import {
|
||||
import { sample } from "../../util/array-utils";
|
||||
import { PageWithError } from "../../views/PageWithError/PageWithError";
|
||||
|
||||
const PageTitle = "Flash Card App - Practice";
|
||||
|
||||
// Do random selection here so we don't keep flipping states with interaction
|
||||
const ExpressionPracticePage: NextPage = () => {
|
||||
// Query info
|
||||
@ -36,10 +38,17 @@ const ExpressionPracticePage: NextPage = () => {
|
||||
|
||||
// Fallback views for expression set content not found
|
||||
if (!expression_set_id) {
|
||||
return <PageWithError message="Expression set not found" />;
|
||||
return (
|
||||
<PageWithError title={PageTitle} message="Expression set not found" />
|
||||
);
|
||||
}
|
||||
if (!expression) {
|
||||
return <PageWithError message="No expressions left in this set" />;
|
||||
return (
|
||||
<PageWithError
|
||||
title={PageTitle}
|
||||
message="No expressions left in this set"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -63,7 +72,7 @@ function ExpressionCardPracticeView({
|
||||
}: ExpressionCardPracticeViewProps) {
|
||||
const [revealed, setRevealed] = useState(false);
|
||||
return (
|
||||
<Page>
|
||||
<Page title={PageTitle}>
|
||||
<div className="page-with-bottom-navigation">
|
||||
<section className="padding-small scroll">
|
||||
<ExpressionCard
|
||||
@ -120,7 +129,6 @@ function DemoteExpressionButton({ expression_id }: ExpressionIdProps) {
|
||||
const { query, pathname, push } = useRouter();
|
||||
const expression_set_id = useExpressionSetQueryId();
|
||||
const handleClick = useCallback(() => {
|
||||
() => {
|
||||
if (expression_set_id === 1) {
|
||||
const filter_ids = query["filter-ids"]
|
||||
? `${query["filter-ids"]} ${expression_id}`
|
||||
@ -138,8 +146,8 @@ function DemoteExpressionButton({ expression_id }: ExpressionIdProps) {
|
||||
expression_set_id: Math.max(1, expression_set_id - 1),
|
||||
});
|
||||
}
|
||||
};
|
||||
}, [expression_id, expression_set_id, pathname, query, push]);
|
||||
}, [expression_id, expression_set_id, pathname, push, query]);
|
||||
|
||||
return (
|
||||
<button
|
||||
className="navigation-item bottom text-navigation grow"
|
||||
|
@ -1,8 +1,10 @@
|
||||
import type { NextPage } from "next";
|
||||
import { Page } from "../components/Page";
|
||||
|
||||
const PageTitle = "Flash Card App";
|
||||
|
||||
const Home: NextPage = () => {
|
||||
return <Page />;
|
||||
return <Page title={PageTitle} />;
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { Page } from "../../components/Page";
|
||||
|
||||
export interface PageWithErrorProps {
|
||||
title: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function PageWithError({ message }: PageWithErrorProps) {
|
||||
export function PageWithError({ title, message }: PageWithErrorProps) {
|
||||
return (
|
||||
<Page>
|
||||
<Page title={title}>
|
||||
<div className="page-with-padding">
|
||||
<p className="text-meta">{message}</p>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user