From 932ae3f961f8d9b70ae341a9f2ddf8f5c8a6e36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=B2=A0?= Date: Fri, 27 Jun 2025 20:38:45 +0900 Subject: [PATCH 01/32] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20API=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=B6=94=EA=B0=80,=20sort=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/middleware.ts | 9 +- .../src/entities/apilog/api/apilog-service.ts | 20 ++ apps/cs/src/entities/apilog/index.ts | 6 + .../entities/apilog/model/apilog-interface.ts | 27 +++ .../entities/loginlog/api/loginlog-service.ts | 7 - apps/cs/src/entities/loginlog/index.ts | 3 +- .../loginlog/model/loginlog-interface.ts | 32 +-- apps/cs/src/pages/apilog/index.ts | 1 + .../src/pages/apilog/model/table-columns.tsx | 59 +++++ apps/cs/src/pages/apilog/ui/apilog-page.tsx | 218 ++++++++++++++++++ .../pages/loginlog/model/table-columns.tsx | 18 +- .../src/pages/loginlog/ui/loginlog-page.tsx | 209 +++++++++++++---- .../pages/site/ui/ip-management-dialog.tsx | 2 +- apps/cs/src/pages/users/ui/users-page.tsx | 6 +- apps/cs/src/shared/config/api.ts | 3 +- apps/cs/src/shared/model/api-interface.ts | 2 +- 16 files changed, 535 insertions(+), 87 deletions(-) create mode 100644 apps/cs/src/entities/apilog/api/apilog-service.ts create mode 100644 apps/cs/src/entities/apilog/index.ts create mode 100644 apps/cs/src/entities/apilog/model/apilog-interface.ts create mode 100644 apps/cs/src/pages/apilog/index.ts create mode 100644 apps/cs/src/pages/apilog/model/table-columns.tsx create mode 100644 apps/cs/src/pages/apilog/ui/apilog-page.tsx diff --git a/apps/cs/middleware.ts b/apps/cs/middleware.ts index 6bdfd9545..61d38c071 100644 --- a/apps/cs/middleware.ts +++ b/apps/cs/middleware.ts @@ -7,11 +7,16 @@ const serverApiUrl = export function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname; const searchParams = req.nextUrl.searchParams; + if (pathname.startsWith("/server")) { - const queryParams = searchParams.toString(); + + const decodedParams = Array.from(searchParams.entries()) + .map(([key, value]) => `${key}=${decodeURIComponent(value)}`) + .join("&"); + const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${ - queryParams ? `?${queryParams}` : "" + decodedParams ? `?${decodedParams}` : "" }`; return NextResponse.rewrite(new URL(newUrl)); } diff --git a/apps/cs/src/entities/apilog/api/apilog-service.ts b/apps/cs/src/entities/apilog/api/apilog-service.ts new file mode 100644 index 000000000..d7167950c --- /dev/null +++ b/apps/cs/src/entities/apilog/api/apilog-service.ts @@ -0,0 +1,20 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import type { + ApiLogList, + ApiLogParams, + ApiLogService, +} from "../model/apilog-interface"; + +export class ApiLogApiService implements ApiLogService { + public async getApiLogList(params: ApiLogParams): Promise { + const response = await client.get( + `${ENDPOINT.USER_SERVICE.APILOG}`, + { params }, + ); + return response.data; + } + +} + +export const ApiLogApi = new ApiLogApiService(); diff --git a/apps/cs/src/entities/apilog/index.ts b/apps/cs/src/entities/apilog/index.ts new file mode 100644 index 000000000..38733364f --- /dev/null +++ b/apps/cs/src/entities/apilog/index.ts @@ -0,0 +1,6 @@ +export { ApiLogApi } from "./api/apilog-service"; +export type { + ApiLog, + ApiLogParams, +} from "./model/apilog-interface"; + diff --git a/apps/cs/src/entities/apilog/model/apilog-interface.ts b/apps/cs/src/entities/apilog/model/apilog-interface.ts new file mode 100644 index 000000000..e8576a26a --- /dev/null +++ b/apps/cs/src/entities/apilog/model/apilog-interface.ts @@ -0,0 +1,27 @@ +import type { PageableList, PageableParams } from "@/shared/model"; + +export interface ApiLogParams extends PageableParams { + siteId?: string; + userId?: string; + apiHttpPmhd?: string; + dmndUrl?: string; + ipAddr?: string; + searchDateFrom?: string; + searchDateTo?: string; +} + +export interface ApiLog { + id: string; + siteId: string; + userId: string; + apiHttpPmhd: string; + dmndUrl: string; + ipAddr: string; + dmndDt: string; +} + +export type ApiLogList = PageableList; + +export interface ApiLogService { + getApiLogList: (params: ApiLogParams) => Promise; +} diff --git a/apps/cs/src/entities/loginlog/api/loginlog-service.ts b/apps/cs/src/entities/loginlog/api/loginlog-service.ts index c115aebcb..17cb2ea01 100644 --- a/apps/cs/src/entities/loginlog/api/loginlog-service.ts +++ b/apps/cs/src/entities/loginlog/api/loginlog-service.ts @@ -1,7 +1,6 @@ import { client } from "@/shared/api"; import { ENDPOINT } from "@/shared/config"; import type { - LoginlogInfo, LoginlogList, LoginlogParams, LoginlogService, @@ -16,12 +15,6 @@ export class LoginlogApiService implements LoginlogService { return response.data; } - public async getLoginlogInfo(lgnSn: string): Promise { - const response = await client.get( - `${ENDPOINT.USER_SERVICE.LOGINLOG}/${lgnSn}`, - ); - return response.data; - } } export const LoginlogApi = new LoginlogApiService(); diff --git a/apps/cs/src/entities/loginlog/index.ts b/apps/cs/src/entities/loginlog/index.ts index 72032d92d..d03672226 100644 --- a/apps/cs/src/entities/loginlog/index.ts +++ b/apps/cs/src/entities/loginlog/index.ts @@ -1,5 +1,6 @@ -export { LoginlogApiService } from "./api/loginlog-service"; +export { LoginlogApi } from "./api/loginlog-service"; export type { Loginlog, LoginlogParams, } from "./model/loginlog-interface"; + diff --git a/apps/cs/src/entities/loginlog/model/loginlog-interface.ts b/apps/cs/src/entities/loginlog/model/loginlog-interface.ts index 850b6ce5d..f35fe2444 100644 --- a/apps/cs/src/entities/loginlog/model/loginlog-interface.ts +++ b/apps/cs/src/entities/loginlog/model/loginlog-interface.ts @@ -1,37 +1,29 @@ import type { PageableList, PageableParams } from "@/shared/model"; export interface LoginlogParams extends PageableParams { - lgnSn?: string; - userId?: string; siteId?: string; + userId?: string; + errOcrnYn?: string; + remoteIp?: string; + lgnMthd?: string; + lgnErrCd?: string; + searchDateFrom?: string; + searchDateTo?: string; } export interface Loginlog { - lgnSn: string; - lgnDt: string; - userId: string; - lgnIp: string; - lgnMethodCd: string; - errOcrnYn: string; - lgnErrCd: string; + id: string; siteId: string; -} - -export interface LoginlogInfo { - lgnSn: string; - lgnDt: string; userId: string; - lgnIp: string; - lgnMethodCd: string; errOcrnYn: string; + remoteIp: string; + lgnMthd: string; lgnErrCd: string; - siteId: string; + lgnDt: string; } export type LoginlogList = PageableList; export interface LoginlogService { - getLoginlogList: (params: LoginlogParams) => Promise; - getLoginlogInfo: (lgnSn: string) => Promise; - + getLoginlogList: (params: LoginlogParams) => Promise; } diff --git a/apps/cs/src/pages/apilog/index.ts b/apps/cs/src/pages/apilog/index.ts new file mode 100644 index 000000000..564b8ae8f --- /dev/null +++ b/apps/cs/src/pages/apilog/index.ts @@ -0,0 +1 @@ +export { ApiLogPage } from "./ui/apilog-page"; diff --git a/apps/cs/src/pages/apilog/model/table-columns.tsx b/apps/cs/src/pages/apilog/model/table-columns.tsx new file mode 100644 index 000000000..554abb544 --- /dev/null +++ b/apps/cs/src/pages/apilog/model/table-columns.tsx @@ -0,0 +1,59 @@ +import dayjs from "dayjs"; +import type { ColumnDef } from "@tanstack/react-table"; +import type { ApiLog } from "@/entities/apilog"; + + +export const columns: ColumnDef[] = [ + { + id: "no", + header: "NO", + cell: ({ row, table }) => { + const totalRows = table.getRowCount(); + const { pageIndex, pageSize } = table.getState().pagination; + return totalRows - (pageIndex * pageSize + row.index); + }, + }, + { + accessorKey: "dmndDt", + header: "요청일시", + cell: ({ row }) => { + const date = dayjs(row.original.dmndDt); + return date.format("YYYY-MM-DD HH:mm:ss"); + }, + }, + { + accessorKey: "userId", + header: "사용자ID", + }, + { + accessorKey: "ipAddr", + header: "요청IP", + }, + { + accessorKey: "apiHttpPmhd", + header: "요청방식", + cell: ({ row }) => { + const val = row.original.apiHttpPmhd; + if (val === "POST") { + return "저장"; + } else if (val === "PUT") { + return "수정"; + } else if (val === "DELETE") { + return "삭제"; + } else if (val === "GET") { + return "조회"; + } else { + return "기타"; + } + }, + }, + { + accessorKey: "dmndUrl", + header: "요청URL", + }, + { + accessorKey: "siteId", + header: "사이트ID", + } +]; + diff --git a/apps/cs/src/pages/apilog/ui/apilog-page.tsx b/apps/cs/src/pages/apilog/ui/apilog-page.tsx new file mode 100644 index 000000000..49ad3a12a --- /dev/null +++ b/apps/cs/src/pages/apilog/ui/apilog-page.tsx @@ -0,0 +1,218 @@ +"use client"; + +import dayjs from "dayjs"; +import { useState } from "react"; +import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import { + getCoreRowModel, + type PaginationState, +} from "@tanstack/react-table"; +import { + Button, + DateRangePicker, + Input, + Label, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@common/components"; +import { ApiLogApi } from "@/entities/apilog"; +import { type ApiLogParams} from "@/entities/apilog/model/apilog-interface"; +import { useDataTable } from "@/shared/lib"; +import { ENDPOINT } from "@/shared/config"; +import { columns } from "@/pages/apilog/model/table-columns"; + + + +type DateRange = { + from: Date | undefined; + to?: Date | undefined; +}; + +function ApiLogPage({ }) { + + // 1주일 전부터 오늘까지 기본 날짜 설정 + const defaultDateRange: DateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + + const [dateRange, setDateRange] = useState(defaultDateRange); + + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: 10, + }); + + const [loginlogPostQuery, setLoginlogPostQuery] = useState< ApiLogParams>({ + userId: "", + siteId: "", + apiHttpPmhd: "", + dmndUrl: "", + ipAddr: "", + searchDateFrom: dayjs().subtract(7, "day").format("YYYY-MM-DD"), + searchDateTo: dayjs().format("YYYY-MM-DD"), + sort:"lgnDt,asc" + }); + + + const query = useQuery({ + queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, pagination], + queryFn: () => + ApiLogApi.getApiLogList({ + ...loginlogPostQuery, + page: pagination.pageIndex, + size: pagination.pageSize, + }), + placeholderData: keepPreviousData, + }); + + const { tableComponent, tableInstance: table } = useDataTable({ + query, + tableOptions: { + columns, + state: { + pagination, + }, + manualPagination: true, + enableMultiRowSelection: true, + getCoreRowModel: getCoreRowModel(), + onPaginationChange: setPagination, + }, + dataTableOptions: { + viewPagination: true, + }, + }); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + query.refetch(); + }; + + const handleLoginlogParamsChange = + (key: keyof ApiLogParams) => (value: unknown) => { + setLoginlogPostQuery({ ...loginlogPostQuery, [key]: value }); + }; + + const handlePresetDateRange = (value: string) => { + let presetDateRange: DateRange | undefined; + switch (value) { + case "1W": + presetDateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "1M": + presetDateRange = { + from: dayjs().subtract(30, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "3M": + presetDateRange = { + from: dayjs().subtract(90, "day").toDate(), + to: dayjs().toDate(), + }; + break; + default: + presetDateRange = undefined; + } + handleDateRangeChange(presetDateRange); + }; + + + + const handleDateRangeChange = (value: DateRange | undefined) => { + setDateRange(value || defaultDateRange); + setLoginlogPostQuery({ + ...loginlogPostQuery, + searchDateFrom: dayjs(value?.from).format("YYYY-MM-DD") ?? dayjs().subtract(7, "day").format("YYYY-MM-DD"), + searchDateTo: dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), + }); + }; + + + + + return ( +
+
+
+ + +
+ +
+
+ + + handleLoginlogParamsChange("userId")(e.target.value) + } + /> + + + +
+
+
+
+
+

로그인로그 목록

+
+ +
+
+
+
{tableComponent}
+
+
+ ); +} + +export {ApiLogPage }; diff --git a/apps/cs/src/pages/loginlog/model/table-columns.tsx b/apps/cs/src/pages/loginlog/model/table-columns.tsx index dbe19f044..4119e0600 100644 --- a/apps/cs/src/pages/loginlog/model/table-columns.tsx +++ b/apps/cs/src/pages/loginlog/model/table-columns.tsx @@ -18,7 +18,7 @@ export const columns: ColumnDef[] = [ header: "등록일", cell: ({ row }) => { const date = dayjs(row.original.lgnDt); - return date.format("YYYY-MM-DD HH24:mi:ss"); + return date.format("YYYY-MM-DD HH:mm:ss"); }, }, { @@ -26,24 +26,24 @@ export const columns: ColumnDef[] = [ header: "사용자ID", }, { - accessorKey: "로그인IP", - header: "remoteIp", + accessorKey: "remoteIp", + header: "로그인IP", }, { accessorKey: "lgnMthd", header: "접속방식", }, { - accessorKey: "오류여부", - header: "errOcrnYn", + accessorKey: "errOcrnYn", + header: "오류여부", }, { - accessorKey: "오류코드", - header: "lgnErrCd", + accessorKey: "lgnErrCd", + header: "오류코드", }, { - accessorKey: "사이트ID", - header: "siteId", + accessorKey: "siteId", + header: "사이트ID", } ]; diff --git a/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx b/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx index 598eacee2..f0483d425 100644 --- a/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx +++ b/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx @@ -1,77 +1,183 @@ "use client"; +import dayjs from "dayjs"; import { useState } from "react"; import { keepPreviousData, useQuery } from "@tanstack/react-query"; import { getCoreRowModel, - useReactTable, type PaginationState, } from "@tanstack/react-table"; -import { Button, DataTable, Input, Label } from "@common/components"; -import { LoginlogApi} from "../../../entities/loginlog/api/loginlog-service"; -import { type LoginlogParams} from "../../../entities/loginlog/model/loginlog-interface"; - +import { + Button, + DateRangePicker, + Input, + Label, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@common/components"; +import { LoginlogApi } from "@/entities/loginlog"; +import { type LoginlogParams} from "@/entities/loginlog/model/loginlog-interface"; +import { useDataTable } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; -import { columns } from "../model/table-columns"; +import { columns } from "@/pages/loginlog/model/table-columns"; -type LoginlogPageProps = { - lgnSn?: string; + + +type DateRange = { + from: Date | undefined; + to?: Date | undefined; }; -function LoginlogPage({ }: LoginlogPageProps) { - const [loginlogQuery, setLoginlogQuery] = useState({ - userId: "", - siteId: "", - }); +function LoginlogPage({ }) { + + // 1주일 전부터 오늘까지 기본 날짜 설정 + const defaultDateRange: DateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + + const [dateRange, setDateRange] = useState(defaultDateRange); + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10, }); - - const { data: loginlogList, refetch } = useQuery({ - queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, , pagination], + + const [loginlogPostQuery, setLoginlogPostQuery] = useState({ + userId: "", + siteId: "", + errOcrnYn: "N", + remoteIp: "", + lgnMthd: "", + lgnErrCd: "", + searchDateFrom: dayjs().subtract(7, "day").format("YYYY-MM-DD"), + searchDateTo: dayjs().format("YYYY-MM-DD"), + sort:"lgnDt,asc" + }); + + + const query = useQuery({ + queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, pagination], queryFn: () => LoginlogApi.getLoginlogList({ - ...loginlogQuery, - page: pagination.pageIndex, + ...loginlogPostQuery, + page: pagination.pageIndex, size: pagination.pageSize, }), - placeholderData: keepPreviousData, + placeholderData: keepPreviousData, }); - const table = useReactTable({ - data: loginlogList?.content ?? [], - columns, - rowCount: loginlogList?.totalElements ?? 0, - state: { pagination }, - manualPagination: true, - enableMultiRowSelection: false, - getCoreRowModel: getCoreRowModel(), - onPaginationChange: setPagination, + const { tableComponent, tableInstance: table } = useDataTable({ + query, + tableOptions: { + columns, + state: { + pagination, + }, + manualPagination: true, + enableMultiRowSelection: true, + getCoreRowModel: getCoreRowModel(), + onPaginationChange: setPagination, + }, + dataTableOptions: { + viewPagination: true, + }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - refetch(); + query.refetch(); }; + const handleLoginlogParamsChange = + (key: keyof LoginlogParams) => (value: unknown) => { + setLoginlogPostQuery({ ...loginlogPostQuery, [key]: value }); + }; + + const handlePresetDateRange = (value: string) => { + let presetDateRange: DateRange | undefined; + switch (value) { + case "1W": + presetDateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "1M": + presetDateRange = { + from: dayjs().subtract(30, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "3M": + presetDateRange = { + from: dayjs().subtract(90, "day").toDate(), + to: dayjs().toDate(), + }; + break; + default: + presetDateRange = undefined; + } + handleDateRangeChange(presetDateRange); + }; + + + + const handleDateRangeChange = (value: DateRange | undefined) => { + setDateRange(value || defaultDateRange); + setLoginlogPostQuery({ + ...loginlogPostQuery, + searchDateFrom: dayjs(value?.from).format("YYYY-MM-DD") ?? dayjs().subtract(7, "day").format("YYYY-MM-DD"), + searchDateTo: dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), + }); + }; + + + + return (
- + + +
+ +
+
+ - setLoginlogQuery({ - ...loginlogQuery, - userId: e.target.value, - }) + handleLoginlogParamsChange("userId")(e.target.value) } /> + + @@ -79,11 +185,30 @@ function LoginlogPage({ }: LoginlogPageProps) {
-

로그인로그 목록

-
-
- -
+
+

로그인로그 목록

+
+ +
+
+
+
{tableComponent}
); diff --git a/apps/cs/src/pages/site/ui/ip-management-dialog.tsx b/apps/cs/src/pages/site/ui/ip-management-dialog.tsx index c2a2c2702..43e2c2155 100644 --- a/apps/cs/src/pages/site/ui/ip-management-dialog.tsx +++ b/apps/cs/src/pages/site/ui/ip-management-dialog.tsx @@ -46,7 +46,7 @@ function IPManagementDialog({ const { data: ipList } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.IPS, props.open], - queryFn: () => IpApi.getIpList({ siteId, sort: [] }), + queryFn: () => IpApi.getIpList({ siteId, sort: "" }), select: (data) => { const ips = data.content.map((item) => ({ ...item, diff --git a/apps/cs/src/pages/users/ui/users-page.tsx b/apps/cs/src/pages/users/ui/users-page.tsx index d6f77deb5..2ffe05eb4 100644 --- a/apps/cs/src/pages/users/ui/users-page.tsx +++ b/apps/cs/src/pages/users/ui/users-page.tsx @@ -51,7 +51,7 @@ function UsersPage() { grpId: "", frDateYmd: "", toDateYmd: "", - sort: ["aprvYmd,desc"], + sort: "regDt,desc" }, }); @@ -288,9 +288,9 @@ function UsersPage() {

회원 목록

-
@@ -208,7 +213,19 @@ function LoginlogPage({ }) { -
{tableComponent}
+
+ {/* Debug: 로딩 상태 표시 */} + {(query.isLoading || query.isPending || isManualLoading) && ( +
+
+
+ +
+
+
+ )} + {tableComponent} +
); diff --git a/apps/cs/src/pages/privacylog/index.ts b/apps/cs/src/pages/privacylog/index.ts new file mode 100644 index 000000000..7bbd75042 --- /dev/null +++ b/apps/cs/src/pages/privacylog/index.ts @@ -0,0 +1 @@ +export { PrivacyLogPage } from "./ui/privacylog-page"; diff --git a/apps/cs/src/pages/privacylog/model/table-columns.tsx b/apps/cs/src/pages/privacylog/model/table-columns.tsx new file mode 100644 index 000000000..a5b52d796 --- /dev/null +++ b/apps/cs/src/pages/privacylog/model/table-columns.tsx @@ -0,0 +1,41 @@ +import dayjs from "dayjs"; +import type { ColumnDef } from "@tanstack/react-table"; +import type { PrivacyLog } from "@/entities/privacylog"; + + +export const columns: ColumnDef[] = [ + { + id: "no", + header: "NO", + cell: ({ row, table }) => { + const totalRows = table.getRowCount(); + const { pageIndex, pageSize } = table.getState().pagination; + return totalRows - (pageIndex * pageSize + row.index); + }, + }, + { + accessorKey: "inqDt", + header: "요청일시", + cell: ({ row }) => { + const date = dayjs(row.original.inqDt); + return date.format("YYYY-MM-DD HH:mm:ss"); + }, + }, + { + accessorKey: "siteNm", + header: "사이트명", + }, + { + accessorKey: "rqstrNm", + header: "조회자명", + }, + { + accessorKey: "rqstrIp", + header: "조회IP", + }, + { + accessorKey: "inqInfoSummary", + header: "조회정보", + } +]; + diff --git a/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx b/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx new file mode 100644 index 000000000..9feea8a02 --- /dev/null +++ b/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx @@ -0,0 +1,206 @@ +"use client"; + +import dayjs from "dayjs"; +import { useState } from "react"; +import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import { + getCoreRowModel, + type PaginationState, +} from "@tanstack/react-table"; +import { + Button, + DateRangePicker, + Input, + Label, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@common/components"; +import { PrivacyLogPrivacy } from "@/entities/privacylog"; +import { type PrivacyLogParams} from "@/entities/privacylog/model/privacylog-interface"; +import { useDataTable } from "@/shared/lib"; +import { ENDPOINT } from "@/shared/config"; +import { columns } from "@/pages/privacylog/model/table-columns"; + + + +type DateRange = { + from: Date | undefined; + to?: Date | undefined; +}; + +function PrivacyLogPage({ }) { + + // 1주일 전부터 오늘까지 기본 날짜 설정 + const defaultDateRange: DateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + + const [dateRange, setDateRange] = useState(defaultDateRange); + + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: 10, + }); + + const [privacylogPostQuery, setprivacylogPostQuery] = useState< PrivacyLogParams>({ + siteId: "", + inqInfoKeywordType: "userName", + inqInfoKeyword: "", + rqstrIp: "", + inqDtStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"), + inqDtEnd: dayjs().format("YYYY-MM-DD"), + sort:"inqDt,asc" + }); + + + const query = useQuery({ + queryKey: [ENDPOINT.USER_SERVICE.PRIVACYLOG, pagination], + queryFn: () => + PrivacyLogPrivacy.getPrivacyLogList({ + ...privacylogPostQuery, + page: pagination.pageIndex, + size: pagination.pageSize, + }), + placeholderData: keepPreviousData, + }); + + const { tableComponent, tableInstance: table } = useDataTable({ + query, + tableOptions: { + columns, + state: { + pagination, + }, + manualPagination: true, + enableMultiRowSelection: true, + getCoreRowModel: getCoreRowModel(), + onPaginationChange: setPagination, + }, + dataTableOptions: { + viewPagination: true, + }, + }); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + query.refetch(); + }; + + const handleprivacylogParamsChange = + (key: keyof PrivacyLogParams) => (value: unknown) => { + setprivacylogPostQuery({ ...privacylogPostQuery, [key]: value }); + }; + + const handlePresetDateRange = (value: string) => { + let presetDateRange: DateRange | undefined; + switch (value) { + case "1W": + presetDateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "1M": + presetDateRange = { + from: dayjs().subtract(30, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "3M": + presetDateRange = { + from: dayjs().subtract(90, "day").toDate(), + to: dayjs().toDate(), + }; + break; + default: + presetDateRange = undefined; + } + handleDateRangeChange(presetDateRange); + }; + + + + const handleDateRangeChange = (value: DateRange | undefined) => { + setDateRange(value || defaultDateRange); + setprivacylogPostQuery({ + ...privacylogPostQuery, + inqDtStart: dayjs(value?.from).format("YYYY-MM-DD") ?? dayjs().subtract(7, "day").format("YYYY-MM-DD"), + inqDtEnd: dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), + }); + }; + + + + + return ( +
+
+
+ + +
+ +
+
+ + + handleprivacylogParamsChange("inqInfoKeyword")(e.target.value) + } + /> + + +
+
+
+
+
+

로그인로그 목록

+
+ +
+
+
+
{tableComponent}
+
+
+ ); +} + +export {PrivacyLogPage }; diff --git a/apps/cs/src/shared/config/api.ts b/apps/cs/src/shared/config/api.ts index b23268e66..ac0f18eca 100644 --- a/apps/cs/src/shared/config/api.ts +++ b/apps/cs/src/shared/config/api.ts @@ -21,6 +21,8 @@ export const ENDPOINT = { ROLES: "/user-service/api/v1/roles", LOGINLOG: "/user-service/api/v1/login-logs", APILOG: "/user-service/api/v1/api-logs", + PRIVACYLOG: "/user-service//api/v1/prvc-inq-logs", + }, CMS_SERVICE: { SITES: "/cms-service/api/v1/sites", From 533923a40aea807590631798eb6ed4f1cfa020b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=B2=A0?= Date: Fri, 27 Jun 2025 22:08:38 +0900 Subject: [PATCH 05/32] =?UTF-8?q?Privacy=20Log=20Route=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/app/(with-base-layout)/privacylog/page.tsx | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/cs/app/(with-base-layout)/privacylog/page.tsx diff --git a/apps/cs/app/(with-base-layout)/privacylog/page.tsx b/apps/cs/app/(with-base-layout)/privacylog/page.tsx new file mode 100644 index 000000000..4b543f360 --- /dev/null +++ b/apps/cs/app/(with-base-layout)/privacylog/page.tsx @@ -0,0 +1,2 @@ +import { PrivacyLogPage } from "@/pages/privacylog"; +export default PrivacyLogPage; From 0e9d865f4429ac9b4fece51c80c876ea20ca8498 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 10:53:41 +0900 Subject: [PATCH 06/32] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20?= =?UTF-8?q?=ED=8F=89=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/src/shared/config/api.ts | 1 + .../post/api/post-evaluation-service.ts | 14 ++++ .../post/model/post-evaluation-interface.ts | 10 +++ apps/cs/src/widgets/post/ui/post.tsx | 72 ++++++++++++++++++- 4 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 apps/cs/src/widgets/post/api/post-evaluation-service.ts create mode 100644 apps/cs/src/widgets/post/model/post-evaluation-interface.ts diff --git a/apps/cs/src/shared/config/api.ts b/apps/cs/src/shared/config/api.ts index ee168407e..8a0d94ef5 100644 --- a/apps/cs/src/shared/config/api.ts +++ b/apps/cs/src/shared/config/api.ts @@ -55,6 +55,7 @@ export const ENDPOINT = { BBS_TEMPLATES: "/board-service/api/v1/bbsTmplt", POSTS: "/board-service/api/v1/posts", POSTS_COMMENTS: "/board-service/api/v1/posts-cmnts", + POST_EVALUATION: "/board-service/api/v1/pstEvl", }, }; diff --git a/apps/cs/src/widgets/post/api/post-evaluation-service.ts b/apps/cs/src/widgets/post/api/post-evaluation-service.ts new file mode 100644 index 000000000..9258ba299 --- /dev/null +++ b/apps/cs/src/widgets/post/api/post-evaluation-service.ts @@ -0,0 +1,14 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import type { + PostEvaluationPayload, + PostEvaluationService, +} from "../model/post-evaluation-interface"; + +export class PostEvaluationApiService implements PostEvaluationService { + public async postEvaluation(payload: PostEvaluationPayload) { + await client.post(ENDPOINT.BOARD_SERVICE.POST_EVALUATION, payload); + } +} + +export const PostEvaluationApi = new PostEvaluationApiService(); diff --git a/apps/cs/src/widgets/post/model/post-evaluation-interface.ts b/apps/cs/src/widgets/post/model/post-evaluation-interface.ts new file mode 100644 index 000000000..c99249d6a --- /dev/null +++ b/apps/cs/src/widgets/post/model/post-evaluation-interface.ts @@ -0,0 +1,10 @@ +export interface PostEvaluationPayload { + pstNo: number; + evlIp?: string; + evlDt?: string; + evlScr: number; +} + +export interface PostEvaluationService { + postEvaluation: (payload: PostEvaluationPayload) => Promise; +} diff --git a/apps/cs/src/widgets/post/ui/post.tsx b/apps/cs/src/widgets/post/ui/post.tsx index a7f3cb43a..040262218 100644 --- a/apps/cs/src/widgets/post/ui/post.tsx +++ b/apps/cs/src/widgets/post/ui/post.tsx @@ -5,14 +5,21 @@ import Image from "next/image"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { useQuery } from "@tanstack/react-query"; -import { Button, Skeleton } from "@common/components"; +import { + Button, + Label, + RadioGroup, + RadioGroupItem, + Skeleton, +} from "@common/components"; import { AttachmentApi } from "@/entities/attachment"; import { PostApi } from "@/entities/post"; -import { useAlertStore, useMutationWrapper, useMenuStore } from "@/shared/lib"; +import { BoardApi } from "@/entities/board"; import { ENDPOINT } from "@/shared/config"; +import { useAlertStore, useMutationWrapper, useMenuStore } from "@/shared/lib"; import { PostAction } from "./post-action"; import { PostComment } from "./post-comment"; -import { BoardApi } from "@/entities/board"; +import { PostEvaluationApi } from "../api/post-evaluation-service"; function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const router = useRouter(); @@ -20,6 +27,7 @@ function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const { bbsInfo, setBbsInfo } = useMenuStore((state) => state); const [filename, setFilename] = useState(""); + const [evlScr, setEvlScr] = useState(5); const { data: boardInfo } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.BBS, bbsId], @@ -72,6 +80,17 @@ function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { }, }); + const { mutate: postEvaluation } = useMutationWrapper({ + mutationFn: (evlScr: number) => + PostEvaluationApi.postEvaluation({ + pstNo: parseInt(pstNo), + evlScr, + }), + onSuccess: () => { + alert("게시물 평가가 완료되었습니다."); + }, + }); + const handleDownload = async () => { if (!downloadResponse) return; try { @@ -187,6 +206,53 @@ function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { ) )} + {bbsInfo?.dgstfnEvlUseYn === "Y" && ( + <> +
+
+

+ 이 페이지에서 제공하는 +
+ 정보에 대하여 만족하시나요? +

+
+ setEvlScr(parseInt(value))} + className="flex items-center space-x-4" + > +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ + )} From 9a38ce33c0d4d2bc02de61b7d22fe1043a8f8ca3 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 13:23:29 +0900 Subject: [PATCH 07/32] =?UTF-8?q?refactor:=20'SITE=5FID'=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=BF=A0=ED=82=A4=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/features/app/api/proxy/[...url]/route.ts | 4 ++-- apps/common/features/src/entities/menu/lib/menu-wrapper.tsx | 5 +++-- apps/common/features/src/shared/api/client.ts | 6 ++++-- apps/common/features/src/shared/config/env.ts | 1 - apps/cs/src/shared/api/client.ts | 3 +++ packages/common/components/src/ui/lnb/index.tsx | 6 +++--- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/common/features/app/api/proxy/[...url]/route.ts b/apps/common/features/app/api/proxy/[...url]/route.ts index d3092c5c1..5d81c93fb 100644 --- a/apps/common/features/app/api/proxy/[...url]/route.ts +++ b/apps/common/features/app/api/proxy/[...url]/route.ts @@ -4,7 +4,6 @@ import { CLAIM_NAME, REFRESH_TOKEN, SERVER_API_URL, - SITE_ID, } from "@/shared/config"; import { cookies } from "next/headers"; import { NextResponse } from "next/server"; @@ -15,9 +14,10 @@ async function handler( method: "GET" | "POST" | "PUT" | "DELETE", ) { const cookieStore = await cookies(); + const siteId = cookieStore.get("site-id-key")?.value ?? ""; const headers: Record = { "Content-Type": "application/json", - "X-Site-Id": SITE_ID, + "X-Site-Id": siteId, }; let body = {}; const isRefreshHandler = params.url.includes("refresh"); diff --git a/apps/common/features/src/entities/menu/lib/menu-wrapper.tsx b/apps/common/features/src/entities/menu/lib/menu-wrapper.tsx index 2855e5ef0..e3007f8be 100644 --- a/apps/common/features/src/entities/menu/lib/menu-wrapper.tsx +++ b/apps/common/features/src/entities/menu/lib/menu-wrapper.tsx @@ -4,10 +4,11 @@ import { useEffect } from "react"; import { usePathname, useRouter } from "next/navigation"; import { MenuAuthorityApi } from "@/entities/menu-authority/@x/menu"; import { getCookie, useAlertStore, useMenuStore } from "@/shared/lib"; -import { SITE_ID } from "@/shared/config"; import { MenuApi } from "../api/menu-service"; import { getCurrentMenu } from "./utils"; +const siteId = getCookie("site-id-key") ?? ""; + const MenuWrapper = ({ children }: { children: React.ReactNode }) => { const router = useRouter(); const pathname = usePathname(); @@ -17,7 +18,7 @@ const MenuWrapper = ({ children }: { children: React.ReactNode }) => { useMenuStore((state) => state); const getCurrentMenuInfo = async () => { - const menuRoles = await MenuApi.getMenuRoles(SITE_ID); + const menuRoles = await MenuApi.getMenuRoles(siteId); if (!menuRoles) return; return getCurrentMenu(menuRoles, pathname ?? ""); }; diff --git a/apps/common/features/src/shared/api/client.ts b/apps/common/features/src/shared/api/client.ts index 709bb44a5..9c41892c0 100644 --- a/apps/common/features/src/shared/api/client.ts +++ b/apps/common/features/src/shared/api/client.ts @@ -1,8 +1,10 @@ import { Client } from "@common/network"; import { BASE_URL } from "../config/api"; -import { SITE_ID } from "../config/env"; +import { getCookie } from "../lib"; + +const siteId = getCookie("site-id-key") ?? ""; export const client = Client.getInstance({ baseURL: BASE_URL, - siteId: SITE_ID, + siteId, }); diff --git a/apps/common/features/src/shared/config/env.ts b/apps/common/features/src/shared/config/env.ts index e8d3161eb..a68868d6b 100644 --- a/apps/common/features/src/shared/config/env.ts +++ b/apps/common/features/src/shared/config/env.ts @@ -2,7 +2,6 @@ export const PORT = process.env.NEXT_PUBLIC_PORT || "13000"; export const PROXY_HOST = process.env.NEXT_PUBLIC_PROXY_HOST || `http://localhost:${PORT}`; export const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL; -export const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "CS"; export const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization"; export const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN || "access-token"; diff --git a/apps/cs/src/shared/api/client.ts b/apps/cs/src/shared/api/client.ts index 709bb44a5..cf37e6671 100644 --- a/apps/cs/src/shared/api/client.ts +++ b/apps/cs/src/shared/api/client.ts @@ -1,6 +1,9 @@ import { Client } from "@common/network"; import { BASE_URL } from "../config/api"; import { SITE_ID } from "../config/env"; +import { setCookie } from "../lib"; + +setCookie("site-id-key", SITE_ID); export const client = Client.getInstance({ baseURL: BASE_URL, diff --git a/packages/common/components/src/ui/lnb/index.tsx b/packages/common/components/src/ui/lnb/index.tsx index 80d9ad87d..a244cb3f7 100644 --- a/packages/common/components/src/ui/lnb/index.tsx +++ b/packages/common/components/src/ui/lnb/index.tsx @@ -3,7 +3,6 @@ import { useState, useEffect, useRef } from "react"; import { useQuery } from "@tanstack/react-query"; import { ChevronRight } from "lucide-react"; -import { getConfig } from "@common/config"; import { ENDPOINT } from "../../config"; import { cn, setCookie } from "../../lib"; import { getMenuList, type MenuItem } from "../../api"; @@ -24,8 +23,9 @@ import { CollapsibleTrigger, } from "../collapsible"; import { getParentIds } from "./lib"; +import { getCookie } from "../../lib"; -const { SITE_ID } = getConfig(); +const siteId = getCookie("site-id-key") ?? ""; export function LNB({ viewOnly, @@ -38,7 +38,7 @@ export function LNB({ }) { const { data: menuList } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES], - queryFn: () => getMenuList(SITE_ID ?? ""), + queryFn: () => getMenuList(siteId), enabled: !viewOnly, }); From 622b74db54752978d9d6154e106376c715c12dc7 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 13:26:29 +0900 Subject: [PATCH 08/32] Merge branch 'iipbs_cs' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs_cs From 855f9b867552751ca07bd33c33209b7c8974b88a Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 13:39:38 +0900 Subject: [PATCH 09/32] =?UTF-8?q?refactor:=20common/components=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=EC=97=90=EC=84=9C=20'SITE=5FID'=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=BF=A0=ED=82=A4=EB=A1=9C=20=EB=8C=80?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/components/src/api/client.ts | 7 +++++-- .../common/components/src/lib/client-ip-guard.tsx | 12 ++++++------ packages/common/components/src/ui/header/index.tsx | 7 +++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/common/components/src/api/client.ts b/packages/common/components/src/api/client.ts index 0226a4f9a..46d5291fd 100644 --- a/packages/common/components/src/api/client.ts +++ b/packages/common/components/src/api/client.ts @@ -1,14 +1,17 @@ import { Client } from "@common/network"; import { getConfig } from "@common/config"; +import { getCookie } from "../lib"; + +const siteId = getCookie("site-id-key") ?? ""; const getClientInstance = () => { const config = getConfig(); - const { PROXY_HOST, SITE_ID } = config; + const { PROXY_HOST } = config; const BASE_URL = `${PROXY_HOST}/server`; return Client.getInstance({ baseURL: BASE_URL, - siteId: SITE_ID ?? "", + siteId, }); }; diff --git a/packages/common/components/src/lib/client-ip-guard.tsx b/packages/common/components/src/lib/client-ip-guard.tsx index e6b30fe81..d1ae1735c 100644 --- a/packages/common/components/src/lib/client-ip-guard.tsx +++ b/packages/common/components/src/lib/client-ip-guard.tsx @@ -1,11 +1,11 @@ import { useEffect, useState } from "react"; import { useQueryClient } from "@tanstack/react-query"; -import { getConfig } from "@common/config"; import { getSiteInfo } from "../api/site"; import { getIpList } from "../api/ip"; import { ENDPOINT } from "../config"; +import { getCookie } from "../lib"; -const { SITE_ID } = getConfig(); +const siteId = getCookie("site-id-key") ?? ""; const ClientIpGuard = ({ currentPath, @@ -29,17 +29,17 @@ const ClientIpGuard = ({ useEffect(() => { (async () => { - if (!SITE_ID || !clientIp) return; + if (!siteId || !clientIp) return; const siteInfo = await queryClient.ensureQueryData({ - queryKey: [ENDPOINT.CMS_SERVICE.SITES, SITE_ID], - queryFn: () => getSiteInfo(SITE_ID), + queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], + queryFn: () => getSiteInfo(siteId), }); if (siteInfo.siteKndCd === "O") return; const { content: ipList } = await getIpList({ - siteId: SITE_ID, + siteId, prmYn: "Y", }); diff --git a/packages/common/components/src/ui/header/index.tsx b/packages/common/components/src/ui/header/index.tsx index 7d4caad94..1b60b1c74 100644 --- a/packages/common/components/src/ui/header/index.tsx +++ b/packages/common/components/src/ui/header/index.tsx @@ -3,7 +3,6 @@ import "./header.css"; import { useEffect, useCallback } from "react"; import { useQuery } from "@tanstack/react-query"; import { images } from "@common/assets"; -import { getConfig } from "@common/config"; import { ENDPOINT } from "../../config"; import { setCookie, getCookie } from "../../lib"; import { @@ -22,7 +21,7 @@ import { import { Button } from "../button"; import { SidebarTrigger } from "../sidebar"; -const { SITE_ID } = getConfig(); +const siteId = getCookie("site-id-key") ?? ""; export function Header({ viewOnly }: { viewOnly?: boolean }) { const { data: userInfo } = useQuery({ @@ -32,8 +31,8 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) { }); const { data: siteInfo } = useQuery({ - queryKey: [ENDPOINT.CMS_SERVICE.SITES, SITE_ID], - queryFn: () => getSiteInfo(SITE_ID ?? ""), + queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], + queryFn: () => getSiteInfo(siteId), select: (data) => { if (data.siteSkn) { const siteSkin = data.siteSkn.toLowerCase(); From 00329ff32b6ac920c11741d79b1365659df629b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=B2=A0?= Date: Mon, 30 Jun 2025 14:20:38 +0900 Subject: [PATCH 10/32] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entities/apilog/model/apilog-interface.ts | 21 +++-- apps/cs/src/pages/apilog/ui/apilog-page.tsx | 77 ++++++++-------- .../src/pages/loginlog/ui/loginlog-page.tsx | 87 +++++++++---------- .../pages/privacylog/ui/privacylog-page.tsx | 2 +- 4 files changed, 89 insertions(+), 98 deletions(-) diff --git a/apps/cs/src/entities/apilog/model/apilog-interface.ts b/apps/cs/src/entities/apilog/model/apilog-interface.ts index e8576a26a..f00e583ad 100644 --- a/apps/cs/src/entities/apilog/model/apilog-interface.ts +++ b/apps/cs/src/entities/apilog/model/apilog-interface.ts @@ -3,25 +3,28 @@ import type { PageableList, PageableParams } from "@/shared/model"; export interface ApiLogParams extends PageableParams { siteId?: string; userId?: string; + userNm?: string; apiHttpPmhd?: string; dmndUrl?: string; ipAddr?: string; - searchDateFrom?: string; - searchDateTo?: string; + dmndDtStart?: string; + dmndDtEnd?: string; } export interface ApiLog { - id: string; + logId: string; siteId: string; - userId: string; - apiHttpPmhd: string; - dmndUrl: string; - ipAddr: string; - dmndDt: string; + siteNm: string; + userId: string; + userNm: string; + apiHttpPmhd: string; + dmndUrl: string; + ipAddr: string; + dmndDt: string; } export type ApiLogList = PageableList; export interface ApiLogService { - getApiLogList: (params: ApiLogParams) => Promise; + getApiLogList: (params: ApiLogParams) => Promise; } diff --git a/apps/cs/src/pages/apilog/ui/apilog-page.tsx b/apps/cs/src/pages/apilog/ui/apilog-page.tsx index 49ad3a12a..51cc960f3 100644 --- a/apps/cs/src/pages/apilog/ui/apilog-page.tsx +++ b/apps/cs/src/pages/apilog/ui/apilog-page.tsx @@ -3,61 +3,54 @@ import dayjs from "dayjs"; import { useState } from "react"; import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import { getCoreRowModel, type PaginationState } from "@tanstack/react-table"; import { - getCoreRowModel, - type PaginationState, -} from "@tanstack/react-table"; -import { - Button, - DateRangePicker, - Input, + Button, + DateRangePicker, + Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, - } from "@common/components"; +} from "@common/components"; import { ApiLogApi } from "@/entities/apilog"; -import { type ApiLogParams} from "@/entities/apilog/model/apilog-interface"; -import { useDataTable } from "@/shared/lib"; +import { type ApiLogParams } from "@/entities/apilog/model/apilog-interface"; +import { useDataTable } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; import { columns } from "@/pages/apilog/model/table-columns"; - - type DateRange = { from: Date | undefined; to?: Date | undefined; }; -function ApiLogPage({ }) { - +function ApiLogPage({}) { // 1주일 전부터 오늘까지 기본 날짜 설정 const defaultDateRange: DateRange = { from: dayjs().subtract(7, "day").toDate(), to: dayjs().toDate(), }; - + const [dateRange, setDateRange] = useState(defaultDateRange); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10, }); - - const [loginlogPostQuery, setLoginlogPostQuery] = useState< ApiLogParams>({ - userId: "", - siteId: "", - apiHttpPmhd: "", - dmndUrl: "", - ipAddr: "", - searchDateFrom: dayjs().subtract(7, "day").format("YYYY-MM-DD"), - searchDateTo: dayjs().format("YYYY-MM-DD"), - sort:"lgnDt,asc" + + const [loginlogPostQuery, setLoginlogPostQuery] = useState({ + userId: "", + siteId: "", + apiHttpPmhd: "", + dmndUrl: "", + ipAddr: "", + dmndDtStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"), + dmndDtEnd: dayjs().format("YYYY-MM-DD"), + sort: "lgnDt,asc", }); - - + const query = useQuery({ queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, pagination], queryFn: () => @@ -92,10 +85,10 @@ function ApiLogPage({ }) { }; const handleLoginlogParamsChange = - (key: keyof ApiLogParams) => (value: unknown) => { - setLoginlogPostQuery({ ...loginlogPostQuery, [key]: value }); - }; - + (key: keyof ApiLogParams) => (value: unknown) => { + setLoginlogPostQuery({ ...loginlogPostQuery, [key]: value }); + }; + const handlePresetDateRange = (value: string) => { let presetDateRange: DateRange | undefined; switch (value) { @@ -123,20 +116,18 @@ function ApiLogPage({ }) { handleDateRangeChange(presetDateRange); }; - - const handleDateRangeChange = (value: DateRange | undefined) => { setDateRange(value || defaultDateRange); setLoginlogPostQuery({ ...loginlogPostQuery, - searchDateFrom: dayjs(value?.from).format("YYYY-MM-DD") ?? dayjs().subtract(7, "day").format("YYYY-MM-DD"), - searchDateTo: dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), + dmndDtStart: + dayjs(value?.from).format("YYYY-MM-DD") ?? + dayjs().subtract(7, "day").format("YYYY-MM-DD"), + dmndDtEnd: + dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), }); }; - - - return (
@@ -162,7 +153,7 @@ function ApiLogPage({ }) { handleLoginlogParamsChange("userId")(e.target.value) } @@ -171,12 +162,12 @@ function ApiLogPage({ }) {
- +
{tableComponent}
); } -export {ApiLogPage }; +export { ApiLogPage }; diff --git a/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx b/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx index 058c03db2..1672a5bd8 100644 --- a/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx +++ b/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx @@ -3,14 +3,11 @@ import dayjs from "dayjs"; import { useState } from "react"; import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import { getCoreRowModel, type PaginationState } from "@tanstack/react-table"; import { - getCoreRowModel, - type PaginationState, -} from "@tanstack/react-table"; -import { - Button, - DateRangePicker, - Input, + Button, + DateRangePicker, + Input, Label, Select, SelectContent, @@ -18,28 +15,25 @@ import { SelectTrigger, SelectValue, LoadingWithImage, - } from "@common/components"; +} from "@common/components"; import { LoginlogApi } from "@/entities/loginlog"; -import { type LoginlogParams} from "@/entities/loginlog/model/loginlog-interface"; -import { useDataTable } from "@/shared/lib"; +import { type LoginlogParams } from "@/entities/loginlog/model/loginlog-interface"; +import { useDataTable } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; import { columns } from "@/pages/loginlog/model/table-columns"; - - type DateRange = { from: Date | undefined; to?: Date | undefined; }; -function LoginlogPage({ }) { - +function LoginlogPage({}) { // 1주일 전부터 오늘까지 기본 날짜 설정 const defaultDateRange: DateRange = { from: dayjs().subtract(7, "day").toDate(), to: dayjs().toDate(), }; - + const [dateRange, setDateRange] = useState(defaultDateRange); const [isManualLoading, setIsManualLoading] = useState(false); @@ -47,20 +41,19 @@ function LoginlogPage({ }) { pageIndex: 0, pageSize: 10, }); - + const [loginlogPostQuery, setLoginlogPostQuery] = useState({ - userId: "", - siteId: "", - errOcrnYn: "N", - remoteIp: "", - lgnMthd: "", - lgnErrCd: "", - searchDateFrom: dayjs().subtract(7, "day").format("YYYY-MM-DD"), - searchDateTo: dayjs().format("YYYY-MM-DD"), - sort:"lgnDt,desc" + userId: "", + siteId: "", + errOcrnYn: "N", + remoteIp: "", + lgnMthd: "", + lgnErrCd: "", + searchDateFrom: dayjs().subtract(7, "day").format("YYYY-MM-DD"), + searchDateTo: dayjs().format("YYYY-MM-DD"), + sort: "lgnDt,desc", }); - - + const query = useQuery({ queryKey: [ENDPOINT.USER_SERVICE.LOGINLOG, pagination], queryFn: () => @@ -98,10 +91,10 @@ function LoginlogPage({ }) { }; const handleLoginlogParamsChange = - (key: keyof LoginlogParams) => (value: unknown) => { - setLoginlogPostQuery({ ...loginlogPostQuery, [key]: value }); - }; - + (key: keyof LoginlogParams) => (value: unknown) => { + setLoginlogPostQuery({ ...loginlogPostQuery, [key]: value }); + }; + const handlePresetDateRange = (value: string) => { let presetDateRange: DateRange | undefined; switch (value) { @@ -129,20 +122,18 @@ function LoginlogPage({ }) { handleDateRangeChange(presetDateRange); }; - - const handleDateRangeChange = (value: DateRange | undefined) => { setDateRange(value || defaultDateRange); setLoginlogPostQuery({ ...loginlogPostQuery, - searchDateFrom: dayjs(value?.from).format("YYYY-MM-DD") ?? dayjs().subtract(7, "day").format("YYYY-MM-DD"), - searchDateTo: dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), + searchDateFrom: + dayjs(value?.from).format("YYYY-MM-DD") ?? + dayjs().subtract(7, "day").format("YYYY-MM-DD"), + searchDateTo: + dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), }); }; - - - return (
@@ -168,7 +159,7 @@ function LoginlogPage({ }) { handleLoginlogParamsChange("userId")(e.target.value) } @@ -183,8 +174,14 @@ function LoginlogPage({ }) { 오류 -
@@ -212,12 +209,12 @@ function LoginlogPage({ }) {
- -
+
+
{/* Debug: 로딩 상태 표시 */} {(query.isLoading || query.isPending || isManualLoading) && ( -
-
+
+
diff --git a/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx b/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx index 9feea8a02..5cb8bf13d 100644 --- a/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx +++ b/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx @@ -203,4 +203,4 @@ function PrivacyLogPage({ }) { ); } -export {PrivacyLogPage }; +export { PrivacyLogPage }; From 5916d48e99ab510c84add9248414afb2c363d510 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 15:53:16 +0900 Subject: [PATCH 11/32] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B3=A0=EC=97=90?= =?UTF-8?q?=20=EC=8A=A4=EC=BC=88=EB=A0=88=ED=86=A4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/components/src/ui/header/index.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/common/components/src/ui/header/index.tsx b/packages/common/components/src/ui/header/index.tsx index 1b60b1c74..ce9419ef1 100644 --- a/packages/common/components/src/ui/header/index.tsx +++ b/packages/common/components/src/ui/header/index.tsx @@ -1,6 +1,6 @@ import "./header.css"; -import { useEffect, useCallback } from "react"; +import { useEffect, useCallback, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { images } from "@common/assets"; import { ENDPOINT } from "../../config"; @@ -20,10 +20,13 @@ import { } from "../dropdown-menu"; import { Button } from "../button"; import { SidebarTrigger } from "../sidebar"; +import { Skeleton } from "../skeleton"; const siteId = getCookie("site-id-key") ?? ""; export function Header({ viewOnly }: { viewOnly?: boolean }) { + const [mounted, setMounted] = useState(false); + const { data: userInfo } = useQuery({ queryKey: [ENDPOINT.USER_SERVICE.USERS], queryFn: () => getUserInfo(), @@ -96,12 +99,20 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) { return () => clearTimeout(timer); }, [userPopupList, openPopup]); + useEffect(() => { + setMounted(true); + }, []); + return (

- logo + {mounted ? ( + logo + ) : ( + + )} {siteInfo?.siteNm} From 8406d7449e5d98a62f44d6c06d7feaf5ef194527 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 15:58:28 +0900 Subject: [PATCH 12/32] =?UTF-8?q?chore:=20common/config=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=20getConfig=20=ED=95=A8=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common/config/src/initialize-config.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/common/config/src/initialize-config.ts b/packages/common/config/src/initialize-config.ts index f1d3178f5..2184db348 100644 --- a/packages/common/config/src/initialize-config.ts +++ b/packages/common/config/src/initialize-config.ts @@ -64,8 +64,5 @@ export function getViteConfig(): EnvConfig { } export function getConfig(): EnvConfig { - if (typeof import.meta?.env !== "undefined") { - return getViteConfig(); - } return getNextConfig(); } From b5d595cb0489f450b75a541d64cc73e1145c13ca Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 15:58:45 +0900 Subject: [PATCH 13/32] =?UTF-8?q?chore:=20=EA=B7=B8=EB=A3=B9=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EB=AA=A9=EB=A1=9D=20columns=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/src/entities/group-user/model/group-user-interface.ts | 1 + apps/cs/src/pages/groups/model/group-users-table-columns.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/cs/src/entities/group-user/model/group-user-interface.ts b/apps/cs/src/entities/group-user/model/group-user-interface.ts index 38daf6fe0..8935bfacc 100644 --- a/apps/cs/src/entities/group-user/model/group-user-interface.ts +++ b/apps/cs/src/entities/group-user/model/group-user-interface.ts @@ -10,6 +10,7 @@ export interface GroupUserListResponseDto { mode: string; groupId: string; userUnqId: string; + userId: string; userName: string; ogdpSeCd: string; ogdpSeNm: string; diff --git a/apps/cs/src/pages/groups/model/group-users-table-columns.tsx b/apps/cs/src/pages/groups/model/group-users-table-columns.tsx index 8d1054aac..e525ac7ab 100644 --- a/apps/cs/src/pages/groups/model/group-users-table-columns.tsx +++ b/apps/cs/src/pages/groups/model/group-users-table-columns.tsx @@ -26,7 +26,7 @@ export const columns: ColumnDef[] = [ enableHiding: false, }, { - accessorKey: "groupId", + accessorKey: "userId", header: "사용자ID", }, { From f915f8ab4b46ebc3e7562ae2768045c44808bbff Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 16:13:26 +0900 Subject: [PATCH 14/32] =?UTF-8?q?remove:=20getClientIp=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/app/api/getClientIp/route.ts | 16 ------- apps/cs/src/entities/ip/index.ts | 1 - .../src/entities/ip/lib/client-ip-guard.tsx | 48 ------------------- 3 files changed, 65 deletions(-) delete mode 100644 apps/cs/app/api/getClientIp/route.ts delete mode 100644 apps/cs/src/entities/ip/lib/client-ip-guard.tsx diff --git a/apps/cs/app/api/getClientIp/route.ts b/apps/cs/app/api/getClientIp/route.ts deleted file mode 100644 index ec9ff72d5..000000000 --- a/apps/cs/app/api/getClientIp/route.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; - -export async function GET(request: NextRequest) { - const ipAddress = - request.headers.get("x-forwarded-for")?.split(",")[0] || "unknown"; - - const ipv4Regex = /^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/; - const match = ipAddress.match(ipv4Regex); - - const normalizedIp = match ? match[1] : ipAddress; - - return NextResponse.json({ - originalIp: ipAddress, - normalizedIp: normalizedIp, - }); -} diff --git a/apps/cs/src/entities/ip/index.ts b/apps/cs/src/entities/ip/index.ts index ef1c5be33..2d244138d 100644 --- a/apps/cs/src/entities/ip/index.ts +++ b/apps/cs/src/entities/ip/index.ts @@ -7,4 +7,3 @@ export { type IpList, type IP, } from "./model/ip-interface"; -export { ClientIpGuard } from "./lib/client-ip-guard"; diff --git a/apps/cs/src/entities/ip/lib/client-ip-guard.tsx b/apps/cs/src/entities/ip/lib/client-ip-guard.tsx deleted file mode 100644 index f3ae452ce..000000000 --- a/apps/cs/src/entities/ip/lib/client-ip-guard.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { useEffect, useState } from "react"; -import { useQueryClient } from "@tanstack/react-query"; -import { SiteApi } from "@/entities/site/@x/ip"; -import { ENDPOINT, SITE_ID } from "@/shared/config"; -import { IpApi } from "../api/ip-service"; - -type ClientIpResponse = { - originalIp: string; - normalizedIp: string; -}; - -const ClientIpGuard = ({ children }: { children: React.ReactNode }) => { - const queryClient = useQueryClient(); - const [isAllowed, setIsAllowed] = useState(true); - - useEffect(() => { - (async () => { - const response = await fetch("/api/getClientIp"); - const { normalizedIp } = (await response.json()) as ClientIpResponse; - - if (!normalizedIp || !SITE_ID) return; - - const siteInfo = await queryClient.ensureQueryData({ - queryKey: [ENDPOINT.CMS_SERVICE.SITES, SITE_ID], - queryFn: () => SiteApi.siteDetail(SITE_ID), - }); - - if (siteInfo.siteKndCd === "O") return; - - const { content: ipList } = await IpApi.getIpList({ - siteId: SITE_ID, - prmYn: "Y", - }); - - const allowedClientIp = ipList.some((ip) => ip.ipAddr === normalizedIp); - setIsAllowed(allowedClientIp); - })(); - }, []); - - if (!isAllowed) { - alert("허용되지 않은 IP로 접근하였습니다."); - return <>; - } - - return <>{children}; -}; - -export { ClientIpGuard }; From 2ee413e077c8cffaef60a88bde1c7b1378890989 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 30 Jun 2025 16:55:34 +0900 Subject: [PATCH 15/32] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/app/api/auth/logout/route.ts | 17 +++++++++++++++++ .../common/components/src/ui/header/index.tsx | 14 +++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 apps/cs/app/api/auth/logout/route.ts diff --git a/apps/cs/app/api/auth/logout/route.ts b/apps/cs/app/api/auth/logout/route.ts new file mode 100644 index 000000000..fdcc9df7c --- /dev/null +++ b/apps/cs/app/api/auth/logout/route.ts @@ -0,0 +1,17 @@ +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; +import { + ACCESS_TOKEN, + AUTH_USER_ID, + CLAIM_NAME, + REFRESH_TOKEN, +} from "@/shared/config"; + +export async function POST() { + const cookieStore = await cookies(); + cookieStore.delete(ACCESS_TOKEN); + cookieStore.delete(REFRESH_TOKEN); + cookieStore.delete(AUTH_USER_ID); + cookieStore.delete(CLAIM_NAME); + return NextResponse.json({ message: "Logged out" }, { status: 200 }); +} diff --git a/packages/common/components/src/ui/header/index.tsx b/packages/common/components/src/ui/header/index.tsx index ce9419ef1..433435009 100644 --- a/packages/common/components/src/ui/header/index.tsx +++ b/packages/common/components/src/ui/header/index.tsx @@ -52,6 +52,18 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) { queryFn: () => getUserPopupList(), }); + const logout = async () => { + try { + const response = await fetch("/api/auth/logout", { + method: "POST", + }); + if (!response.ok) throw new Error("Failed to logout"); + window.location.href = "/auth/login"; + } catch (error) { + console.error(error); + } + }; + const openPopup = useCallback(async (popup: Popup) => { try { const cookieName = `cs-popup-hide-for-day-${popup.popupSn}`; @@ -139,7 +151,7 @@ export function Header({ viewOnly }: { viewOnly?: boolean }) {

접속 IP

- 로그아웃 + 로그아웃
From 9f0d984a94fe7f4d9da7e9a573a77c1ba7da57fa Mon Sep 17 00:00:00 2001 From: jcchoi Date: Mon, 30 Jun 2025 16:59:09 +0900 Subject: [PATCH 16/32] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 가이드 추가 --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index ba078fb13..0e0043129 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,26 @@ rm -rf node_modules pnpm-lock.yaml pnpm install ``` +### 8. 로그아웃 처리 가이드 + + * 참고 파일 + - apps/cs/app/api/auth/logout/route.ts + - packages/common/components/src/ui/header/index.tsx (55-65 line) + +각 서비스 폴더에 ‘/app/api/auth/logout/route.ts’ 생성해야 합니다(코드는 cs에서 확인). + +** 로그아웃 처리되면 ‘/auth/login’ 페이지로 이동됩니다. + +### 9. 'SITE_ID’ 환경변수를 쿠키로 대체하는 가이드(공통 모듈 사용하기위한 필수 사항) + + * 참고 파일: apps/cs/src/shared/api/client.ts (쿠키 저장 처리) + apps/cs/src/shared/lib/cookie.ts (쿠키 공통 모듈) + + `SITE_ID` 환경변수를 처음 사용하는 파일 또는 최상단 클라이언트 컴포넌트에서 “site-id-key” 쿠키에 `SITE_ID` 저장 + + + + ## 기술 스택 - React(^18) From 419099d233853810fba4ac3843127c503dc87536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=B2=A0?= Date: Mon, 30 Jun 2025 19:33:31 +0900 Subject: [PATCH 17/32] =?UTF-8?q?=ED=8D=BC=EA=B0=80=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/widgets/post/ui/post-action.tsx | 22 + pnpm-lock.yaml | 3690 +++++++++-------- 2 files changed, 1994 insertions(+), 1718 deletions(-) diff --git a/apps/common/features/src/widgets/post/ui/post-action.tsx b/apps/common/features/src/widgets/post/ui/post-action.tsx index 4eaa960cb..eb0acef5f 100644 --- a/apps/common/features/src/widgets/post/ui/post-action.tsx +++ b/apps/common/features/src/widgets/post/ui/post-action.tsx @@ -2,6 +2,7 @@ import { useRouter, usePathname } from "next/navigation"; import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { Button } from "@common/components"; import { useMenuStore, useUserStore } from "@/shared/lib"; +import { useState } from 'react'; type PostActionProps = { bbsId: string; @@ -16,6 +17,7 @@ function PostAction({ children, handleDelete }: PostActionProps) { const { confirm } = useConfirm(); const bbsInfo = useMenuStore((state) => state.bbsInfo); const userInfo = useUserStore((state) => state.userInfo); + const [copied, setCopied] = useState(false); const onDelete = async () => { if (await confirm("삭제하시겠습니까?")) handleDelete(); @@ -33,11 +35,31 @@ function PostAction({ children, handleDelete }: PostActionProps) { // 비회원 return true; }; + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(window.location.href); + setCopied(true); + setTimeout(() => setCopied(false), 2000); // 2초 후 상태 초기화 + alert("복사되었습니다..") + } catch (err) { + console.error('복사 실패:', err); + } + }; + return ( <> {children}
+ + + ); +} + +export { AuthorityButton }; diff --git a/apps/common/features/src/widgets/post/ui/post-action.tsx b/apps/common/features/src/widgets/post/ui/post-action.tsx index 4eaa960cb..b063f7636 100644 --- a/apps/common/features/src/widgets/post/ui/post-action.tsx +++ b/apps/common/features/src/widgets/post/ui/post-action.tsx @@ -2,21 +2,24 @@ import { useRouter, usePathname } from "next/navigation"; import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { Button } from "@common/components"; import { useMenuStore, useUserStore } from "@/shared/lib"; +import { AuthorityButton } from "@/entities/menu-authority"; type PostActionProps = { - bbsId: string; - pstNo: string; + registerId?: string; children: React.ReactNode; handleDelete: () => Promise; }; -function PostAction({ children, handleDelete }: PostActionProps) { +function PostAction({ registerId, children, handleDelete }: PostActionProps) { const router = useRouter(); const pathname = usePathname(); const { confirm } = useConfirm(); const bbsInfo = useMenuStore((state) => state.bbsInfo); const userInfo = useUserStore((state) => state.userInfo); + const actionButtonAuthrt = + userInfo?.adminRoleYn === "Y" || userInfo?.userUnqId === registerId; + const onDelete = async () => { if (await confirm("삭제하시겠습니까?")) handleDelete(); }; @@ -46,15 +49,19 @@ function PostAction({ children, handleDelete }: PostActionProps) { > 목록 - + {actionButtonAuthrt && ( + router.push(`${pathname}/modify`)} + > + 수정 + + )} {bbsInfo?.ansUseYn === "Y" && ( - + + )} + {actionButtonAuthrt && ( + + 삭제 + )} -
); diff --git a/apps/common/features/src/widgets/post/ui/post.tsx b/apps/common/features/src/widgets/post/ui/post.tsx index bd8db7c21..8033938cf 100644 --- a/apps/common/features/src/widgets/post/ui/post.tsx +++ b/apps/common/features/src/widgets/post/ui/post.tsx @@ -125,7 +125,7 @@ function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { return ( <> - +

{postData?.pstTtl} From 0dad2a0e508989528839328e89e3fed746d071d1 Mon Sep 17 00:00:00 2001 From: bicochan Date: Tue, 1 Jul 2025 16:29:03 +0900 Subject: [PATCH 26/32] =?UTF-8?q?[common/features]=20chore:=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20api=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/features/src/entities/post/api/post-service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/features/src/entities/post/api/post-service.ts b/apps/common/features/src/entities/post/api/post-service.ts index 1e5ac5146..0d1cc7fe0 100644 --- a/apps/common/features/src/entities/post/api/post-service.ts +++ b/apps/common/features/src/entities/post/api/post-service.ts @@ -26,7 +26,7 @@ export class PostApiService implements PostService { public async getPostInfo(bbsId: number, pstNo: number): Promise { const response = await client.get( - `${ENDPOINT.BOARD_SERVICE.POSTS_USER}/${bbsId}/${pstNo}`, + `${ENDPOINT.BOARD_SERVICE.POSTS_USER}/edit/${bbsId}/${pstNo}`, ); return response.data; } From de0958acbe0e56471cfdfd65ce5c906a7283bb02 Mon Sep 17 00:00:00 2001 From: bicochan Date: Tue, 1 Jul 2025 16:49:54 +0900 Subject: [PATCH 27/32] =?UTF-8?q?[common/features]=20refactor:=20PageLayou?= =?UTF-8?q?t=20menuPaths=20=EC=BF=BC=EB=A6=AC=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/(with-base-layout)/(pst)/layout.tsx | 19 ++++++++---- .../src/entities/menu/api/menu-service.ts | 13 ++++++-- .../features/src/entities/menu/index.ts | 2 +- .../features/src/entities/menu/lib/utils.ts | 6 ++-- .../src/entities/menu/model/menu-interface.ts | 30 +++++++++++++++---- 5 files changed, 52 insertions(+), 18 deletions(-) diff --git a/apps/common/features/app/(with-base-layout)/(pst)/layout.tsx b/apps/common/features/app/(with-base-layout)/(pst)/layout.tsx index 3f700d076..f181eb64f 100644 --- a/apps/common/features/app/(with-base-layout)/(pst)/layout.tsx +++ b/apps/common/features/app/(with-base-layout)/(pst)/layout.tsx @@ -1,6 +1,9 @@ "use client"; -import { useMenuStore } from "@/shared/lib"; +import { useQuery } from "@tanstack/react-query"; +import { MenuApi } from "@/entities/menu"; +import { ENDPOINT } from "@/shared/config"; +import { getCookie, useMenuStore } from "@/shared/lib"; import { PageLayout } from "@/shared/ui/page-layout"; export default function PostLayout({ @@ -8,13 +11,19 @@ export default function PostLayout({ }: { children: React.ReactNode; }) { + const menuCd = getCookie("menu-code-key"); const bbsInfo = useMenuStore((state) => state.bbsInfo); + const { data } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.MENUS, menuCd], + queryFn: () => MenuApi.getMenuInfo(menuCd!), + enabled: !!menuCd, + }); + + const menuPaths = data?.menuPath?.split(">").map((path) => path.trim()); + return ( - + {children} ); diff --git a/apps/common/features/src/entities/menu/api/menu-service.ts b/apps/common/features/src/entities/menu/api/menu-service.ts index 4424f8d37..055bc9371 100644 --- a/apps/common/features/src/entities/menu/api/menu-service.ts +++ b/apps/common/features/src/entities/menu/api/menu-service.ts @@ -1,14 +1,21 @@ import { client } from "@/shared/api"; import { ENDPOINT } from "@/shared/config"; -import type { MenuItem, MenuService } from "../model/menu-interface"; +import type { MenuInfo, MenuRole, MenuService } from "../model/menu-interface"; export class MenuApiService implements MenuService { - async getMenuRoles(siteId: string): Promise { - const response = await client.get( + async getMenuRoles(siteId: string): Promise { + const response = await client.get( `${ENDPOINT.CMS_SERVICE.MENU_ROLES}/${siteId}`, ); return response.data; } + + async getMenuInfo(menuCd: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`, + ); + return response.data; + } } export const MenuApi = new MenuApiService(); diff --git a/apps/common/features/src/entities/menu/index.ts b/apps/common/features/src/entities/menu/index.ts index 04f63e38b..730326591 100644 --- a/apps/common/features/src/entities/menu/index.ts +++ b/apps/common/features/src/entities/menu/index.ts @@ -1,2 +1,2 @@ +export { MenuApi } from "./api/menu-service"; export { MenuWrapper } from "./lib/menu-wrapper"; -export type { MenuItem } from "./model/menu-interface"; diff --git a/apps/common/features/src/entities/menu/lib/utils.ts b/apps/common/features/src/entities/menu/lib/utils.ts index 1cf4514d9..bb2fadb88 100644 --- a/apps/common/features/src/entities/menu/lib/utils.ts +++ b/apps/common/features/src/entities/menu/lib/utils.ts @@ -1,9 +1,9 @@ -import type { MenuItem } from "../model/menu-interface"; +import type { MenuRole } from "../model/menu-interface"; export const getCurrentMenu = ( - menus: MenuItem[], + menus: MenuRole[], pathname: string, -): MenuItem | null => { +): MenuRole | null => { for (const menu of menus) { if ( menu.urlPath !== "" && diff --git a/apps/common/features/src/entities/menu/model/menu-interface.ts b/apps/common/features/src/entities/menu/model/menu-interface.ts index 12c7d007a..885e02745 100644 --- a/apps/common/features/src/entities/menu/model/menu-interface.ts +++ b/apps/common/features/src/entities/menu/model/menu-interface.ts @@ -1,11 +1,8 @@ -export interface MenuItem { +interface Menu { menuCd: number; menuKornNm: string; menuEngNm: string; - parentId: number | null; sortSeq: number; - iconNm?: string; - children: MenuItem[] | null; levelNo: number; urlPath: string; menuLnkgTypeCd: string; @@ -15,9 +12,30 @@ export interface MenuItem { useYn: string; otptYn: string; newWndwYn: string; +} + +export interface MenuRole extends Menu { + parentId: number | null; + iconNm?: string; + children: MenuRole[] | null; requiredUrlPath: boolean; } -export interface MenuService { - getMenuRoles(siteId: string): Promise; +export interface MenuInfo extends Menu { + siteId: string; + menuSubKornNm: string; + menuSubEngNm: string; + iconName: string; + menuLnkgTypeCdNm: string; + prntMenuCd: number; + evlUseYn: string; + menuLnkgSnNm: string; + menuPicUserUnqId: string; + menuPicUserUnqIdNm: string; + menuPicDsgnYmd: string; +} + +export interface MenuService { + getMenuRoles(siteId: string): Promise; + getMenuInfo(menuCd: string): Promise; } From 05c9345e0160013b8fda23119750ae5d3b94be23 Mon Sep 17 00:00:00 2001 From: bicochan Date: Tue, 1 Jul 2025 17:09:40 +0900 Subject: [PATCH 28/32] =?UTF-8?q?[apps/cs,=20common/features]=20refactor:?= =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EB=AC=BC=20=EC=A1=B0=ED=9A=8C=20api=20'an?= =?UTF-8?q?sUseYn'=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/src/entities/post/model/post-interface.ts | 1 + .../features/src/widgets/post/model/post-table-columns.tsx | 5 +++-- apps/common/features/src/widgets/post/ui/post-page.tsx | 1 + apps/cs/src/entities/post/model/post-interface.ts | 1 + apps/cs/src/widgets/post/model/post-table-columns.tsx | 5 +++-- apps/cs/src/widgets/post/ui/post-page.tsx | 1 + 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/common/features/src/entities/post/model/post-interface.ts b/apps/common/features/src/entities/post/model/post-interface.ts index 11778002f..1b6b14953 100644 --- a/apps/common/features/src/entities/post/model/post-interface.ts +++ b/apps/common/features/src/entities/post/model/post-interface.ts @@ -9,6 +9,7 @@ export interface PostParams extends PageableParams { prdPstgYn?: string; siteId?: string; bbsTypeCd?: string; + ansUseYn?: string; } export interface Post { diff --git a/apps/common/features/src/widgets/post/model/post-table-columns.tsx b/apps/common/features/src/widgets/post/model/post-table-columns.tsx index 2084b69ac..2e4f14d2f 100644 --- a/apps/common/features/src/widgets/post/model/post-table-columns.tsx +++ b/apps/common/features/src/widgets/post/model/post-table-columns.tsx @@ -50,12 +50,13 @@ export const columns: ColumnDef[] = [ accessorKey: "pstTtl", header: "제목", cell: ({ row }) => { - const { ansPstn, pstTtl, inqNocs, cmntCnt } = row.original; + const { ansPstn = 0, pstTtl, inqNocs, cmntCnt } = row.original; + const indentPadding = ansPstn > 0 ? (ansPstn - 1) * 20 : 0; return (
{ansPstn > 0 && (
diff --git a/apps/common/features/src/widgets/post/ui/post-page.tsx b/apps/common/features/src/widgets/post/ui/post-page.tsx index f53af0ee8..3e7d74f04 100644 --- a/apps/common/features/src/widgets/post/ui/post-page.tsx +++ b/apps/common/features/src/widgets/post/ui/post-page.tsx @@ -81,6 +81,7 @@ function PostPage({ bbsId }: { bbsId: string }) { queryFn: () => PostApi.getPostList(parseInt(bbsId), { ...postParams, + ansUseYn: bbsInfo?.ansUseYn, page: pagination.pageIndex, size: pagination.pageSize, }), diff --git a/apps/cs/src/entities/post/model/post-interface.ts b/apps/cs/src/entities/post/model/post-interface.ts index 86e27afd5..783053dd7 100644 --- a/apps/cs/src/entities/post/model/post-interface.ts +++ b/apps/cs/src/entities/post/model/post-interface.ts @@ -9,6 +9,7 @@ export interface PostParams extends PageableParams { prdPstgYn?: string; siteId?: string; bbsTypeCd?: string; + ansUseYn?: string; } export interface RecentPostParams extends PageableParams { diff --git a/apps/cs/src/widgets/post/model/post-table-columns.tsx b/apps/cs/src/widgets/post/model/post-table-columns.tsx index c16f7a931..596fbc1a8 100644 --- a/apps/cs/src/widgets/post/model/post-table-columns.tsx +++ b/apps/cs/src/widgets/post/model/post-table-columns.tsx @@ -51,12 +51,13 @@ export const columns: ColumnDef[] = [ accessorKey: "pstTtl", header: "제목", cell: ({ row }) => { - const { ansPstn, pstTtl, inqNocs, cmntCnt } = row.original; + const { ansPstn = 0, pstTtl, inqNocs, cmntCnt } = row.original; + const indentPadding = ansPstn > 0 ? (ansPstn - 1) * 20 : 0; return (
{ansPstn > 0 && (
diff --git a/apps/cs/src/widgets/post/ui/post-page.tsx b/apps/cs/src/widgets/post/ui/post-page.tsx index 75384ad13..af4a01fc7 100644 --- a/apps/cs/src/widgets/post/ui/post-page.tsx +++ b/apps/cs/src/widgets/post/ui/post-page.tsx @@ -83,6 +83,7 @@ function PostPage({ bbsId }: { bbsId: string }) { PostApi.getPostList(parseInt(bbsId), { ...postParams, bbsTypeCd: bbsInfo?.bbsTypeCd, + ansUseYn: bbsInfo?.ansUseYn, page: pagination.pageIndex, size: pagination.pageSize, }), From b001e2861bd2d448b752803332e76fdd4e91b8da Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 2 Jul 2025 09:32:11 +0900 Subject: [PATCH 29/32] =?UTF-8?q?[common/features]=20fix:=20=EB=B9=8C?= =?UTF-8?q?=EB=93=9C=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/features/app/(with-base-layout)/layout.tsx | 4 ++-- apps/common/features/src/entities/menu/index.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/common/features/app/(with-base-layout)/layout.tsx b/apps/common/features/app/(with-base-layout)/layout.tsx index 970ccce5e..5bbd7d024 100644 --- a/apps/common/features/app/(with-base-layout)/layout.tsx +++ b/apps/common/features/app/(with-base-layout)/layout.tsx @@ -3,7 +3,7 @@ import { usePathname, useRouter } from "next/navigation"; import { useQueryClient } from "@tanstack/react-query"; import { BaseLayout } from "@common/components"; -import type { MenuItem } from "@/entities/menu"; +import type { MenuRole } from "@/entities/menu"; import { useMenuStore } from "@/shared/lib"; export default function WithBaseLayout({ @@ -17,7 +17,7 @@ export default function WithBaseLayout({ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo); - const handleMenuClick = (item: MenuItem) => { + const handleMenuClick = (item: MenuRole) => { setCurrentMenuInfo(item); router.push(item.urlPath); }; diff --git a/apps/common/features/src/entities/menu/index.ts b/apps/common/features/src/entities/menu/index.ts index 730326591..458867586 100644 --- a/apps/common/features/src/entities/menu/index.ts +++ b/apps/common/features/src/entities/menu/index.ts @@ -1,2 +1,3 @@ export { MenuApi } from "./api/menu-service"; export { MenuWrapper } from "./lib/menu-wrapper"; +export type { MenuRole } from "./model/menu-interface"; From 5092dfa6e6ba268ac182f9984311288aa9e12812 Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 2 Jul 2025 09:33:07 +0900 Subject: [PATCH 30/32] =?UTF-8?q?[apps/cs]=20chore:=20menu=20wrapper=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20pathname=20=EB=B3=80=EA=B2=BD=EB=90=A0=20?= =?UTF-8?q?=EB=95=8C=EB=A7=88=EB=8B=A4=20=EC=8B=A4=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/src/entities/menu/lib/menu-wrapper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cs/src/entities/menu/lib/menu-wrapper.tsx b/apps/cs/src/entities/menu/lib/menu-wrapper.tsx index 7ecf2e6dd..1f1080cac 100644 --- a/apps/cs/src/entities/menu/lib/menu-wrapper.tsx +++ b/apps/cs/src/entities/menu/lib/menu-wrapper.tsx @@ -43,7 +43,7 @@ const MenuWrapper = ({ children }: { children: React.ReactNode }) => { const response = await getPageMenuAuthority(); if (response?.length) setPageMenuAuthority(response[0]!); })(); - }, []); + }, [pathname]); useEffect(() => { if (!pageMenuAuthority) return; From 4723d90658b301ef70b1e1205c2b7a1d3dc387f3 Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 2 Jul 2025 09:54:19 +0900 Subject: [PATCH 31/32] =?UTF-8?q?[common/features,=20apps/cs]=20feat:=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=A0=95=EB=A0=AC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/shared/model/api-interface.ts | 2 +- .../src/widgets/post/ui/post-page.tsx | 22 ++++++++++++++- apps/cs/src/widgets/post/ui/post-page.tsx | 27 ++++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/apps/common/features/src/shared/model/api-interface.ts b/apps/common/features/src/shared/model/api-interface.ts index 133c0c401..8218bfb0d 100644 --- a/apps/common/features/src/shared/model/api-interface.ts +++ b/apps/common/features/src/shared/model/api-interface.ts @@ -30,5 +30,5 @@ export interface PageableList { export interface PageableParams { page?: number; size?: number; - sort?: string[]; + sort?: string; } diff --git a/apps/common/features/src/widgets/post/ui/post-page.tsx b/apps/common/features/src/widgets/post/ui/post-page.tsx index 3e7d74f04..5a459835f 100644 --- a/apps/common/features/src/widgets/post/ui/post-page.tsx +++ b/apps/common/features/src/widgets/post/ui/post-page.tsx @@ -42,6 +42,7 @@ function PostPage({ bbsId }: { bbsId: string }) { const { bbsInfo, pageMenuAuthority } = useMenuStore((state) => state); const thumbRefs = useRef>(new Map()); + const [tableSort, setTableSort] = useState(""); const [postParams, setPostParams] = useState({ keywordType: "title", keyword: "", @@ -77,13 +78,14 @@ function PostPage({ bbsId }: { bbsId: string }) { isLoading, refetch, } = useQuery({ - queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pagination], + queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pagination, tableSort], queryFn: () => PostApi.getPostList(parseInt(bbsId), { ...postParams, ansUseYn: bbsInfo?.ansUseYn, page: pagination.pageIndex, size: pagination.pageSize, + sort: tableSort, }), }); @@ -201,6 +203,24 @@ function PostPage({ bbsId }: { bbsId: string }) { ))} +
diff --git a/apps/cs/src/widgets/post/ui/post-page.tsx b/apps/cs/src/widgets/post/ui/post-page.tsx index af4a01fc7..a37cdec84 100644 --- a/apps/cs/src/widgets/post/ui/post-page.tsx +++ b/apps/cs/src/widgets/post/ui/post-page.tsx @@ -46,6 +46,7 @@ function PostPage({ bbsId }: { bbsId: string }) { const bbsInfo = useMenuStore((state) => state.bbsInfo); const thumbRefs = useRef>(new Map()); + const [tableSort, setTableSort] = useState(""); const [postParams, setPostParams] = useState({ keywordType: "title", keyword: "", @@ -78,7 +79,12 @@ function PostPage({ bbsId }: { bbsId: string }) { isLoading, refetch, } = useQuery({ - queryKey: [ENDPOINT.BOARD_SERVICE.POSTS, bbsInfo?.bbsTypeCd, pagination], + queryKey: [ + ENDPOINT.BOARD_SERVICE.POSTS, + bbsInfo?.bbsTypeCd, + pagination, + tableSort, + ], queryFn: () => PostApi.getPostList(parseInt(bbsId), { ...postParams, @@ -86,6 +92,7 @@ function PostPage({ bbsId }: { bbsId: string }) { ansUseYn: bbsInfo?.ansUseYn, page: pagination.pageIndex, size: pagination.pageSize, + sort: tableSort, }), enabled: !!bbsInfo?.bbsTypeCd, }); @@ -205,6 +212,24 @@ function PostPage({ bbsId }: { bbsId: string }) { ))} +

From bba2b1db2ce605579c21b32253ba25ab5681c77f Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 2 Jul 2025 10:00:23 +0900 Subject: [PATCH 32/32] =?UTF-8?q?[common/features]=20feat:=20getPostEditIn?= =?UTF-8?q?fo=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/src/entities/post/api/post-service.ts | 10 ++++++++++ .../features/src/entities/post/model/post-interface.ts | 1 + .../features/src/pages/(pst)/faq/ui/modify-page.tsx | 2 +- .../features/src/pages/(pst)/image/ui/modify-page.tsx | 2 +- .../features/src/pages/(pst)/movie/ui/modify-page.tsx | 2 +- .../features/src/pages/(pst)/normal/ui/modify-page.tsx | 2 +- .../features/src/pages/(pst)/notice/ui/modify-page.tsx | 2 +- 7 files changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/common/features/src/entities/post/api/post-service.ts b/apps/common/features/src/entities/post/api/post-service.ts index 0d1cc7fe0..c7bd0c3af 100644 --- a/apps/common/features/src/entities/post/api/post-service.ts +++ b/apps/common/features/src/entities/post/api/post-service.ts @@ -25,6 +25,16 @@ export class PostApiService implements PostService { } public async getPostInfo(bbsId: number, pstNo: number): Promise { + const response = await client.get( + `${ENDPOINT.BOARD_SERVICE.POSTS_USER}/${bbsId}/${pstNo}`, + ); + return response.data; + } + + public async getPostEditInfo( + bbsId: number, + pstNo: number, + ): Promise { const response = await client.get( `${ENDPOINT.BOARD_SERVICE.POSTS_USER}/edit/${bbsId}/${pstNo}`, ); diff --git a/apps/common/features/src/entities/post/model/post-interface.ts b/apps/common/features/src/entities/post/model/post-interface.ts index 1b6b14953..de8c44891 100644 --- a/apps/common/features/src/entities/post/model/post-interface.ts +++ b/apps/common/features/src/entities/post/model/post-interface.ts @@ -78,6 +78,7 @@ export type PostUpdateFormData = z.infer; export interface PostService { getPostList(bbsId: number, params: PostParams): Promise; getPostInfo(bbsId: number, pstNo: number): Promise; + getPostEditInfo(bbsId: number, pstNo: number): Promise; createPost(data: PostFormData): Promise; updatePost( bbsId: number, diff --git a/apps/common/features/src/pages/(pst)/faq/ui/modify-page.tsx b/apps/common/features/src/pages/(pst)/faq/ui/modify-page.tsx index 6987cb0bc..5c25d21e0 100644 --- a/apps/common/features/src/pages/(pst)/faq/ui/modify-page.tsx +++ b/apps/common/features/src/pages/(pst)/faq/ui/modify-page.tsx @@ -20,7 +20,7 @@ function ModifyPage({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const { data: postInfo } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pstNo], - queryFn: () => PostApi.getPostInfo(parseInt(bbsId), parseInt(pstNo)), + queryFn: () => PostApi.getPostEditInfo(parseInt(bbsId), parseInt(pstNo)), }); const { mutateAsync: updatePost } = useMutation({ diff --git a/apps/common/features/src/pages/(pst)/image/ui/modify-page.tsx b/apps/common/features/src/pages/(pst)/image/ui/modify-page.tsx index d292fea42..a68d24a86 100644 --- a/apps/common/features/src/pages/(pst)/image/ui/modify-page.tsx +++ b/apps/common/features/src/pages/(pst)/image/ui/modify-page.tsx @@ -20,7 +20,7 @@ function ModifyPage({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const { data: postInfo } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pstNo], - queryFn: () => PostApi.getPostInfo(parseInt(bbsId), parseInt(pstNo)), + queryFn: () => PostApi.getPostEditInfo(parseInt(bbsId), parseInt(pstNo)), }); const { mutateAsync: updatePost } = useMutation({ diff --git a/apps/common/features/src/pages/(pst)/movie/ui/modify-page.tsx b/apps/common/features/src/pages/(pst)/movie/ui/modify-page.tsx index f9fc11f3d..815112523 100644 --- a/apps/common/features/src/pages/(pst)/movie/ui/modify-page.tsx +++ b/apps/common/features/src/pages/(pst)/movie/ui/modify-page.tsx @@ -20,7 +20,7 @@ function ModifyPage({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const { data: postInfo } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pstNo], - queryFn: () => PostApi.getPostInfo(parseInt(bbsId), parseInt(pstNo)), + queryFn: () => PostApi.getPostEditInfo(parseInt(bbsId), parseInt(pstNo)), }); const { mutateAsync: updatePost } = useMutation({ diff --git a/apps/common/features/src/pages/(pst)/normal/ui/modify-page.tsx b/apps/common/features/src/pages/(pst)/normal/ui/modify-page.tsx index c47b1999c..9c2ef6f5f 100644 --- a/apps/common/features/src/pages/(pst)/normal/ui/modify-page.tsx +++ b/apps/common/features/src/pages/(pst)/normal/ui/modify-page.tsx @@ -20,7 +20,7 @@ function ModifyPage({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const { data: postInfo } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pstNo], - queryFn: () => PostApi.getPostInfo(parseInt(bbsId), parseInt(pstNo)), + queryFn: () => PostApi.getPostEditInfo(parseInt(bbsId), parseInt(pstNo)), }); const { mutateAsync: updatePost } = useMutation({ diff --git a/apps/common/features/src/pages/(pst)/notice/ui/modify-page.tsx b/apps/common/features/src/pages/(pst)/notice/ui/modify-page.tsx index 7a46a7d6b..0e04d616a 100644 --- a/apps/common/features/src/pages/(pst)/notice/ui/modify-page.tsx +++ b/apps/common/features/src/pages/(pst)/notice/ui/modify-page.tsx @@ -20,7 +20,7 @@ function ModifyPage({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { const { data: postInfo } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_USER, bbsId, pstNo], - queryFn: () => PostApi.getPostInfo(parseInt(bbsId), parseInt(pstNo)), + queryFn: () => PostApi.getPostEditInfo(parseInt(bbsId), parseInt(pstNo)), }); const { mutateAsync: updatePost } = useMutation({