Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notice 페이지 API 연동 및 컴포넌트 교체 #284

Merged
merged 6 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from 4 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
292 changes: 164 additions & 128 deletions public/sw.js
Copy link
Contributor

Choose a reason for hiding this comment

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

📌 public 안에있는 변경사항 파일은 PR에 포함되는 파일일까요?!

Large diffs are not rendered by default.

201 changes: 102 additions & 99 deletions public/workbox-c95f9b89.js → public/workbox-1bb06f5e.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/app/_api/notice/getNotices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axiosInstance from '@/lib/axios/axiosInstance';
import { NoticeListItemType } from '@/lib/types/noticeType';

const getNotices = async () => {
const result = await axiosInstance.get<NoticeListItemType[]>('/admin/notices');

return result.data;
};

export default getNotices;
Copy link
Contributor

Choose a reason for hiding this comment

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

나현님, 해당 API 엔드포인트는 어드민 공지 조회로 보이는데 API가 잘못 연결된게 맞을까요?
어드민, 사용자에 따라 필요한 필드가 다르기 때문에 사용자용 공지 조회는 GET "/notices"를 사용하는 것으로 알고있습니다~! 참고로 어드민은 공개, 비공개에 상관없이 모든 게시물이 노출됩니다!

File renamed without changes.
18 changes: 14 additions & 4 deletions src/app/notices/NoticeList.tsx → src/app/notice/NoticeList.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
'use client';

import Image from 'next/image';
import { useQuery } from '@tanstack/react-query';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import getNotices from '../_api/notice/getNotices';

import { NoticeListItemType } from '@/lib/types/noticeType';
import { NOTICE_LIST_MOCKDATA } from './mockdata';

import * as styles from './NoticeList.css';
import Link from 'next/link';

