diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/DashboardCard.module.css b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/DashboardCard.module.css
new file mode 100644
index 0000000..96fd49f
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/DashboardCard.module.css
@@ -0,0 +1,48 @@
+.dashboardCard.dashboardCard {
+ padding: 15px 20px;
+ background: var(--white);
+ border: 1px solid var(--gray-300);
+ border-radius: 8px;
+ transition: background-color 0.3s ease;
+}
+
+.dashboardCard.dashboardCard:hover {
+ background: var(--violet-light);
+}
+
+.titleContainer {
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ align-items: center;
+ gap: 12px;
+}
+
+.dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 999px;
+}
+
+.title,
+.crown {
+ font-size: 18px;
+ font-weight: 500;
+}
+
+.title {
+ color: var(--black-100);
+ font-size: 14px;
+ font-weight: 600;
+}
+
+.arrowWrapper {
+ flex: 1;
+ text-align: right;
+}
+
+@media screen and (min-width: 768px) {
+ .title {
+ font-size: 16px;
+ }
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/DashboardCard.tsx b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/DashboardCard.tsx
new file mode 100644
index 0000000..d37c556
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/DashboardCard.tsx
@@ -0,0 +1,39 @@
+import type { Dashboard } from '@/app/(with-header-sidebar)/mydashboard/_types/dashboards';
+import Image from 'next/image';
+import { useRouter } from 'next/navigation';
+import Button from '@/components/Button';
+import styles from './DashboardCard.module.css';
+
+export default function DashboardCard({
+ id,
+ color,
+ title,
+ createdByMe,
+}: Dashboard) {
+ const router = useRouter();
+
+ return (
+
+ );
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Dashboards.module.css b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Dashboards.module.css
new file mode 100644
index 0000000..98fae96
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Dashboards.module.css
@@ -0,0 +1,46 @@
+.dashboardsWrapper {
+ display: grid;
+ grid-template-rows: repeat(6, 1fr);
+ grid-template-columns: 1fr;
+ gap: 8px;
+}
+
+.addDashboard.addDashboard {
+ background: var(--white);
+ color: var(--black-100);
+ font-size: 14px;
+ font-weight: 600;
+ padding: 15px 20px;
+ background: var(--white);
+ border: 1px solid var(--gray-300);
+ border-radius: 8px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 12px;
+ transition: background-color 0.3s ease;
+}
+
+.addDashboard.addDashboard:hover {
+ background-color: var(--violet-light);
+}
+
+.addIconWrapper {
+ border-radius: 4px;
+ background: var(--violet-light);
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+}
+
+@media screen and (min-width: 768px) {
+ .dashboardsWrapper {
+ grid-template-rows: repeat(3, 1fr);
+ grid-template-columns: repeat(2, 1fr);
+ gap: 10px;
+ }
+
+ .addDashboard.addDashboard {
+ font-size: 16px;
+ }
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Dashboards.tsx b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Dashboards.tsx
new file mode 100644
index 0000000..8320cd2
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Dashboards.tsx
@@ -0,0 +1,44 @@
+'use client';
+
+import useDashboards from '../../_hooks/useDashboards';
+import Pagination from './Pagination';
+import DashboardCard from './DashboardCard';
+import Button from '@/components/Button';
+import Image from 'next/image';
+import styles from './Dashboards.module.css';
+
+const PAGE_SIZE = 5;
+
+export default function Dashboards() {
+ const { page, dashboards, totalPages, handlePageChange } = useDashboards({
+ pageSize: PAGE_SIZE,
+ });
+
+ return (
+
+
+
+ {dashboards.map((board) => (
+
+ ))}
+
+ {dashboards.length > 0 && (
+
+ )}
+
+ );
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Pagination.module.css b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Pagination.module.css
new file mode 100644
index 0000000..280ae13
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Pagination.module.css
@@ -0,0 +1,41 @@
+.pagination {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 16px;
+ margin-top: 16px;
+}
+
+.pageNavigation {
+ color: var(--black-100);
+ font-size: 14px;
+ font-weight: 400;
+}
+
+.arrowLeft.arrowLeft,
+.arrowRight.arrowRight {
+ border: 1px solid var(--gray-300);
+ background: var(--white);
+ width: 40px;
+ height: 40px;
+ transition: background-color 0.3s ease;
+}
+
+.arrowLeft.arrowLeft {
+ border-radius: 4px 0px 0px 4px;
+}
+
+.arrowRight.arrowRight {
+ border-radius: 0px 4px 4px 0px;
+ border-left: none;
+}
+
+.arrowLeft.arrowLeft:hover,
+.arrowRight.arrowRight:hover {
+ background: var(--violet-light);
+}
+
+.arrowLeft.arrowLeft:disabled,
+.arrowRight.arrowRight:disabled {
+ background: var(--white);
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Pagination.tsx b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Pagination.tsx
new file mode 100644
index 0000000..26a8a17
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/dashboards/Pagination.tsx
@@ -0,0 +1,58 @@
+import Image from 'next/image';
+import Button from '@/components/Button';
+import styles from './Pagination.module.css';
+
+export default function Pagination({
+ currentPage,
+ totalPages,
+ onPageChange,
+}: {
+ currentPage: number;
+ totalPages: number;
+ onPageChange: (direction: 'next' | 'prev') => void;
+}) {
+ const isFirstPage = currentPage === 1;
+ const isLastPage = currentPage >= totalPages;
+
+ const leftArrowSrc = isFirstPage
+ ? '/icons/arrow_left_light.svg'
+ : '/icons/arrow_left.svg';
+
+ const rightArrowSrc = isLastPage
+ ? '/icons/arrow_right_light.svg'
+ : '/icons/arrow_right.svg';
+
+ return (
+
+
{`${totalPages} 페이지 중 ${currentPage}`}
+
+
+
+
+
+ );
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/invitations/Invitations.module.css b/src/app/(with-header-sidebar)/mydashboard/_components/invitations/Invitations.module.css
new file mode 100644
index 0000000..d1a3a48
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/invitations/Invitations.module.css
@@ -0,0 +1,43 @@
+.invitations {
+ background-color: var(--white);
+ border-radius: 8px;
+ min-height: 260px;
+ margin-top: 16px;
+ padding: 24px 20px 80px 20px;
+}
+
+.title {
+ color: var(--black-100);
+ font-size: 14px;
+ font-weight: 700;
+}
+
+.descriptionWrapper {
+ text-align: center;
+ margin-top: 60px;
+}
+
+.description {
+ color: var(--gray-400);
+ font-size: 12px;
+ font-weight: 400;
+}
+
+@media screen and (min-width: 768px) {
+ .invitations {
+ margin-top: 40px;
+ }
+
+ .title {
+ font-size: 24px;
+ }
+
+ .descriptionWrapper {
+ text-align: center;
+ margin-top: 64px;
+ }
+
+ .description {
+ font-size: 18px;
+ }
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_components/invitations/Invitations.tsx b/src/app/(with-header-sidebar)/mydashboard/_components/invitations/Invitations.tsx
new file mode 100644
index 0000000..12f1b0d
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_components/invitations/Invitations.tsx
@@ -0,0 +1,19 @@
+import Image from 'next/image';
+import styles from './Invitations.module.css';
+
+export default function Invitations() {
+ return (
+
+ );
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_hooks/useApi.ts b/src/app/(with-header-sidebar)/mydashboard/_hooks/useApi.ts
index b392917..db41251 100644
--- a/src/app/(with-header-sidebar)/mydashboard/_hooks/useApi.ts
+++ b/src/app/(with-header-sidebar)/mydashboard/_hooks/useApi.ts
@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback } from 'react';
import { AxiosResponse, AxiosError } from 'axios';
-import axiosInstance from '../_utils/axiosInstance';
+import axiosInstance from '../_lib/axiosInstance';
type UseApiFetchReturnType = {
data: T | null;
diff --git a/src/app/(with-header-sidebar)/mydashboard/_hooks/useDashboards.ts b/src/app/(with-header-sidebar)/mydashboard/_hooks/useDashboards.ts
new file mode 100644
index 0000000..9904687
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_hooks/useDashboards.ts
@@ -0,0 +1,29 @@
+import { useState } from 'react';
+import useApi from '@/app/(with-header-sidebar)/mydashboard/_hooks/useApi';
+import type { GetDashboardsResponse } from '@/app/(with-header-sidebar)/mydashboard/_types/dashboards';
+
+interface UseDashboardsParams {
+ pageSize: number;
+}
+
+export default function useDashboards({ pageSize }: UseDashboardsParams) {
+ const [page, setPage] = useState(1);
+ const { data } = useApi('/dashboards', {
+ method: 'GET',
+ params: { navigationMethod: 'pagination', page, size: pageSize },
+ });
+
+ const dashboards = data?.dashboards ?? [];
+ const totalCount = data?.totalCount ?? 0;
+ const totalPages = Math.ceil(totalCount / pageSize);
+
+ const handlePageChange = (direction: 'next' | 'prev') => {
+ setPage((prevPage) => {
+ if (direction === 'next' && prevPage < totalPages) return prevPage + 1;
+ if (direction === 'prev' && prevPage > 1) return prevPage - 1;
+ return prevPage;
+ });
+ };
+
+ return { page, dashboards, totalPages, handlePageChange };
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/_utils/axiosInstance.ts b/src/app/(with-header-sidebar)/mydashboard/_lib/axiosInstance.ts
similarity index 79%
rename from src/app/(with-header-sidebar)/mydashboard/_utils/axiosInstance.ts
rename to src/app/(with-header-sidebar)/mydashboard/_lib/axiosInstance.ts
index 858fb8c..0ab2c3a 100644
--- a/src/app/(with-header-sidebar)/mydashboard/_utils/axiosInstance.ts
+++ b/src/app/(with-header-sidebar)/mydashboard/_lib/axiosInstance.ts
@@ -1,4 +1,4 @@
-import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
+import axios, { AxiosInstance } from 'axios';
import { BASE_URL } from '@/constants/urls';
const axiosInstance: AxiosInstance = axios.create({
@@ -24,10 +24,4 @@ axiosInstance.interceptors.request.use(
}
);
-export const apiCall = async (
- config: AxiosRequestConfig
-): Promise> => {
- return axiosInstance.request(config);
-};
-
export default axiosInstance;
diff --git a/src/app/(with-header-sidebar)/mydashboard/_lib/dashboardsApi.ts b/src/app/(with-header-sidebar)/mydashboard/_lib/dashboardsApi.ts
new file mode 100644
index 0000000..981abbe
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/_lib/dashboardsApi.ts
@@ -0,0 +1,21 @@
+import axiosInstance from './axiosInstance';
+import { GetDashboardsRequestParams } from '../_types/dashboards';
+
+export const dashboardsApi = {
+ // getMyDashboards: (params: GetDashboardsRequestParams) =>
+ // axiosInstance.get('/dashboards'),
+ // upcoming: () => axiosInstance.get('movie/upcoming'),
+
+ getMyDashboards: (params: GetDashboardsRequestParams) =>
+ axiosInstance.get('/dashboards', {
+ params,
+ }),
+
+ // 첫번째 인자 url 두번째에 쿼리 prams를 넘겨준다.
+ // searchMovie: (terms) =>
+ // axiosInstance.get(`search/movie`, {
+ // params: {
+ // query: terms,
+ // },
+ // }),
+};
diff --git a/src/app/(with-header-sidebar)/mydashboard/page.module.css b/src/app/(with-header-sidebar)/mydashboard/page.module.css
new file mode 100644
index 0000000..38f72a7
--- /dev/null
+++ b/src/app/(with-header-sidebar)/mydashboard/page.module.css
@@ -0,0 +1,5 @@
+.mydashboard {
+ height: 100%;
+ background: var(--gray-100);
+ padding: 20px 24px;
+}
diff --git a/src/app/(with-header-sidebar)/mydashboard/page.tsx b/src/app/(with-header-sidebar)/mydashboard/page.tsx
index 6540575..4c4304e 100644
--- a/src/app/(with-header-sidebar)/mydashboard/page.tsx
+++ b/src/app/(with-header-sidebar)/mydashboard/page.tsx
@@ -1,3 +1,12 @@
+import Dashboards from './_components/dashboards/Dashboards';
+import Invitations from './_components/invitations/Invitations';
+import styles from './page.module.css';
+
export default function Page() {
- return my page
;
+ return (
+
+
+
+
+ );
}
diff --git a/src/components/MainContainer.module.css b/src/components/MainContainer.module.css
index e69de29..d466598 100644
--- a/src/components/MainContainer.module.css
+++ b/src/components/MainContainer.module.css
@@ -0,0 +1,3 @@
+.main {
+ height: 100%;
+}
diff --git a/src/components/MainContainer.tsx b/src/components/MainContainer.tsx
index edf065c..5b4e4d3 100644
--- a/src/components/MainContainer.tsx
+++ b/src/components/MainContainer.tsx
@@ -6,7 +6,7 @@ export default function MainContainer({ children }: { children: ReactNode }) {
return (
<>
- {children}
+ {children}
>
);
}
diff --git a/src/components/header/Header.module.css b/src/components/header/Header.module.css
index d801a97..6f3a97d 100644
--- a/src/components/header/Header.module.css
+++ b/src/components/header/Header.module.css
@@ -21,7 +21,7 @@
gap: 6px;
}
-.button {
+.button.button {
padding: 6px 12px;
display: flex;
align-items: center;
@@ -32,6 +32,11 @@
color: var(--gray-500);
font-size: 14px;
font-weight: 500;
+ transition: background-color 0.3s ease;
+}
+
+.button.button:hover {
+ background-color: var(--violet-light);
}
.icon {
@@ -72,6 +77,7 @@
display: flex;
flex-direction: column;
gap: 5px;
+ background: var(--white);
}
.myMenu div {
@@ -81,7 +87,7 @@
.myMenu div:hover {
cursor: pointer;
- background: var(--gray-200);
+ background: var(--violet-light);
}
@media screen and (min-width: 768px) {
diff --git a/src/components/sidebar/Dashboards.module.css b/src/components/sidebar/Dashboards.module.css
index 9a5290c..d30729a 100644
--- a/src/components/sidebar/Dashboards.module.css
+++ b/src/components/sidebar/Dashboards.module.css
@@ -32,21 +32,27 @@
font-weight: 500;
}
-.arrowLeft,
-.arrowRight {
+.arrowLeft.arrowLeft,
+.arrowRight.arrowRight {
border: 1px solid var(--gray-300);
border-right: none;
border-radius: 0;
background: var(--white);
height: 35px;
+ transition: background-color 0.3s ease;
}
-.arrowRight {
+.arrowRight.arrowRight {
border-top: none;
}
-.arrowLeft:disabled,
-.arrowRight:disabled {
+.arrowLeft.arrowLeft:hover,
+.arrowRight.arrowRight:hover {
+ background-color: var(--violet-light);
+}
+
+.arrowLeft.arrowLeft:disabled,
+.arrowRight.arrowRight:disabled {
background: var(--white);
}
@@ -55,7 +61,12 @@
margin-top: 10px;
display: flex;
flex-direction: column;
- gap: 15px;
+ }
+
+ .titleContainer {
+ justify-content: flex-start;
+ gap: 16px;
+ padding: 20px 10px;
}
.title,
@@ -67,28 +78,22 @@
margin-left: -8px;
}
- .titleContainer {
- justify-content: flex-start;
- gap: 16px;
- padding: 8px 10px;
- }
-
.arrowWrapper {
margin-top: 20px;
}
- .arrowLeft,
- .arrowRight {
+ .arrowLeft.arrowLeft,
+ .arrowRight.arrowRight {
border: 1px solid var(--gray-300);
width: 40px;
height: 40px;
}
- .arrowLeft {
+ .arrowLeft.arrowLeft {
border-radius: 4px 0px 0px 4px;
}
- .arrowRight {
+ .arrowRight.arrowRight {
border-radius: 0px 4px 4px 0px;
}
}
diff --git a/src/components/sidebar/Dashboards.tsx b/src/components/sidebar/Dashboards.tsx
index c028efc..7e359f6 100644
--- a/src/components/sidebar/Dashboards.tsx
+++ b/src/components/sidebar/Dashboards.tsx
@@ -1,35 +1,21 @@
import Link from 'next/link';
import { usePathname } from 'next/navigation';
-import type {
- Dashboard,
- GetDashboardsResponse,
-} from '@/app/(with-header-sidebar)/mydashboard/_types/dashboards';
-import useApi from '@/app/(with-header-sidebar)/mydashboard/_hooks/useApi';
+import type { Dashboard } from '@/app/(with-header-sidebar)/mydashboard/_types/dashboards';
import Image from 'next/image';
import Button from '../Button';
-import { useState } from 'react';
import styles from './Dashboards.module.css';
+import useDashboards from '@/app/(with-header-sidebar)/mydashboard/_hooks/useDashboards';
const PAGE_SIZE = 12;
export default function Dashboards() {
- const [page, setPage] = useState(1);
- const { data } = useApi('/dashboards', {
- method: 'GET',
- params: { navigationMethod: 'pagination', page, size: PAGE_SIZE },
+ const { page, dashboards, totalPages, handlePageChange } = useDashboards({
+ pageSize: PAGE_SIZE,
});
- const dashboards = data?.dashboards ?? [];
- const totalCount = data?.totalCount ?? 0;
- const totalPages = Math.ceil(totalCount / PAGE_SIZE);
-
- const handlePageChange = (direction: 'next' | 'prev') => {
- setPage((prevPage) => {
- if (direction === 'next' && prevPage < totalPages) return prevPage + 1;
- if (direction === 'prev' && prevPage > 1) return prevPage - 1;
- return prevPage;
- });
- };
+ if (dashboards.length === 0) {
+ return null;
+ }
return (
diff --git a/src/components/sidebar/SideBar.module.css b/src/components/sidebar/SideBar.module.css
index 5fa9178..f54fec4 100644
--- a/src/components/sidebar/SideBar.module.css
+++ b/src/components/sidebar/SideBar.module.css
@@ -5,7 +5,7 @@
gap: 15px;
}
-.logo {
+.logo.logo {
background-color: transparent;
padding-top: 22px;
margin-bottom: 10px;
@@ -20,7 +20,7 @@
display: none;
}
-.addButton {
+.addButton.addButton {
background-color: transparent;
width: 20px;
}