From 57070ed49b95ac393cc697c952ec02020b5d0ba2 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Tue, 8 Jul 2025 02:40:49 +0900 Subject: [PATCH] #32 --- frontend/src/App.tsx | 2 +- frontend/src/components/TopNav.tsx | 226 +++++++++--------- .../src/components/users/UserCodeDialogue.tsx | 2 +- frontend/src/pages/users/SettingPage.tsx | 17 +- 4 files changed, 131 insertions(+), 116 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ba1a5bd..8394017 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -44,7 +44,7 @@ export default () => { if (data.valid) setUser (toCamel (data.user, { deep: true })) else - createUser () + await createUser () }) () } else diff --git a/frontend/src/components/TopNav.tsx b/frontend/src/components/TopNav.tsx index 6ab44de..b4db746 100644 --- a/frontend/src/components/TopNav.tsx +++ b/frontend/src/components/TopNav.tsx @@ -10,14 +10,14 @@ import { cn } from '@/lib/utils' import type { Tag, User, WikiPage } from '@/types' -type Props = { user: User - setUser: (user: User) => void } +type Props = { user: User + setUser: (user: User) => void } const enum Menu { None, - Post, - User, - Tag, - Wiki } + Post, + User, + Tag, + Wiki } const TopNav: React.FC = ({ user, setUser }: Props) => { @@ -35,14 +35,14 @@ const TopNav: React.FC = ({ user, setUser }: Props) => { const [postCount, setPostCount] = useState (null) const MyLink = ({ to, title, menu, base }: { to: string - title: string - menu?: Menu - base?: string }) => ( + title: string + menu?: Menu + base?: string }) => ( - {title} + (location.pathname.startsWith (base ?? to) + ? 'bg-gray-700 px-4 font-bold' + : 'px-2'))}> + {title} ) const whenTagSearchChanged = ev => { @@ -53,8 +53,8 @@ const TopNav: React.FC = ({ user, setUser }: Props) => { const q: string = ev.target.value.split (' ').at (-1) if (!(q)) { - setSuggestions ([]) - return + setSuggestions ([]) + return } } @@ -66,8 +66,8 @@ const TopNav: React.FC = ({ user, setUser }: Props) => { const q: string = ev.target.value.split (' ').at (-1) if (!(q)) { - setSuggestions ([]) - return + setSuggestions ([]) + return } } @@ -79,16 +79,16 @@ const TopNav: React.FC = ({ user, setUser }: Props) => { const q: string = ev.target.value.split (' ').at (-1) if (!(q)) { - setSuggestions ([]) - return + setSuggestions ([]) + return } } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && wikiSearch.length && (!(suggestionsVsbl) || activeIndex < 0)) { - navigate (`/wiki/${ encodeURIComponent (wikiSearch) }`) - setSuggestionsVsbl (false) + navigate (`/wiki/${ encodeURIComponent (wikiSearch) }`) + setSuggestionsVsbl (false) } } @@ -120,105 +120,113 @@ const TopNav: React.FC = ({ user, setUser }: Props) => { void ((async () => { try { - const { data: pageData } = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`) - const wikiPage: WikiPage = toCamel (pageData, { deep: true }) + const { data: pageData } = await axios.get (`${ API_BASE_URL }/wiki/${ wikiId }`) + const wikiPage: WikiPage = toCamel (pageData, { deep: true }) - const { data: tagData } = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`) - const tag: Tag = toCamel (tagData, { deep: true }) + const { data: tagData } = await axios.get (`${ API_BASE_URL }/tags/name/${ wikiPage.title }`) + const tag: Tag = toCamel (tagData, { deep: true }) - setPostCount (tag.postCount) + setPostCount (tag.postCount) } catch { - setPostCount (0) + setPostCount (0) } }) ()) }, [wikiId]) return ( <> - - {(() => { - const className = 'bg-gray-700 text-white px-3 flex items-center w-full min-h-[40px]' - const subClass = 'hover:text-orange-500 h-full flex items-center px-3' - const inputBox = 'flex items-center px-3 mx-2' - const Separator = () => | - switch (selectedMenu) - { - case Menu.Post: - return ( -
- 一覧 - 投稿追加 - ヘルプ -
) - case Menu.Tag: - return ( -
- setSuggestionsVsbl (true)} - onBlur={() => setSuggestionsVsbl (false)} - onKeyDown={handleKeyDown} /> - タグ - 別名タグ - 上位タグ - タグのつけ方 - ヘルプ -
) - case Menu.Wiki: - return ( -
- setSuggestionsVsbl (true)} - onBlur={() => setSuggestionsVsbl (false)} - onKeyDown={handleKeyDown} /> - 検索 - 新規 - 全体履歴 - ヘルプ - {(/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) && - <> - - 広場 ({postCount || 0}) - 履歴 - 編輯 - } -
) - case Menu.User: - return ( -
- setSuggestionsVsbl (true)} - onBlur={() => setSuggestionsVsbl (false)} - onKeyDown={handleKeyDown} /> - 一覧 - {user && お前} -
) - } - }) ()} + + {(() => { + const className = 'bg-gray-700 text-white px-3 flex items-center w-full min-h-[40px]' + const subClass = 'hover:text-orange-500 h-full flex items-center px-3' + const inputBox = 'flex items-center px-3 mx-2' + const Separator = () => | + switch (selectedMenu) + { + case Menu.Post: + return ( +
+ 一覧 + 投稿追加 + ヘルプ +
) + case Menu.Tag: + return ( +
+ {/* TODO: リリース後にやる */} + {/* setSuggestionsVsbl (true)} + onBlur={() => setSuggestionsVsbl (false)} + onKeyDown={handleKeyDown} /> */} + タグ + 別名タグ + 上位タグ + タグのつけ方 + ヘルプ +
) + case Menu.Wiki: + return ( +
+ {/* TODO: リリース後にやる */} + {/* setSuggestionsVsbl (true)} + onBlur={() => setSuggestionsVsbl (false)} + onKeyDown={handleKeyDown} /> */} + 検索 + 新規 + 全体履歴 + ヘルプ + {(/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId) && + <> + + 広場 ({postCount || 0}) + 履歴 + 編輯 + } +
) + case Menu.User: + return ( +
+ {/* TODO: リリース後にやる */} + {/* setSuggestionsVsbl (true)} + onBlur={() => setSuggestionsVsbl (false)} + onKeyDown={handleKeyDown} /> */} + {/* 一覧 + {user && お前} */} + {user && 設定} +
) + } + }) ()} ) } diff --git a/frontend/src/components/users/UserCodeDialogue.tsx b/frontend/src/components/users/UserCodeDialogue.tsx index f0bde1f..084366c 100644 --- a/frontend/src/components/users/UserCodeDialogue.tsx +++ b/frontend/src/components/users/UserCodeDialogue.tsx @@ -19,7 +19,7 @@ type Props = { visible: boolean export default ({ visible, onVisibleChange, user, setUser }: Props) => { const handleChange = async () => { - if (!(confirm ('引継ぎコードを再発行しますか?'))) + if (!(confirm ('引継ぎコードを再発行しますか?\n再発行するとほかのブラウザからはログアウトされます.'))) return const { data } = await axios.post (`${ API_BASE_URL }/users/code/renew`, { }, { headers: { diff --git a/frontend/src/pages/users/SettingPage.tsx b/frontend/src/pages/users/SettingPage.tsx index 35deb86..7774694 100644 --- a/frontend/src/pages/users/SettingPage.tsx +++ b/frontend/src/pages/users/SettingPage.tsx @@ -1,3 +1,5 @@ +import axios from 'axios' +import toCamel from 'camelcase-keys' import { useEffect, useState } from 'react' import { Helmet } from 'react-helmet-async' @@ -7,8 +9,9 @@ import PageTitle from '@/components/common/PageTitle' import MainArea from '@/components/layout/MainArea' import InheritDialogue from '@/components/users/InheritDialogue' import UserCodeDialogue from '@/components/users/UserCodeDialogue' -import { API_BASE_URL, SITE_TITLE } from '@/config' import { Button } from '@/components/ui/button' +import { toast } from '@/components/ui/use-toast' +import { API_BASE_URL, SITE_TITLE } from '@/config' import type { User } from '@/types' @@ -22,14 +25,18 @@ export default ({ user, setUser }: Props) => { const [inheritVsbl, setInheritVsbl] = useState (false) const handleSubmit = async () => { - const formData = new FormData () + if (!(user)) + return + + const formData = new FormData formData.append ('name', name) try { - await axios.post (`${ API_BASE_URL }/users`, formData, { headers: { - 'Content-Type': 'multipart/form-data', - 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } }) + const { data } = await axios.put (`${ API_BASE_URL }/users/${ user.id }`, formData, { + headers: { 'Content-Type': 'multipart/form-data', + 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } }) + setUser (user => ({ ...user, ...data })) toast ({ title: '設定を更新しました.' }) } catch