Skip to content

Commit

Permalink
refactor(client): move chat to story package (#247)
Browse files Browse the repository at this point in the history
* refactor(client): move chat to story package

Signed-off-by: Vitaly Kuprin <vitas_s@inbox.lv>

* chore: cleanups

Signed-off-by: Vitaly Kuprin <vitas_s@inbox.lv>

---------

Signed-off-by: Vitaly Kuprin <vitas_s@inbox.lv>
  • Loading branch information
vkuprin authored Nov 24, 2024
1 parent 960abea commit c09517e
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 59 deletions.
1 change: 0 additions & 1 deletion GomokuClient/packages/gomoku-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"@lingui/macro": "^4.14.0",
"@lingui/react": "^4.14.0",
"@microsoft/signalr": "^8.0.7",
"@radix-ui/react-scroll-area": "^1.2.1",
"@sentry/react": "^8.38.0",
"@sentry/vite-plugin": "^2.22.6",
"@tanstack/react-query": "^5.60.5",
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion GomokuClient/packages/gomoku-core/src/features/index.ts

This file was deleted.

12 changes: 11 additions & 1 deletion GomokuClient/packages/gomoku-core/src/pages/JoinGame.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { AlertDialog, toaster } from "@gomoku/story";
import { GamePlayersInfo } from "@gomoku/story";
import { GameTime, GameTimeMobile, Board } from "@gomoku/story";
import { Chat } from "@gomoku/story";
import { useParams } from "@tanstack/react-router";

import type { SwaggerTypes } from "@gomoku/api";
import type { GameTimeProps } from "@gomoku/story";

import { useAuthToken } from "@/context";
import { Chat } from "@/features";
import { useChat, useJoinGame, useMobileDesign } from "@/hooks";

interface JoinGameProps {
Expand Down Expand Up @@ -134,6 +134,16 @@ const JoinGame = ({ gameHistory }: JoinGameProps) => {
isConnected={isConnected}
sendMessage={sendMessage}
username={jwtDecodedInfo?.username || ""}
texts={{
title: "Chat",
inputPlaceholder: "Type a message...",
sendButtonText: "Send",
sendingButtonText: "Sending...",
charactersText: "characters",
connectingText: "Connecting...",
noMessagesText: "No messages yet. Start the conversation!",
errorSendingMessage: "Error sending message",
}}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Chat } from "./Chat";

import type { Meta, StoryObj } from "@storybook/react";

import { toaster } from "@/ui/toaster";

const meta: Meta<typeof Chat> = {
title: "Components/Chat",
component: Chat,
argTypes: {
texts: {
control: { type: "object" },
description: "Customizable text content for the chat component",
},
isConnected: {
control: { type: "boolean" },
description: "Connection status of the chat",
},
messages: {
control: { type: "object" },
description: "Array of chat messages",
},
username: {
control: { type: "text" },
description: "Current user username",
},
},
};

export default meta;

type Story = StoryObj<typeof Chat>;

const mockMessages = [
"User1: Hello from Gomoku!",
"User2: Hello from Gomoku!",
"User3: Hello from Gomoku!",
"User4: Hello from Gomoku!",
"User5: Hello from Gomoku!",
"User6: Hello from Gomoku!",
"User7: Hello from Gomoku!",
"User8: Hello from Gomoku!",
"User9: Hello from Gomoku!",
"User10: Hello from Gomoku!",
];

const defaultTexts = {
title: "Chat",
inputPlaceholder: "Type a message...",
sendButtonText: "Send",
sendingButtonText: "Sending...",
charactersText: "characters",
connectingText: "Connecting...",
noMessagesText: "No messages yet. Start the conversation!",
errorSendingMessage: "Error sending message",
};

export const Default: Story = {
args: {
isConnected: true,
messages: mockMessages,
username: "User1",
texts: defaultTexts,
sendMessage: async () => toaster.show("Sending message..."),
},
};

export const Connecting: Story = {
args: {
isConnected: false,
messages: [],
username: "User1",
texts: defaultTexts,
sendMessage: async () => toaster.show("Sending message..."),
},
};

export const EmptyChat: Story = {
args: {
isConnected: true,
messages: [],
username: "User1",
texts: defaultTexts,
sendMessage: async () => toaster.show("Sending message..."),
},
};

export const CustomTexts: Story = {
args: {
isConnected: true,
messages: mockMessages,
username: "User1",
texts: {
...defaultTexts,
title: "Custom Chat Title",
inputPlaceholder: "Write something nice...",
sendButtonText: "→",
noMessagesText: "Be the first to say hello!",
},
sendMessage: async () => toaster.show("Sending message..."),
},
};
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
import { ScrollArea } from "@radix-ui/react-scroll-area";
import { useState, useEffect, useRef } from "react";

import type { KeyboardEvent } from "react";

import { useMobileDesign } from "@/hooks";
import {
Button,
toaster,
Card,
CardContent,
CardHeader,
CardTitle,
} from "@gomoku/story";
import { t } from "@lingui/macro";
import { ScrollArea } from "@radix-ui/react-scroll-area";
import { useState, useEffect, useRef } from "react";

import type { KeyboardEvent } from "react";

import { useMobileDesign } from "@/hooks";
} from "@/ui";

export interface ChatProps {
messages: string[];
isConnected: boolean;
sendMessage: (message: string) => Promise<void>;
username: string;
texts: {
title: string;
inputPlaceholder: string;
sendButtonText: string;
sendingButtonText: string;
charactersText: string;
connectingText: string;
noMessagesText: string;
errorSendingMessage: string;
};
}

export const Chat = ({
messages,
isConnected,
sendMessage,
username,
texts,
}: ChatProps) => {
const [messageInput, setMessageInput] = useState("");
const [isSending, setIsSending] = useState(false);
Expand All @@ -41,7 +51,7 @@ export const Chat = ({
setMessageInput("");
} catch (error) {
console.error("Failed to send message", error);
toaster.show("Error sending message", "error");
toaster.show(texts.errorSendingMessage, "error");
} finally {
setIsSending(false);
}
Expand Down Expand Up @@ -75,7 +85,7 @@ export const Chat = ({
}}
>
<CardHeader>
<CardTitle>{t`Chat`}</CardTitle>
<CardTitle>{texts.title}</CardTitle>
</CardHeader>
<CardContent>
{isConnected ? (
Expand All @@ -91,7 +101,7 @@ export const Chat = ({
}}
onKeyDown={handleKeyDown}
className="flex-1 rounded-md border px-3 py-2"
placeholder={"Type a message..."}
placeholder={texts.inputPlaceholder}
maxLength={MAX_MESSAGE_LENGTH}
/>
<Button
Expand All @@ -100,11 +110,11 @@ export const Chat = ({
disabled={!messageInput.trim() || isSending}
className="border-[#3e3e3e] bg-[#3e3e3e] text-base text-[#bababa] hover:bg-[#4a4a4a] sm:h-14 sm:text-xl"
>
{isSending ? t`Sending...` : t`Send`}
{isSending ? texts.sendingButtonText : texts.sendButtonText}
</Button>
</div>
<div className="text-sm text-[#bababa]">
{messageInput.length}/{MAX_MESSAGE_LENGTH} {t`characters`}
{messageInput.length}/{MAX_MESSAGE_LENGTH} {texts.charactersText}
</div>
<ScrollArea
ref={scrollAreaRef}
Expand All @@ -115,7 +125,6 @@ export const Chat = ({
>
{messages.map((msg, index) => (
<div
//TODO: check if key is matching behaviour
key={msg}
ref={index === messages.length - 1 ? scrollAreaRef : null}
className={`mb-2 rounded p-2 ${
Expand All @@ -132,10 +141,8 @@ export const Chat = ({
</div>
) : (
<div>
{t`Connecting...`}
<div className="text-gray-500">
{t`No messages yet. Start the conversation!`}
</div>
{texts.connectingText}
<div className="text-gray-500">{texts.noMessagesText}</div>
</div>
)}
</CardContent>
Expand Down
1 change: 1 addition & 0 deletions GomokuClient/packages/gomoku-story/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from "./SectionList";
export * from "./OnlinePlayersInfo";
export * from "./ErrorBoundary";
export * from "./GameTime";
export * from "./Chat";
1 change: 0 additions & 1 deletion GomokuClient/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,6 @@ __metadata:
"@lingui/macro": "npm:^4.14.0"
"@lingui/react": "npm:^4.14.0"
"@microsoft/signalr": "npm:^8.0.7"
"@radix-ui/react-scroll-area": "npm:^1.2.1"
"@sentry/react": "npm:^8.38.0"
"@sentry/vite-plugin": "npm:^2.22.6"
"@tanstack/eslint-plugin-query": "npm:^5.60.1"
Expand Down

0 comments on commit c09517e

Please sign in to comment.