function NoticeList() {
const { data: notices } = useQuery<NoticeListItemType[]>({
queryKey: [QUERY_KEYS.getAllNotices],
queryFn: getNotices,
staleTime: 1000 * 60 * 30,
});
Comment on lines +14 to +18
Copy link
Contributor

Choose a reason for hiding this comment

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

한가지 궁금한점이 NoticeListItemType 타입은 itemImageUrl 필드를 가지고 있는데, 해당 필드는 게시물을 생성할 때 콘텐츠블록에 이미지 블록을 의미하는 것이 맞을까요? 아니면 대표 이미지가 있는 것인지 해당 이미지가 UI상 노출되는 부분을 확인할 수 없어서 여쭤봅니다~!


return (
<ul className={styles.noticeListWrapper}>
{NOTICE_LIST_MOCKDATA?.map((item: NoticeListItemType) => (
<li key={item.id}>
{notices?.map((item: NoticeListItemType, index) => (
<li key={index}>
<NoticeListItem item={item} />
Copy link
Contributor

Choose a reason for hiding this comment

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

key를 index로 하신 이유가 있을까요?! 👀 사용자만큼은 아니지만 게시물도 생성 및 수정이 빈번하게 될 수 있기 때문에 id를 key값으로 지정하는 것이 더 안전해보입니다!

</li>
))}
Expand All @@ -26,7 +36,7 @@ interface NoticeListItemProps {

function NoticeListItem({ item }: NoticeListItemProps) {
return (
<Link href={`/notices/${item.id}`} className={styles.listItemWrapper}>
<Link href={`/notice/${item.id}`} className={styles.listItemWrapper}>
<div>
<h3 className={styles.noticeTitle}>{item.title}</h3>
<p className={styles.noticeDescription}>{item.description}</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ export const category = style({
borderRadius: '16px',
});

export const header = style({
padding: '10px 16px 0',

backgroundColor: vars.color.blue,
});

export const back = style({
fontSize: '1.4rem',
color: vars.color.lightgray,
cursor: 'pointer',
});

export const title = style({
marginTop: '14px',
marginBottom: '11px',
Expand Down
70 changes: 70 additions & 0 deletions src/app/notice/[noticeId]/NoticeDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use client';

import Link from 'next/link';
import { useQuery } from '@tanstack/react-query';
import { usePathname } from 'next/navigation';
import { useRouter } from 'next/navigation';

import getNoticeDetail from '@/app/_api/notice/getNoticeDetail';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import { NoticeDetailType } from '@/lib/types/noticeType';

import * as styles from './NoticeDetail.css';
import NoticeDetailInfo from '@/components/NoticeDetail/NoticeDetailInfo';

function NoticeDetailComponent() {
const pathname = usePathname();
const noticeId = pathname?.split('/').pop();
const noticeIdNumber = noticeId ? Number(noticeId) : null;
const router = useRouter();

const {
data: notice,
isLoading,
isError,
} = useQuery<NoticeDetailType>({
queryKey: [QUERY_KEYS.getNoticeDetail, noticeIdNumber],
queryFn: () => getNoticeDetail(noticeIdNumber as number),
enabled: noticeIdNumber !== null, // noticeIdNumber가 유효한 경우에만 실행
});
Copy link
Contributor

Choose a reason for hiding this comment

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

나현님, Next.js의 Dynamic Routes의 경우에는 라우트(경로) 파라미터(slug)를 params라는 props로 받아올 수 있습니다~!
이 방법을 사용하면 path를 얻기위해 use client를 사용하지 않아도 되고, 따로 가공하지 않아도 되므로 코드를 간결하게 유지할 수 있다는 장점이 있습니다.

function NoticeDetailComponent({ params }: { params: { noticeId: number } }) {
  const noticeId = params.noticeId;
  
  // useQuery
  enabled: !!noticeId,

 ...


if (!notice) {
return null;
}

return (
<>
<div className={styles.header}>
<span className={styles.back} onClick={() => router.back()}>
뒤로가기
</span>
</div>
<NoticeDetailInfo noticeData={notice} />
<section className={styles.signPostWrapper}>
{notice?.prevNotice && (
<Link href={`/notice/${notice?.prevNotice.id}`}>
<div className={styles.listItemWrapper}>
<div className={styles.sign}>이전글</div>
<div className={styles.noticeTitle}>{notice?.prevNotice?.title}</div>
<p className={styles.noticeDescription}>{notice?.prevNotice?.description}</p>
</div>
</Link>
)}
{notice?.nextNotice && (
<Link href={`/notice/${notice?.nextNotice.id}`}>
<div className={styles.listItemWrapper}>
<div className={styles.sign}>다음글</div>
<div className={styles.noticeTitle}>{notice?.nextNotice?.title}</div>
<p className={styles.noticeDescription}>{notice?.nextNotice?.description}</p>
</div>
</Link>
)}
<Link href={'/notice'}>
<button className={styles.link}>목록보기</button>
</Link>
</section>
</>
);
}

export default NoticeDetailComponent;
File renamed without changes.
Copy link
Contributor

Choose a reason for hiding this comment

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

📌 사용하지 않는 목업데이터는 삭제하면 좋을 것 같아요~!

File renamed without changes.
Copy link
Contributor

Choose a reason for hiding this comment

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

📌

File renamed without changes.
2 changes: 2 additions & 0 deletions src/app/notices/page.tsx → src/app/notice/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import NoticeList from './NoticeList';
import Header from '@/components/Header/Header';

function NoticePage() {
return (
<section>
<Header title={'게시판'} left={'back'} />
<NoticeList />
</section>
);
Expand Down
75 changes: 0 additions & 75 deletions src/app/notices/[noticeId]/NoticeDetail.tsx

This file was deleted.

29 changes: 0 additions & 29 deletions src/app/notices/layout.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/NoticeDetail/NoticeDetailInfo.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const created = style({
});

export const contents = style({
paddingTop: '2rem',
padding: '2rem 1.6rem 0 1.6rem',

Comment on lines 50 to 52
Copy link
Contributor

Choose a reason for hiding this comment

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

(의견) 나현님, 이 부분은 contents 자체에 패딩을 주기 보다는 NoticeDetailInfo 컴포넌트를 사용하는 곳에 div태그로 감싸고 여기에 패딩을 주면 어떨까요?!

display: 'flex',
flexDirection: 'column',
Expand Down
1 change: 1 addition & 0 deletions src/lib/constants/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const QUERY_KEYS = {
getAdminAllNotice: 'getAdminAllNotice',

// 공지
getAllNotices: 'getAllNotices',
getNoticeCategories: 'getNoticeCategories',
getNoticeDetail: 'getNoticeDetail',
};
Loading