From 8b0d74fee8e59304d995066a6ece78325226d018 Mon Sep 17 00:00:00 2001 From: JAESEON PARK Date: Fri, 31 Jul 2026 16:06:46 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=9B=8C=ED=81=AC=EC=8A=A4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=AA=A9=EB=A1=9D/=EB=A9=A4?= =?UTF-8?q?=EB=B2=84=EA=B4=80=EB=A6=AC/=EC=84=A4=EC=A0=95/=EC=95=8C?= =?UTF-8?q?=EB=A6=BC/=ED=83=80=EC=9E=84=EB=9D=BC=EC=9D=B8=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timeline/TimelinePerformancePanel.tsx | 18 +- src/pages/dashboard/timeline/Timeline.tsx | 210 ++++++------ src/pages/setting/Setting.tsx | 157 ++++----- src/pages/workspace/MemberManagement.tsx | 67 ++-- src/pages/workspace/Workspace.tsx | 10 +- src/pages/workspace/WorkspaceSetting.tsx | 301 +++++++++--------- 6 files changed, 403 insertions(+), 360 deletions(-) diff --git a/src/components/timeline/TimelinePerformancePanel.tsx b/src/components/timeline/TimelinePerformancePanel.tsx index 849f6a69..ff0c7642 100644 --- a/src/components/timeline/TimelinePerformancePanel.tsx +++ b/src/components/timeline/TimelinePerformancePanel.tsx @@ -18,10 +18,12 @@ import Button from "@/components/common/button/Button"; import ChartLegend from "@/components/common/chart/ChartLegend"; import Drawer from "@/components/common/drawer/Drawer"; import { DropdownMenu } from "@/components/common/dropdownmenu/DropdownMenu"; +import { ErrorBoundary } from "@/components/common/error/ErrorBoundary"; import { Skeleton } from "@/components/common/skeleton/Skeleton"; import TimelinePeriodSelector from "@/components/timeline/TimelinePeriodSelector"; import TimelineDailyTrendChart from "./charts/TimelineDailyTrendChart"; +import ChartErrorFallback from "../common/error/ChartErrorFallback"; import ChevronRightIcon from "@/assets/icon/chevron/chevron-right.svg?react"; import MoreIcon from "@/assets/icon/common/more.svg?react"; @@ -367,13 +369,15 @@ export default function TimelinePerformancePanel({ disableNext={!canGoNext} /> - + + + diff --git a/src/pages/dashboard/timeline/Timeline.tsx b/src/pages/dashboard/timeline/Timeline.tsx index ca5b4117..077c7279 100644 --- a/src/pages/dashboard/timeline/Timeline.tsx +++ b/src/pages/dashboard/timeline/Timeline.tsx @@ -22,6 +22,8 @@ import { useTimelineDetail } from "@/hooks/timeline/useTimelineDetail"; import { useTimelineList } from "@/hooks/timeline/useTimelineList"; import Button from "@/components/common/button/Button"; +import AreaErrorFallback from "@/components/common/error/AreaErrorFallback"; +import { ErrorBoundary } from "@/components/common/error/ErrorBoundary"; import Modal from "@/components/common/modal/Modal"; import ModalContent from "@/components/common/modal/ModalContent"; import TimelineSkeleton from "@/components/timeline/skeleton/TimelineSkeleton"; @@ -279,115 +281,121 @@ export default function Timeline() { className="flex w-full min-w-0 flex-col" style={{ height: TIMELINE_PAGE_HEIGHT }} > -
-
-
- - -
- -
- - -
- - - Sort - - +
+
+
+ + +
+ +
+ + +
+ + + Sort + + + + Filter + +
-
- {hasNoTimelines ? ( - setIsCreateOpen(true)} /> - ) : ( -
+ {hasNoTimelines ? ( + setIsCreateOpen(true)} /> + ) : (
- - {hasNoVisibleBars ? ( -
-

- 이 기간에 표시할 타임라인이 없어요 -

-

- 다른 기간으로 이동하거나 보기 단위를 변경해 보세요 -

-
- ) : ( - + - {bars.map((bar) => ( - handleEditTimeline(bar.id)} - onDelete={() => - handleDeleteTimeline({ id: bar.id, name: bar.title }) - } - /> - ))} - - )} + className="sticky top-0" + /> + {hasNoVisibleBars ? ( +
+

+ 이 기간에 표시할 타임라인이 없어요 +

+

+ 다른 기간으로 이동하거나 보기 단위를 변경해 보세요 +

+
+ ) : ( + + {bars.map((bar) => ( + handleEditTimeline(bar.id)} + onDelete={() => + handleDeleteTimeline({ id: bar.id, name: bar.title }) + } + /> + ))} + + )} +
-
- )} -
+ )} +
+ + {/* 생성 */}
) : ( - { - if (!value) { + + { + if (!value) { + setDraftOrgNotif((prev) => ({ + ...prev, + masterEnabled: false, + slackEnabled: false, + discordEnabled: false, + })); + setDraftChannel({ browserPush: false, emailNotif: false }); + setDraftWorkspaceNotif({ + clickAlarm: false, + weeklyReport: false, + }); + return; + } setDraftOrgNotif((prev) => ({ ...prev, - masterEnabled: false, - slackEnabled: false, - discordEnabled: false, + masterEnabled: true, + slackEnabled: + prev.slackConnected && savedOrgNotif.slackEnabled, + discordEnabled: + prev.discordConnected && savedOrgNotif.discordEnabled, })); - setDraftChannel({ browserPush: false, emailNotif: false }); - setDraftWorkspaceNotif({ - clickAlarm: false, - weeklyReport: false, - }); - return; + setDraftChannel(savedChannel); + setDraftWorkspaceNotif(savedWorkspaceNotif); + }} + browserPush={draftChannel.browserPush} + emailNotif={draftChannel.emailNotif} + onBrowserPushChange={(value) => + setDraftChannel((prev) => ({ ...prev, browserPush: value })) } - setDraftOrgNotif((prev) => ({ - ...prev, - masterEnabled: true, - slackEnabled: prev.slackConnected && savedOrgNotif.slackEnabled, - discordEnabled: - prev.discordConnected && savedOrgNotif.discordEnabled, - })); - setDraftChannel(savedChannel); - setDraftWorkspaceNotif(savedWorkspaceNotif); - }} - browserPush={draftChannel.browserPush} - emailNotif={draftChannel.emailNotif} - onBrowserPushChange={(value) => - setDraftChannel((prev) => ({ ...prev, browserPush: value })) - } - onEmailNotifChange={(value) => - setDraftChannel((prev) => ({ ...prev, emailNotif: value })) - } - slackEnabled={draftOrgNotif.slackEnabled} - slackConnected={draftOrgNotif.slackConnected} - slackWebhookUrl={slackWebhookUrl} - slackWebhookError={slackWebhookError} - onSlackWebhookUrlChange={(value) => { - setSlackWebhookUrl(value); - if (slackWebhookError) setSlackWebhookError(""); - }} - onSlackEnabledChange={(value) => - setDraftOrgNotif((prev) => ({ ...prev, slackEnabled: value })) - } - onConnectSlack={handleConnectSlack} - onDisconnectSlack={handleDisconnectSlack} - discordEnabled={draftOrgNotif.discordEnabled} - discordConnected={draftOrgNotif.discordConnected} - discordWebhookUrl={discordWebhookUrl} - discordWebhookError={discordWebhookError} - onDiscordWebhookUrlChange={(value) => { - setDiscordWebhookUrl(value); - if (discordWebhookError) setDiscordWebhookError(""); - }} - onDiscordEnabledChange={(value) => - setDraftOrgNotif((prev) => ({ ...prev, discordEnabled: value })) - } - onConnectDiscord={handleConnectDiscord} - onDisconnectDiscord={handleDisconnectDiscord} - workspaceName={currentWorkspaceName} - clickAlarm={draftWorkspaceNotif.clickAlarm} - weeklyReport={draftWorkspaceNotif.weeklyReport} - onClickAlarmChange={(value) => - setDraftWorkspaceNotif((prev) => ({ ...prev, clickAlarm: value })) - } - onWeeklyReportChange={(value) => - setDraftWorkspaceNotif((prev) => ({ - ...prev, - weeklyReport: value, - })) - } - workspaceNotifiDisabled={workspaceNotifiDisabled} - pendingOrgAction={pendingOrgAction} - /> + onEmailNotifChange={(value) => + setDraftChannel((prev) => ({ ...prev, emailNotif: value })) + } + slackEnabled={draftOrgNotif.slackEnabled} + slackConnected={draftOrgNotif.slackConnected} + slackWebhookUrl={slackWebhookUrl} + slackWebhookError={slackWebhookError} + onSlackWebhookUrlChange={(value) => { + setSlackWebhookUrl(value); + if (slackWebhookError) setSlackWebhookError(""); + }} + onSlackEnabledChange={(value) => + setDraftOrgNotif((prev) => ({ ...prev, slackEnabled: value })) + } + onConnectSlack={handleConnectSlack} + onDisconnectSlack={handleDisconnectSlack} + discordEnabled={draftOrgNotif.discordEnabled} + discordConnected={draftOrgNotif.discordConnected} + discordWebhookUrl={discordWebhookUrl} + discordWebhookError={discordWebhookError} + onDiscordWebhookUrlChange={(value) => { + setDiscordWebhookUrl(value); + if (discordWebhookError) setDiscordWebhookError(""); + }} + onDiscordEnabledChange={(value) => + setDraftOrgNotif((prev) => ({ ...prev, discordEnabled: value })) + } + onConnectDiscord={handleConnectDiscord} + onDisconnectDiscord={handleDisconnectDiscord} + workspaceName={currentWorkspaceName} + clickAlarm={draftWorkspaceNotif.clickAlarm} + weeklyReport={draftWorkspaceNotif.weeklyReport} + onClickAlarmChange={(value) => + setDraftWorkspaceNotif((prev) => ({ + ...prev, + clickAlarm: value, + })) + } + onWeeklyReportChange={(value) => + setDraftWorkspaceNotif((prev) => ({ + ...prev, + weeklyReport: value, + })) + } + workspaceNotifiDisabled={workspaceNotifiDisabled} + pendingOrgAction={pendingOrgAction} + /> + )} diff --git a/src/pages/workspace/MemberManagement.tsx b/src/pages/workspace/MemberManagement.tsx index 985a5bfc..6094667c 100644 --- a/src/pages/workspace/MemberManagement.tsx +++ b/src/pages/workspace/MemberManagement.tsx @@ -14,6 +14,8 @@ import { useCoreMutation, useCoreQuery } from "@/hooks/customQuery"; import { useNotificationMembers } from "@/hooks/setting/useNotificationMembers"; import { useUpdateNotificationMembers } from "@/hooks/setting/useUpdateNotificationMembers"; +import AreaErrorFallback from "@/components/common/error/AreaErrorFallback"; +import { ErrorBoundary } from "@/components/common/error/ErrorBoundary"; import DeleteMemberModal from "@/components/workspace/DeleteMemberModal"; import MemberList from "@/components/workspace/MemberList"; import MemberManagementLoading from "@/components/workspace/MemberManagementLoading"; @@ -339,36 +341,41 @@ export default function MemberManagement() { return (
-
- - - - - -
+ +
+ + + + + +
+
); } diff --git a/src/pages/workspace/Workspace.tsx b/src/pages/workspace/Workspace.tsx index e4d4c732..6db5c093 100644 --- a/src/pages/workspace/Workspace.tsx +++ b/src/pages/workspace/Workspace.tsx @@ -13,6 +13,8 @@ import type { TCreateOrgRequest } from "@/types/workspace/workspace"; import { useCoreMutation, useCoreQuery } from "@/hooks/customQuery"; import Button from "@/components/common/button/Button"; +import AreaErrorFallback from "@/components/common/error/AreaErrorFallback"; +import { ErrorBoundary } from "@/components/common/error/ErrorBoundary"; import Input from "@/components/common/input/Input"; import Modal from "@/components/common/modal/Modal"; import TextareaField from "@/components/common/textarea/TextareaField"; @@ -211,8 +213,12 @@ export default function WorkspacePage() { 생성하기 - - {renderWorkspaceContent()} + + {renderWorkspaceContent()} +
diff --git a/src/pages/workspace/WorkspaceSetting.tsx b/src/pages/workspace/WorkspaceSetting.tsx index f7c7c049..eb19dbba 100644 --- a/src/pages/workspace/WorkspaceSetting.tsx +++ b/src/pages/workspace/WorkspaceSetting.tsx @@ -6,6 +6,8 @@ import { useCoreMutation, useCoreQuery } from "@/hooks/customQuery"; import Button from "@/components/common/button/Button"; import Card from "@/components/common/card/Card"; +import AreaErrorFallback from "@/components/common/error/AreaErrorFallback"; +import { ErrorBoundary } from "@/components/common/error/ErrorBoundary"; import Input from "@/components/common/input/Input"; import Modal from "@/components/common/modal/Modal"; import ModalContent from "@/components/common/modal/ModalContent"; @@ -203,165 +205,170 @@ export default function WorkspaceSetting() { )} {!loading && !errorMsg && ( - <> - -
-
-
- 로고 이미지 -
- - -
- +
+ + +
+
+
+ setName(e.target.value)} + disabled={!isAdmin || saving || deleting} + /> + setDesc(e.target.value)} + minRows={4} + className="min-h-90" + disabled={!isAdmin || saving || deleting} + /> +
+
+ {isAdmin && ( +
+
-
-
- setName(e.target.value)} - disabled={!isAdmin || saving || deleting} - /> - setDesc(e.target.value)} - minRows={4} - className="min-h-90" - disabled={!isAdmin || saving || deleting} - /> -
-
- {isAdmin && ( -
- - -
- )} - + )} + - { - if (!deleting) { - setDeleteOpen(false); - setDeleteNameSnapshot(""); - setDeleteConfirmInput(""); - } - }} - title="워크스페이스를 삭제할게요" - size="lg" - disableOverlayClick={deleting} - > - + + )} ); From 28393bc130f88991fd5ec9491e3e8659b1109135 Mon Sep 17 00:00:00 2001 From: JAESEON PARK Date: Fri, 31 Jul 2026 16:48:49 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20import=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=ED=83=80=EC=9E=84=EB=9D=BC=EC=9D=B8=20?= =?UTF-8?q?=EC=84=B1=EA=B3=BC=ED=8C=A8=EB=84=90=20errorboundary=EC=97=90?= =?UTF-8?q?=20resetkey=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../timeline/TimelinePerformancePanel.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/timeline/TimelinePerformancePanel.tsx b/src/components/timeline/TimelinePerformancePanel.tsx index ff0c7642..90ece4da 100644 --- a/src/components/timeline/TimelinePerformancePanel.tsx +++ b/src/components/timeline/TimelinePerformancePanel.tsx @@ -18,12 +18,12 @@ import Button from "@/components/common/button/Button"; import ChartLegend from "@/components/common/chart/ChartLegend"; import Drawer from "@/components/common/drawer/Drawer"; import { DropdownMenu } from "@/components/common/dropdownmenu/DropdownMenu"; +import ChartErrorFallback from "@/components/common/error/ChartErrorFallback"; import { ErrorBoundary } from "@/components/common/error/ErrorBoundary"; import { Skeleton } from "@/components/common/skeleton/Skeleton"; import TimelinePeriodSelector from "@/components/timeline/TimelinePeriodSelector"; import TimelineDailyTrendChart from "./charts/TimelineDailyTrendChart"; -import ChartErrorFallback from "../common/error/ChartErrorFallback"; import ChevronRightIcon from "@/assets/icon/chevron/chevron-right.svg?react"; import MoreIcon from "@/assets/icon/common/more.svg?react"; @@ -369,7 +369,16 @@ export default function TimelinePerformancePanel({ disableNext={!canGoNext} /> - +