[as] feat: 대시보드 공지사항 섹션 구현
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
| 항목 | 내용 |
|
||||
| ---------- | -------------------------------------------- |
|
||||
| 버전 | 1.1 |
|
||||
| 버전 | 1.2 |
|
||||
| 프로세스명 | UI설계 |
|
||||
| 화면명 | 전국 행정지원 지도 (대시보드 메인) |
|
||||
| 화면 ID | TBD |
|
||||
@@ -37,9 +37,9 @@
|
||||
│ │ └───────────────┘ └───────────────┘ │
|
||||
│ ├─────────────────────────────────────────────────┤
|
||||
│ │ [영역 C] 알림이력 │
|
||||
│ │ 알림이력 업데이트 HH:mm [전체보기] │
|
||||
│ │ 알림이력 업데이트 HH:mm [전체보기]│
|
||||
│ │ [오늘 N건] [지연 N건] [완료대기 N건] │
|
||||
│ │ [뱃지] [일자] 제목 [처리하기] │
|
||||
│ │ [뱃지] [일자] 제목 [처리하기]│
|
||||
│ │ … (최대 5건) │
|
||||
│ ├─────────────────────────────────────────────────┤
|
||||
│ │ [영역 D] 공지사항 [더보기] │
|
||||
@@ -60,7 +60,7 @@ BEGIN
|
||||
DISPLAY 진행상황 카드 (영역 B) // docPrgrsSttsList, TOTAL 행 제외
|
||||
DISPLAY 알림 통계 칩 · 알림 목록 (영역 C) // notiStats, notiList
|
||||
|
||||
CALL 공지사항 목록조회(…) // TBD — 대시보드 API에 없음
|
||||
CALL getUserPostList(UserPostSearchParams) // board-service, AS_DASHBOARD_BBS_ID
|
||||
DISPLAY 공지사항 그리드 (영역 D)
|
||||
|
||||
CALL 지도 마커/음영 조회(…) // TBD — 대시보드 API에 없음
|
||||
@@ -77,11 +77,11 @@ BEGIN
|
||||
END ON
|
||||
|
||||
ON 영역 D [더보기] 버튼 CLICK DO
|
||||
NAVIGATE 공지사항 목록 // TBD
|
||||
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID} // as 앱 공지 목록 라우트 미구현. st/cm 관례
|
||||
END ON
|
||||
|
||||
ON 영역 D 행 CLICK DO
|
||||
NAVIGATE 공지사항 상세 // TBD
|
||||
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}
|
||||
END ON
|
||||
|
||||
ON 영역 B 카드 CLICK DO
|
||||
@@ -165,12 +165,12 @@ END
|
||||
|
||||
카드 클릭 시 **해당 문서 목록 페이지**로 이동한다. `docSeComCd` → 라우트 고정 매핑.
|
||||
|
||||
| 동작 | `docSeComCd` | 이동 경로 |
|
||||
| --------- | ------------ | ------------------- |
|
||||
| 카드 클릭 | `FNRS` | `/fnrs-cnsltn` |
|
||||
| 카드 클릭 | `INSTL` | `/instl-sncn` |
|
||||
| 카드 클릭 | `CNFM` | `/design-cnstn` |
|
||||
| 카드 클릭 | `SEWER` | `/sewer-bsc-plan` |
|
||||
| 동작 | `docSeComCd` | 이동 경로 |
|
||||
| --------- | ------------ | ----------------- |
|
||||
| 카드 클릭 | `FNRS` | `/fnrs-cnsltn` |
|
||||
| 카드 클릭 | `INSTL` | `/instl-sncn` |
|
||||
| 카드 클릭 | `CNFM` | `/design-cnstn` |
|
||||
| 카드 클릭 | `SEWER` | `/sewer-bsc-plan` |
|
||||
|
||||
---
|
||||
|
||||
@@ -180,11 +180,11 @@ END
|
||||
|
||||
### 6-1. 헤더
|
||||
|
||||
| 표시명 | Field / 소스 | 비고 |
|
||||
| ------------- | ------------ | --------------------------------------------------------------------------------- |
|
||||
| 섹션 타이틀 | — | 고정 문구 `알림이력` |
|
||||
| 표시명 | Field / 소스 | 비고 |
|
||||
| ------------- | ------------ | --------------------------------------------------------------------------------------- |
|
||||
| 섹션 타이틀 | — | 고정 문구 `알림이력` |
|
||||
| 업데이트 시각 | (client) | 스크린샷 `업데이트 10:32`. API 필드 없음. `getMainDashboard` 마지막 fetch 시각(`HH:mm`) |
|
||||
| 전체보기 | Button | `/nti-hstry`로 이동 |
|
||||
| 전체보기 | Button | `/nti-hstry`로 이동 |
|
||||
|
||||
### 6-2. 통계 칩
|
||||
|
||||
@@ -247,33 +247,48 @@ END
|
||||
|
||||
## 7. 영역 D — 공지사항
|
||||
|
||||
`getMainDashboard`에 공지 필드가 없다. 목록·더보기 API·라우트는 **TBD**. as 앱에 board-service 엔티티 없음.
|
||||
`getMainDashboard`에 공지 필드는 없다. **board-service** `getUserPostList`로 별도 조회한다.
|
||||
|
||||
- Base: `GET /board-service/api/v1/posts/user/{AS_DASHBOARD_BBS_ID}`
|
||||
- `AS_DASHBOARD_BBS_ID` = `NEXT_PUBLIC_AS_DASHBOARD_BBS_ID` (로컬 예: `7`)
|
||||
- 클라이언트: `@/entities/board` — `postApi.getUserPostList` / `useUserPostList`
|
||||
|
||||
페이지네이션 컨트롤은 없다. 요약 목록만 표시한다 (`page=0`, `size=3`).
|
||||
|
||||
### 7-1. 헤더·버튼
|
||||
|
||||
| 버튼명 | 동작 |
|
||||
| ------ | -------------------------------- |
|
||||
| 더보기 | 공지사항 목록으로 이동. 경로 TBD |
|
||||
| 버튼명 | 동작 |
|
||||
| ------ | ------------------------------------------------------------------------------------------- |
|
||||
| 더보기 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}` 로 이동. as 앱에 공지 목록 라우트는 없음(st/cm 관례) |
|
||||
|
||||
### 7-2. 그리드 컬럼
|
||||
|
||||
스크린샷 헤더 순서.
|
||||
스크린샷 헤더 순서. `UserPost`.
|
||||
|
||||
| 표시명 | Field | 비고 |
|
||||
| ------ | ----- | ------------------------------------------------------ |
|
||||
| 번호 | TBD | 고정글은 `[공지]` 뱃지, 그 외 순번. 고정 여부 필드 TBD |
|
||||
| 제목 | TBD | 예: `2024년 시스템 업데이트 공지사항` |
|
||||
| 작성자 | TBD | 예: `관리자`, `시스템관리자` |
|
||||
| 작성일 | TBD | 표시 `YYYY-MM-DD` |
|
||||
| 조회수 | TBD | 숫자 |
|
||||
| 표시명 | Field | 비고 |
|
||||
| ------ | --------- | ---------------------------------------------------- |
|
||||
| 번호 | `rowNo` | `upndFixYn` = `Y` 이면 `[공지]` Badge, 그 외 `rowNo` |
|
||||
| 제목 | `pstTtl` | truncate |
|
||||
| 작성자 | `wrtrNm` | |
|
||||
| 작성일 | `regDt` | 표시 `YYYY-MM-DD` (응답 datetime) |
|
||||
| 조회수 | `inqNocs` | 숫자 |
|
||||
|
||||
페이지네이션 없음 (대시보드 요약, 건수 TBD).
|
||||
조회 파라미터 (`UserPostSearchParams`):
|
||||
|
||||
| 필드 | 값 | 비고 |
|
||||
| ------------- | ----------- | ------------------------------------------ |
|
||||
| `page` | `0` | Spring 0-based |
|
||||
| `size` | `3` | 대시보드 요약. 스크린샷 3행 |
|
||||
| `keywordType` | `bbsTypeCd` | st 대시보드 공지 패널과 동일 |
|
||||
| `keyword` | `BBSNOTICE` | 게시판 유형. path의 bbsId와 함께 공지 한정 |
|
||||
|
||||
응답에 있으나 그리드에 **표시하지 않음**: `bbsId`, `pstNo`(행 키·상세 이동), `pstCn`, `upndFixYn`(번호 열 판정만), `rgtrNm`, `atflCd` 등.
|
||||
|
||||
### 7-3. 행 상호작용
|
||||
|
||||
| 동작 | 설명 |
|
||||
| ------- | ------------------------ |
|
||||
| 행 클릭 | 공지 상세 이동. 경로 TBD |
|
||||
| 동작 | 설명 |
|
||||
| ------- | ------------------------------------------------------------------------------ |
|
||||
| 행 클릭 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}` (as 앱 공지 상세 라우트 미구현) |
|
||||
|
||||
---
|
||||
|
||||
@@ -287,8 +302,9 @@ END
|
||||
| 인증 | `Authorization` 헤더. 프론트는 `client` 인터셉터. 로그인 기관 권한은 서버가 사용자 캐시로 적용 |
|
||||
| 클라이언트 모듈 | `@/entities/dashboard` — `dashboardService` / `useGetMainDashboard` |
|
||||
| 알림 읽음 | `@/entities/noti` — `notiService.readNoti` / `useReadNoti` |
|
||||
| 공지사항 | `@/entities/board` — `postApi.getUserPostList` / `useUserPostList` |
|
||||
|
||||
영역 A(지도)·영역 D(공지)는 본 컨트롤러 범위 밖 → **TBD**.
|
||||
영역 A(지도)는 본 컨트롤러·board-service 범위 밖 → **TBD**.
|
||||
|
||||
### 8-2. 대시보드 메인 조회 — `getMainDashboard`
|
||||
|
||||
@@ -354,11 +370,36 @@ Body 없음. 성공 시 `dashboardBaseKey`(및 필요 시 `notiBaseKey`) invalid
|
||||
| ------------------- | ------ | --- | ----------- | ------------ | --- |
|
||||
| 지도 마커·음영 조회 | TBD | TBD | TBD | TBD | TBD |
|
||||
|
||||
### 8-5. 공지사항 — TBD
|
||||
### 8-5. 공지사항 — `getUserPostList`
|
||||
|
||||
| 기능 | Method | URL | Request DTO | Response DTO | API |
|
||||
| ----------------------- | ------ | --- | ----------- | ------------ | --- |
|
||||
| 대시보드 공지 요약 목록 | TBD | TBD | TBD | TBD | TBD |
|
||||
board-service. bbsId는 환경변수 `AS_DASHBOARD_BBS_ID`로 path에 고정한다.
|
||||
|
||||
| 기능 | Method | URL | Request DTO | Response DTO | API |
|
||||
| ----------------------- | ------ | ------------------------------------------ | ----------------------------- | ------------------------ | --------------------------------------------- |
|
||||
| 대시보드 공지 요약 목록 | GET | `/board-service/api/v1/posts/user/{bbsId}` | Query: `UserPostSearchParams` | `PageResponse<UserPost>` | `postApi.getUserPostList` / `useUserPostList` |
|
||||
|
||||
**Request (`UserPostSearchParams`)** — 본 화면 고정값
|
||||
|
||||
| 필드 | 필수 | 설명 |
|
||||
| ------------- | ---- | -------------- |
|
||||
| `page` | N | `0` |
|
||||
| `size` | N | `3` |
|
||||
| `keywordType` | N | `bbsTypeCd` |
|
||||
| `keyword` | N | `BBSNOTICE` |
|
||||
| `popupYn` 등 | N | 본 화면 미사용 |
|
||||
|
||||
**Response (`UserPost`) — 화면 매핑 필드**
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
| ----------- | ------ | --------------------------- |
|
||||
| `rowNo` | number | 번호. 고정글이 아니면 표시 |
|
||||
| `pstNo` | number | 게시 번호. 상세 이동 키 |
|
||||
| `bbsId` | number | 게시판 ID |
|
||||
| `pstTtl` | string | 제목 |
|
||||
| `wrtrNm` | string | 작성자 |
|
||||
| `regDt` | string | 작성일 |
|
||||
| `inqNocs` | number | 조회수 |
|
||||
| `upndFixYn` | string | 상단고정 `Y`/`N` → `[공지]` |
|
||||
|
||||
---
|
||||
|
||||
@@ -368,47 +409,50 @@ Body 없음. 성공 시 `dashboardBaseKey`(및 필요 시 `notiBaseKey`) invalid
|
||||
|
||||
- 라우트: 기존 홈 `app/(main)/(with-base-layout)/page.tsx` → `pages/home` (현재 `MainPage` 플레이스홀더)
|
||||
- UI: `@common/components` — Card, Badge, Button, Table(공지). 지도 라이브러리 TBD
|
||||
- 데이터: React Query `useGetMainDashboard()`. 처리하기는 `useReadNoti()`
|
||||
- 데이터: React Query `useGetMainDashboard()`. 처리하기는 `useReadNoti()`. 공지는 `useUserPostList()`
|
||||
- 진행상황 카드: `docSeComCd`로 4슬롯 매핑. `TOTAL` 제외
|
||||
- 알림 목록: 테이블이 아닌 행 리스트(뱃지 + 일자 + 제목 + 버튼)
|
||||
- 공지: 컬럼 확정 후 `@tanstack/react-table` 또는 단순 Table. 페이지네이션 없음
|
||||
- 공지: `@tanstack/react-table` + `useDataTable`, 페이지네이션 없음
|
||||
- 검색 조건 URL 동기화: 본 화면 필터 없음. `searchYear` UI가 생기면 그때 검토
|
||||
|
||||
### 9-2. 모듈·파일 배치
|
||||
|
||||
| 구분 | 경로 |
|
||||
| ------------- | ----------------------------------------------------------- |
|
||||
| 라우트 | `app/(main)/(with-base-layout)/page.tsx` |
|
||||
| 페이지 | `pages/home/ui/main-page.tsx` |
|
||||
| 지도 | `pages/home/ui/national-as-map.tsx` (신규, API TBD) |
|
||||
| 진행상황 카드 | `pages/home/ui/doc-prgrs-stts-cards.tsx` (신규) |
|
||||
| 알림이력 | `pages/home/ui/dashboard-noti-list.tsx` (신규) |
|
||||
| 공지사항 | `pages/home/ui/dashboard-notice-table.tsx` (신규, API TBD) |
|
||||
| Entity API | `entities/dashboard/api/dashboard-service.ts` |
|
||||
| Entity Hook | `entities/dashboard/api/queries.ts` → `useGetMainDashboard` |
|
||||
| Entity Model | `entities/dashboard/model/dashboard-interface.ts` |
|
||||
| 알림 읽음 | `entities/noti` → `useReadNoti` |
|
||||
| 구분 | 경로 |
|
||||
| ------------- | ------------------------------------------------------------ |
|
||||
| 라우트 | `app/(main)/(with-base-layout)/page.tsx` |
|
||||
| 페이지 | `pages/dashboard/ui/dashboard-page.tsx` |
|
||||
| 지도 | `pages/dashboard/ui/national-as-map.tsx` (API TBD, Skeleton) |
|
||||
| 진행상황 카드 | `pages/dashboard/ui/doc-prgrs-stts-cards.tsx` |
|
||||
| 알림이력 | `pages/dashboard/ui/dashboard-noti-list.tsx` |
|
||||
| 공지사항 | `pages/dashboard/ui/dashboard-notice-table.tsx` |
|
||||
| 공지 컬럼 | `pages/dashboard/model/dashboard-notice-table-columns.tsx` |
|
||||
| Entity API | `entities/dashboard/api/dashboard-service.ts` |
|
||||
| Entity Hook | `entities/dashboard/api/queries.ts` → `useGetMainDashboard` |
|
||||
| Entity Model | `entities/dashboard/model/dashboard-interface.ts` |
|
||||
| 알림 읽음 | `entities/noti` → `useReadNoti` |
|
||||
| 공지 Entity | `entities/board` → `useUserPostList` |
|
||||
|
||||
Entity(`getMainDashboard`) 구현됨. 영역 B·C 화면 구현. 영역 A·D는 Skeleton.
|
||||
Entity(`getMainDashboard`, `getUserPostList`) 구현됨. 영역 B·C·D 화면 구현. 영역 A는 Skeleton.
|
||||
|
||||
### 9-3. 영역별 UI 매핑
|
||||
|
||||
| 영역 | 컴포넌트 | 데이터 |
|
||||
| ---- | ------------------------ | -------------------------------------------------------------------- |
|
||||
| A | `national-as-map` | Skeleton (지도 API TBD) |
|
||||
| B | `doc-prgrs-stts-cards` | `useGetMainDashboard` → `docPrgrsSttsList` (`TOTAL` 제외, 코드 매핑) |
|
||||
| 영역 | 컴포넌트 | 데이터 |
|
||||
| ---- | ------------------------ | ---------------------------------------------------------------------------- |
|
||||
| A | `national-as-map` | Skeleton (지도 API TBD) |
|
||||
| B | `doc-prgrs-stts-cards` | `useGetMainDashboard` → `docPrgrsSttsList` (`TOTAL` 제외, 코드 매핑) |
|
||||
| C | `dashboard-noti-list` | 동 훅 → `notiStats`, `notiList`. 처리 → `useReadNoti`. 전체보기 `/nti-hstry` |
|
||||
| D | `dashboard-notice-table` | Skeleton (공지 API TBD) |
|
||||
| D | `dashboard-notice-table` | `useUserPostList` → `content[]`. [더보기]·행 클릭 → `/cms/bbsnotice/...` |
|
||||
|
||||
### 9-4. 다이얼로그·라우팅
|
||||
|
||||
| 항목 | 내용 |
|
||||
| -------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| 다이얼로그 | 없음 |
|
||||
| 본 화면 라우트 | `/` (홈) |
|
||||
| 항목 | 내용 |
|
||||
| -------------- | -------------------------------------------------------------------------------------- |
|
||||
| 다이얼로그 | 없음 |
|
||||
| 본 화면 라우트 | `/` (홈) |
|
||||
| 알림 처리 이동 | [처리하기] → `readNoti` 후 `notiUrl` (알림이력과 동일, SEWER URL은 상세 세그먼트 제거) |
|
||||
| 알림 전체보기 | `/nti-hstry` |
|
||||
| 공지 더보기 | TBD |
|
||||
| 알림 전체보기 | `/nti-hstry` |
|
||||
| 공지 더보기 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}` (as 앱 공지 라우트 미구현, st/cm 관례) |
|
||||
| 공지 행 클릭 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}` |
|
||||
| 진행상황 카드 | §5-3 목록 라우트 (`/fnrs-cnsltn`, `/instl-sncn`, `/design-cnstn`, `/sewer-bsc-plan`) |
|
||||
|
||||
### 9-5. 데이터 흐름
|
||||
@@ -421,7 +465,9 @@ BEGIN
|
||||
DISPLAY 영역 B // docPrgrsSttsList — FNRS/INSTL/CNFM/SEWER 슬롯
|
||||
DISPLAY 영역 C // notiStats + notiList(≤5)
|
||||
|
||||
CALL 공지 목록 // TBD → 영역 D
|
||||
CALL getUserPostList({ page: 0, size: 3, keywordType: "bbsTypeCd", keyword: "BBSNOTICE" })
|
||||
DISPLAY 영역 D
|
||||
|
||||
CALL 지도 데이터 // TBD → 영역 A
|
||||
|
||||
ON 영역 C [전체보기] CLICK DO
|
||||
@@ -441,7 +487,11 @@ BEGIN
|
||||
END ON
|
||||
|
||||
ON 영역 D [더보기] CLICK DO
|
||||
NAVIGATE 공지 목록 // TBD
|
||||
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID}
|
||||
END ON
|
||||
|
||||
ON 영역 D 행 CLICK DO
|
||||
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}
|
||||
END ON
|
||||
|
||||
END
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const subDomain = process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
reactStrictMode: true,
|
||||
@@ -7,6 +9,31 @@ const nextConfig: NextConfig = {
|
||||
experimental: {
|
||||
globalNotFound: true,
|
||||
},
|
||||
|
||||
async rewrites() {
|
||||
return {
|
||||
beforeFiles: [
|
||||
{
|
||||
source: "/_next/static/:path*",
|
||||
destination: `${subDomain}/_next/static/:path*`,
|
||||
has: [
|
||||
{
|
||||
type: "header",
|
||||
key: "referer",
|
||||
value: "(.*)/cms(.*)",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
afterFiles: [
|
||||
{
|
||||
source: "/cms/:path*",
|
||||
destination: `${subDomain}/cms/:path*`,
|
||||
},
|
||||
],
|
||||
fallback: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
import type { UserPostSearchParams } from "../model/post-interface";
|
||||
|
||||
import { postApi } from "./post-service";
|
||||
|
||||
export function useUserPostList(params?: UserPostSearchParams) {
|
||||
return useQuery({
|
||||
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS, params],
|
||||
queryFn: () => postApi.getUserPostList(params),
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { AS_DASHBOARD_BBS_ID, ENDPOINT } from "@/shared/config";
|
||||
|
||||
import { PostService, UserPostListResponse, UserPostSearchParams } from "../model/post-interface";
|
||||
|
||||
async function getUserPostList(params?: UserPostSearchParams): Promise<UserPostListResponse> {
|
||||
const response = await client.get<UserPostListResponse>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}/user/${AS_DASHBOARD_BBS_ID}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export const postApi: PostService = {
|
||||
getUserPostList,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
export { useUserPostList } from "./api/post-queries";
|
||||
export { postApi } from "./api/post-service";
|
||||
export type {
|
||||
PostService,
|
||||
UserPost,
|
||||
UserPostListResponse,
|
||||
UserPostSearchParams,
|
||||
} from "./model/post-interface";
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { PageableParams, PageResponse } from "@/shared/model";
|
||||
|
||||
export interface UserPostSearchParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
popupYn?: string;
|
||||
upndFixYn?: string;
|
||||
prdPstgYn?: string;
|
||||
siteId?: string;
|
||||
bbsTypeCd?: string;
|
||||
ansUseYn?: string;
|
||||
}
|
||||
|
||||
export interface UserPost {
|
||||
rowNo: number;
|
||||
bbsId: number;
|
||||
pstNo: number;
|
||||
pstTtl: string;
|
||||
pstCn: string;
|
||||
inqNocs: number;
|
||||
rfrncUrl: string;
|
||||
popupYn: string;
|
||||
upndFixYn: string;
|
||||
prdPstgYn: string;
|
||||
rootPath: string;
|
||||
pstPath: string;
|
||||
ansPstn: number;
|
||||
wrtrNm: string;
|
||||
wrtrCplc: string;
|
||||
atflCd: string;
|
||||
regDt: string;
|
||||
rgtrNm: string;
|
||||
cmntCnt: number;
|
||||
}
|
||||
|
||||
export type UserPostListResponse = PageResponse<UserPost>;
|
||||
|
||||
export interface PostService {
|
||||
getUserPostList(params?: UserPostSearchParams): Promise<UserPostListResponse>;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { createColumnHelper } from "@tanstack/react-table";
|
||||
|
||||
import { dayjs } from "@/shared/lib";
|
||||
import type { UserPost } from "@/entities/board";
|
||||
import { Badge } from "@common/components";
|
||||
|
||||
const columnHelper = createColumnHelper<UserPost>();
|
||||
|
||||
export const dashboardNoticeColumns = [
|
||||
columnHelper.display({
|
||||
id: "no",
|
||||
header: "번호",
|
||||
meta: { align: "center" },
|
||||
cell: ({ row }) => {
|
||||
if (row.original.upndFixYn === "Y") {
|
||||
return <Badge size="lg">공지</Badge>;
|
||||
}
|
||||
return row.original.rowNo;
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("pstTtl", {
|
||||
header: "제목",
|
||||
meta: { align: "left" },
|
||||
cell: ({ getValue }) => <div className="min-w-[12rem] truncate px-2 text-left">{getValue()}</div>,
|
||||
}),
|
||||
columnHelper.accessor("wrtrNm", {
|
||||
header: "작성자",
|
||||
meta: { align: "center" },
|
||||
}),
|
||||
columnHelper.accessor("regDt", {
|
||||
header: "작성일",
|
||||
meta: { align: "center" },
|
||||
cell: ({ getValue }) => (getValue() ? dayjs(getValue()).format("YYYY-MM-DD") : "-"),
|
||||
}),
|
||||
columnHelper.accessor("inqNocs", {
|
||||
header: "조회수",
|
||||
meta: { align: "center" },
|
||||
}),
|
||||
];
|
||||
@@ -1,16 +1,58 @@
|
||||
import { Skeleton } from "@common/components";
|
||||
"use client";
|
||||
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { getCoreRowModel } from "@tanstack/react-table";
|
||||
|
||||
import { AS_DASHBOARD_BBS_ID } from "@/shared/config";
|
||||
import { useDataTable } from "@/shared/lib";
|
||||
import { type UserPost, type UserPostSearchParams, useUserPostList } from "@/entities/board";
|
||||
import { Button } from "@common/components";
|
||||
|
||||
import { dashboardNoticeColumns } from "../model/dashboard-notice-table-columns";
|
||||
|
||||
const DASHBOARD_NOTICE_LIST_PARAMS: UserPostSearchParams = {
|
||||
page: 0,
|
||||
size: 3,
|
||||
keywordType: "bbsTypeCd",
|
||||
keyword: "BBSNOTICE",
|
||||
};
|
||||
|
||||
export function DashboardNoticeTable() {
|
||||
const router = useRouter();
|
||||
const userPostListQuery = useUserPostList(DASHBOARD_NOTICE_LIST_PARAMS);
|
||||
|
||||
const handleRowClick = (post: UserPost) => {
|
||||
if (!AS_DASHBOARD_BBS_ID) return;
|
||||
router.push(`/cms/bbsnotice/${AS_DASHBOARD_BBS_ID}/${post.pstNo}`);
|
||||
};
|
||||
|
||||
const handleMoreClick = () => {
|
||||
if (!AS_DASHBOARD_BBS_ID) return;
|
||||
router.push(`/cms/bbsnotice/${AS_DASHBOARD_BBS_ID}`);
|
||||
};
|
||||
|
||||
const { tableComponent } = useDataTable({
|
||||
query: userPostListQuery,
|
||||
tableOptions: {
|
||||
columns: dashboardNoticeColumns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
},
|
||||
dataTableOptions: {
|
||||
variant: "line",
|
||||
onRowClick: handleRowClick,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<section className="card card-border mx-0 bg-background">
|
||||
<div className="card-header flex items-center justify-between">
|
||||
<h3 className="text-2xl font-semibold">공지사항</h3>
|
||||
<Button type="button" size="sm" color="white" onClick={handleMoreClick}>
|
||||
더보기
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 p-4">
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
</div>
|
||||
{tableComponent}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ export const ENDPOINT = {
|
||||
ST_ANLS_MST: "/statverify-service/api/v1/st-anls-mst",
|
||||
},
|
||||
DC_SERVICE: "/dc-service/api/v1",
|
||||
BOARD_SERVICE: {
|
||||
POSTS: "/board-service/api/v1/posts",
|
||||
},
|
||||
};
|
||||
|
||||
export const JWT_EXPIRATION_TIME = 1800000;
|
||||
|
||||
@@ -9,3 +9,4 @@ export const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN || "access-toke
|
||||
export const REFRESH_TOKEN = process.env.NEXT_PUBLIC_REFRESH_TOKEN || "refresh-token";
|
||||
export const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id";
|
||||
export const COOKIE_DOMAIN = process.env.NEXT_PUBLIC_COOKIE_DOMAIN;
|
||||
export const AS_DASHBOARD_BBS_ID = process.env.NEXT_PUBLIC_AS_DASHBOARD_BBS_ID;
|
||||
|
||||
@@ -38,6 +38,11 @@ export function useDataTable<T>({ query, tableOptions, dataTableOptions }: UseDa
|
||||
</div>
|
||||
),
|
||||
Empty: <NoData />,
|
||||
Error: (
|
||||
<p className="py-6 text-center text-lg text-muted-foreground">
|
||||
데이터를 불러오는 중 오류가 발생했습니다.
|
||||
</p>
|
||||
),
|
||||
Success: () => <DataTable table={table} {...dataTableOptions} />,
|
||||
}),
|
||||
tableInstance: table,
|
||||
|
||||
Reference in New Issue
Block a user