| @@ -20,6 +20,7 @@ | |||||
| "markdown-it": "^14.1.0", | "markdown-it": "^14.1.0", | ||||
| "react": "^19.1.0", | "react": "^19.1.0", | ||||
| "react-dom": "^19.1.0", | "react-dom": "^19.1.0", | ||||
| "react-helmet": "^6.1.0", | |||||
| "react-markdown": "^10.1.0", | "react-markdown": "^10.1.0", | ||||
| "react-markdown-editor-lite": "^1.3.4", | "react-markdown-editor-lite": "^1.3.4", | ||||
| "react-router-dom": "^6.30.0", | "react-router-dom": "^6.30.0", | ||||
| @@ -3974,7 +3975,6 @@ | |||||
| "version": "4.0.0", | "version": "4.0.0", | ||||
| "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | ||||
| "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", | ||||
| "dev": true, | |||||
| "license": "MIT" | "license": "MIT" | ||||
| }, | }, | ||||
| "node_modules/js-yaml": { | "node_modules/js-yaml": { | ||||
| @@ -4120,6 +4120,18 @@ | |||||
| "url": "https://github.com/sponsors/wooorm" | "url": "https://github.com/sponsors/wooorm" | ||||
| } | } | ||||
| }, | }, | ||||
| "node_modules/loose-envify": { | |||||
| "version": "1.4.0", | |||||
| "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", | |||||
| "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", | |||||
| "license": "MIT", | |||||
| "dependencies": { | |||||
| "js-tokens": "^3.0.0 || ^4.0.0" | |||||
| }, | |||||
| "bin": { | |||||
| "loose-envify": "cli.js" | |||||
| } | |||||
| }, | |||||
| "node_modules/lru-cache": { | "node_modules/lru-cache": { | ||||
| "version": "5.1.1", | "version": "5.1.1", | ||||
| "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", | ||||
| @@ -4909,7 +4921,6 @@ | |||||
| "version": "4.1.1", | "version": "4.1.1", | ||||
| "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", | ||||
| "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", | ||||
| "dev": true, | |||||
| "license": "MIT", | "license": "MIT", | ||||
| "engines": { | "engines": { | ||||
| "node": ">=0.10.0" | "node": ">=0.10.0" | ||||
| @@ -5284,6 +5295,17 @@ | |||||
| "node": ">= 0.8.0" | "node": ">= 0.8.0" | ||||
| } | } | ||||
| }, | }, | ||||
| "node_modules/prop-types": { | |||||
| "version": "15.8.1", | |||||
| "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", | |||||
| "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", | |||||
| "license": "MIT", | |||||
| "dependencies": { | |||||
| "loose-envify": "^1.4.0", | |||||
| "object-assign": "^4.1.1", | |||||
| "react-is": "^16.13.1" | |||||
| } | |||||
| }, | |||||
| "node_modules/property-information": { | "node_modules/property-information": { | ||||
| "version": "7.1.0", | "version": "7.1.0", | ||||
| "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", | "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", | ||||
| @@ -5361,6 +5383,33 @@ | |||||
| "react": "^19.1.0" | "react": "^19.1.0" | ||||
| } | } | ||||
| }, | }, | ||||
| "node_modules/react-fast-compare": { | |||||
| "version": "3.2.2", | |||||
| "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", | |||||
| "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", | |||||
| "license": "MIT" | |||||
| }, | |||||
| "node_modules/react-helmet": { | |||||
| "version": "6.1.0", | |||||
| "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", | |||||
| "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", | |||||
| "license": "MIT", | |||||
| "dependencies": { | |||||
| "object-assign": "^4.1.1", | |||||
| "prop-types": "^15.7.2", | |||||
| "react-fast-compare": "^3.1.1", | |||||
| "react-side-effect": "^2.1.0" | |||||
| }, | |||||
| "peerDependencies": { | |||||
| "react": ">=16.3.0" | |||||
| } | |||||
| }, | |||||
| "node_modules/react-is": { | |||||
| "version": "16.13.1", | |||||
| "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", | |||||
| "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", | |||||
| "license": "MIT" | |||||
| }, | |||||
| "node_modules/react-markdown": { | "node_modules/react-markdown": { | ||||
| "version": "10.1.0", | "version": "10.1.0", | ||||
| "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", | "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", | ||||
| @@ -5492,6 +5541,15 @@ | |||||
| "react-dom": ">=16.8" | "react-dom": ">=16.8" | ||||
| } | } | ||||
| }, | }, | ||||
| "node_modules/react-side-effect": { | |||||
| "version": "2.1.2", | |||||
| "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz", | |||||
| "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==", | |||||
| "license": "MIT", | |||||
| "peerDependencies": { | |||||
| "react": "^16.3.0 || ^17.0.0 || ^18.0.0" | |||||
| } | |||||
| }, | |||||
| "node_modules/react-style-singleton": { | "node_modules/react-style-singleton": { | ||||
| "version": "2.2.3", | "version": "2.2.3", | ||||
| "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", | "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", | ||||
| @@ -21,6 +21,7 @@ | |||||
| "markdown-it": "^14.1.0", | "markdown-it": "^14.1.0", | ||||
| "react": "^19.1.0", | "react": "^19.1.0", | ||||
| "react-dom": "^19.1.0", | "react-dom": "^19.1.0", | ||||
| "react-helmet": "^6.1.0", | |||||
| "react-markdown": "^10.1.0", | "react-markdown": "^10.1.0", | ||||
| "react-markdown-editor-lite": "^1.3.4", | "react-markdown-editor-lite": "^1.3.4", | ||||
| "react-router-dom": "^6.30.0", | "react-router-dom": "^6.30.0", | ||||
| @@ -0,0 +1,25 @@ | |||||
| import React, { useEffect, useState } from 'react' | |||||
| type Props = { tabs: { [key: string]: React.ReactNode } | |||||
| init?: string } | |||||
| export default ({ tabs, init }: Props) => { | |||||
| const [current, setCurrent] = useState<string> (init | |||||
| ?? Object.keys (tabs)?.[0] | |||||
| ?? '') | |||||
| return ( | |||||
| <div className="mt-4"> | |||||
| {Object.entries (tabs).map (([name, element]) => ( | |||||
| <a href="#" | |||||
| className="text-blue-400 hover:underline cursor-pointer" | |||||
| onClick={(event) => { | |||||
| event.preventDefault () | |||||
| setCurrent (name) | |||||
| }}> | |||||
| {name} | |||||
| </a>))} | |||||
| {current && tabs[current]} | |||||
| </div>) | |||||
| } | |||||
| @@ -1,4 +1,5 @@ | |||||
| import React, { useEffect, useState } from 'react' | import React, { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams } from 'react-router-dom' | import { Link, useLocation, useParams } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | import { API_BASE_URL, SITE_TITLE } from '@/config' | ||||
| @@ -9,6 +10,7 @@ import { cn } from '@/lib/utils' | |||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import TagDetailSidebar from '@/components/TagDetailSidebar' | import TagDetailSidebar from '@/components/TagDetailSidebar' | ||||
| import PostEditForm from '@/components/PostEditForm' | import PostEditForm from '@/components/PostEditForm' | ||||
| import TabControl from '@/components/common/TabControl' | |||||
| import type { Post, Tag, User } from '@/types' | import type { Post, Tag, User } from '@/types' | ||||
| @@ -69,20 +71,13 @@ export default ({ user }: Props) => { | |||||
| setEditing (true) | setEditing (true) | ||||
| }, [editing]) | }, [editing]) | ||||
| if (!(post)) | |||||
| return ( | |||||
| <> | |||||
| <TagDetailSidebar post={null} /> | |||||
| <MainArea>Loading...</MainArea> | |||||
| </>) | |||||
| if (post) | |||||
| document.title = `${ post.title || post.url } | ${ SITE_TITLE }` | |||||
| const url = post ? new URL (post.url) : undefined | const url = post ? new URL (post.url) : undefined | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <Helmet> | |||||
| {post && <title>{`${ post.title || post.url } | ${ SITE_TITLE }`}</title>} | |||||
| </Helmet> | |||||
| <TagDetailSidebar post={post} /> | <TagDetailSidebar post={post} /> | ||||
| <MainArea> | <MainArea> | ||||
| {post | {post | ||||
| @@ -107,16 +102,13 @@ export default ({ user }: Props) => { | |||||
| {post.viewed ? '閲覧済' : '未閲覧'} | {post.viewed ? '閲覧済' : '未閲覧'} | ||||
| </Button> | </Button> | ||||
| {(['admin', 'member'].includes (user.role) && editing) && | {(['admin', 'member'].includes (user.role) && editing) && | ||||
| <div className="mt-4"> | |||||
| <span className="text-blue-400 hover:underline cursor-pointer"> | |||||
| 編輯 | |||||
| </span> | |||||
| <PostEditForm post={post} | |||||
| onSave={newPost => { | |||||
| setPost (newPost) | |||||
| toast ({ description: '更新しました.' }) | |||||
| }} /> | |||||
| </div>} | |||||
| <TabControl tabs={{ | |||||
| ['編輯']: ( | |||||
| <PostEditForm post={post} | |||||
| onSave={newPost => { | |||||
| setPost (newPost) | |||||
| toast ({ description: '更新しました.' }) | |||||
| }} />) }} />} | |||||
| </div>) | </div>) | ||||
| : 'Loading...'} | : 'Loading...'} | ||||
| </MainArea> | </MainArea> | ||||
| @@ -1,4 +1,5 @@ | |||||
| import React, { useEffect, useState, useRef } from 'react' | import React, { useEffect, useState, useRef } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | import { API_BASE_URL, SITE_TITLE } from '@/config' | ||||
| @@ -48,8 +49,6 @@ export default () => { | |||||
| description: '入力を確認してください。' }))) | description: '入力を確認してください。' }))) | ||||
| } | } | ||||
| document.title = `広場に投稿を追加 | ${ SITE_TITLE }` | |||||
| useEffect (() => { | useEffect (() => { | ||||
| void (axios.get ('/api/tags') | void (axios.get ('/api/tags') | ||||
| .then (res => setTags (res.data)) | .then (res => setTags (res.data)) | ||||
| @@ -113,6 +112,9 @@ export default () => { | |||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`広場に投稿を追加 | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| <div className="max-w-xl mx-auto p-4 space-y-4"> | <div className="max-w-xl mx-auto p-4 space-y-4"> | ||||
| <h1 className="text-2xl font-bold mb-2">広場に投稿を追加する</h1> | <h1 className="text-2xl font-bold mb-2">広場に投稿を追加する</h1> | ||||
| @@ -1,4 +1,5 @@ | |||||
| import React, { useEffect, useState } from 'react' | import React, { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation } from 'react-router-dom' | import { Link, useLocation } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | import { API_BASE_URL, SITE_TITLE } from '@/config' | ||||
| @@ -17,10 +18,6 @@ export default () => { | |||||
| // const anyFlg = query.get ('match') === 'any' | // const anyFlg = query.get ('match') === 'any' | ||||
| const anyFlg = false | const anyFlg = false | ||||
| const tags = tagsQuery.split (' ').filter (e => e !== '') | const tags = tagsQuery.split (' ').filter (e => e !== '') | ||||
| if (tags.length) | |||||
| document.title = `${ tags.join (anyFlg ? ' or ' : ' and ') } | ${ SITE_TITLE }` | |||||
| else | |||||
| document.title = `${ SITE_TITLE } 〜 ぼざクリも、ぼざろ外も、外伝もあるんだよ` | |||||
| useEffect(() => { | useEffect(() => { | ||||
| const fetchPosts = async () => { | const fetchPosts = async () => { | ||||
| @@ -42,6 +39,13 @@ export default () => { | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <Helmet> | |||||
| <title> | |||||
| {tags.length | |||||
| ? `${ tags.join (anyFlg ? ' or ' : ' and ') } | ${ SITE_TITLE }` | |||||
| : `${ SITE_TITLE } 〜 ぼざクリも、ぼざろ外も、外伝もあるんだよ`} | |||||
| </title> | |||||
| </Helmet> | |||||
| <TagSidebar posts={posts} /> | <TagSidebar posts={posts} /> | ||||
| <MainArea> | <MainArea> | ||||
| <div className="flex flex-wrap gap-4 p-4"> | <div className="flex flex-wrap gap-4 p-4"> | ||||
| @@ -1,8 +1,9 @@ | |||||
| import { useEffect, useState } from 'react' | import { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | ||||
| import ReactMarkdown from 'react-markdown' | import ReactMarkdown from 'react-markdown' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL } from '@/config' | |||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | |||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' | import { WikiIdBus } from '@/lib/eventBus/WikiIdBus' | ||||
| @@ -38,6 +39,9 @@ export default () => { | |||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`${ title } Wiki | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| {(wikiPage && version) && ( | {(wikiPage && version) && ( | ||||
| <div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4"> | <div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4"> | ||||
| {wikiPage.pred ? ( | {wikiPage.pred ? ( | ||||
| @@ -1,8 +1,9 @@ | |||||
| import { useEffect, useState } from 'react' | import { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams } from 'react-router-dom' | import { Link, useLocation, useParams } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import { API_BASE_URL } from '@/config' | |||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | |||||
| import type { WikiPageDiff } from '@/types' | import type { WikiPageDiff } from '@/types' | ||||
| @@ -25,6 +26,9 @@ export default () => { | |||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| <h1>{diff?.title}</h1> | <h1>{diff?.title}</h1> | ||||
| <div className="prose mx-auto p-4"> | <div className="prose mx-auto p-4"> | ||||
| {diff ? ( | {diff ? ( | ||||
| @@ -1,4 +1,5 @@ | |||||
| import React, { useEffect, useState, useRef } from 'react' | import React, { useEffect, useState, useRef } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | import { API_BASE_URL, SITE_TITLE } from '@/config' | ||||
| @@ -47,12 +48,13 @@ export default () => { | |||||
| setTitle (res.data.title) | setTitle (res.data.title) | ||||
| setBody (res.data.body) | setBody (res.data.body) | ||||
| })) | })) | ||||
| document.title = `Wiki ページを編輯 | ${ SITE_TITLE }` | |||||
| }, [id]) | }, [id]) | ||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`Wiki ページを編輯 | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| <div className="max-w-xl mx-auto p-4 space-y-4"> | <div className="max-w-xl mx-auto p-4 space-y-4"> | ||||
| <h1 className="text-2xl font-bold mb-2">Wiki ページを編輯</h1> | <h1 className="text-2xl font-bold mb-2">Wiki ページを編輯</h1> | ||||
| @@ -1,8 +1,9 @@ | |||||
| import { useEffect, useState } from 'react' | import { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams } from 'react-router-dom' | import { Link, useLocation, useParams } from 'react-router-dom' | ||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL } from '@/config' | |||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | |||||
| import type { WikiPageChange } from '@/types' | import type { WikiPageChange } from '@/types' | ||||
| @@ -21,6 +22,9 @@ export default () => { | |||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`Wiki 変更履歴 | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| <table className="table-auto w-full border-collapse"> | <table className="table-auto w-full border-collapse"> | ||||
| <thead> | <thead> | ||||
| <tr> | <tr> | ||||
| @@ -1,4 +1,5 @@ | |||||
| import React, { useEffect, useState, useRef } from 'react' | import React, { useEffect, useState, useRef } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | import { Link, useLocation, useParams, useNavigate } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | import { API_BASE_URL, SITE_TITLE } from '@/config' | ||||
| @@ -42,12 +43,11 @@ export default () => { | |||||
| description: '入力を確認してください。' }))) | description: '入力を確認してください。' }))) | ||||
| } | } | ||||
| useEffect (() => { | |||||
| document.title = `新規 Wiki ページ | ${ SITE_TITLE }` | |||||
| }, []) | |||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`新規 Wiki ページ | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| <div className="max-w-xl mx-auto p-4 space-y-4"> | <div className="max-w-xl mx-auto p-4 space-y-4"> | ||||
| <h1 className="text-2xl font-bold mb-2">新規 Wiki ページ</h1> | <h1 className="text-2xl font-bold mb-2">新規 Wiki ページ</h1> | ||||
| @@ -1,8 +1,9 @@ | |||||
| import React, { useEffect, useState } from 'react' | import React, { useEffect, useState } from 'react' | ||||
| import { Helmet } from 'react-helmet' | |||||
| import { Link } from 'react-router-dom' | import { Link } from 'react-router-dom' | ||||
| import axios from 'axios' | import axios from 'axios' | ||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import { API_BASE_URL } from '@/config' | |||||
| import { API_BASE_URL, SITE_TITLE } from '@/config' | |||||
| import type { Category, WikiPage } from '@/types' | import type { Category, WikiPage } from '@/types' | ||||
| @@ -29,6 +30,9 @@ export default () => { | |||||
| return ( | return ( | ||||
| <MainArea> | <MainArea> | ||||
| <Helmet> | |||||
| <title>{`Wiki | ${ SITE_TITLE }`}</title> | |||||
| </Helmet> | |||||
| <div className="max-w-xl"> | <div className="max-w-xl"> | ||||
| <h2 className="text-xl mb-4">Wiki</h2> | <h2 className="text-xl mb-4">Wiki</h2> | ||||
| <form onSubmit={handleSearch} className="space-y-2"> | <form onSubmit={handleSearch} className="space-y-2"> | ||||