Compare commits
No commits in common. "b03179727170c31fc87510166e838a44ed1f3679" and "d3301da0ad259d9e3df07513bb4f535a406a23f4" have entirely different histories.
b031797271
...
d3301da0ad
1
.env
1
.env
@ -1,3 +1,2 @@
|
|||||||
NEXT_PUBLIC_FIRST_NAME=Ivan
|
NEXT_PUBLIC_FIRST_NAME=Ivan
|
||||||
NEXT_PUBLIC_LAST_NAME=Li
|
NEXT_PUBLIC_LAST_NAME=Li
|
||||||
BACKEND_URI=http://127.0.0.1:7132/graphql
|
|
||||||
|
@ -1,98 +1,6 @@
|
|||||||
import { useMemo } from "react";
|
import { ApolloClient, InMemoryCache } from "@apollo/client";
|
||||||
import { ApolloClient, from, HttpLink, InMemoryCache } from "@apollo/client";
|
|
||||||
import { concatPagination } from "@apollo/client/utilities";
|
|
||||||
import { equals, mergeDeepWith } from "ramda";
|
|
||||||
import { onError } from "@apollo/client/link/error";
|
|
||||||
|
|
||||||
export const client = new ApolloClient({
|
export const client = new ApolloClient({
|
||||||
uri: "/api/graphql",
|
uri: "/api/graphql",
|
||||||
cache: new InMemoryCache(),
|
cache: new InMemoryCache(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const APOLLO_STATE_PROP_NAME = "__APOLLO_STATE__";
|
|
||||||
|
|
||||||
let apolloClient: ApolloClient<InMemoryCache>;
|
|
||||||
|
|
||||||
function createApolloClient() {
|
|
||||||
const httpLink = new HttpLink({
|
|
||||||
uri:
|
|
||||||
typeof window === "undefined"
|
|
||||||
? process.env.BACKEND_URI
|
|
||||||
: "/api/graphql", // Server URL (must be absolute)
|
|
||||||
credentials: "same-origin", // Additional fetch() options like `credentials` or `headers`
|
|
||||||
});
|
|
||||||
|
|
||||||
const errorLink = onError(({ graphQLErrors, networkError }) => {
|
|
||||||
if (graphQLErrors)
|
|
||||||
graphQLErrors.forEach(({ message, locations, path }) =>
|
|
||||||
console.log(
|
|
||||||
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (networkError) console.log(`[Network error]: ${networkError}`);
|
|
||||||
});
|
|
||||||
return new ApolloClient({
|
|
||||||
ssrMode: typeof window === "undefined",
|
|
||||||
link: from([errorLink, httpLink]),
|
|
||||||
cache: new InMemoryCache({
|
|
||||||
typePolicies: {
|
|
||||||
Query: {
|
|
||||||
fields: {
|
|
||||||
allPosts: concatPagination(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function initializeApollo(initialState = null) {
|
|
||||||
const _apolloClient = apolloClient ?? createApolloClient();
|
|
||||||
|
|
||||||
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
|
|
||||||
// gets hydrated here
|
|
||||||
if (initialState) {
|
|
||||||
// Get existing cache, loaded during client side data fetching
|
|
||||||
const existingCache = _apolloClient.extract();
|
|
||||||
|
|
||||||
// Merge the existing cache into data passed from getStaticProps/getServerSideProps
|
|
||||||
const data = mergeDeepWith(
|
|
||||||
(a, b) => {
|
|
||||||
if (Array.isArray(a) && Array.isArray(b)) {
|
|
||||||
return [
|
|
||||||
...a,
|
|
||||||
...b.filter((bi) => a.every((ai) => !equals(ai, bi))),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initialState,
|
|
||||||
existingCache
|
|
||||||
);
|
|
||||||
|
|
||||||
// Restore the cache with the merged data
|
|
||||||
_apolloClient.cache.restore(data);
|
|
||||||
}
|
|
||||||
// For SSG and SSR always create a new Apollo Client
|
|
||||||
if (typeof window === "undefined") return _apolloClient;
|
|
||||||
// Create the Apollo Client once in the client
|
|
||||||
if (!apolloClient) apolloClient = _apolloClient;
|
|
||||||
|
|
||||||
return _apolloClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addApolloState(client, pageProps) {
|
|
||||||
if (pageProps?.props) {
|
|
||||||
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useApollo(pageProps) {
|
|
||||||
const state = pageProps[APOLLO_STATE_PROP_NAME];
|
|
||||||
const store = useMemo(() => initializeApollo(state), [state]);
|
|
||||||
return store;
|
|
||||||
}
|
|
||||||
|
@ -10,14 +10,3 @@ export const ARTICLE_FOR_HOME = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ARTICLE = gql`
|
|
||||||
query Article($id: String!) {
|
|
||||||
article(id: $id) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
content
|
|
||||||
publishedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
import React, { createContext, FC, useContext, useEffect, useState } from "react";
|
|
||||||
|
|
||||||
const getInitialTheme = (): Mode => {
|
|
||||||
if (typeof window === "undefined") {
|
|
||||||
return 'auto';
|
|
||||||
}
|
|
||||||
const text = window?.localStorage?.getItem('theme');
|
|
||||||
switch (text) {
|
|
||||||
case 'dark': return 'dark';
|
|
||||||
case 'light': return 'light';
|
|
||||||
default: return 'auto';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
type RawMode = "light" | "dark";
|
|
||||||
type Mode = RawMode | "auto";
|
|
||||||
|
|
||||||
interface Content {
|
|
||||||
mode: Mode;
|
|
||||||
setMode: (mode: Mode) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ThemeContext = createContext<Content>({
|
|
||||||
mode: 'error' as Mode,
|
|
||||||
setMode: (_) => {console.log},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const ThemeProvider: FC = ({ children }) => {
|
|
||||||
const [mode, setMode] = useState<Mode>(() => getInitialTheme());
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (window) {
|
|
||||||
localStorage.setItem("theme", mode);
|
|
||||||
let _mode = mode;
|
|
||||||
if (_mode === "auto") {
|
|
||||||
_mode =
|
|
||||||
window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
||||||
}
|
|
||||||
if (_mode === "dark") {
|
|
||||||
window.document.documentElement.classList.add("dark");
|
|
||||||
} else {
|
|
||||||
window.document.documentElement.classList.remove("dark");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [mode]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ThemeContext.Provider value={{ mode, setMode }}>
|
|
||||||
{children}
|
|
||||||
</ThemeContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useTheme () {
|
|
||||||
return useContext(ThemeContext);
|
|
||||||
}
|
|
@ -1,12 +1,13 @@
|
|||||||
.wrapper {
|
.wrapper {
|
||||||
@apply bg-green-400 text-white min-h-screen;
|
@apply bg-green-400 text-white;
|
||||||
:global(.dark) & {
|
:global(.dark) & {
|
||||||
@apply bg-gray-800 text-gray-400;
|
@apply bg-gray-800 text-gray-400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@apply overflow-hidden flex flex-col fixed top-0;
|
@apply overflow-hidden flex flex-col fixed top-0;
|
||||||
@apply text-center shadow-2xl h-screen;
|
@apply text-center shadow-2xl;
|
||||||
|
height: 100vh;
|
||||||
padding-top: 10vh;
|
padding-top: 10vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import { useTheme } from "../commons/theme";
|
|
||||||
|
|
||||||
export const SwitchTheme = () => {
|
|
||||||
const { setMode, mode } = useTheme();
|
|
||||||
|
|
||||||
if (mode === "light") {
|
|
||||||
return <button onClick={() => setMode("dark")}>暗色</button>;
|
|
||||||
}
|
|
||||||
return <button onClick={() => setMode("light")}>亮色</button>;
|
|
||||||
};
|
|
42
package-lock.json
generated
42
package-lock.json
generated
@ -13,7 +13,6 @@
|
|||||||
"next": "10.2.0",
|
"next": "10.2.0",
|
||||||
"postcss-import": "^14.0.1",
|
"postcss-import": "^14.0.1",
|
||||||
"postcss-nested": "^5.0.5",
|
"postcss-nested": "^5.0.5",
|
||||||
"ramda": "^0.27.1",
|
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2"
|
"react-dom": "17.0.2"
|
||||||
},
|
},
|
||||||
@ -28,7 +27,6 @@
|
|||||||
"@types/graphql": "^14.5.0",
|
"@types/graphql": "^14.5.0",
|
||||||
"@types/postcss-import": "^12.0.0",
|
"@types/postcss-import": "^12.0.0",
|
||||||
"@types/postcss-nested": "^4.2.3",
|
"@types/postcss-nested": "^4.2.3",
|
||||||
"@types/ramda": "^0.27.40",
|
|
||||||
"@types/react": "^17.0.4",
|
"@types/react": "^17.0.4",
|
||||||
"@types/tailwindcss": "^2.0.2",
|
"@types/tailwindcss": "^2.0.2",
|
||||||
"autoprefixer": "^10.2.5",
|
"autoprefixer": "^10.2.5",
|
||||||
@ -2472,15 +2470,6 @@
|
|||||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/ramda": {
|
|
||||||
"version": "0.27.40",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.40.tgz",
|
|
||||||
"integrity": "sha512-V99ZfTH2tqVYdLDAlgh2uT+N074HPgqnAsMjALKSBqogYd0HbuuGMqNukJ6fk9Ml/Htaus76fsc4Yh3p7q1VdQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ts-toolbelt": "^6.15.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "17.0.4",
|
"version": "17.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz",
|
||||||
@ -7692,11 +7681,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ramda": {
|
|
||||||
"version": "0.27.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
|
||||||
"integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw=="
|
|
||||||
},
|
|
||||||
"node_modules/randombytes": {
|
"node_modules/randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
@ -8948,12 +8932,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-toolbelt": {
|
|
||||||
"version": "6.15.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz",
|
|
||||||
"integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "1.14.1",
|
"version": "1.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
@ -11539,15 +11517,6 @@
|
|||||||
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/ramda": {
|
|
||||||
"version": "0.27.40",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.40.tgz",
|
|
||||||
"integrity": "sha512-V99ZfTH2tqVYdLDAlgh2uT+N074HPgqnAsMjALKSBqogYd0HbuuGMqNukJ6fk9Ml/Htaus76fsc4Yh3p7q1VdQ==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"ts-toolbelt": "^6.15.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@types/react": {
|
"@types/react": {
|
||||||
"version": "17.0.4",
|
"version": "17.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.4.tgz",
|
||||||
@ -15715,11 +15684,6 @@
|
|||||||
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ramda": {
|
|
||||||
"version": "0.27.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz",
|
|
||||||
"integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw=="
|
|
||||||
},
|
|
||||||
"randombytes": {
|
"randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
@ -16724,12 +16688,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
|
||||||
"integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw=="
|
"integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw=="
|
||||||
},
|
},
|
||||||
"ts-toolbelt": {
|
|
||||||
"version": "6.15.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz",
|
|
||||||
"integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.14.1",
|
"version": "1.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
"next": "10.2.0",
|
"next": "10.2.0",
|
||||||
"postcss-import": "^14.0.1",
|
"postcss-import": "^14.0.1",
|
||||||
"postcss-nested": "^5.0.5",
|
"postcss-nested": "^5.0.5",
|
||||||
"ramda": "^0.27.1",
|
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2"
|
"react-dom": "17.0.2"
|
||||||
},
|
},
|
||||||
@ -31,7 +30,6 @@
|
|||||||
"@types/graphql": "^14.5.0",
|
"@types/graphql": "^14.5.0",
|
||||||
"@types/postcss-import": "^12.0.0",
|
"@types/postcss-import": "^12.0.0",
|
||||||
"@types/postcss-nested": "^4.2.3",
|
"@types/postcss-nested": "^4.2.3",
|
||||||
"@types/ramda": "^0.27.40",
|
|
||||||
"@types/react": "^17.0.4",
|
"@types/react": "^17.0.4",
|
||||||
"@types/tailwindcss": "^2.0.2",
|
"@types/tailwindcss": "^2.0.2",
|
||||||
"autoprefixer": "^10.2.5",
|
"autoprefixer": "^10.2.5",
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
@apply bg-gray-700 text-gray-300;
|
@apply bg-gray-700 text-gray-300;
|
||||||
}
|
}
|
||||||
.wrapper {
|
.wrapper {
|
||||||
@apply mx-auto max-w-screen-lg;
|
@apply mx-auto max-w-screen-xl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pageHeader {
|
.pageHeader {
|
||||||
|
@ -4,22 +4,19 @@ import React from "react";
|
|||||||
import { GlobalSidebar } from "../components/layouts/global-sidebar";
|
import { GlobalSidebar } from "../components/layouts/global-sidebar";
|
||||||
import styles from "./_app.module.css";
|
import styles from "./_app.module.css";
|
||||||
import { ApolloProvider } from "@apollo/client";
|
import { ApolloProvider } from "@apollo/client";
|
||||||
import { useApollo } from "../commons/graphql/client";
|
import { client } from "../commons/graphql/client";
|
||||||
import { ThemeProvider, useTheme } from '../commons/theme';
|
|
||||||
import { SwitchTheme } from '../components/switch-theme';
|
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
const apolloClient = useApollo(pageProps);
|
|
||||||
return (
|
return (
|
||||||
<ApolloProvider client={apolloClient}>
|
<ApolloProvider client={client}>
|
||||||
<ThemeProvider>
|
|
||||||
<div className={styles.page}>
|
<div className={styles.page}>
|
||||||
<GlobalSidebar className={styles.sidebar} />
|
<GlobalSidebar className={styles.sidebar} />
|
||||||
<div className={styles.primary}>
|
<div className={styles.primary}>
|
||||||
<header className={styles.pageHeader}>
|
<header className={styles.pageHeader}>
|
||||||
<h1>{"Ivan Li 的个人博客"}</h1>
|
<h1>{"Ivan Li 的个人博客"}</h1>
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
<SwitchTheme />
|
<button onClick={() => switchTheme("light")}>亮色</button>
|
||||||
|
<button onClick={() => switchTheme("dark")}>暗色</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
@ -27,9 +24,20 @@ function MyApp({ Component, pageProps }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ThemeProvider>
|
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function switchTheme(mode: "light" | "dark" | "auto") {
|
||||||
|
if (mode === "auto") {
|
||||||
|
mode = "light";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === "dark") {
|
||||||
|
document.documentElement.classList.add("dark");
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove("dark");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default MyApp;
|
export default MyApp;
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import { FC } from "react";
|
|
||||||
import styles from "./article.module.css";
|
|
||||||
import { GetServerSideProps, GetStaticProps } from "next";
|
|
||||||
import { addApolloState, initializeApollo } from "../../commons/graphql/client";
|
|
||||||
import { ARTICLE } from "../../commons/graphql/queries";
|
|
||||||
import { Article } from "../../commons/graphql/generated";
|
|
||||||
import { useQuery } from '@apollo/client';
|
|
||||||
import { useRouter } from 'next/router';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
article: Article;
|
|
||||||
}
|
|
||||||
const ArticleDetails: FC<Props> = ({ article }) => {
|
|
||||||
// const router = useRouter()
|
|
||||||
// const { data } = useQuery<{ article: Article }>(ARTICLE, {
|
|
||||||
// variables: router.query,
|
|
||||||
// });
|
|
||||||
return (
|
|
||||||
<main className={styles.articleDetails}>
|
|
||||||
<article className={styles.article}>
|
|
||||||
<header>
|
|
||||||
<h1>{article.title}</h1>
|
|
||||||
<time>{article.publishedAt}</time>
|
|
||||||
</header>
|
|
||||||
<div dangerouslySetInnerHTML={{__html: article.content}}></div>
|
|
||||||
</article>
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
|
|
||||||
const apolloClient = initializeApollo();
|
|
||||||
|
|
||||||
const { data } = await apolloClient.query<{ article: Article }>({
|
|
||||||
query: ARTICLE,
|
|
||||||
variables: params,
|
|
||||||
});
|
|
||||||
|
|
||||||
return addApolloState(apolloClient, {
|
|
||||||
props: { article: data.article },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ArticleDetails;
|
|
@ -1,28 +0,0 @@
|
|||||||
.articleDetail {
|
|
||||||
}
|
|
||||||
.article {
|
|
||||||
@apply bg-gray-50 m-2 overflow-hidden rounded-xl;
|
|
||||||
|
|
||||||
:global(.dark) & {
|
|
||||||
@apply bg-gray-800;
|
|
||||||
}
|
|
||||||
& > header {
|
|
||||||
@apply my-8 mx-4;
|
|
||||||
h1 {
|
|
||||||
@apply text-2xl font-medium;
|
|
||||||
|
|
||||||
:global(.dark) & {
|
|
||||||
@apply text-gray-200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time {
|
|
||||||
@apply text-sm text-gray-500;
|
|
||||||
:global(.dark) & {
|
|
||||||
@apply text-gray-400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& > div {
|
|
||||||
@apply my-4 leading-8 mx-4 lg:mx-6 xl:mx-8 text-justify;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +1,23 @@
|
|||||||
import { useQuery } from "@apollo/client";
|
import { useQuery } from '@apollo/client';
|
||||||
import { GetServerSideProps } from 'next';
|
import { Article } from '../commons/graphql/generated';
|
||||||
import Link from "next/link";
|
import { ARTICLE_FOR_HOME } from '../commons/graphql/queries';
|
||||||
import React from "react";
|
import styles from './index.module.css';
|
||||||
import { addApolloState, initializeApollo } from '../commons/graphql/client';
|
|
||||||
import { Article } from "../commons/graphql/generated";
|
|
||||||
import { ARTICLE_FOR_HOME } from "../commons/graphql/queries";
|
|
||||||
import styles from "./index.module.css";
|
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const { data, loading } = useQuery<{articles: Article[]}>(ARTICLE_FOR_HOME);
|
const { data, loading } = useQuery<{articles: Article[]}>(ARTICLE_FOR_HOME);
|
||||||
|
|
||||||
return (
|
return <main className={styles.index}>
|
||||||
<main className={styles.index}>
|
|
||||||
<ol>
|
<ol>
|
||||||
{data?.articles?.map((article) => (
|
{
|
||||||
<Item article={article} key={article.id} />
|
data?.articles?.map(article => <Item article={article} key={article.id} />)
|
||||||
))}
|
}
|
||||||
</ol>
|
</ol>
|
||||||
</main>
|
</main>;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Item({article}: {article: Article}) {
|
function Item({article}: {article: Article}) {
|
||||||
return (
|
return <li className={styles.item}>
|
||||||
<Link href={`/articles/${article.id}`}>
|
|
||||||
<li className={styles.item}>
|
|
||||||
<h2 className={styles.title}>{article.title}</h2>
|
<h2 className={styles.title}>{article.title}</h2>
|
||||||
<p className={styles.description}>{article.content}</p>
|
<p className={styles.description}>{article.content}</p>
|
||||||
</li>
|
</li>
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
|
|
||||||
const apolloClient = initializeApollo();
|
|
||||||
|
|
||||||
await apolloClient.query({
|
|
||||||
query: ARTICLE_FOR_HOME,
|
|
||||||
});
|
|
||||||
|
|
||||||
return addApolloState(apolloClient, {
|
|
||||||
props: {},
|
|
||||||
});
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user