client: refactor header component for improved SSR
This commit is contained in:
parent
e7cec9b827
commit
a1fef656bb
17 changed files with 289 additions and 290 deletions
|
@ -1,7 +1,8 @@
|
||||||
import { GeistProvider, CssBaseline, Themes } from "@geist-ui/core"
|
import Header from "@components/header"
|
||||||
|
import { GeistProvider, CssBaseline, Themes, Page } from "@geist-ui/core"
|
||||||
import type { NextComponentType, NextPageContext } from "next"
|
import type { NextComponentType, NextPageContext } from "next"
|
||||||
import { SkeletonTheme } from "react-loading-skeleton"
|
import { SkeletonTheme } from "react-loading-skeleton"
|
||||||
import { useTheme } from 'next-themes'
|
|
||||||
const App = ({
|
const App = ({
|
||||||
Component,
|
Component,
|
||||||
pageProps,
|
pageProps,
|
||||||
|
@ -50,9 +51,10 @@ const App = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return (<GeistProvider themes={[customTheme]} themeType={"custom"} >
|
return (<GeistProvider themes={[customTheme]} themeType={"custom"}>
|
||||||
<SkeletonTheme baseColor={skeletonBaseColor} highlightColor={skeletonHighlightColor}>
|
<SkeletonTheme baseColor={skeletonBaseColor} highlightColor={skeletonHighlightColor}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
|
<Header />
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</SkeletonTheme>
|
</SkeletonTheme>
|
||||||
</GeistProvider >)
|
</GeistProvider >)
|
||||||
|
|
|
@ -29,7 +29,7 @@ const Auth = ({ page }: { page: "signup" | "signin" }) => {
|
||||||
const res = await resp.json()
|
const res = await resp.json()
|
||||||
setRequiresServerPassword(res.requiresPasscode)
|
setRequiresServerPassword(res.requiresPasscode)
|
||||||
} else {
|
} else {
|
||||||
setErrorMsg("Something went wrong.")
|
setErrorMsg("Something went wrong. Is the server running?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,62 @@
|
||||||
.tabs {
|
.tabs {
|
||||||
flex: 1 1;
|
justify-content: center;
|
||||||
padding: 0 var(--gap);
|
display: flex;
|
||||||
|
margin-top: var(--gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .buttons > button,
|
||||||
|
.tabs .buttons > a > button {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs .active {
|
||||||
|
border-bottom: 1px solid var(--darker-gray) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile {
|
.mobile {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
display: none !important;
|
margin-top: var(--gap);
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 650px) {
|
@media only screen and (max-width: 650px) {
|
||||||
.tabs {
|
.tabs {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls button:active,
|
.controls button:active,
|
||||||
.controls button:focus,
|
.controls button:focus,
|
||||||
.controls button:hover {
|
.controls button:hover {
|
||||||
outline: 1px solid rgba(0, 0, 0, 0.2);
|
outline: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: min-content;
|
width: min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectContent {
|
.selectContent {
|
||||||
width: auto;
|
width: auto;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,197 +0,0 @@
|
||||||
|
|
||||||
import { ButtonGroup, Page, Spacer, Tabs, useBodyScroll, useMediaQuery, } from "@geist-ui/core";
|
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from "react";
|
|
||||||
import styles from './header.module.css';
|
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import useSignedIn from "../../lib/hooks/use-signed-in";
|
|
||||||
|
|
||||||
import HomeIcon from '@geist-ui/icons/home';
|
|
||||||
import MenuIcon from '@geist-ui/icons/menu';
|
|
||||||
import GitHubIcon from '@geist-ui/icons/github';
|
|
||||||
import SignOutIcon from '@geist-ui/icons/userX';
|
|
||||||
import SignInIcon from '@geist-ui/icons/user';
|
|
||||||
import SignUpIcon from '@geist-ui/icons/userPlus';
|
|
||||||
import NewIcon from '@geist-ui/icons/plusCircle';
|
|
||||||
import YourIcon from '@geist-ui/icons/list'
|
|
||||||
import MoonIcon from '@geist-ui/icons/moon';
|
|
||||||
import SettingsIcon from '@geist-ui/icons/settings';
|
|
||||||
import SunIcon from '@geist-ui/icons/sun';
|
|
||||||
import { useTheme } from "next-themes"
|
|
||||||
import { Button } from "@geist-ui/core";
|
|
||||||
import useUserData from "@lib/hooks/use-user-data";
|
|
||||||
|
|
||||||
type Tab = {
|
|
||||||
name: string
|
|
||||||
icon: JSX.Element
|
|
||||||
value: string
|
|
||||||
onClick?: () => void
|
|
||||||
href?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const Header = () => {
|
|
||||||
const router = useRouter();
|
|
||||||
const [selectedTab, setSelectedTab] = useState<string>(router.pathname === '/' ? 'home' : router.pathname.split('/')[1]);
|
|
||||||
const [expanded, setExpanded] = useState<boolean>(false)
|
|
||||||
const [, setBodyHidden] = useBodyScroll(null, { scrollLayer: true })
|
|
||||||
const isMobile = useMediaQuery('xs', { match: 'down' })
|
|
||||||
const { signedIn: isSignedIn, signout } = useSignedIn()
|
|
||||||
const userData = useUserData();
|
|
||||||
const [pages, setPages] = useState<Tab[]>([])
|
|
||||||
const { setTheme, resolvedTheme } = useTheme()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setBodyHidden(expanded)
|
|
||||||
}, [expanded, setBodyHidden])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isMobile) {
|
|
||||||
setExpanded(false)
|
|
||||||
}
|
|
||||||
}, [isMobile])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const defaultPages: Tab[] = [
|
|
||||||
{
|
|
||||||
name: isMobile ? "GitHub" : "",
|
|
||||||
href: "https://github.com/maxleiter/drift",
|
|
||||||
icon: <GitHubIcon />,
|
|
||||||
value: "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: isMobile ? "Change theme" : "",
|
|
||||||
onClick: function () {
|
|
||||||
if (typeof window !== 'undefined')
|
|
||||||
setTheme(resolvedTheme === 'light' ? 'dark' : 'light');
|
|
||||||
},
|
|
||||||
icon: resolvedTheme === 'light' ? <MoonIcon /> : <SunIcon />,
|
|
||||||
value: "theme",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
if (isSignedIn)
|
|
||||||
setPages([
|
|
||||||
{
|
|
||||||
name: 'new',
|
|
||||||
icon: <NewIcon />,
|
|
||||||
value: 'new',
|
|
||||||
href: '/new'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'yours',
|
|
||||||
icon: <YourIcon />,
|
|
||||||
value: 'yours',
|
|
||||||
href: '/mine'
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: 'settings',
|
|
||||||
// icon: <SettingsIcon />,
|
|
||||||
// value: 'settings',
|
|
||||||
// href: '/settings'
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
name: 'sign out',
|
|
||||||
icon: <SignOutIcon />,
|
|
||||||
value: 'signout',
|
|
||||||
onClick: signout
|
|
||||||
},
|
|
||||||
...defaultPages
|
|
||||||
])
|
|
||||||
else
|
|
||||||
setPages([
|
|
||||||
{
|
|
||||||
name: 'home',
|
|
||||||
icon: <HomeIcon />,
|
|
||||||
value: 'home',
|
|
||||||
href: '/'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Sign in',
|
|
||||||
icon: <SignInIcon />,
|
|
||||||
value: 'signin',
|
|
||||||
href: '/signin'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Sign up',
|
|
||||||
icon: <SignUpIcon />,
|
|
||||||
value: 'signup',
|
|
||||||
href: '/signup'
|
|
||||||
},
|
|
||||||
...defaultPages
|
|
||||||
])
|
|
||||||
if (userData?.role === "admin") {
|
|
||||||
setPages((pages) => [
|
|
||||||
...pages,
|
|
||||||
{
|
|
||||||
name: 'admin',
|
|
||||||
icon: <SettingsIcon />,
|
|
||||||
value: 'admin',
|
|
||||||
href: '/admin'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
}
|
|
||||||
// TODO: investigate deps causing infinite loop
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [isMobile, isSignedIn, resolvedTheme, userData])
|
|
||||||
|
|
||||||
const onTabChange = useCallback((tab: string) => {
|
|
||||||
if (typeof window === 'undefined') return
|
|
||||||
const match = pages.find(page => page.value === tab)
|
|
||||||
if (match?.onClick) {
|
|
||||||
match.onClick()
|
|
||||||
} else {
|
|
||||||
router.push(match?.href || '/')
|
|
||||||
}
|
|
||||||
}, [pages, router])
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Page.Header height={'var(--page-nav-height)'} marginBottom={2}>
|
|
||||||
<div className={styles.tabs}>
|
|
||||||
<Tabs
|
|
||||||
value={selectedTab}
|
|
||||||
leftSpace={0}
|
|
||||||
align="center"
|
|
||||||
hideDivider
|
|
||||||
hideBorder
|
|
||||||
onChange={onTabChange}>
|
|
||||||
{pages.map((tab) => {
|
|
||||||
return <Tabs.Item
|
|
||||||
font="14px"
|
|
||||||
label={<>{tab.icon} {tab.name}</>}
|
|
||||||
value={tab.value}
|
|
||||||
key={`${tab.value}`}
|
|
||||||
/>
|
|
||||||
})}
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
<div className={styles.controls}>
|
|
||||||
<Button
|
|
||||||
auto
|
|
||||||
type="abort"
|
|
||||||
onClick={() => setExpanded(!expanded)}
|
|
||||||
aria-label="Menu"
|
|
||||||
>
|
|
||||||
<Spacer height={5 / 6} width={0} />
|
|
||||||
<MenuIcon />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{isMobile && expanded && (<div className={styles.mobile}>
|
|
||||||
<ButtonGroup vertical>
|
|
||||||
{pages.map((tab, index) => {
|
|
||||||
return <Button
|
|
||||||
key={`${tab.name}-${index}`}
|
|
||||||
onClick={() => onTabChange(tab.value)}
|
|
||||||
icon={tab.icon}
|
|
||||||
>
|
|
||||||
{tab.name}
|
|
||||||
</Button>
|
|
||||||
})}
|
|
||||||
</ButtonGroup>
|
|
||||||
</div>)}
|
|
||||||
</Page.Header >
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Header
|
|
|
@ -1,10 +1,207 @@
|
||||||
import dynamic from 'next/dynamic'
|
|
||||||
|
|
||||||
const Header = dynamic(import('./header'), {
|
import { ButtonGroup, Button, Page, Spacer, useBodyScroll, useMediaQuery, } from "@geist-ui/core";
|
||||||
// ssr: false,
|
|
||||||
// loading: () => <MenuSkeleton />,
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
})
|
import styles from './header.module.css';
|
||||||
|
import useSignedIn from "../../lib/hooks/use-signed-in";
|
||||||
|
|
||||||
|
import HomeIcon from '@geist-ui/icons/home';
|
||||||
|
import MenuIcon from '@geist-ui/icons/menu';
|
||||||
|
import GitHubIcon from '@geist-ui/icons/github';
|
||||||
|
import SignOutIcon from '@geist-ui/icons/userX';
|
||||||
|
import SignInIcon from '@geist-ui/icons/user';
|
||||||
|
import SignUpIcon from '@geist-ui/icons/userPlus';
|
||||||
|
import NewIcon from '@geist-ui/icons/plusCircle';
|
||||||
|
import YourIcon from '@geist-ui/icons/list'
|
||||||
|
import MoonIcon from '@geist-ui/icons/moon';
|
||||||
|
import SettingsIcon from '@geist-ui/icons/settings';
|
||||||
|
import SunIcon from '@geist-ui/icons/sun';
|
||||||
|
import { useTheme } from "next-themes"
|
||||||
|
import useUserData from "@lib/hooks/use-user-data";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
type Tab = {
|
||||||
|
name: string
|
||||||
|
icon: JSX.Element
|
||||||
|
value: string
|
||||||
|
onClick?: () => void
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
const router = useRouter()
|
||||||
|
const [expanded, setExpanded] = useState<boolean>(false)
|
||||||
|
const [, setBodyHidden] = useBodyScroll(null, { scrollLayer: true })
|
||||||
|
const isMobile = useMediaQuery('xs', { match: 'down' })
|
||||||
|
const { signedIn: isSignedIn, signout } = useSignedIn()
|
||||||
|
const userData = useUserData();
|
||||||
|
const [pages, setPages] = useState<Tab[]>([])
|
||||||
|
const { setTheme, resolvedTheme } = useTheme()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setBodyHidden(expanded)
|
||||||
|
}, [expanded, setBodyHidden])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isMobile) {
|
||||||
|
setExpanded(false)
|
||||||
|
}
|
||||||
|
}, [isMobile])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const defaultPages: Tab[] = [
|
||||||
|
{
|
||||||
|
name: isMobile ? "GitHub" : "",
|
||||||
|
href: "https://github.com/maxleiter/drift",
|
||||||
|
icon: <GitHubIcon />,
|
||||||
|
value: "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: isMobile ? "Change theme" : "",
|
||||||
|
onClick: function () {
|
||||||
|
if (typeof window !== 'undefined')
|
||||||
|
setTheme(resolvedTheme === 'light' ? 'dark' : 'light');
|
||||||
|
},
|
||||||
|
icon: resolvedTheme === 'light' ? <MoonIcon /> : <SunIcon />,
|
||||||
|
value: "theme",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if (isSignedIn)
|
||||||
|
setPages([
|
||||||
|
{
|
||||||
|
name: 'new',
|
||||||
|
icon: <NewIcon />,
|
||||||
|
value: 'new',
|
||||||
|
href: '/new'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'yours',
|
||||||
|
icon: <YourIcon />,
|
||||||
|
value: 'yours',
|
||||||
|
href: '/mine'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// name: 'settings',
|
||||||
|
// icon: <SettingsIcon />,
|
||||||
|
// value: 'settings',
|
||||||
|
// href: '/settings'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
name: 'sign out',
|
||||||
|
icon: <SignOutIcon />,
|
||||||
|
value: 'signout',
|
||||||
|
// onClick: signout,
|
||||||
|
href: '/signout'
|
||||||
|
},
|
||||||
|
...defaultPages
|
||||||
|
])
|
||||||
|
else
|
||||||
|
setPages([
|
||||||
|
{
|
||||||
|
name: 'home',
|
||||||
|
icon: <HomeIcon />,
|
||||||
|
value: 'home',
|
||||||
|
href: '/'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sign in',
|
||||||
|
icon: <SignInIcon />,
|
||||||
|
value: 'signin',
|
||||||
|
href: '/signin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sign up',
|
||||||
|
icon: <SignUpIcon />,
|
||||||
|
value: 'signup',
|
||||||
|
href: '/signup'
|
||||||
|
},
|
||||||
|
...defaultPages
|
||||||
|
])
|
||||||
|
if (userData?.role === "admin") {
|
||||||
|
setPages((pages) => [
|
||||||
|
...pages,
|
||||||
|
{
|
||||||
|
name: 'admin',
|
||||||
|
icon: <SettingsIcon />,
|
||||||
|
value: 'admin',
|
||||||
|
href: '/admin'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
// TODO: investigate deps causing infinite loop
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [isMobile, isSignedIn, resolvedTheme, userData])
|
||||||
|
|
||||||
|
const onTabChange = useCallback((tab: string) => {
|
||||||
|
if (typeof window === 'undefined') return
|
||||||
|
const match = pages.find(page => page.value === tab)
|
||||||
|
if (match?.onClick) {
|
||||||
|
match.onClick()
|
||||||
|
}
|
||||||
|
}, [pages])
|
||||||
|
|
||||||
|
const getButton = useCallback((tab: Tab) => {
|
||||||
|
const activeStyle = router.pathname === tab.href ? styles.active : ""
|
||||||
|
if (tab.onClick) {
|
||||||
|
return <Button
|
||||||
|
auto={isMobile ? false : true}
|
||||||
|
key={tab.value}
|
||||||
|
icon={tab.icon}
|
||||||
|
onClick={() => onTabChange(tab.value)}
|
||||||
|
className={`${styles.tab} ${activeStyle}`}
|
||||||
|
shadow={false}
|
||||||
|
>
|
||||||
|
{tab.name ? tab.name : undefined}
|
||||||
|
</Button>
|
||||||
|
} else if (tab.href) {
|
||||||
|
return <Link key={tab.value} href={tab.href}>
|
||||||
|
<a className={styles.tab}>
|
||||||
|
<Button
|
||||||
|
className={activeStyle}
|
||||||
|
auto={isMobile ? false : true}
|
||||||
|
icon={tab.icon}
|
||||||
|
shadow={false}
|
||||||
|
>
|
||||||
|
{tab.name ? tab.name : undefined}
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
|
}, [isMobile, onTabChange, router.pathname])
|
||||||
|
|
||||||
|
const buttons = useMemo(() => pages.map(getButton), [pages, getButton])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page.Header height={'var(--page-nav-height)'} marginBottom={2}>
|
||||||
|
<div className={styles.tabs}>
|
||||||
|
<div className={styles.buttons}>
|
||||||
|
{buttons}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.controls}>
|
||||||
|
<Button
|
||||||
|
effect={false}
|
||||||
|
auto
|
||||||
|
type="abort"
|
||||||
|
onClick={() => setExpanded(!expanded)}
|
||||||
|
aria-label="Menu"
|
||||||
|
>
|
||||||
|
<Spacer height={5 / 6} width={0} />
|
||||||
|
<MenuIcon />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{isMobile && expanded && (<div className={styles.mobile}>
|
||||||
|
<ButtonGroup vertical style={{
|
||||||
|
background: "var(--bg)",
|
||||||
|
}}>
|
||||||
|
{buttons}
|
||||||
|
</ButtonGroup>
|
||||||
|
</div>)}
|
||||||
|
</Page.Header >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default Header
|
export default Header
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import Header from "@components/header/header"
|
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import VisibilityBadge from "@components/badges/visibility-badge"
|
import VisibilityBadge from "@components/badges/visibility-badge"
|
||||||
import DocumentComponent from '@components/view-document'
|
import DocumentComponent from '@components/view-document'
|
||||||
|
@ -88,9 +87,6 @@ const PostPage = ({ post }: Props) => {
|
||||||
isPrivate={false}
|
isPrivate={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
<Page.Content className={homeStyles.main}>
|
<Page.Content className={homeStyles.main}>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<span className={styles.title}>
|
<span className={styles.title}>
|
||||||
|
|
|
@ -12,6 +12,7 @@ const useSignedIn = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const signin = (token: string) => {
|
const signin = (token: string) => {
|
||||||
setSignedIn(true)
|
setSignedIn(true)
|
||||||
|
// TODO: investigate SameSite / CORS cookie security
|
||||||
Cookies.set("drift-token", token)
|
Cookies.set("drift-token", token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,8 @@ import '@styles/globals.css'
|
||||||
import type { AppProps as NextAppProps } from "next/app";
|
import type { AppProps as NextAppProps } from "next/app";
|
||||||
|
|
||||||
import 'react-loading-skeleton/dist/skeleton.css'
|
import 'react-loading-skeleton/dist/skeleton.css'
|
||||||
import { SkeletonTheme } from 'react-loading-skeleton';
|
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { CssBaseline, GeistProvider, Themes } from '@geist-ui/core';
|
import { ThemeProvider } from 'next-themes'
|
||||||
import { useTheme, ThemeProvider } from 'next-themes'
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
import App from '@components/app';
|
import App from '@components/app';
|
||||||
|
|
||||||
type AppProps<P = any> = {
|
type AppProps<P = any> = {
|
||||||
|
|
|
@ -11,18 +11,19 @@ export function middleware(req: NextRequest) {
|
||||||
!req.nextUrl.pathname.startsWith('/api') &&
|
!req.nextUrl.pathname.startsWith('/api') &&
|
||||||
// header added when next/link pre-fetches a route
|
// header added when next/link pre-fetches a route
|
||||||
!req.headers.get('x-middleware-preflight')
|
!req.headers.get('x-middleware-preflight')
|
||||||
if (isPageRequest) {
|
|
||||||
if (pathname === '/signout') {
|
|
||||||
// If you're signed in we remove the cookie and redirect to the home page
|
|
||||||
// If you're not signed in we redirect to the home page
|
|
||||||
if (signedIn) {
|
|
||||||
const resp = NextResponse.redirect(getURL(''));
|
|
||||||
resp.clearCookie('drift-token');
|
|
||||||
resp.clearCookie('drift-userid');
|
|
||||||
|
|
||||||
return resp
|
if (pathname === '/signout') {
|
||||||
}
|
// If you're signed in we remove the cookie and redirect to the home page
|
||||||
} else if (pathname === '/') {
|
// If you're not signed in we redirect to the home page
|
||||||
|
if (signedIn) {
|
||||||
|
const resp = NextResponse.redirect(getURL(''));
|
||||||
|
resp.clearCookie('drift-token');
|
||||||
|
resp.clearCookie('drift-userid');
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
} else if (isPageRequest) {
|
||||||
|
if (pathname === '/') {
|
||||||
if (signedIn) {
|
if (signedIn) {
|
||||||
return NextResponse.redirect(getURL('new'))
|
return NextResponse.redirect(getURL('new'))
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,6 @@ const AdminPage = () => {
|
||||||
}, [router, signedIn])
|
}, [router, signedIn])
|
||||||
return (
|
return (
|
||||||
<Page className={styles.wrapper}>
|
<Page className={styles.wrapper}>
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<Admin />
|
<Admin />
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
|
|
|
@ -5,7 +5,6 @@ import styles from '@styles/Home.module.css'
|
||||||
const Expired = () => {
|
const Expired = () => {
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<Header />
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<Note type="error" label={false}>
|
<Note type="error" label={false}>
|
||||||
<Text h4>Error: The Drift you're trying to view has expired.</Text>
|
<Text h4>Error: The Drift you're trying to view has expired.</Text>
|
||||||
|
|
|
@ -5,21 +5,30 @@ import HomeComponent from '@components/home'
|
||||||
import { Page, Text, Spacer, Tabs, Textarea, Card } from '@geist-ui/core'
|
import { Page, Text, Spacer, Tabs, Textarea, Card } from '@geist-ui/core'
|
||||||
|
|
||||||
export async function getStaticProps() {
|
export async function getStaticProps() {
|
||||||
const resp = await fetch(process.env.API_URL + `/welcome`,
|
try {
|
||||||
{
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"x-secret-key": process.env.SECRET_KEY || ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const { title, content, rendered } = await resp.json()
|
const resp = await fetch(process.env.API_URL + `/welcome`,
|
||||||
return {
|
{
|
||||||
props: {
|
method: "GET",
|
||||||
introContent: content || null,
|
headers: {
|
||||||
rendered: rendered || null,
|
"Content-Type": "application/json",
|
||||||
introTitle: title || null,
|
"x-secret-key": process.env.SECRET_KEY || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { title, content, rendered } = await resp.json()
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
introContent: content || null,
|
||||||
|
rendered: rendered || null,
|
||||||
|
introTitle: title || null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
error: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,17 +37,16 @@ type Props = {
|
||||||
introContent: string
|
introContent: string
|
||||||
introTitle: string
|
introTitle: string
|
||||||
rendered: string
|
rendered: string
|
||||||
|
error?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const Home = ({ rendered, introContent, introTitle }: Props) => {
|
const Home = ({ rendered, introContent, introTitle, error }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Page className={styles.wrapper}>
|
<Page className={styles.wrapper}>
|
||||||
<PageSeo />
|
<PageSeo />
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<HomeComponent rendered={rendered} introContent={introContent} introTitle={introTitle} />
|
{error && <Text>Something went wrong. Is the server running?</Text>}
|
||||||
|
{!error && <HomeComponent rendered={rendered} introContent={introContent} introTitle={introTitle} />}
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,9 +10,6 @@ import { Page } from '@geist-ui/core';
|
||||||
const Home = ({ morePosts, posts, error }: { morePosts: boolean, posts: Post[]; error: boolean; }) => {
|
const Home = ({ morePosts, posts, error }: { morePosts: boolean, posts: Post[]; error: boolean; }) => {
|
||||||
return (
|
return (
|
||||||
<Page className={styles.wrapper}>
|
<Page className={styles.wrapper}>
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<MyPosts morePosts={morePosts} error={error} posts={posts} />
|
<MyPosts morePosts={morePosts} error={error} posts={posts} />
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
|
|
|
@ -24,10 +24,6 @@ const NewFromExisting = ({
|
||||||
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
||||||
<link rel="stylesheet" href="/css/react-datepicker.css" />
|
<link rel="stylesheet" href="/css/react-datepicker.css" />
|
||||||
</Head>
|
</Head>
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<NewPost initialPost={post} newPostParent={parentId} />
|
<NewPost initialPost={post} newPostParent={parentId} />
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
|
|
|
@ -14,10 +14,6 @@ const New = () => {
|
||||||
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
||||||
<link rel="stylesheet" href="/css/react-datepicker.css" />
|
<link rel="stylesheet" href="/css/react-datepicker.css" />
|
||||||
</Head>
|
</Head>
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<NewPost />
|
<NewPost />
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
import { Page } from '@geist-ui/core';
|
import { Page } from '@geist-ui/core';
|
||||||
import PageSeo from "@components/page-seo";
|
import PageSeo from "@components/page-seo";
|
||||||
import Auth from "@components/auth";
|
import Auth from "@components/auth";
|
||||||
import Header from "@components/header/header";
|
|
||||||
import styles from '@styles/Home.module.css'
|
import styles from '@styles/Home.module.css'
|
||||||
const SignIn = () => (
|
const SignIn = () => (
|
||||||
<Page width={"100%"}>
|
<Page width={"100%"}>
|
||||||
<PageSeo title="Drift - Sign In" />
|
<PageSeo title="Drift - Sign In" />
|
||||||
|
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<Auth page="signin" />
|
<Auth page="signin" />
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default SignIn
|
export default SignIn
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
import { Page } from '@geist-ui/core';
|
import { Page } from '@geist-ui/core';
|
||||||
import Auth from "@components/auth";
|
import Auth from "@components/auth";
|
||||||
import Header from "@components/header/header";
|
|
||||||
import PageSeo from '@components/page-seo';
|
import PageSeo from '@components/page-seo';
|
||||||
import styles from '@styles/Home.module.css'
|
import styles from '@styles/Home.module.css'
|
||||||
|
|
||||||
const SignUp = () => (
|
const SignUp = () => (
|
||||||
<Page width="100%">
|
<Page width="100%">
|
||||||
<PageSeo title="Drift - Sign Up" />
|
<PageSeo title="Drift - Sign Up" />
|
||||||
|
|
||||||
<Page.Header>
|
|
||||||
<Header />
|
|
||||||
</Page.Header>
|
|
||||||
<Page.Content className={styles.main}>
|
<Page.Content className={styles.main}>
|
||||||
<Auth page="signup" />
|
<Auth page="signup" />
|
||||||
</Page.Content>
|
</Page.Content>
|
||||||
|
|
Loading…
Reference in a new issue