Skip to content

Commit

Permalink
Merge pull request #266 from boostcampwm-2024/Feature/#260_workspace์˜โ€ฆ
Browse files Browse the repository at this point in the history
โ€ฆmemberCount_์‹ค์‹œ๊ฐ„_๋ฏธ๋™๊ธฐํ™”_ํ˜„์ƒ

Feature/#260 workspace์˜member count ์‹ค์‹œ๊ฐ„ ๋ฏธ๋™๊ธฐํ™” ํ˜„์ƒ
  • Loading branch information
github-actions[bot] authored Dec 2, 2024
2 parents 4c4b302 + fb19818 commit ffdd857
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 7 deletions.
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "tsc -b && vite build",
"build": "tsc -b && panda codegen && vite build",
"lint": "eslint \"src/**/*.{ts,tsx}\" --fix",
"preview": "vite preview",
"prepare": "panda codegen"
Expand Down
10 changes: 9 additions & 1 deletion client/src/components/modal/InviteModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// InviteModal.tsx
import { useState } from "react";
import { useState, useEffect, useRef } from "react";
import { modalContentContainer, titleText, descriptionText, emailInput } from "./InviteModal.style";
import { Modal } from "./modal";

Expand All @@ -11,6 +11,13 @@ interface InviteModalProps {

export const InviteModal = ({ isOpen, onClose, onInvite }: InviteModalProps) => {
const [email, setEmail] = useState("");
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
if (isOpen) {
inputRef.current?.focus();
}
}, [isOpen]);

