Fix top nagivation flickering, add 404 page

This commit is contained in:
Thiago Chaves 2022-07-16 01:02:26 +03:00
parent ae30e8d4a8
commit b43abafa1c
8 changed files with 82 additions and 41 deletions

View File

@ -1,17 +1,17 @@
import Head from "next/head";
import { PropsWithChildren } from "react"; import { PropsWithChildren } from "react";
import { Navigation } from "../Navigation";
export interface PageProps { export interface PageProps {
className?: string; title: string;
} }
export function Page({ className, children }: PropsWithChildren<PageProps>) { export function Page({ title, children }: PropsWithChildren<PageProps>) {
return ( return (
<div className="page"> <>
<header> <Head>
<Navigation /> <title>{title}</title>
</header> </Head>
<main className={className}>{children}</main> {children}
</div> </>
); );
} }

10
src/pages/404.tsx Normal file
View 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;

View File

@ -1,7 +1,17 @@
import "../styles/globals.css"; import "../styles/globals.css";
import "../styles/components.css"; import "../styles/components.css";
import type { AppProps } from "next/app"; import type { AppProps } from "next/app";
import { Navigation } from "../components";
export default function MyApp({ Component, pageProps }: AppProps) { export default function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />; return (
<div className="page">
<header>
<Navigation />
</header>
<main>
<Component {...pageProps} />
</main>
</div>
);
} }

View File

@ -8,6 +8,10 @@ import { useExpressionSetQueryId } from "../../hooks/useExpressionSetQueryId";
import { useExpressionsInSet } from "../../hooks/useExpressionsInSet"; import { useExpressionsInSet } from "../../hooks/useExpressionsInSet";
import { PageWithError } from "../../views/PageWithError/PageWithError"; import { PageWithError } from "../../views/PageWithError/PageWithError";
function pageTitle(name?: string) {
return `Flash Card App - ${name || "Sets"}`;
}
const ExpressionSetDetailsPage: NextPage = () => { const ExpressionSetDetailsPage: NextPage = () => {
const expression_set_id = useExpressionSetQueryId(); const expression_set_id = useExpressionSetQueryId();
const expression_set = useExpressionSet(expression_set_id); const expression_set = useExpressionSet(expression_set_id);
@ -15,13 +19,15 @@ const ExpressionSetDetailsPage: NextPage = () => {
// Fallback for expression set not found // Fallback for expression set not found
if (!expression_set) { if (!expression_set) {
return <PageWithError message="Expression set not found" />; return (
<PageWithError title={pageTitle()} message="Expression set not found" />
);
} }
// Fallback for expression set empty // Fallback for expression set empty
if (expressions.length === 0) if (expressions.length === 0)
return ( return (
<Page> <Page title={pageTitle(expression_set.name)}>
<div className="page-with-padding scroll"> <div className="page-with-padding scroll">
<ExpressionSetInfo <ExpressionSetInfo
id={expression_set.id!} id={expression_set.id!}
@ -35,7 +41,7 @@ const ExpressionSetDetailsPage: NextPage = () => {
); );
return ( return (
<Page> <Page title={pageTitle(expression_set.name)}>
<div className="page-with-bottom-navigation"> <div className="page-with-bottom-navigation">
<section className="padding-small scroll"> <section className="padding-small scroll">
<ExpressionSetInfo <ExpressionSetInfo

View File

@ -8,15 +8,19 @@ import { useExpressionsInSet } from "../../hooks/useExpressionsInSet";
import { IndexedExpressionSet } from "../../model"; import { IndexedExpressionSet } from "../../model";
import { PageWithError } from "../../views/PageWithError"; import { PageWithError } from "../../views/PageWithError";
const PageTitle = "Flash Card App - Sets";
const ExpressionSetListPage: NextPage = () => { const ExpressionSetListPage: NextPage = () => {
const expression_sets = useExpressionSets(); const expression_sets = useExpressionSets();
if (!expression_sets?.length) { if (!expression_sets?.length) {
return <PageWithError message="No expression sets found" />; return (
<PageWithError title={PageTitle} message="No expression sets found" />
);
} }
return ( return (
<Page> <Page title={PageTitle}>
<div className="page-with-padding content-list scroll"> <div className="page-with-padding content-list scroll">
{expression_sets.map(({ id, name, description }) => ( {expression_sets.map(({ id, name, description }) => (
<ExpressionSetLink <ExpressionSetLink

View File

@ -16,6 +16,8 @@ import {
import { sample } from "../../util/array-utils"; import { sample } from "../../util/array-utils";
import { PageWithError } from "../../views/PageWithError/PageWithError"; 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 // Do random selection here so we don't keep flipping states with interaction
const ExpressionPracticePage: NextPage = () => { const ExpressionPracticePage: NextPage = () => {
// Query info // Query info
@ -36,10 +38,17 @@ const ExpressionPracticePage: NextPage = () => {
// Fallback views for expression set content not found // Fallback views for expression set content not found
if (!expression_set_id) { if (!expression_set_id) {
return <PageWithError message="Expression set not found" />; return (
<PageWithError title={PageTitle} message="Expression set not found" />
);
} }
if (!expression) { if (!expression) {
return <PageWithError message="No expressions left in this set" />; return (
<PageWithError
title={PageTitle}
message="No expressions left in this set"
/>
);
} }
return ( return (
@ -63,7 +72,7 @@ function ExpressionCardPracticeView({
}: ExpressionCardPracticeViewProps) { }: ExpressionCardPracticeViewProps) {
const [revealed, setRevealed] = useState(false); const [revealed, setRevealed] = useState(false);
return ( return (
<Page> <Page title={PageTitle}>
<div className="page-with-bottom-navigation"> <div className="page-with-bottom-navigation">
<section className="padding-small scroll"> <section className="padding-small scroll">
<ExpressionCard <ExpressionCard
@ -120,7 +129,6 @@ function DemoteExpressionButton({ expression_id }: ExpressionIdProps) {
const { query, pathname, push } = useRouter(); const { query, pathname, push } = useRouter();
const expression_set_id = useExpressionSetQueryId(); const expression_set_id = useExpressionSetQueryId();
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
() => {
if (expression_set_id === 1) { if (expression_set_id === 1) {
const filter_ids = query["filter-ids"] const filter_ids = query["filter-ids"]
? `${query["filter-ids"]} ${expression_id}` ? `${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_set_id: Math.max(1, expression_set_id - 1),
}); });
} }
}; }, [expression_id, expression_set_id, pathname, push, query]);
}, [expression_id, expression_set_id, pathname, query, push]);
return ( return (
<button <button
className="navigation-item bottom text-navigation grow" className="navigation-item bottom text-navigation grow"

View File

@ -1,8 +1,10 @@
import type { NextPage } from "next"; import type { NextPage } from "next";
import { Page } from "../components/Page"; import { Page } from "../components/Page";
const PageTitle = "Flash Card App";
const Home: NextPage = () => { const Home: NextPage = () => {
return <Page />; return <Page title={PageTitle} />;
}; };
export default Home; export default Home;

View File

@ -1,12 +1,13 @@
import { Page } from "../../components/Page"; import { Page } from "../../components/Page";
export interface PageWithErrorProps { export interface PageWithErrorProps {
title: string;
message: string; message: string;
} }
export function PageWithError({ message }: PageWithErrorProps) { export function PageWithError({ title, message }: PageWithErrorProps) {
return ( return (
<Page> <Page title={title}>
<div className="page-with-padding"> <div className="page-with-padding">
<p className="text-meta">{message}</p> <p className="text-meta">{message}</p>
</div> </div>