Add page management

This commit is contained in:
Kacper Donat 2020-09-08 21:39:00 +02:00
parent 62b4b53fb4
commit aa472e1237
10 changed files with 145 additions and 28 deletions

View File

@ -5,6 +5,7 @@ import { UserState } from "@/state/reducer/user";
import * as user from "./user";
import * as edition from "./edition";
import * as page from "./page"
export const axios = Axios.create({
baseURL: process.env.API_BASE_URL || "https://system-praktyk.stg.kadet.net/api/",
@ -29,7 +30,8 @@ axios.interceptors.request.use(config => {
const api = {
user,
edition
edition,
page
}
export default api;

27
src/api/page.tsx Normal file
View File

@ -0,0 +1,27 @@
// MOCK
import { Page } from "@/data/page";
const tos = `<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Bestiarum vero nullum iudicium puto. Quare ad ea primum, si videtur; <b>Duo Reges: constructio interrete.</b> <i>Eam tum adesse, cum dolor omnis absit;</i> Sed ad bona praeterita redeamus. <mark>Facillimum id quidem est, inquam.</mark> Apud ceteros autem philosophos, qui quaesivit aliquid, tacet; </p>
<p><a href="http://loripsum.net/" target="_blank">Quorum altera prosunt, nocent altera.</a> Eam stabilem appellas. <i>Sed nimis multa.</i> Quo plebiscito decreta a senatu est consuli quaestio Cn. Sin laboramus, quis est, qui alienae modum statuat industriae? <mark>Quod quidem nobis non saepe contingit.</mark> Si autem id non concedatur, non continuo vita beata tollitur. <a href="http://loripsum.net/" target="_blank">Illum mallem levares, quo optimum atque humanissimum virum, Cn.</a> <i>Id est enim, de quo quaerimus.</i> </p>
<p>Ille vero, si insipiens-quo certe, quoniam tyrannus -, numquam beatus; Sin dicit obscurari quaedam nec apparere, quia valde parva sint, nos quoque concedimus; Et quod est munus, quod opus sapientiae? Ab hoc autem quaedam non melius quam veteres, quaedam omnino relicta. </p>
`
export async function get(slug: string): Promise<Page> {
if (slug === "/regulamin" || slug === "/rules") {
return {
id: "tak",
content: {
pl: tos,
en: tos,
},
title: {
pl: "Regulamin Praktyk",
en: "Terms of Internship",
},
}
}
throw new Error();
}

View File

@ -91,13 +91,17 @@ function App() {
</div>
<div className="header__nav">
<nav className="header__top">
<ul className="header__menu"></ul>
<ul className="header__menu">
</ul>
<UserMenu className="header__user"/>
<div className="header__divider"/>
<LanguageSwitcher className="header__language-switcher"/>
</nav>
<nav className="header__bottom">
<ul className="header__menu header__menu--main"></ul>
<ul className="header__menu header__menu--main">
<li><Link to={ route("home") }>{ t("pages.my-internship.header") }</Link></li>
<li><Link to="/regulamin">Regulamin</Link></li>
</ul>
</nav>
</div>
</header>

View File

@ -3,3 +3,8 @@ export type Identifier = string;
export interface Identifiable {
id?: Identifier
}
export type Multilingual<T> = {
pl: T,
en: T
}

6
src/data/page.ts Normal file
View File

@ -0,0 +1,6 @@
import { Identifiable, Multilingual } from "@/data/common";
export interface Page extends Identifiable {
title: Multilingual<string>;
content: Multilingual<string>;
}

View File

@ -1,22 +0,0 @@
import { Page } from "@/pages/base";
import { Box, Button, Container, Divider, Typography } from "@material-ui/core";
import { route } from "@/routing";
import { Link as RouterLink } from "react-router-dom";
import React from "react";
export const NotFoundPage = () => {
return <Page title="Strona nie została znaleziona">
<Container>
<Typography variant="h1">404</Typography>
<Typography variant="h2">Strona nie została znaleziona</Typography>
<Box my={ 4 }>
<Divider variant="fullWidth"/>
</Box>
<Button to={ route("home") } color="primary" component={ RouterLink }>strona główna</Button>
</Container>
</Page>
}
export default NotFoundPage;

51
src/pages/fallback.tsx Normal file
View File

@ -0,0 +1,51 @@
import { Page } from "@/pages/base";
import { Box, Button, CircularProgress, Container, Divider, Typography } from "@material-ui/core";
import { Link as RouterLink, useLocation } from "react-router-dom";
import React, { useMemo } from "react";
import { route } from "@/routing";
import { useAsync } from "@/hooks";
import api from "@/api";
export const FallbackPage = () => {
const location = useLocation();
const promise = useMemo(() => api.page.get(location.pathname), [ location.pathname ]);
const { isLoading, value, error } = useAsync(promise);
console.log({ isLoading, value, error, location });
if (isLoading) {
return <CircularProgress />
}
if (error) {
return <Page title="Strona nie została znaleziona">
<Container>
<Typography variant="h1">404</Typography>
<Typography variant="h2">Strona nie została znaleziona</Typography>
<Box my={ 4 }>
<Divider variant="fullWidth"/>
</Box>
<Button to={ route("home") } color="primary" component={ RouterLink }>strona główna</Button>
</Container>
</Page>
}
if (value) {
return <Page title={ value.title.pl }>
<Page.Header maxWidth="md">
<Page.Title>{ value.title.pl }</Page.Title>
</Page.Header>
<Container>
<div dangerouslySetInnerHTML={{ __html: value.content.pl }} />
</Container>
</Page>
}
return <Page/>;
}
export default FallbackPage;

View File

@ -1,3 +1,3 @@
export * from "./internship/proposal";
export * from "./errors/not-found"
export * from "./main"
export * from "./fallback"

View File

@ -2,7 +2,7 @@ import React, { ReactComponentElement } from "react";
import { MainPage } from "@/pages/main";
import { RouteProps } from "react-router-dom";
import { InternshipProposalFormPage, InternshipProposalPreviewPage } from "@/pages/internship/proposal";
import { NotFoundPage } from "@/pages/errors/not-found";
import { FallbackPage } from "@/pages/fallback";
import SubmitPlanPage from "@/pages/internship/plan";
import { UserLoginPage } from "@/pages/user/login";
import { RegisterEditionPage } from "@/pages/edition/register";
@ -28,7 +28,7 @@ export const routes: Route[] = [
{ name: "user_login", path: "/user/login", exact: true, content: () => <UserLoginPage /> },
// fallback route for 404 pages
{ name: "fallback", path: "*", content: () => <NotFoundPage/> }
{ name: "fallback", path: "*", content: () => <FallbackPage/> }
]
const routeNameMap = new Map(routes.filter(({ name }) => !!name).map(({ name, path }) => [name, path instanceof Array ? path[0] : path])) as Map<string, string>

View File

@ -45,12 +45,56 @@
.header__nav {
flex: 1 1 auto;
display: flex;
flex-direction: column;
}
.header__top .header__menu {
margin-right: auto;
}
.header__bottom {
display: flex;
flex: 1 1 auto;
}
.header__menu--main {
display: flex;
list-style: none;
margin: 0;
font-size: 1.25rem;
padding-left: 0.75rem;
> li {
display: flex;
> a {
padding: 16px;
color: white;
text-decoration: none;
font-weight: bold;
display: flex;
align-items: center;
position: relative;
&:hover {
background: $brand;
&::before {
display: block;
bottom: 0;
left: 0;
right: 0;
height: 4px;
position: absolute;
background: white;
content: '';
}
}
}
}
}
.header__language-switcher {
padding: 0;
display: flex;