const handleInvite = () => {
onInvite(email);
Expand All @@ -30,6 +37,7 @@ export const InviteModal = ({ isOpen, onClose, onInvite }: InviteModalProps) =>
<h2 className={titleText}>์›Œํฌ์ŠคํŽ˜์ด์Šค ์ดˆ๋Œ€</h2>
<p className={descriptionText}>์ดˆ๋Œ€ํ•  ์‚ฌ์šฉ์ž์˜ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”</p>
<input
ref={inputRef}
className={emailInput}
onChange={(e) => setEmail(e.target.value)}
placeholder="์ด๋ฉ”์ผ ์ฃผ์†Œ ์ž…๋ ฅ"
Expand Down
11 changes: 10 additions & 1 deletion client/src/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,16 @@ export const Modal = ({
return createPortal(
<AnimatePresence>
{isOpen && (
<div className={container}>
<div
role="dialog"
className={container}
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => {
if (e.key === "Escape") {
secondaryButtonOnClick?.();
}
}}
>
<motion.div
initial={overlayAnimation.initial}
animate={overlayAnimation.animate}
Expand Down
14 changes: 12 additions & 2 deletions client/src/components/sidebar/components/menuButton/MenuButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { InviteModal } from "@src/components/modal/InviteModal";
import { useModal } from "@src/components/modal/useModal";
import { useSocketStore } from "@src/stores/useSocketStore";
import { useToastStore } from "@src/stores/useToastStore";
import { useWorkspaceStore } from "@src/stores/useWorkspaceStore";
import { useUserInfo } from "@stores/useUserStore";
import { menuItemWrapper, textBox, menuButtonContainer } from "./MenuButton.style";
import { MenuIcon } from "./components/MenuIcon";
Expand All @@ -18,7 +19,7 @@ export const MenuButton = () => {
openModal: openInviteModal,
closeModal: closeInviteModal,
} = useModal();

const currentRole = useWorkspaceStore((state) => state.currentRole);
const handleMenuClick = () => {
setIsOpen((prev) => !prev);
};
Expand Down Expand Up @@ -81,6 +82,15 @@ export const MenuButton = () => {
workspaceId: workspace.id,
});
};

const handleInviteModal = () => {
if (isInviteModalOpen) return;
if (currentRole === "editor") {
addToast("Editor ๊ถŒํ•œ์œผ๋กœ๋Š” ์ดˆ๋Œ€ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
return;
}
openInviteModal();
};
return (
<>
<button
Expand All @@ -92,7 +102,7 @@ export const MenuButton = () => {
<MenuIcon />
<p className={textBox}>{name ?? "Nocta"}</p>
</button>
<WorkspaceSelectModal isOpen={isOpen} userName={name} onInviteClick={openInviteModal} />
<WorkspaceSelectModal isOpen={isOpen} userName={name} onInviteClick={handleInviteModal} />
<InviteModal
isOpen={isInviteModalOpen}
onClose={closeInviteModal}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { WorkspaceListItem } from "@noctaCrdt/Interfaces"; // ์ด์ „์— ๋งŒ๋“ 
import { useSocketStore } from "@src/stores/useSocketStore";
import { useToastStore } from "@src/stores/useToastStore";
import { useUserInfo } from "@src/stores/useUserStore";
import { useWorkspaceStore } from "@src/stores/useWorkspaceStore";
import {
itemContainer,
itemContent,
Expand All @@ -28,10 +29,12 @@ export const WorkspaceSelectItem = ({
const { userId } = useUserInfo();
const { workspace, switchWorkspace } = useSocketStore();
const { addToast } = useToastStore();
const setCurrentRole = useWorkspaceStore((state) => state.setCurrentRole);
const isActive = workspace?.id === id; // ํ˜„์žฌ ์›Œํฌ์ŠคํŽ˜์ด์Šค ํ™•์ธ
const handleClick = () => {
if (!isActive) {
switchWorkspace(userId, id);
setCurrentRole(role);
addToast(`์›Œํฌ์ŠคํŽ˜์ด์Šค(${name})์— ์ ‘์†ํ•˜์˜€์Šต๋‹ˆ๋‹ค.`);
}
};
Expand Down
14 changes: 13 additions & 1 deletion client/src/stores/useSocketStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "@noctaCrdt/Interfaces";
import { io, Socket } from "socket.io-client";
import { create } from "zustand";
import { useWorkspaceStore } from "./useWorkspaceStore";

class BatchProcessor {
private batch: any[] = [];
Expand Down Expand Up @@ -136,7 +137,7 @@ export const useSocketStore = create<SocketStore>((set, get) => ({

socket.on("workspace", (workspace: WorkSpaceSerializedProps) => {
const { setWorkspace } = get();
setWorkspace(workspace); // ์ˆ˜์ •๋œ ๋ถ€๋ถ„
setWorkspace(workspace);
});

socket.on("workspace/connections", (connections: Record<string, number>) => {
Expand All @@ -153,12 +154,23 @@ export const useSocketStore = create<SocketStore>((set, get) => ({

socket.on("workspace/list", (workspaces: WorkspaceListItem[]) => {
set({ availableWorkspaces: workspaces });
const { availableWorkspaces } = get();
console.log(availableWorkspaces);
const { workspace } = get();
const currentWorkspace = availableWorkspaces.find((ws) => ws.id === workspace!.id);
if (currentWorkspace) {
useWorkspaceStore.getState().setCurrentRole(currentWorkspace.role);
}
});

socket.on("error", (error: Error) => {
console.error("Socket error:", error);
});

socket.on("workspace/role", (data: { role: "owner" | "editor" }) => {
useWorkspaceStore.getState().setCurrentRole(data.role);
});

socket.connect();
},

Expand Down
15 changes: 15 additions & 0 deletions client/src/stores/useWorkspaceStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { create } from "zustand";

// ์›Œํฌ์ŠคํŽ˜์ด์Šค ๊ถŒํ•œ ํƒ€์ž… ์ •์˜

interface WorkspaceStore {
// ํ˜„์žฌ ์„ ํƒ๋œ ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ ๊ถŒํ•œ
currentRole: string | null;
// ๊ถŒํ•œ ์„ค์ • ํ•จ์ˆ˜
setCurrentRole: (role: string | null) => void;
}

export const useWorkspaceStore = create<WorkspaceStore>((set) => ({
currentRole: null,
setCurrentRole: (role) => set({ currentRole: role }),
}));
6 changes: 5 additions & 1 deletion server/src/workspace/workspace.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,13 +279,17 @@ export class WorkspaceGateway implements OnGatewayInit, OnGatewayConnection, OnG
this.logger.log(`Sending workspace list to client ${client.id}`);
server.to(socketId).emit("workspace/list", workspaceList);
}

// 5. ์ดˆ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์„ฑ๊ณต ๋ฉ”์‹œ์ง€
client.emit("invite/workspace/success", {
email: data.email,
workspaceId: data.workspaceId,
message: `${targetUser.name}์œ ์ €๋ฅผ ์ดˆ๋Œ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค.`,
});
const sentUserUpdatedWorkspaces = await this.workSpaceService.getUserWorkspaces(
client.data.userId,
);
// 6. ์ดˆ๋Œ€ํ•œ ์‚ฌ์šฉ์ž์˜ UI์— ์ตœ์‹  workspace/list ๋ฐ˜์˜
client.emit("workspace/list", sentUserUpdatedWorkspaces);
} catch (error) {
this.logger.error(
`Workspace Invite ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ - Client ID: ${clientInfo.clientId}`,
Expand Down

0 comments on commit ffdd857

Please sign in to comment.