Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export default function Column({ id, title }: DashboardColumn) {
if (newCards.length < PAGE_SIZE || nextCursorId === null) {
setIsLast(true);
}
} catch (error) {
console.error("Failed to load card list :", error);
} finally {
setIsLoading(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,32 @@ export default function DashboardEditSection({
token: string;
}) {
const [data, setData] = useState<DashboardDetail | null>(null);
const [loading, setLoading] = useState(false);
const [dashboardName, setDashboardName] = useState("");
const [selectedColor, setSelectedColor] = useState<ColorCode | "">("");
const [isFormValid, setIsFormValid] = useState(false);
const setDashboardId = useDashboardStore((state) => state.setDashboardId);

useEffect(() => {
const getData = async () => {
const data = await fetchDashboard({
token,
id: String(id),
});
setData(data);
setDashboardName(data.title);
setSelectedColor(data.color);
};
setLoading(true);

getData();
try {
const getData = async () => {
const data = await fetchDashboard({
token,
id: String(id),
});
setData(data);
setDashboardName(data.title);
setSelectedColor(data.color);
};

getData();
} catch (error) {
console.error("Failed to load dashboard:", error);
} finally {
setLoading(false);
}
}, []);

const onColorSelect = (color: ColorCode | "") => {
Expand All @@ -54,18 +63,27 @@ export default function DashboardEditSection({
};

const editDashboard = async () => {
await putDashboard({
token,
title: dashboardName,
color: selectedColor,
id,
});
setLoading(true);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 부분 고민중인 부분이에요..! setLoading(true)와 setLoading(false)가 여러 곳에서 반복적으로 사용되니까 custom hook으로 분리해서 사용하는 방법을 고민하고 있었어요..!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확실히 반복되는 코드가 많더라구요... 커스텀 훅이 있어도 좋겠네요!


try {
await putDashboard({
token,
title: dashboardName,
color: selectedColor,
id,
});

window.location.replace(`/dashboard/${id}`);
setDashboardId(String(id));
window.location.replace(`/dashboard/${id}`);
setDashboardId(String(id));
} catch (error) {
console.error("Failed to edit dashboard :", error);
} finally {
setLoading(false);
}
};

if (!data) return;
if (loading) return <p>Loading...</p>;

return (
<div className="w-full p-4 rounded-lg bg-white tablet:p-6">
Expand All @@ -91,7 +109,7 @@ export default function DashboardEditSection({
onClick={editDashboard}
disabled={!isFormValid}
>
변경
{!loading && "변경"}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import { useDashboardStore } from "@/lib/store/useDashboardStore";
import { deleteDashboard } from "@/lib/apis/dashboardsApi";
Expand All @@ -12,17 +13,27 @@ export default function DeleteButton({
id: number;
token: string;
}) {
const [loading, setLoading] = useState(false);

const router = useRouter();
const setDashboardId = useDashboardStore((state) => state.setDashboardId);

const handleDeleteClick = async () => {
await deleteDashboard({
token,
id,
});
setLoading(true);

try {
await deleteDashboard({
token,
id,
});

router.push(ROUTE.MYDASHBOARD);
setDashboardId(null);
router.push(ROUTE.MYDASHBOARD);
setDashboardId(null);
} catch (error) {
console.error("Failed to delete dashboard :", error);
} finally {
setLoading(false);
}
};

return (
Expand All @@ -31,7 +42,7 @@ export default function DeleteButton({
onClick={handleDeleteClick}
className="max-w-[320px] h-[52px] rounded-lg border border-gray-400 bg-gray-200 font-medium text-lg text-gray-800 tablet:h-[62px] tablet:text-2lg hover:bg-gray-300"
>
대시보드 삭제하기
{!loading && "대시보드 삭제하기"}
</button>
);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from "react";
import { Invitation } from "@/lib/types";
import { deleteInvitation } from "@/lib/apis/dashboardsApi";
import Button from "@/components/common/button/Button";
Expand All @@ -12,14 +13,24 @@ export default function InvitationCard({
invitee,
token,
}: InvitationCardProps) {
const [loading, setLoading] = useState(false);

const handleDeleteClick = async () => {
await deleteInvitation({
token,
dashboardId: dashboard.id,
invitationId: id,
});
setLoading(true);

try {
await deleteInvitation({
token,
dashboardId: dashboard.id,
invitationId: id,
});

window.location.reload();
window.location.reload();
} catch (error) {
console.error("Failed to delete invitation :", error);
} finally {
setLoading(false);
}
};

return (
Expand All @@ -31,7 +42,7 @@ export default function InvitationCard({
onClick={handleDeleteClick}
className="w-[52px] max-h-[32px] tablet:w-[84px]"
>
취소
{!loading && "취소"}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,28 @@ export default function InvitationSection({
token: string;
}) {
const [items, setItems] = useState<Invitation[]>([]);
const [loading, setLoading] = useState(false);
const [page, setPage] = useState(1);
const [totalCount, setTotalCount] = useState(0);
const totalPage = Math.ceil(totalCount / PAGE_SIZE);

const handleLoad = async () => {
const { invitations, totalCount } = await fetchInvitationList({
token,
id,
page,
size: PAGE_SIZE,
});
setItems(invitations);
setTotalCount(totalCount);
setLoading(true);

try {
const { invitations, totalCount } = await fetchInvitationList({
token,
id,
page,
size: PAGE_SIZE,
});
setItems(invitations);
setTotalCount(totalCount);
} catch (error) {
console.error("Failed to load invitation:", error);
} finally {
setLoading(false);
}
};

useEffect(() => {
Expand All @@ -48,6 +57,8 @@ export default function InvitationSection({
}
};

if (loading) return <p>Loading...</p>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로딩 상태 표시 좋네요! 다만 단순히 텍스트를 표시하는 대신에 로딩 스피너나 스켈레톤을 넣어서 UI가 자연스럽게 표시되도록 하는 방법도 좋겠어요!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요 우선은 loading 상태 사용을 위해서 임시로 이렇게 해놨는데, 금요일 리팩토링 때 아름님이 말씀하신 것처럼 스켈레톤을 사용하거나 하는 식으로 UI를 바꿔볼 생각입니다!


return (
<div className="flex flex-col gap-[26px] w-full p-4 rounded-lg bg-white tablet:gap-[17px] tablet:p-6">
<div className="flex justify-between items-center tablet:items-start">
Expand Down
53 changes: 38 additions & 15 deletions src/app/(after-login)/mydashboard/_components/InvitationCard.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useDashboardStore } from "@/lib/store/useDashboardStore";
import { Invitation } from "@/lib/types";
Expand All @@ -14,29 +15,47 @@ export default function InvitationCard({
dashboard,
token,
}: InvitationCardProps) {
const [loading, setLoading] = useState(false);

const newDashboardId = String(dashboard.id);
const router = useRouter();
const setDashboardId = useDashboardStore((state) => state.setDashboardId);

const handleApproveInvite = async () => {
await putInvitation({
token,
invitationId: id,
inviteAccepted: true,
});
setLoading(true);

try {
await putInvitation({
token,
invitationId: id,
inviteAccepted: true,
});

router.push(`/dashboard/${newDashboardId}`);
setDashboardId(newDashboardId);
router.push(`/dashboard/${newDashboardId}`);
setDashboardId(newDashboardId);
} catch (error) {
console.error("Failed to approve invitation :", error);
} finally {
setLoading(false);
}
};

const handleRejectInvite = async () => {
await putInvitation({
token,
invitationId: id,
inviteAccepted: false,
});
setLoading(true);

try {
await putInvitation({
token,
invitationId: id,
inviteAccepted: false,
});

window.location.reload();
window.location.reload();
} catch (error) {
console.error("Failed to reject invitation :", error);
} finally {
setLoading(false);
}
};

return (
Expand Down Expand Up @@ -66,15 +85,19 @@ export default function InvitationCard({
radius="sm"
className="flex-1 max-h-[32px] tablet:max-w-[72px] pc:max-w-[84px]"
>
<div className="font-medium text-xs tablet:text-md">수락</div>
<div className="font-medium text-xs tablet:text-md">
{!loading && "수락"}
</div>
</Button>
<Button
variant="whiteViolet"
onClick={handleRejectInvite}
radius="sm"
className="flex-1 max-h-[32px] tablet:max-w-[72px] pc:max-w-[84px]"
>
<div className="font-medium text-xs tablet:text-md">거절</div>
<div className="font-medium text-xs tablet:text-md">
{!loading && "거절"}
</div>
</Button>
</div>
</div>
Expand Down
15 changes: 10 additions & 5 deletions src/components/common/alert/AlertProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ export default function AlertProvider() {

const handleDeleteClick = async () => {
if (!accessToken || !selectedColumnId) return;
await deleteColumn({
token: accessToken,
columnId: Number(selectedColumnId),
});
router.refresh();

try {
await deleteColumn({
token: accessToken,
columnId: Number(selectedColumnId),
});
router.refresh();
} catch (error) {
console.error("Failed to delete column :", error);
}
};

return (
Expand Down
22 changes: 15 additions & 7 deletions src/components/common/modal/MenuButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import MenuButtonIcon from "../../../../public/icon/menu_icon.svg";
import { useTaskStore } from "@/lib/store/useTaskStore";

export default function MenuButton() {
const [loading, setLoading] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const { openModal, closeModal } = useModalStore();
const { selectedTaskId } = useTaskStore();
Expand All @@ -18,14 +19,21 @@ export default function MenuButton() {

const handleDelete = async () => {
if (!selectedTaskId) return;
setLoading(true);

await deleteCard({
token: accessToken,
cardId: selectedTaskId,
});
try {
await deleteCard({
token: accessToken,
cardId: selectedTaskId,
});

closeModal();
window.location.reload();
closeModal();
window.location.reload();
} catch (error) {
console.error("Failed to delete card :", error);
} finally {
setLoading(false);
}
};

return (
Expand All @@ -50,7 +58,7 @@ export default function MenuButton() {
onClick={handleDelete}
className="w-[81px] h-8 rounded font-normal text-md text-gray-800 hover:text-violet hover:bg-violet-8"
>
삭제하기
{!loading && "삭제하기"}
</button>
</div>
)}
Expand Down
Loading