Layout extraction refactoring
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
import { FC } from "react";
|
import { FC } from "react";
|
||||||
import Head from "next/head";
|
import { Stack, HStack, Heading, Text, Icon, useColorModeValue } from "@chakra-ui/react";
|
||||||
import { Stack, VStack, HStack, Heading, Text, Icon, useColorModeValue } from "@chakra-ui/react";
|
|
||||||
import { FaSadTear } from "react-icons/fa";
|
import { FaSadTear } from "react-icons/fa";
|
||||||
import Header from "./Header";
|
import Layout from "./Layout";
|
||||||
import Footer from "./Footer";
|
|
||||||
|
|
||||||
const statusTexts: {
|
const statusTexts: {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
@@ -20,38 +18,26 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CustomError: FC<Props> = ({ statusCode }) => (
|
const CustomError: FC<Props> = ({ statusCode }) => (
|
||||||
<>
|
<Layout customTitle={`${statusCode} - ${statusTexts?.[statusCode] ?? statusTexts.fallback}`}>
|
||||||
<Head>
|
<Stack
|
||||||
<title>
|
color={useColorModeValue("lingva.900", "lingva.100")}
|
||||||
{statusCode} - {statusTexts?.[statusCode] ?? statusTexts.fallback}
|
direction={["column", null, "row"]}
|
||||||
</title>
|
justify="center"
|
||||||
<link rel="icon" href="/favicon.svg" />
|
align="center"
|
||||||
</Head>
|
spacing={4}
|
||||||
|
w="full"
|
||||||
<VStack h="100vh">
|
>
|
||||||
<Header/>
|
<HStack align="center" spacing={5}>
|
||||||
<Stack
|
<Heading as="h1" size="3xl">
|
||||||
as="main"
|
{statusCode}
|
||||||
flexGrow={1}
|
</Heading>
|
||||||
color={useColorModeValue("lingva.900", "lingva.100")}
|
<Icon as={FaSadTear} boxSize={10} />
|
||||||
direction={["column", null, "row"]}
|
</HStack>
|
||||||
justify="center"
|
<Text as="h2" fontSize="xl">
|
||||||
align="center"
|
{statusTexts?.[statusCode] ?? statusTexts.fallback}
|
||||||
spacing={4}
|
</Text>
|
||||||
>
|
</Stack>
|
||||||
<HStack align="center" spacing={5}>
|
</Layout>
|
||||||
<Heading as="h1" size="3xl">
|
|
||||||
{statusCode}
|
|
||||||
</Heading>
|
|
||||||
<Icon as={FaSadTear} boxSize={10} />
|
|
||||||
</HStack>
|
|
||||||
<Text as="h2" fontSize="xl">
|
|
||||||
{statusTexts?.[statusCode] ?? statusTexts.fallback}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
<Footer/>
|
|
||||||
</VStack>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export default CustomError;
|
export default CustomError;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { FC, ChangeEvent } from "react";
|
import { FC, ChangeEvent } from "react";
|
||||||
import { Select } from "@chakra-ui/react";
|
import { Select } from "@chakra-ui/react";
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
value: string,
|
value: string,
|
||||||
onChange: (e: ChangeEvent<any>) => void,
|
onChange: (e: ChangeEvent<any>) => void,
|
||||||
|
|||||||
52
components/Layout.tsx
Normal file
52
components/Layout.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { Flex, VStack, Button, Link } from "@chakra-ui/react";
|
||||||
|
import Head from "next/head";
|
||||||
|
import Header from "./Header";
|
||||||
|
import Footer from "./Footer";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
customTitle?: string
|
||||||
|
[key: string]: any
|
||||||
|
};
|
||||||
|
|
||||||
|
const title = "Lingva Translate";
|
||||||
|
|
||||||
|
const Layout: FC<Props> = ({ customTitle, children }) => (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>
|
||||||
|
{customTitle ?? title}
|
||||||
|
</title>
|
||||||
|
<link rel="icon" href="/favicon.svg" />
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
as={Link}
|
||||||
|
href="#main"
|
||||||
|
userSelect="none"
|
||||||
|
position="absolute"
|
||||||
|
top="-100px"
|
||||||
|
left="0"
|
||||||
|
_focus={{
|
||||||
|
top: "0"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Skip to content
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<VStack minH="100vh" spacing={8}>
|
||||||
|
<Header />
|
||||||
|
<Flex
|
||||||
|
as="main"
|
||||||
|
id="main"
|
||||||
|
flexGrow={1}
|
||||||
|
w="full"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Flex>
|
||||||
|
<Footer />
|
||||||
|
</VStack>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Layout;
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
export { default as CustomError } from "./CustomError";
|
export { default as CustomError } from "./CustomError";
|
||||||
export { default as Header } from "./Header";
|
export { default as Layout } from "./Layout";
|
||||||
export { default as Footer } from "./Footer";
|
|
||||||
export { default as LangSelect } from "./LangSelect";
|
export { default as LangSelect } from "./LangSelect";
|
||||||
export { default as TranslationArea } from "./TranslationArea";
|
export { default as TranslationArea } from "./TranslationArea";
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { useState, useEffect, useReducer, FC, ChangeEvent } from "react";
|
import { useState, useEffect, useReducer, FC, ChangeEvent } from "react";
|
||||||
import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from "next";
|
import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from "next";
|
||||||
import Head from "next/head";
|
|
||||||
import Router from "next/router";
|
import Router from "next/router";
|
||||||
import { Stack, VStack, HStack, IconButton, Button, Link } from "@chakra-ui/react";
|
import { Stack, VStack, HStack, IconButton } from "@chakra-ui/react";
|
||||||
import { FaExchangeAlt } from "react-icons/fa";
|
import { FaExchangeAlt } from "react-icons/fa";
|
||||||
import { CustomError, Header, Footer, LangSelect, TranslationArea } from "../components";
|
import { CustomError, Layout, LangSelect, TranslationArea } from "../components";
|
||||||
import { useToastOnLoad } from "../hooks";
|
import { useToastOnLoad } from "../hooks";
|
||||||
import { googleScrape, extractSlug } from "../utils/translate";
|
import { googleScrape, extractSlug } from "../utils/translate";
|
||||||
import { retrieveFiltered } from "../utils/language";
|
import { retrieveFiltered } from "../utils/language";
|
||||||
@@ -55,80 +54,50 @@ const Page: FC<InferGetStaticPropsType<typeof getStaticProps>> = ({ translation,
|
|||||||
return statusCode ? (
|
return statusCode ? (
|
||||||
<CustomError statusCode={statusCode} />
|
<CustomError statusCode={statusCode} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Layout>
|
||||||
<Head>
|
<VStack px={[8, null, 24, 40]} w="full">
|
||||||
<title>
|
<HStack px={[1, null, 3, 4]} w="full">
|
||||||
Lingva Translate
|
<LangSelect
|
||||||
</title>
|
id="source"
|
||||||
<link rel="icon" href="/favicon.svg" />
|
aria-label="Source language"
|
||||||
</Head>
|
value={source}
|
||||||
|
onChange={handleChange}
|
||||||
<Button
|
langs={sourceLangs}
|
||||||
as={Link}
|
/>
|
||||||
href="#main"
|
<IconButton
|
||||||
userSelect="none"
|
aria-label="Switch languages"
|
||||||
position="absolute"
|
icon={<FaExchangeAlt />}
|
||||||
top="-100px"
|
colorScheme="lingva"
|
||||||
left="0"
|
variant="ghost"
|
||||||
_focus={{
|
onClick={() => dispatch({ type: Actions.SWITCH_LANGS })}
|
||||||
top: "0"
|
isDisabled={source === "auto"}
|
||||||
}}
|
/>
|
||||||
>
|
<LangSelect
|
||||||
Skip to content
|
id="target"
|
||||||
</Button>
|
aria-label="Target language"
|
||||||
|
value={target}
|
||||||
<VStack minH="100vh" spacing={8}>
|
onChange={handleChange}
|
||||||
<Header />
|
langs={targetLangs}
|
||||||
<VStack
|
/>
|
||||||
as="main"
|
</HStack>
|
||||||
id="main"
|
<Stack direction={["column", null, "row"]} w="full">
|
||||||
px={[8, null, 24, 40]}
|
<TranslationArea
|
||||||
flexGrow={1}
|
id="query"
|
||||||
w="full">
|
aria-label="Translation query"
|
||||||
<HStack px={[1, null, 3, 4]} w="full">
|
placeholder="Text"
|
||||||
<LangSelect
|
value={query}
|
||||||
id="source"
|
onChange={handleChange}
|
||||||
aria-label="Source language"
|
/>
|
||||||
value={source}
|
<TranslationArea
|
||||||
onChange={handleChange}
|
id="translation"
|
||||||
langs={sourceLangs}
|
aria-label="Translation result"
|
||||||
/>
|
placeholder="Translation"
|
||||||
<IconButton
|
value={translation ?? ""}
|
||||||
aria-label="Switch languages"
|
readOnly={true}
|
||||||
icon={<FaExchangeAlt />}
|
/>
|
||||||
colorScheme="lingva"
|
</Stack>
|
||||||
variant="ghost"
|
|
||||||
onClick={() => dispatch({ type: Actions.SWITCH_LANGS })}
|
|
||||||
isDisabled={source === "auto"}
|
|
||||||
/>
|
|
||||||
<LangSelect
|
|
||||||
id="target"
|
|
||||||
aria-label="Target language"
|
|
||||||
value={target}
|
|
||||||
onChange={handleChange}
|
|
||||||
langs={targetLangs}
|
|
||||||
/>
|
|
||||||
</HStack>
|
|
||||||
<Stack direction={["column", null, "row"]} w="full">
|
|
||||||
<TranslationArea
|
|
||||||
id="query"
|
|
||||||
aria-label="Translation query"
|
|
||||||
placeholder="Text"
|
|
||||||
value={query}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
<TranslationArea
|
|
||||||
id="translation"
|
|
||||||
aria-label="Translation result"
|
|
||||||
placeholder="Translation"
|
|
||||||
value={translation ?? ""}
|
|
||||||
readOnly={true}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</VStack>
|
|
||||||
<Footer />
|
|
||||||
</VStack>
|
</VStack>
|
||||||
</>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user