diff --git a/apps/common/features/src/entities/posting/ui/posting-dialog.tsx b/apps/common/features/src/entities/posting/ui/posting-dialog.tsx index 6bc8a02a7..bbb8afb8c 100644 --- a/apps/common/features/src/entities/posting/ui/posting-dialog.tsx +++ b/apps/common/features/src/entities/posting/ui/posting-dialog.tsx @@ -185,6 +185,15 @@ function PostingDialog({ postingType, postingTargets }: PostingDialogProps) { ...prev, [siteId]: value, })); + + // 상시 선택 시 게시 기간 미설정 + if (value === "99") { + handleUpdateFields(siteId)({ + pstgPrdSeCd: value, + }); + return; + } + setRememberPeriodDate((prev) => ({ ...prev, [siteId]: { from, to }, diff --git a/apps/common/features/src/pages/(post)/faq/ui/faq-page.tsx b/apps/common/features/src/pages/(post)/faq/ui/faq-page.tsx index aa67a17c5..6255bb27a 100644 --- a/apps/common/features/src/pages/(post)/faq/ui/faq-page.tsx +++ b/apps/common/features/src/pages/(post)/faq/ui/faq-page.tsx @@ -20,7 +20,7 @@ import { Skeleton, } from "@common/components"; import { AttachmentApi } from "@/entities/attachment"; -import { PostApi, type PostParams } from "@/entities/post"; +import { PostApi, PostPageGuard, type PostParams } from "@/entities/post"; import { useAlertStore, useMenuStore, useUserStore } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; import dayjs from "dayjs"; @@ -103,143 +103,147 @@ function FaqPage({ bbsId }: { bbsId: string }) { }; return ( -
-
-
- - - - setPostParams({ ...postParams, keyword: e.target.value }) - } - className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]" - /> - -
-
-
-
-
-

콘텐츠 목록

-
- {pageMenuAuthority?.regAuthrtYn === "Y" && ( - - )} - {pageMenuAuthority?.delAuthrtYn === "Y" && ( - - )} + +
+
+
+ + + + setPostParams({ ...postParams, keyword: e.target.value }) + } + className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]" + /> + +
+
+
+
+
+

콘텐츠 목록

