Skip to content

Commit ed2d9f4

Browse files
authored
Merge pull request #77 from gyoyeon-kim/card-table
Moal : 새로운 대시보드(위치, 뒷배경 수정) + Header : HeaderBebridge api 데이터 저장
2 parents c89ade2 + f3e087e commit ed2d9f4

File tree

12 files changed

+210
-133
lines changed

12 files changed

+210
-133
lines changed

src/api/members.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
import axios from "axios";
22
import { MemberType } from "@/components/Gnb/members";
33

4-
export const getMembers = async () => {
5-
const response = await axios.get<{ results: MemberType[] }>(
6-
"https://sp-taskify-api.vercel.app/13-4/members"
4+
interface ApiResponse {
5+
members: MemberType[]; // 실제 데이터
6+
totalCount: number;
7+
}
8+
9+
export const getMembers = async (dashboardId?: string | string[]) => {
10+
if (!dashboardId) {
11+
console.error("dashboardID가 없습니다.");
12+
return [];
13+
}
14+
15+
const token = process.env.NEXT_PUBLIC_API_TOKEN;
16+
const numericDashboardId =
17+
typeof dashboardId === "string" ? Number(dashboardId) : undefined;
18+
19+
const response = await axios.get<ApiResponse>(
20+
`https://sp-taskify-api.vercel.app/13-4/members?page=1&size=20&dashboardId=${numericDashboardId}`,
21+
{
22+
headers: {
23+
Authorization: `Bearer ${token}`,
24+
},
25+
}
726
);
8-
return response.data.results || [];
27+
console.log(response.data);
28+
console.log(response.data.members);
29+
30+
return response.data.members || [];
931
};

src/components/Gnb/HeaderBebridge.tsx

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,26 @@ import { MemberType } from "@/components/Gnb/members";
44
import { getMembers } from "@/api/members";
55
import RandomProfile from "../table/member/RandomProfile";
66
import ModalInviting from "./ModalInviting";
7+
import NewDashboard from "../modal/NewDashboard";
8+
9+
interface HeaderBebridgeProps {
10+
dashboardId?: string | string[];
11+
}
712

813
/*dummy data*/
914
const user = {
1015
nickname: "배유철",
11-
profileImageUrl: "../svgs/dummy-icon.png",
16+
profileImageUrl: "",
1217
};
1318

14-
const HeaderBebridge = () => {
19+
const HeaderBebridge: React.FC<HeaderBebridgeProps> = ({ dashboardId }) => {
20+
// dashboardId 받을 수 있게 변경
21+
1522
/*멤버 목록 profileImageUrl loading*/
1623
const [isLoading, setIsLoading] = useState(true);
1724
const [members, setMembers] = useState<MemberType[]>([]);
1825
/*관리 버튼 클릭 이벤트 함수*/
1926
const router = useRouter();
20-
const { dashboardId } = router.query;
2127
const goToDashboardEdit = () => {
2228
router.push(`/dashboard/${dashboardId}/edit`);
2329
};
@@ -34,8 +40,10 @@ const HeaderBebridge = () => {
3440
useEffect(() => {
3541
const fetchMembers = async () => {
3642
try {
37-
const members = await getMembers();
38-
setMembers(members);
43+
if (dashboardId) {
44+
const members = await getMembers(dashboardId);
45+
setMembers(members);
46+
}
3947
} catch (error) {
4048
console.error("멤버 불러오기 실패:", error);
4149
} finally {
@@ -44,7 +52,7 @@ const HeaderBebridge = () => {
4452
};
4553

4654
fetchMembers();
47-
}, []);
55+
}, [dashboardId]);
4856

4957
return (
5058
<header className="w-full h-[50px] sm:h-[60px] md:h-[70px] flex items-center justify-center bg-white border-b-[1px] border-b-[#D9D9D9]">
@@ -86,7 +94,8 @@ const HeaderBebridge = () => {
8694
<span className="text-sm md:text-base text-gray1">초대하기</span>
8795
</button>
8896
{/*임시 컴포넌트명, 추후 정식 초대 모달 컴포넌트로 교체*/}
89-
{isModalOpen && <ModalInviting onClose={closeInviteModal} />}
97+
98+
{isModalOpen && <NewDashboard onClose={closeInviteModal} />}
9099
</div>
91100

92101
{/*4개의 프로필 아이콘 표시, 나머지 멤버 숫자 +n 아이콘으로 표시*/}
@@ -96,12 +105,17 @@ const HeaderBebridge = () => {
96105
) : (
97106
<>
98107
{members.slice(0, 4).map((member) => (
99-
<img
100-
key={member.id}
101-
src={member.profileImageUrl || "/svgs/dummy-icon.png"}
102-
alt={member.nickname}
103-
className="w-[34px] h-[34px] md:w-[38px] md:h-[38px] rounded-full border-[2px] border-white"
104-
/>
108+
<div key={member.id}>
109+
{member.profileImageUrl ? (
110+
<img
111+
src={member.profileImageUrl}
112+
alt={member.nickname}
113+
className="w-[34px] h-[34px] md:w-[38px] md:h-[38px] rounded-full border-[2px] border-white"
114+
/>
115+
) : (
116+
<RandomProfile name={member.nickname} />
117+
)}
118+
</div>
105119
))}
106120
{members.length > 4 && (
107121
<div className="w-[34px] h-[34px] md:w-[38px] md:h-[38px] flex items-center justify-center rounded-full border-[2px] border-white bg-[#F4D7DA] font-16m text-[#D25B68]">
@@ -127,9 +141,10 @@ const HeaderBebridge = () => {
127141
className="w-full h-full rounded-full object-cover"
128142
/>
129143
) : (
130-
<RandomProfile name={user.nickname} index={2} />
144+
<RandomProfile name={user.nickname} />
131145
)}
132146
</div>
147+
133148
<span className="hidden md:block text-black3 md:text-base md:font-medium">
134149
{user.nickname}
135150
</span>

src/components/card/Profile.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ export default function ProfileCard() {
6161
onChange={setEmail}
6262
pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
6363
invalidMessage="유효한 이메일 주소를 입력하세요."
64-
className="mb-2"
6564
/>
6665

6766
<Input

src/components/modal/NewDashboard.tsx

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export default function NewDashboard({ onClose }: { onClose?: () => void }) {
3131
}
3232
);
3333
console.log("대시보드 생성 성공:", response.data);
34+
alert("대시보드가 성공적으로 생성되었습니다.");
3435
console.log(loading);
3536

3637
onClose?.(); // 모달 닫기
@@ -42,54 +43,56 @@ export default function NewDashboard({ onClose }: { onClose?: () => void }) {
4243
};
4344

4445
return (
45-
<div className="sm:w-[584px] sm:h-[344px] w-[327px] h-[312px] bg-white sm:rounded-[16px] rounded-[8px] shadow-md p-[24px] flex flex-col">
46-
<h2 className="text-sm sm:text-[24px] font-bold">새로운 대시보드</h2>
47-
<Input
48-
type="text"
49-
onChange={setTitle}
50-
label="대시보드 이름"
51-
labelClassName="text-lg sm:text-base text-black3 mt-6"
52-
placeholder="뉴프로젝트"
53-
className="max-w-[620px] mb-1"
54-
/>
46+
<div className="fixed inset-0 flex items-center justify-center bg-black/35 z-50">
47+
<div className="bg-white p-6 rounded-lg shadow-lg w-[327px] sm:w-[584px] sm:h-[344px]">
48+
<h2 className="text-sm sm:text-[24px] font-bold">새로운 대시보드</h2>
49+
<Input
50+
type="text"
51+
onChange={setTitle}
52+
label="대시보드 이름"
53+
labelClassName="text-lg sm:text-base text-black3 mt-6"
54+
placeholder="뉴프로젝트"
55+
className="max-w-[620px] mb-1"
56+
/>
5557

56-
<div className="mt-3 flex relative">
57-
{colors.map((color, index) => (
58-
<div key={index} className="relative">
59-
<button
60-
className="cursor-pointer w-[30px] h-[30px] rounded-full mr-2"
61-
style={{ backgroundColor: color }}
62-
onClick={() => setSelected(index)}
63-
/>
64-
{selected === index && (
65-
<Image
66-
src="/svgs/check.svg"
67-
alt="선택표시 이미지"
68-
width={23}
69-
height={23}
70-
className="absolute top-4 left-4 transform -translate-x-1/2 -translate-y-1/2"
58+
<div className="mt-3 flex relative">
59+
{colors.map((color, index) => (
60+
<div key={index} className="relative">
61+
<button
62+
className="cursor-pointer w-[30px] h-[30px] rounded-full mr-2"
63+
style={{ backgroundColor: color }}
64+
onClick={() => setSelected(index)}
7165
/>
72-
)}
73-
</div>
74-
))}
75-
</div>
66+
{selected === index && (
67+
<Image
68+
src="/svgs/check.svg"
69+
alt="선택표시 이미지"
70+
width={23}
71+
height={23}
72+
className="absolute top-4 left-4 transform -translate-x-1/2 -translate-y-1/2"
73+
/>
74+
)}
75+
</div>
76+
))}
77+
</div>
7678

77-
<div className="mt-8 flex justify-between">
78-
<button
79-
onClick={onClose}
80-
className="cursor-pointer sm:w-[256px] sm:h-[54px] w-[295px] h-[54px] rounded-[8px] border border-[var(--color-gray3)] text-[var(--color-gray1)]"
81-
>
82-
취소
83-
</button>
84-
<button
85-
onClick={handleSubmit}
86-
disabled={!title || selected === null}
87-
className={`cursor-pointer sm:w-[256px] sm:h-[54px] w-[295px] h-[54px] rounded-[8px]
79+
<div className="mt-8 flex justify-between">
80+
<button
81+
onClick={onClose}
82+
className="cursor-pointer sm:w-[256px] sm:h-[54px] w-[295px] h-[54px] rounded-[8px] border border-[var(--color-gray3)] text-[var(--color-gray1)]"
83+
>
84+
취소
85+
</button>
86+
<button
87+
onClick={handleSubmit}
88+
disabled={!title || selected === null}
89+
className={`cursor-pointer sm:w-[256px] sm:h-[54px] w-[295px] h-[54px] rounded-[8px]
8890
border border-[var(--color-gray3)] text-[var(--color-white)]
8991
${!title || selected === null ? "bg-gray-300 cursor-not-allowed" : "bg-[var(--primary)]"}`}
90-
>
91-
생성
92-
</button>
92+
>
93+
생성
94+
</button>
95+
</div>
9396
</div>
9497
</div>
9598
);

0 commit comments

Comments
 (0)