Skip to content

Commit

Permalink
Merge pull request #377 from boostcampwm-2024/feature-fe-#374
Browse files Browse the repository at this point in the history
노드 색상 변경 기능 추가
  • Loading branch information
yewonJin authored Dec 3, 2024
2 parents 231a0f7 + 364fc66 commit 693e6c2
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 7 deletions.
2 changes: 2 additions & 0 deletions apps/frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useSyncedUsers } from "@/entities/user";
import { useProtectedWorkspace } from "@/features/workspace";
import { CanvasView } from "@/widgets/CanvasView";
import { EditorView } from "@/widgets/EditorView";
import { NodeToolsView } from "@/widgets/NodeToolsView";
import { PageSideBarView } from "@/widgets/PageSideBarView";
import { CanvasToolsView } from "@/widgets/CanvasToolsView";
import { SideWrapper } from "@/shared/ui";
Expand Down Expand Up @@ -30,6 +31,7 @@ function App() {
>
<PageSideBarView />
<CanvasToolsView />
<NodeToolsView />
</SideWrapper>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/src/entities/node/model/nodeTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type NoteNodeData = {
title: string;
id: number;
emoji: string;
color: string;
};

export type NoteNodeType = FlowNode<NoteNodeData, "note">;
1 change: 1 addition & 0 deletions apps/frontend/src/entities/node/ui/NoteNode/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function NoteNode({
return (
<div
className={`h-24 w-48 rounded-lg border-[1px] ${isClicked ? "border-[#8dbaef]" : "border-[#eaeaea]"} bg-white p-3 shadow-sm`}
style={{ backgroundColor: data.color }}
onClick={handleNodeClick}
>
<Handle
Expand Down
17 changes: 14 additions & 3 deletions apps/frontend/src/features/canvas/model/useCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ export const useCanvas = () => {
const newNode: YNode = {
id: existingNode.id,
type: "note",
data: { title: value, id: pageId, emoji: existingNode.data.emoji },
data: {
title: value,
id: pageId,
emoji: existingNode.data.emoji,
color: existingNode.data.color,
},
position: existingNode.position,
selected: false,
isHolding: false,
Expand All @@ -99,7 +104,12 @@ export const useCanvas = () => {
const newNode: YNode = {
id: pageId,
type: "note",
data: { title: existingNode.data.title, id: pageId, emoji: value },
data: {
title: existingNode.data.title,
id: pageId,
emoji: value,
color: existingNode.data.color,
},
position: existingNode.position,
selected: false,
isHolding: false,
Expand All @@ -108,6 +118,7 @@ export const useCanvas = () => {
nodesMap.set(pageId, newNode);
});
}, [ydoc]);

useEffect(() => {
if (!ydoc) return;

Expand All @@ -131,7 +142,7 @@ export const useCanvas = () => {
event.changes.keys.forEach((change, key) => {
const nodeId = key;
if (change.action === "add" || change.action === "update") {
const updatedNode = nodesMap.get(nodeId) as Node;
const updatedNode = nodesMap.get(nodeId) as YNode;
setNodes((nds) => {
const index = nds.findIndex((n) => n.id === nodeId);
if (index === -1) {
Expand Down
5 changes: 2 additions & 3 deletions apps/frontend/src/features/canvasTools/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { CursorButton } from "./ui/CursorButton";
export { CursorPreview } from "./ui/CursorPreview";
export { ProfileForm } from "./ui/ProfileForm";
export { ProfilePanel } from "./ui/ProfilePanel";
export { NewNodePanel } from "./ui/NewNodePanel";
export { NodePanel } from "./ui/NodePanel";
export { ProfilePanel } from "./ui/ProfilePanel";
45 changes: 45 additions & 0 deletions apps/frontend/src/features/canvasTools/ui/NodeForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { usePopover } from "@/shared/model";

interface NodeFormProps {
changeNodeColor: (color: string) => void;
}

export function NodeForm({ changeNodeColor }: NodeFormProps) {
const { close } = usePopover();

const nodeBackgroundColors = {
white: "#FFFFFF",
grey: "#F1F1EF",
brown: "#F4EEEE",
orange: "#FBEBDD",
yellow: "#FCF3DB",
green: "#EDF3ED",
blue: "#E7F3F8",
purple: "#F7F3F8",
pink: "#FBF2F5",
red: "#FDEBEC",
};

const handleButtonClick = (color: string) => {
changeNodeColor(color);
close();
};

return (
<div className="flex flex-col gap-2">
<p className="text-sm text-neutral-500">Background color</p>
<div className="grid grid-cols-5 gap-4">
{Object.entries(nodeBackgroundColors).map(([key, color]) => {
return (
<button
key={key}
onClick={() => handleButtonClick(color)}
className="h-7 w-7 rounded-md border-[1px] border-neutral-300 hover:cursor-pointer"
style={{ backgroundColor: color }}
/>
);
})}
</div>
</div>
);
}
47 changes: 47 additions & 0 deletions apps/frontend/src/features/canvasTools/ui/NodePanel/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useEffect, useState } from "react";

import { NodeForm } from "../NodeForm";
import { Node } from "@/entities/node";
import { useYDocStore } from "@/shared/model";
import { Popover } from "@/shared/ui";

interface NodePanelProps {
currentPage: string;
}

export function NodePanel({ currentPage }: NodePanelProps) {
const [currentColor, setCurrentColor] = useState("#ffffff");
const { ydoc } = useYDocStore();

const changeNodeColor = (color: string) => {
const nodesMap = ydoc.getMap("nodes");
const id = currentPage.toString();

const existingNode = nodesMap.get(id) as Node;
nodesMap.set(id, {
...existingNode,
data: { ...existingNode.data, color },
});
setCurrentColor(color);
};

useEffect(() => {
const nodesMap = ydoc.getMap("nodes");
const currentNode = nodesMap.get(currentPage.toString()) as Node;
setCurrentColor(currentNode.data.color as string);
}, [currentPage]);

return (
<Popover placement="bottom" align="start" offset={{ x: -11, y: 16 }}>
<Popover.Trigger>
<button
className="flex h-7 w-7 items-center justify-center rounded-md border-[1px] border-neutral-300"
style={{ backgroundColor: currentColor }}
/>
</Popover.Trigger>
<Popover.Content className="rounded-lg border bg-white p-3 shadow-md">
<NodeForm changeNodeColor={changeNodeColor} />
</Popover.Content>
</Popover>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CursorPreview, ProfileForm } from "@/features/canvasTools";
import { CursorPreview } from "../CursorPreview";
import { ProfileForm } from "../ProfileForm";
import { usePopover } from "@/shared/model";

interface ProfilePanelProps {
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/src/widgets/NodeToolsView/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { NodeToolsView } from "./ui";
14 changes: 14 additions & 0 deletions apps/frontend/src/widgets/NodeToolsView/ui/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { usePageStore } from "@/entities/page";
import { NodePanel } from "@/features/canvasTools/ui/NodePanel";

export function NodeToolsView() {
const { currentPage } = usePageStore();

if (!currentPage) return null;

return (
<div className="z-10 flex flex-row rounded-xl border-[1px] border-neutral-200 bg-white p-2.5 text-black shadow-md">
<NodePanel currentPage={currentPage.toString()} />
</div>
);
}

0 comments on commit 693e6c2

Please sign in to comment.