+
+ {pageMenuAuthority?.regAuthrtYn === "Y" && ( + + )} + {pageMenuAuthority?.delAuthrtYn === "Y" && ( + + )} +
-
-
-
- e.stopPropagation()} - onCheckedChange={handleAllCheckboxChange} - /> - +
+
+ e.stopPropagation()} + onCheckedChange={handleAllCheckboxChange} + /> + +
+ {isFetched ? ( + + {postList?.content.map((item) => ( +
+ e.stopPropagation()} + onCheckedChange={(checked) => + handleCheckboxChange(item.pstNo, checked) + } + className="mx-2 my-6" + /> + + +
+
+ Q + {item.pstTtl} +
+ + 등록일: {dayjs(item.regDt).format("YYYY-MM-DD")} + +
+
+ +
+ + A + +
+
+                              {item.pstCn}
+                            
+ +
+
+ + +
+
+
+
+
+ ))} +
+ ) : ( + + )}
- {isFetched ? ( - - {postList?.content.map((item) => ( -
- e.stopPropagation()} - onCheckedChange={(checked) => - handleCheckboxChange(item.pstNo, checked) - } - className="mx-2 my-6" - /> - - -
-
- Q - {item.pstTtl} -
- - 등록일: {dayjs(item.regDt).format("YYYY-MM-DD")} - -
-
- -
- - A - -
-
-                            {item.pstCn}
-                          
- -
-
- - -
-
-
-
-
- ))} -
- ) : ( - - )}
-
+
); } diff --git a/apps/cs/middleware.ts b/apps/cs/middleware.ts index 61d38c071..79d2c8f65 100644 --- a/apps/cs/middleware.ts +++ b/apps/cs/middleware.ts @@ -1,5 +1,12 @@ import { NextRequest, NextResponse } from "next/server"; -import { CLAIM_NAME, AUTH_USER_ID } from "./src/shared/config"; +import { + CLAIM_NAME, + AUTH_USER_ID, + PORT, + PROXY_HOST, + SERVER_API_URL, + SITE_ID, +} from "./src/shared/config"; const serverApiUrl = process.env.NEXT_PUBLIC_SERVER_API_URL ?? "http://localhost:3000"; @@ -7,17 +14,23 @@ const serverApiUrl = export function middleware(req: NextRequest) { const pathname = req.nextUrl.pathname; const searchParams = req.nextUrl.searchParams; - + + const logMessages: string[] = [ + `[Middleware Request] ${new Date().toISOString()}`, + `[Environment]\n Mode: ${process.env.NODE_ENV}\n Port: ${PORT}\n Proxy Host: ${PROXY_HOST}\n Server API URL: ${SERVER_API_URL}\n Site ID: ${SITE_ID}`, + `[Request]\n Original Pathname: ${pathname}`, + ]; if (pathname.startsWith("/server")) { - - const decodedParams = Array.from(searchParams.entries()) - .map(([key, value]) => `${key}=${decodeURIComponent(value)}`) - .join("&"); - + const queryParams = searchParams.toString(); const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${ - decodedParams ? `?${decodedParams}` : "" + queryParams ? `?${queryParams}` : "" }`; + + logMessages.push(` Rewritten URL: ${newUrl}`); + logMessages.push("\n--------------------------------\n"); + console.log(logMessages.join("\n")); + return NextResponse.rewrite(new URL(newUrl)); } @@ -30,6 +43,10 @@ export function middleware(req: NextRequest) { if (token) requestHeaders.set(CLAIM_NAME, token); if (userId) requestHeaders.set(AUTH_USER_ID, userId); + logMessages.push(` Rewritten URL: ${newUrl}`); + logMessages.push("\n--------------------------------\n"); + console.log(logMessages.join("\n")); + return NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, }); @@ -39,6 +56,8 @@ export function middleware(req: NextRequest) { return NextResponse.redirect(new URL("/dashboard", req.url)); } + logMessages.push("\n--------------------------------\n"); + console.log(logMessages.join("\n")); return NextResponse.next(); } diff --git a/apps/cs/src/entities/content/model/contents-interface.ts b/apps/cs/src/entities/content/model/contents-interface.ts index 7709eea08..54e42729a 100644 --- a/apps/cs/src/entities/content/model/contents-interface.ts +++ b/apps/cs/src/entities/content/model/contents-interface.ts @@ -67,11 +67,22 @@ export const contentsDetailSchema = z.object({ useYn: z.string(), }); -export const contentsFormSchema = contentsDetailSchema.omit({ - contsVer: true, - aprvDt: true, - autzr: true, -}); +export const contentsFormSchema = contentsDetailSchema + .omit({ + contsVer: true, + aprvDt: true, + autzr: true, + }) + .extend({ + contsSn: z.number().optional(), + aprvCd: z + .enum([ + CONTENTS_APPROVE_STATUS.DRAFT, + CONTENTS_APPROVE_STATUS.REQUESTED, + CONTENTS_APPROVE_STATUS.APPROVED, + ]) + .optional(), + }); export type Contents = z.infer; export type ContentsDetail = z.infer; diff --git a/apps/cs/src/entities/posting/ui/posting-dialog.tsx b/apps/cs/src/entities/posting/ui/posting-dialog.tsx index f32f6afda..1ebe83a98 100644 --- a/apps/cs/src/entities/posting/ui/posting-dialog.tsx +++ b/apps/cs/src/entities/posting/ui/posting-dialog.tsx @@ -194,6 +194,15 @@ function PostingDialog({ ...prev, [siteId]: value, })); + + // 상시 선택 시 게시 기간 미설정 + if (value === "99") { + handleUpdateFields(siteId)({ + pstgPrdSeCd: value, + }); + return; + } + setRememberPeriodDate((prev) => ({ ...prev, [siteId]: { from, to }, diff --git a/apps/cs/src/entities/user/index.ts b/apps/cs/src/entities/user/index.ts index 7b4615e01..8927256f9 100644 --- a/apps/cs/src/entities/user/index.ts +++ b/apps/cs/src/entities/user/index.ts @@ -4,6 +4,7 @@ export { userSaveSchema, userPasswordUpdateSchema, userUpdateSchema, + type UserStateCode, type UserSearchParams, type UserListResponse, type UserSaveData, diff --git a/apps/cs/src/entities/user/model/user-interface.ts b/apps/cs/src/entities/user/model/user-interface.ts index 69320e8c7..012fe9e92 100644 --- a/apps/cs/src/entities/user/model/user-interface.ts +++ b/apps/cs/src/entities/user/model/user-interface.ts @@ -9,7 +9,8 @@ export const USER_STATE_CODE = { 삭제: "09", } as const; -type UserStateCode = (typeof USER_STATE_CODE)[keyof typeof USER_STATE_CODE]; +export type UserStateCode = + (typeof USER_STATE_CODE)[keyof typeof USER_STATE_CODE]; // 사용자 검색 파라미터 export interface UserSearchParams extends PageableParams { diff --git a/apps/cs/src/pages/(post)/faq/ui/faq-page.tsx b/apps/cs/src/pages/(post)/faq/ui/faq-page.tsx index 8ddd3006a..f23a70663 100644 --- a/apps/cs/src/pages/(post)/faq/ui/faq-page.tsx +++ b/apps/cs/src/pages/(post)/faq/ui/faq-page.tsx @@ -23,6 +23,7 @@ import { import { AttachmentApi } from "@/entities/attachment"; import { PostApi, + PostPageGuard, deleteReasonMessages, type PostParams, } from "@/entities/post"; @@ -120,143 +121,147 @@ function FaqPage({ bbsId }: { bbsId: string }) { }; return ( -
-
-
- - - - setPostParams({ ...postParams, keyword: e.target.value }) - } - className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]" - /> - -
-
-
-
-
-

콘텐츠 목록

-
- router.push(`${pathname}/register`)} - > - 등록 - - - 선택삭제 - + +
+
+
+ + + + setPostParams({ ...postParams, keyword: e.target.value }) + } + className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]" + /> + +
+
+
+
+
+

콘텐츠 목록

+
+ router.push(`${pathname}/register`)} + > + 등록 + + + 선택삭제 + +
-
-
-
- e.stopPropagation()} - onCheckedChange={handleAllCheckboxChange} - /> - +
+
+ e.stopPropagation()} + onCheckedChange={handleAllCheckboxChange} + /> + +
+ {isFetched ? ( + + {postList?.content.map((item) => ( +
+ e.stopPropagation()} + onCheckedChange={(checked) => + handleCheckboxChange(item.pstNo, checked) + } + className="mx-2 my-6" + /> + + +
+
+ Q + {item.pstTtl} +
+ + 등록일: {dayjs(item.regDt).format("YYYY-MM-DD")} + +
+
+ +
+ + A + +
+
+                              {item.pstCn}
+                            
+ +
+
+ + +
+
+
+
+
+ ))} +
+ ) : ( + + )}
- {isFetched ? ( - - {postList?.content.map((item) => ( -
- e.stopPropagation()} - onCheckedChange={(checked) => - handleCheckboxChange(item.pstNo, checked) - } - className="mx-2 my-6" - /> - - -
-
- Q - {item.pstTtl} -
- - 등록일: {dayjs(item.regDt).format("YYYY-MM-DD")} - -
-
- -
- - A - -
-
-                            {item.pstCn}
-                          
- -
-
- - -
-
-
-
-
- ))} -
- ) : ( - - )}
-
+
); } diff --git a/apps/cs/src/pages/admin/ui/admin-page.tsx b/apps/cs/src/pages/admin/ui/admin-page.tsx index 95d2c4e91..c2d3aa5af 100644 --- a/apps/cs/src/pages/admin/ui/admin-page.tsx +++ b/apps/cs/src/pages/admin/ui/admin-page.tsx @@ -38,7 +38,7 @@ function AdminPage() { const alert = useAlertStore((state) => state.setMessage); const { confirm } = useConfirm(); - const [keywordType, setKeywordType] = useState(""); + const [keywordType, setKeywordType] = useState("userId"); const [keyword, setKeyword] = useState(""); const [grpId, setGrpId] = useState(""); const [searchParams, setSearchParams] = useState({ diff --git a/apps/cs/src/pages/banner/model/posting-table-columns.tsx b/apps/cs/src/pages/banner/model/posting-table-columns.tsx index 3daee86f8..7d3b06a65 100644 --- a/apps/cs/src/pages/banner/model/posting-table-columns.tsx +++ b/apps/cs/src/pages/banner/model/posting-table-columns.tsx @@ -35,9 +35,14 @@ export const columns: ColumnDef[] = [ accessorKey: "pstgPrdSeNm", header: "게시기간", cell: ({ row }) => { + const pstgPrdSeCd = row.original.pstgPrdSeCd; const pstgPrdSeNm = row.original.pstgPrdSeNm; const pstgBgngDt = row.original.pstgBgngDt; const pstgEndDt = row.original.pstgEndDt; + + if (pstgPrdSeCd === "99") { + return pstgPrdSeNm; + } return `${pstgPrdSeNm} (${dayjs(pstgBgngDt).format("YYYY-MM-DD")} ~ ${dayjs(pstgEndDt).format("YYYY-MM-DD")})`; }, }, diff --git a/apps/cs/src/pages/contents/ui/create-page.tsx b/apps/cs/src/pages/contents/ui/create-page.tsx index dfbb2a9fb..6868d6937 100644 --- a/apps/cs/src/pages/contents/ui/create-page.tsx +++ b/apps/cs/src/pages/contents/ui/create-page.tsx @@ -34,7 +34,7 @@ function CreatePage() {

콘텐츠 등록

- +
); } diff --git a/apps/cs/src/pages/contents/ui/modify-page.tsx b/apps/cs/src/pages/contents/ui/modify-page.tsx index e783e9c1c..c6347ea59 100644 --- a/apps/cs/src/pages/contents/ui/modify-page.tsx +++ b/apps/cs/src/pages/contents/ui/modify-page.tsx @@ -1,5 +1,6 @@ "use client"; +import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useConfirm } from "@frontend-opensource/use-react-hooks"; @@ -24,6 +25,7 @@ import { useAlertStore, useMutationWrapper } from "@/shared/lib"; import { ContentsForm } from "./contents-form"; function ModifyPage({ sequential }: { sequential: string }) { + const router = useRouter(); const { confirm } = useConfirm(); const queryClient = useQueryClient(); const alert = useAlertStore((state) => state.setMessage); @@ -51,9 +53,11 @@ function ModifyPage({ sequential }: { sequential: string }) { mutationFn: (data: ContentsFormData) => ContentsApi.createContents(data), onSuccess: () => { setContsVer(0); - alert("수정되었습니다."); - queryClient.invalidateQueries({ - queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn], + alert("수정되었습니다.", () => { + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn], + }); + router.back(); }); }, }); @@ -62,7 +66,7 @@ function ModifyPage({ sequential }: { sequential: string }) { mutationFn: (data: ContentsFormData) => ContentsApi.updateContents(contsSn, contsVer, data), onSuccess: () => { - alert("수정되었습니다."); + alert("수정되었습니다.", router.back); }, }); @@ -70,9 +74,11 @@ function ModifyPage({ sequential }: { sequential: string }) { mutationFn: () => ContentsApi.deleteContents(contsSn, contsVer), onSuccess: () => { setContsVer(0); - alert("삭제되었습니다."); - queryClient.invalidateQueries({ - queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn], + alert("삭제되었습니다.", () => { + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS_DETAILS, contsSn], + }); + router.back(); }); }, }); diff --git a/apps/cs/src/pages/file/ui/file-page.tsx b/apps/cs/src/pages/file/ui/file-page.tsx index 8243d47d1..8b5eba617 100644 --- a/apps/cs/src/pages/file/ui/file-page.tsx +++ b/apps/cs/src/pages/file/ui/file-page.tsx @@ -39,8 +39,7 @@ function FilePage() { mutationFn: (atflId: string) => AttachmentApi.deleteAttachmentByAtflId(atflId), onSuccess: () => { - query.refetch(); - alert("삭제되었습니다."); + alert("삭제되었습니다.", query.refetch); }, }); diff --git a/apps/cs/src/pages/groups/ui/add-user-dialog.tsx b/apps/cs/src/pages/groups/ui/add-user-dialog.tsx index aafba70db..4f8a205ff 100644 --- a/apps/cs/src/pages/groups/ui/add-user-dialog.tsx +++ b/apps/cs/src/pages/groups/ui/add-user-dialog.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { keepPreviousData, useQuery, @@ -22,6 +22,7 @@ import { DialogFooter, Input, Checkbox, + Label, } from "@common/components"; import { UserApi, @@ -41,7 +42,8 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) { const alert = useAlertStore((state) => state.setMessage); const [open, setOpen] = useState(false); - const [userSearchQuery, setUserSearchQuery] = useState({ + const [userName, setUserName] = useState(""); + const [searchParam, setSearchParam] = useState({ userName: "", }); const [pagination, setPagination] = useState({ @@ -53,10 +55,10 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) { ); const query = useQuery({ - queryKey: [ENDPOINT.USER_SERVICE.USERS, userSearchQuery, pagination], + queryKey: [ENDPOINT.USER_SERVICE.USERS, searchParam, pagination], queryFn: () => UserApi.findPageUser({ - ...userSearchQuery, + ...searchParam, page: pagination.pageIndex, size: pagination.pageSize, }), @@ -118,6 +120,9 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) { onRowSelectionChange: setUserRowSelection, getRowId: (row) => row.userUnqId, }, + dataTableOptions: { + viewPagination: true, + }, }); const handleAddUsers = async () => { @@ -144,10 +149,30 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) { } }; - const handleSearch = () => { - setPagination({ pageIndex: 0, pageSize: 10 }); + const handleSearch = (e: React.FormEvent) => { + e.preventDefault(); + e.stopPropagation(); + setPagination({ + ...pagination, + pageIndex: 0, + }); + setSearchParam({ userName }); }; + const resetSearch = () => { + setPagination({ + pageIndex: 0, + pageSize: 10, + }); + setUserName(""); + setSearchParam({ userName: "" }); + setUserRowSelection({}); + }; + + useEffect(() => { + if (open) resetSearch(); + }, [open]); + return ( @@ -157,20 +182,31 @@ function AddUserDialog({ groupId }: AdditionalUserDialogProps) { 사용자 추가 -
- - setUserSearchQuery({ - ...userSearchQuery, - userName: e.target.value, - }) - } - className="!text-[1.3rem]" - placeholder="사용자 이름으로 검색" - /> - -
+
+
+ + setUserName(e.target.value)} + placeholder="사용자 이름으로 검색" + /> +
+ + +
{tableComponent}