Skip to content

Commit 84e4980

Browse files
committed
チャットタイトルの実装、削除ボタン追加など
1 parent 0aa1904 commit 84e4980

11 files changed

Lines changed: 847 additions & 130 deletions

File tree

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
"use client";
2+
3+
import { ChatAreaStateUpdater } from "@/(docs)/chatAreaState";
4+
import { getChatOne } from "@/lib/chatHistory";
5+
import { LanguageEntry, MarkdownSection, PageEntry } from "@/lib/docs";
6+
import { Heading } from "@/markdown/heading";
7+
import { StyledMarkdown } from "@/markdown/markdown";
8+
import clsx from "clsx";
9+
import Link from "next/link";
10+
11+
interface Props {
12+
chatId: string;
13+
chatData: Awaited<ReturnType<typeof getChatOne>>;
14+
targetLang: LanguageEntry | undefined;
15+
targetPage: PageEntry | undefined;
16+
targetSection: MarkdownSection | undefined;
17+
}
18+
export function ChatAreaContent(props: Props) {
19+
const { chatId, chatData, targetLang, targetPage, targetSection } = props;
20+
21+
const messagesAndDiffs = [
22+
...chatData.messages.map((msg) => ({ type: "message" as const, ...msg })),
23+
...chatData.diff.map((diff) => ({ type: "diff" as const, ...diff })),
24+
];
25+
messagesAndDiffs.sort(
26+
(a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
27+
);
28+
29+
return (
30+
<aside
31+
className={clsx(
32+
// モバイルでは全画面表示する
33+
"fixed inset-0 pt-20 bg-base-100",
34+
// PCではスクロールで動かない右サイドバー
35+
"lg:sticky lg:top-0 lg:pt-4 lg:w-1/3 lg:h-screen lg:shadow-md lg:bg-base-200 ",
36+
"p-4",
37+
"flex flex-col",
38+
"overflow-y-auto"
39+
)}
40+
>
41+
<ChatAreaStateUpdater chatId={chatId} />
42+
<div className="flex flex-row items-center">
43+
<span className="flex-1 text-base font-bold opacity-40">
44+
AIへの質問
45+
</span>
46+
<Link className="btn btn-ghost" href="/chat" scroll={false}>
47+
<svg
48+
className="w-8 h-8 -scale-x-100"
49+
viewBox="0 0 24 24"
50+
fill="none"
51+
xmlns="http://www.w3.org/2000/svg"
52+
>
53+
<path
54+
d="M18 17L13 12L18 7M11 17L6 12L11 7"
55+
stroke="currentColor"
56+
strokeWidth="1.5"
57+
strokeLinecap="round"
58+
strokeLinejoin="round"
59+
/>
60+
</svg>
61+
<span className="text-lg">閉じる</span>
62+
</Link>
63+
</div>
64+
<Heading level={2} className="mt-2!">
65+
{chatData.title}
66+
</Heading>
67+
<div className="flex-none breadcrumbs text-sm">
68+
<ul className="flex-wrap">
69+
<li>
70+
<Link href={`/${targetLang?.id}/${targetLang?.pages[0].slug}`}>
71+
{targetLang?.name}
72+
</Link>
73+
</li>
74+
<li>
75+
<Link href={`/${chatData.section.pagePath}`}>
76+
{targetPage?.index}. {targetPage?.name}
77+
</Link>
78+
</li>
79+
<li>
80+
<Link href={`/${chatData.section.pagePath}#${chatData.sectionId}`}>
81+
{targetSection?.title}
82+
</Link>
83+
</li>
84+
</ul>
85+
</div>
86+
<div className="flex flex-wrap items-center">
87+
<div className="flex-1 text-sm opacity-40" suppressHydrationWarning>
88+
{chatData.createdAt.toLocaleString()}
89+
</div>
90+
<button
91+
className="btn btn-error btn-soft btn-sm"
92+
onClick={() => alert("TODO: チャットの削除機能")}
93+
>
94+
{/*<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->*/}
95+
<svg
96+
className="w-4 h-4"
97+
viewBox="0 0 24 24"
98+
fill="none"
99+
xmlns="http://www.w3.org/2000/svg"
100+
>
101+
<path
102+
d="M10 11V17"
103+
stroke="currentColor"
104+
strokeWidth="2"
105+
strokeLinecap="round"
106+
strokeLinejoin="round"
107+
/>
108+
<path
109+
d="M14 11V17"
110+
stroke="currentColor"
111+
strokeWidth="2"
112+
strokeLinecap="round"
113+
strokeLinejoin="round"
114+
/>
115+
<path
116+
d="M4 7H20"
117+
stroke="currentColor"
118+
strokeWidth="2"
119+
strokeLinecap="round"
120+
strokeLinejoin="round"
121+
/>
122+
<path
123+
d="M6 7H12H18V18C18 19.6569 16.6569 21 15 21H9C7.34315 21 6 19.6569 6 18V7Z"
124+
stroke="currentColor"
125+
strokeWidth="2"
126+
strokeLinecap="round"
127+
strokeLinejoin="round"
128+
/>
129+
<path
130+
d="M9 5C9 3.89543 9.89543 3 11 3H13C14.1046 3 15 3.89543 15 5V7H9V5Z"
131+
stroke="currentColor"
132+
strokeWidth="2"
133+
strokeLinecap="round"
134+
strokeLinejoin="round"
135+
/>
136+
</svg>
137+
削除
138+
</button>
139+
</div>
140+
<div className="divider" />
141+
{messagesAndDiffs.map((msg, index) =>
142+
msg.type === "message" ? (
143+
msg.role === "user" ? (
144+
<div key={index} className="chat chat-end">
145+
<div
146+
className="chat-bubble p-0.5! bg-secondary/30"
147+
style={{ maxWidth: "100%", wordBreak: "break-word" }}
148+
>
149+
<StyledMarkdown content={msg.content} />
150+
</div>
151+
</div>
152+
) : msg.role === "ai" ? (
153+
<div key={index} className="">
154+
<StyledMarkdown content={msg.content} />
155+
</div>
156+
) : (
157+
<div key={index} className="text-error">
158+
{msg.content}
159+
</div>
160+
)
161+
) : (
162+
<div
163+
key={index}
164+
className={clsx(
165+
"bg-base-300 rounded-lg border border-2 border-secondary/50"
166+
)}
167+
>
168+
{/* pb-0だとmargin collapsingが起きて変な隙間が空く */}
169+
<del
170+
className={clsx(
171+
"block p-2 pb-[1px] bg-error/10",
172+
"line-through decoration-[color-mix(in_oklab,var(--color-error)_70%,currentColor)]"
173+
)}
174+
>
175+
<StyledMarkdown content={msg.search} />
176+
</del>
177+
<ins className="block no-underline p-2 pt-[1px] bg-success/10">
178+
<StyledMarkdown content={msg.replace} />
179+
</ins>
180+
</div>
181+
)
182+
)}
183+
</aside>
184+
);
185+
}
Lines changed: 8 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import { ChatAreaStateUpdater } from "@/(docs)/chatAreaState";
21
import { getChatOne, initContext } from "@/lib/chatHistory";
32
import { getMarkdownSections, getPagesList } from "@/lib/docs";
4-
import { StyledMarkdown } from "@/markdown/markdown";
5-
import clsx from "clsx";
6-
import Link from "next/link";
3+
import { ChatAreaContent } from "./chatArea";
74

85
export default async function ChatPage({
96
params,
@@ -25,91 +22,13 @@ export default async function ChatPage({
2522
const sections = await getMarkdownSections(targetLang!.id, targetPage!.slug);
2623
const targetSection = sections.find((sec) => sec.id === chatData.sectionId);
2724

28-
const messagesAndDiffs = [
29-
...chatData.messages.map((msg) => ({ type: "message" as const, ...msg })),
30-
...chatData.diff.map((diff) => ({ type: "diff" as const, ...diff })),
31-
];
32-
messagesAndDiffs.sort(
33-
(a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
34-
);
3525
return (
36-
<aside
37-
className={clsx(
38-
// モバイルでは全画面表示する
39-
"fixed inset-0 pt-20 bg-base-100",
40-
// PCではスクロールで動かない右サイドバー
41-
"lg:sticky lg:top-0 lg:pt-4 lg:w-1/3 lg:h-screen lg:shadow-md lg:bg-base-200 ",
42-
"p-4",
43-
"flex flex-col gap-2",
44-
"overflow-y-auto"
45-
)}
46-
>
47-
<ChatAreaStateUpdater chatId={chatId} />
48-
{chatId}
49-
<div className="flex-none breadcrumbs text-sm">
50-
<ul className="flex-wrap">
51-
<li>
52-
<Link href={`/${targetLang?.id}/${targetLang?.pages[0].slug}`}>
53-
{targetLang?.name}
54-
</Link>
55-
</li>
56-
<li>
57-
<Link href={`/${chatData.section.pagePath}`}>
58-
{targetPage?.index}. {targetPage?.name}
59-
</Link>
60-
</li>
61-
<li>
62-
<Link href={`/${chatData.section.pagePath}#${chatData.sectionId}`}>
63-
{targetSection?.title}
64-
</Link>
65-
</li>
66-
</ul>
67-
</div>
68-
<Link className="btn" href="/chat">
69-
閉じる
70-
</Link>
71-
{messagesAndDiffs.map((msg, index) =>
72-
msg.type === "message" ? (
73-
msg.role === "user" ? (
74-
<div key={index} className="chat chat-end">
75-
<div
76-
className="chat-bubble p-0.5! bg-secondary/30"
77-
style={{ maxWidth: "100%", wordBreak: "break-word" }}
78-
>
79-
<StyledMarkdown content={msg.content} />
80-
</div>
81-
</div>
82-
) : msg.role === "ai" ? (
83-
<div key={index} className="">
84-
<StyledMarkdown content={msg.content} />
85-
</div>
86-
) : (
87-
<div key={index} className="text-error">
88-
{msg.content}
89-
</div>
90-
)
91-
) : (
92-
<div
93-
key={index}
94-
className={clsx(
95-
"bg-base-300 rounded-lg border border-2 border-secondary/50"
96-
)}
97-
>
98-
{/* pb-0だとmargin collapsingが起きて変な隙間が空く */}
99-
<del
100-
className={clsx(
101-
"block p-2 pb-[1px] bg-error/10",
102-
"line-through decoration-[color-mix(in_oklab,var(--color-error)_70%,currentColor)]"
103-
)}
104-
>
105-
<StyledMarkdown content={msg.search} />
106-
</del>
107-
<ins className="block no-underline p-2 pt-[1px] bg-success/10">
108-
<StyledMarkdown content={msg.replace} />
109-
</ins>
110-
</div>
111-
)
112-
)}
113-
</aside>
26+
<ChatAreaContent
27+
chatId={chatId}
28+
chatData={chatData}
29+
targetLang={targetLang}
30+
targetPage={targetPage}
31+
targetSection={targetSection}
32+
/>
11433
);
11534
}

app/(docs)/@docs/[lang]/[pageId]/pageContent.tsx

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,18 @@ function ChatListForSection(props: {
256256
"border border-base-content/10 rounded-sm shadow-sm bg-base-200"
257257
)}
258258
>
259-
<li className="menu-title">チャット</li>
260-
{filteredChatHistories.map(({ chatId }) => (
259+
<li className="menu-title flex-row items-center gap-1">
260+
<ChatIcon />
261+
AIへの質問
262+
</li>
263+
{filteredChatHistories.map(({ title, chatId }) => (
261264
<li key={chatId} className="">
262265
<Link
263266
className="link link-info"
264267
href={`/chat/${chatId}`}
265268
scroll={false}
266269
>
267-
{chatId}
270+
{title}
268271
</Link>
269272
</li>
270273
))}
@@ -278,27 +281,7 @@ function ChatListForSection(props: {
278281
)}
279282
>
280283
<summary className="btn btn-outline btn-secondary btn-sm">
281-
{/*<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->*/}
282-
<svg
283-
className="w-4 h-4"
284-
viewBox="3.5 2.5 18 18"
285-
fill="none"
286-
xmlns="http://www.w3.org/2000/svg"
287-
>
288-
<path
289-
fillRule="evenodd"
290-
clipRule="evenodd"
291-
d="M5.5 12C5.49988 14.613 6.95512 17.0085 9.2741 18.2127C11.5931 19.4169 14.3897 19.2292 16.527 17.726L19.5 18V12C19.5 8.13401 16.366 5 12.5 5C8.63401 5 5.5 8.13401 5.5 12Z"
292-
stroke="currentColor"
293-
strokeWidth="1.5"
294-
strokeLinecap="round"
295-
strokeLinejoin="round"
296-
/>
297-
<path
298-
d="M9.5 13.25C9.08579 13.25 8.75 13.5858 8.75 14C8.75 14.4142 9.08579 14.75 9.5 14.75V13.25ZM13.5 14.75C13.9142 14.75 14.25 14.4142 14.25 14C14.25 13.5858 13.9142 13.25 13.5 13.25V14.75ZM9.5 10.25C9.08579 10.25 8.75 10.5858 8.75 11C8.75 11.4142 9.08579 11.75 9.5 11.75V10.25ZM15.5 11.75C15.9142 11.75 16.25 11.4142 16.25 11C16.25 10.5858 15.9142 10.25 15.5 10.25V11.75ZM9.5 14.75H13.5V13.25H9.5V14.75ZM9.5 11.75H15.5V10.25H9.5V11.75Z"
299-
fill="currentColor"
300-
/>
301-
</svg>
284+
<ChatIcon />
302285
{filteredChatHistories.length}
303286
</summary>
304287
<ul
@@ -308,14 +291,14 @@ function ChatListForSection(props: {
308291
"border border-base-content/10 rounded-sm shadow-sm bg-base-200"
309292
)}
310293
>
311-
{filteredChatHistories.map(({ chatId }) => (
294+
{filteredChatHistories.map(({ title, chatId }) => (
312295
<li key={chatId} className="">
313296
<Link
314297
className="link link-info"
315298
href={`/chat/${chatId}`}
316299
scroll={false}
317300
>
318-
{chatId}
301+
{title}
319302
</Link>
320303
</li>
321304
))}
@@ -324,3 +307,31 @@ function ChatListForSection(props: {
324307
</>
325308
);
326309
}
310+
311+
function ChatIcon() {
312+
return (
313+
<>
314+
{/*<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->*/}
315+
<svg
316+
className="w-4 h-4"
317+
viewBox="3.5 2.5 18 18"
318+
fill="none"
319+
xmlns="http://www.w3.org/2000/svg"
320+
>
321+
<path
322+
fillRule="evenodd"
323+
clipRule="evenodd"
324+
d="M5.5 12C5.49988 14.613 6.95512 17.0085 9.2741 18.2127C11.5931 19.4169 14.3897 19.2292 16.527 17.726L19.5 18V12C19.5 8.13401 16.366 5 12.5 5C8.63401 5 5.5 8.13401 5.5 12Z"
325+
stroke="currentColor"
326+
strokeWidth="1.5"
327+
strokeLinecap="round"
328+
strokeLinejoin="round"
329+
/>
330+
<path
331+
d="M9.5 13.25C9.08579 13.25 8.75 13.5858 8.75 14C8.75 14.4142 9.08579 14.75 9.5 14.75V13.25ZM13.5 14.75C13.9142 14.75 14.25 14.4142 14.25 14C14.25 13.5858 13.9142 13.25 13.5 13.25V14.75ZM9.5 10.25C9.08579 10.25 8.75 10.5858 8.75 11C8.75 11.4142 9.08579 11.75 9.5 11.75V10.25ZM15.5 11.75C15.9142 11.75 16.25 11.4142 16.25 11C16.25 10.5858 15.9142 10.25 15.5 10.25V11.75ZM9.5 14.75H13.5V13.25H9.5V14.75ZM9.5 11.75H15.5V10.25H9.5V11.75Z"
332+
fill="currentColor"
333+
/>
334+
</svg>
335+
</>
336+
);
337+
}

0 commit comments

Comments
 (0)