-
{postData?.pstTtl}
-
-
- -
- 작성자: {postData?.wrtrNm}
-
- -
- 등록일: {dayjs(postData?.regDt).format("YYYY-MM-DD")}
-
- -
- 조회수: {postData?.inqNocs}
-
-
+ <>
+
+
+
+ {postData?.pstTtl}
+
+
+
+ -
+ 작성자: {postData?.wrtrNm}
+
+ -
+ 등록일: {dayjs(postData?.regDt).format("YYYY-MM-DD")}
+
+ -
+ 조회수: {postData?.inqNocs}
+
+
+
+
+ {bbsInfo?.bbsTypeCd === "BBSIMAGE" && (
+ <>
+ {isLoading && (
+
+
+
+ )}
+ {imageUrl && (
+
+
+
+ )}
+ >
+ )}
+ {bbsInfo?.bbsTypeCd === "BBSMOVIE" && (
+
+
+
+ )}
+
+ {postData?.pstCn ?? ""}
+
+ {isFetching ? (
+
+
+
+ ) : (
+ filename && (
+ <>
+
+
+ 첨부파일
+
+
+ >
+ )
+ )}
-
-
-
-
- 첨부파일
-
-
-
+
+
+ >
);
}
diff --git a/apps/common/features/src/widgets/post/ui/posting-period-selector.tsx b/apps/common/features/src/widgets/post/ui/posting-period-selector.tsx
new file mode 100644
index 000000000..9c23995a6
--- /dev/null
+++ b/apps/common/features/src/widgets/post/ui/posting-period-selector.tsx
@@ -0,0 +1,84 @@
+import dayjs from "dayjs";
+import { useState } from "react";
+import { CodeSelect } from "@/entities/code";
+import { DateRangePicker } from "@common/components";
+
+type PostingDate = {
+ pstgBgngDt: string | undefined;
+ pstgEndDt: string | undefined;
+};
+
+function PostingPeriodSelector({
+ defaultValues,
+ disabled,
+ handlePeriodValueChange,
+ handlePostingDateChange,
+}: {
+ defaultValues?: {
+ pstgPrdSeCd?: string | null;
+ pstgBgngDt?: string | null;
+ pstgEndDt?: string | null;
+ };
+ disabled: boolean;
+ handlePeriodValueChange: (periodCode: string, date?: PostingDate) => void;
+ handlePostingDateChange: (date?: PostingDate) => void;
+}) {
+ const [periodCode, setPeriodCode] = useState
(null);
+
+ const onPeriodCodeChange = (periodCode: string) => {
+ setPeriodCode(periodCode);
+ handlePeriodValueChange(periodCode, {
+ pstgBgngDt: `${dayjs().format("YYYY-MM-DD 00:00:00")}`,
+ pstgEndDt: `${dayjs().add(parseInt(periodCode), "day").format("YYYY-MM-DD 23:59:59")}`,
+ });
+ };
+
+ const onDateChange = (date?: {
+ from: Date | undefined;
+ to?: Date | undefined;
+ }) => {
+ handlePostingDateChange({
+ pstgBgngDt: dayjs(date?.from).format("YYYY-MM-DD 00:00:00"),
+ pstgEndDt: dayjs(date?.to).format("YYYY-MM-DD 23:59:59"),
+ });
+ };
+
+ const postingPeriodFormat = (periodCode: number | null) => {
+ if (!periodCode) return "";
+ if (periodCode === 99) return "상시";
+ return `${dayjs().format("YYYY-MM-DD")} ~ ${dayjs()
+ .add(periodCode, "day")
+ .format("YYYY-MM-DD")}`;
+ };
+
+ return (
+
+
+ {periodCode ? (
+
+ 게시 기간: {postingPeriodFormat(parseInt(periodCode))}
+
+ ) : (
+ defaultValues?.pstgBgngDt &&
+ defaultValues?.pstgEndDt && (
+
+ 게시 기간:{" "}
+
+ {dayjs(defaultValues?.pstgBgngDt).format("YYYY-MM-DD")} ~{" "}
+ {dayjs(defaultValues?.pstgEndDt).format("YYYY-MM-DD")}
+
+
+ )
+ )}
+ {periodCode === "0" && }
+
+ );
+}
+
+export { PostingPeriodSelector };
diff --git a/apps/common/features/src/widgets/post/ui/with-preview-file-uploader.tsx b/apps/common/features/src/widgets/post/ui/with-preview-file-uploader.tsx
new file mode 100644
index 000000000..760a3e7ef
--- /dev/null
+++ b/apps/common/features/src/widgets/post/ui/with-preview-file-uploader.tsx
@@ -0,0 +1,125 @@
+import Image from "next/image";
+import { useEffect, useState } from "react";
+import type { HttpResponse } from "tus-js-client";
+import type { FieldPath, UseFormReturn } from "react-hook-form";
+import { FileUploader, Label, Progress } from "@common/components";
+import { handleTusUpload } from "@/entities/tus";
+import { AttachmentApi, type Attachment } from "@/entities/attachment";
+import type { PostFormData, PostUpdateFormData } from "@/entities/post";
+import { setCookie, useAlertStore, useMenuStore } from "@/shared/lib";
+import type { BbsType } from "@/shared/store/menu-store";
+
+function WithPreviewFileUploader({
+ form,
+ attachmentData,
+}: {
+ form: UseFormReturn;
+ attachmentData?: Attachment[];
+}) {
+ const alert = useAlertStore((state) => state.setMessage);
+ const bbsInfo = useMenuStore((state) => state.bbsInfo);
+
+ const [thumbnailUrl, setThumbnailUrl] = useState("");
+ const [progress, setProgress] = useState(0);
+
+ const fileAccept = (bbsTypeCd: BbsType) => {
+ switch (bbsTypeCd) {
+ case "BBSIMAGE":
+ return ".jpeg,.jpg,.png";
+ case "BBSMOVIE":
+ return ".mp4,.mov,.avi,.wmv,.mkv";
+ default:
+ return "";
+ }
+ };
+
+ const handleTusResponse = async (res: HttpResponse) => {
+ const fileInfo = res.getHeader("X-File-Info");
+ if (
+ typeof fileInfo !== "string" ||
+ fileInfo === undefined ||
+ fileInfo === null
+ )
+ return;
+
+ const { atflCd, atflId } = JSON.parse(fileInfo) ?? {};
+ if (atflCd) form.setValue("atflCd" as FieldPath, atflCd);
+ if (atflId) {
+ let imageUrl = "";
+ if (bbsInfo?.bbsTypeCd === "BBSIMAGE") {
+ imageUrl = await AttachmentApi.getImageUrlByAtflId(atflId);
+ }
+ if (bbsInfo?.bbsTypeCd === "BBSMOVIE") {
+ imageUrl = await AttachmentApi.getMovieThumbnailUrlByAtflId(atflId);
+ }
+ setThumbnailUrl(imageUrl);
+ }
+ };
+
+ const handleProgress = (percentage: string) => {
+ setProgress(parseInt(percentage));
+ };
+
+ const onUpload = (e: React.ChangeEvent) => {
+ const files = e.target.files;
+ if (!files) return;
+ if (bbsInfo?.atflMaxCnt && files.length > bbsInfo.atflMaxCnt) {
+ alert("첨부파일 최대 개수를 초과했습니다.");
+ return;
+ }
+
+ for (const file of files) {
+ const fileSize = Math.round(file.size / 1024); // Byte -> KB
+ if (bbsInfo?.atflMaxFileSz && fileSize > bbsInfo.atflMaxFileSz) {
+ alert("첨부파일 최대 크기를 초과했습니다.");
+ return;
+ }
+ setCookie("atfl-cd-key", "");
+ handleTusUpload(file, {
+ handleResponse: handleTusResponse,
+ handleProgress,
+ });
+ }
+ };
+
+ useEffect(() => {
+ if (!attachmentData || attachmentData.length === 0) return;
+ (async () => {
+ const imageUrl = await AttachmentApi.getImageUrlByAtflId(
+ attachmentData[0]?.atflId as string,
+ );
+ setThumbnailUrl(imageUrl);
+ })();
+ }, [attachmentData]);
+
+ return (
+
+
+
+ {thumbnailUrl && (
+
+ )}
+
+
+
+
+ }
+ />
+ );
+}
+
+export { WithPreviewFileUploader };
diff --git a/apps/common/features/tailwind.config.ts b/apps/common/features/tailwind.config.ts
index 5f9a2750d..91117df86 100644
--- a/apps/common/features/tailwind.config.ts
+++ b/apps/common/features/tailwind.config.ts
@@ -5,11 +5,19 @@ import presetConfig from "../../../tailwind.config.preset";
export default {
presets: [presetConfig],
content: [
- "./src/**/*.{js,ts,jsx,tsx,mdx}",
- "../../../packages/common/components/src/ui/**/*.{js,ts,jsx,tsx,mdx}",
+ "./src/**/*.{js,ts,jsx,tsx}",
+ "../../../packages/common/components/src/ui/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
+ fontFamily: {
+ noto: ['"Noto Sans KR"', "sans-serif"],
+ },
+ colors: {
+ secondary: {
+ background: "var(--secondary-background)",
+ },
+ },
boxShadow: {
blur: "0 0 10px -1px rgba(0, 0, 0, 0.06)",
},
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/[pstNo]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/[pstNo]/page.tsx
new file mode 100644
index 000000000..7c8d6ee86
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/[pstNo]/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage } from "@/pages/(post)/faq";
+
+export default async function PstBbsFaqPostModifyPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/page.tsx
new file mode 100644
index 000000000..12fe535a5
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/page.tsx
@@ -0,0 +1,10 @@
+import { FaqPage } from "@/pages/(post)/faq";
+
+export default async function PstBbsFaqPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/register/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/register/page.tsx
new file mode 100644
index 000000000..e768a48db
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsfaq/[bbsId]/register/page.tsx
@@ -0,0 +1,10 @@
+import { CreatePage } from "@/pages/(post)/faq";
+
+export default async function PstBbsFaqRegisterPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/[pstNo]/modify/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/[pstNo]/modify/page.tsx
new file mode 100644
index 000000000..0ae940a3e
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/[pstNo]/modify/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage } from "@/pages/(post)/image";
+
+export default async function PstBbsImagePostModifyPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/[pstNo]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/[pstNo]/page.tsx
new file mode 100644
index 000000000..7b70daf45
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/[pstNo]/page.tsx
@@ -0,0 +1,10 @@
+import { ImagePost } from "@/pages/(post)/image";
+
+export default async function PstBbsImagePostPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/page.tsx
new file mode 100644
index 000000000..add5e7dde
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/page.tsx
@@ -0,0 +1,10 @@
+import { ImagePage } from "@/pages/(post)/image";
+
+export default async function PstBbsImagePage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/register/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/register/page.tsx
new file mode 100644
index 000000000..537b7f2af
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsimage/[bbsId]/register/page.tsx
@@ -0,0 +1,10 @@
+import { CreatePage } from "@/pages/(post)/image";
+
+export default async function PstBbsImageRegisterPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/[pstNo]/modify/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/[pstNo]/modify/page.tsx
new file mode 100644
index 000000000..7cd9664a6
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/[pstNo]/modify/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage } from "@/pages/(post)/movie";
+
+export default async function PstBbsMoviePostModifyPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/[pstNo]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/[pstNo]/page.tsx
new file mode 100644
index 000000000..51615fd10
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/[pstNo]/page.tsx
@@ -0,0 +1,10 @@
+import { MoviePost } from "@/pages/(post)/movie";
+
+export default async function PstBbsMoviePostPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/page.tsx
new file mode 100644
index 000000000..b5d9daf91
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/page.tsx
@@ -0,0 +1,10 @@
+import { MoviePage } from "@/pages/(post)/movie";
+
+export default async function PstBbsMoviePage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/register/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/register/page.tsx
new file mode 100644
index 000000000..368832658
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsmovie/[bbsId]/register/page.tsx
@@ -0,0 +1,10 @@
+import { CreatePage } from "@/pages/(post)/movie";
+
+export default async function PstBbsMovieRegisterPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/answer/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/answer/page.tsx
new file mode 100644
index 000000000..ad83352bc
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/answer/page.tsx
@@ -0,0 +1,10 @@
+import { CreatePage } from "@/pages/(post)/normal";
+
+export default async function PstBbsNormalAnswerPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/modify/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/modify/page.tsx
new file mode 100644
index 000000000..25b98f655
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/modify/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage } from "@/pages/(post)/normal";
+
+export default async function PstBbsNormalPostModifyPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/page.tsx
new file mode 100644
index 000000000..17d7c35cb
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/[pstNo]/page.tsx
@@ -0,0 +1,10 @@
+import { NormalPost } from "@/pages/(post)/normal";
+
+export default async function PstBbsNormalPostPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/page.tsx
new file mode 100644
index 000000000..b1e4a9318
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/page.tsx
@@ -0,0 +1,10 @@
+import { NormalPage } from "@/pages/(post)/normal";
+
+export default async function PstBbsNormalPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/register/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/register/page.tsx
new file mode 100644
index 000000000..9f7fe74cc
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnormal/[bbsId]/register/page.tsx
@@ -0,0 +1,10 @@
+import { CreatePage } from "@/pages/(post)/normal";
+
+export default async function PstBbsNormalRegisterPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx
new file mode 100644
index 000000000..8ee233879
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage } from "@/pages/(post)/notice";
+
+export default async function PstBbsNoticePostModifyPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/[pstNo]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/[pstNo]/page.tsx
new file mode 100644
index 000000000..5e080048b
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/[pstNo]/page.tsx
@@ -0,0 +1,10 @@
+import { NoticePost } from "@/pages/(post)/notice";
+
+export default async function PstBbsNoticePostPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string; pstNo: string }>;
+}) {
+ const { bbsId, pstNo } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/page.tsx
new file mode 100644
index 000000000..7694f9005
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/page.tsx
@@ -0,0 +1,10 @@
+import { NoticePage } from "@/pages/(post)/notice";
+
+export default async function PstBbsNoticePage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/register/page.tsx b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/register/page.tsx
new file mode 100644
index 000000000..6ea34f58f
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/(post)/bbsnotice/[bbsId]/register/page.tsx
@@ -0,0 +1,10 @@
+import { CreatePage } from "@/pages/(post)/notice";
+
+export default async function PstBbsNoticeRegisterPage({
+ params,
+}: {
+ params: Promise<{ bbsId: string }>;
+}) {
+ const { bbsId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/code/page.tsx b/apps/cs/app/(with-base-layout)/code/page.tsx
new file mode 100644
index 000000000..3ac19ec1c
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/code/page.tsx
@@ -0,0 +1,2 @@
+import { CodePage } from "@/pages/code";
+export default CodePage;
diff --git a/apps/cs/app/(with-base-layout)/layout.tsx b/apps/cs/app/(with-base-layout)/layout.tsx
index 8af048390..3c1a527d7 100644
--- a/apps/cs/app/(with-base-layout)/layout.tsx
+++ b/apps/cs/app/(with-base-layout)/layout.tsx
@@ -16,7 +16,7 @@ export default function WithBaseLayout({
const pathname = usePathname();
const queryClient = useQueryClient();
- const { setCurrentMenuInfo } = useMenuStore((state) => state);
+ const setCurrentMenuInfo = useMenuStore((state) => state.setCurrentMenuInfo);
const handleMenuClick = (item: MenuItem) => {
setCurrentMenuInfo(item);
diff --git a/apps/cs/app/(with-base-layout)/popup/page.tsx b/apps/cs/app/(with-base-layout)/popup/page.tsx
new file mode 100644
index 000000000..684e5bc58
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/popup/page.tsx
@@ -0,0 +1,2 @@
+import { PopupPage } from "@/pages/popup";
+export default PopupPage;
diff --git a/apps/cs/app/(with-base-layout)/popup/register/[popupSn]/page.tsx b/apps/cs/app/(with-base-layout)/popup/register/[popupSn]/page.tsx
new file mode 100644
index 000000000..e7388967f
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/popup/register/[popupSn]/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage as VModifyPage } from "@/pages/popup";
+
+export default async function ModifyPage({
+ params,
+}: {
+ params: Promise<{ popupSn: string }>;
+}) {
+ const { popupSn } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/popup/register/page.tsx b/apps/cs/app/(with-base-layout)/popup/register/page.tsx
new file mode 100644
index 000000000..d330844d3
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/popup/register/page.tsx
@@ -0,0 +1,2 @@
+import { CreatePage } from "@/pages/popup";
+export default CreatePage;
diff --git a/apps/cs/app/(with-base-layout)/recent/page.tsx b/apps/cs/app/(with-base-layout)/recent/page.tsx
new file mode 100644
index 000000000..02ed5aba7
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/recent/page.tsx
@@ -0,0 +1,2 @@
+import { RecentPage } from "@/pages/recent";
+export default RecentPage;
diff --git a/apps/cs/app/(with-base-layout)/role/page.tsx b/apps/cs/app/(with-base-layout)/role/page.tsx
new file mode 100644
index 000000000..fa962e93c
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/role/page.tsx
@@ -0,0 +1,2 @@
+import { RolePage } from "@/pages/role";
+export default RolePage;
diff --git a/apps/cs/app/(with-base-layout)/role/register/[roleId]/page.tsx b/apps/cs/app/(with-base-layout)/role/register/[roleId]/page.tsx
new file mode 100644
index 000000000..53ba411c8
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/role/register/[roleId]/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage as VMModifyPage } from "@/pages/role";
+
+export default async function ModifyPage({
+ params,
+}: {
+ params: Promise<{ roleId: string }>;
+}) {
+ const { roleId } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/role/register/page.tsx b/apps/cs/app/(with-base-layout)/role/register/page.tsx
new file mode 100644
index 000000000..d0a8eb9e0
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/role/register/page.tsx
@@ -0,0 +1,2 @@
+import { CreatePage } from "@/pages/role";
+export default CreatePage;
diff --git a/apps/cs/app/(with-base-layout)/schedule/page.tsx b/apps/cs/app/(with-base-layout)/schedule/page.tsx
new file mode 100644
index 000000000..ec64bf14c
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/schedule/page.tsx
@@ -0,0 +1,2 @@
+import { SchedulePage } from "@/pages/schedule";
+export default SchedulePage;
diff --git a/apps/cs/app/(with-base-layout)/schedule/register/[schdlSn]/page.tsx b/apps/cs/app/(with-base-layout)/schedule/register/[schdlSn]/page.tsx
new file mode 100644
index 000000000..90c4eb133
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/schedule/register/[schdlSn]/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage as VModifyPage } from "@/pages/schedule";
+
+export default async function ModifyPage({
+ params,
+}: {
+ params: Promise<{ schdlSn: string }>;
+}) {
+ const { schdlSn } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/schedule/register/page.tsx b/apps/cs/app/(with-base-layout)/schedule/register/page.tsx
new file mode 100644
index 000000000..7013caac7
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/schedule/register/page.tsx
@@ -0,0 +1,2 @@
+import { CreatePage } from "@/pages/schedule";
+export default CreatePage;
diff --git a/apps/cs/app/(with-base-layout)/survey/[srvySn]/modify/page.tsx b/apps/cs/app/(with-base-layout)/survey/[srvySn]/modify/page.tsx
new file mode 100644
index 000000000..23c487092
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/survey/[srvySn]/modify/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage as VModifyPage } from "@/pages/survey";
+
+export default async function ModifyPage({
+ params,
+}: {
+ params: Promise<{ srvySn: string }>;
+}) {
+ const { srvySn } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/survey/[srvySn]/page.tsx b/apps/cs/app/(with-base-layout)/survey/[srvySn]/page.tsx
new file mode 100644
index 000000000..382c62b5a
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/survey/[srvySn]/page.tsx
@@ -0,0 +1,10 @@
+import { DetailPage as VDetailPage } from "@/pages/survey";
+
+export default async function DetailPage({
+ params,
+}: {
+ params: Promise<{ srvySn: string }>;
+}) {
+ const { srvySn } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/survey/page.tsx b/apps/cs/app/(with-base-layout)/survey/page.tsx
new file mode 100644
index 000000000..85db42486
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/survey/page.tsx
@@ -0,0 +1,2 @@
+import { SurveyPage } from "@/pages/survey";
+export default SurveyPage;
diff --git a/apps/cs/app/(with-base-layout)/survey/register/page.tsx b/apps/cs/app/(with-base-layout)/survey/register/page.tsx
new file mode 100644
index 000000000..3d7307937
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/survey/register/page.tsx
@@ -0,0 +1,2 @@
+import { CreatePage } from "@/pages/survey";
+export default CreatePage;
diff --git a/apps/cs/app/(with-base-layout)/users/page.tsx b/apps/cs/app/(with-base-layout)/users/page.tsx
new file mode 100644
index 000000000..35a8db5ae
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/users/page.tsx
@@ -0,0 +1,2 @@
+import { UsersPage } from "@/pages/users";
+export default UsersPage;
diff --git a/apps/cs/app/(without-base-layout)/view/popup/[popupSn]/page.tsx b/apps/cs/app/(without-base-layout)/view/popup/[popupSn]/page.tsx
new file mode 100644
index 000000000..16cd8e0af
--- /dev/null
+++ b/apps/cs/app/(without-base-layout)/view/popup/[popupSn]/page.tsx
@@ -0,0 +1,10 @@
+import { ViewPopup as VViewPopup } from "@/pages/popup";
+
+export default async function ViewPopup({
+ params,
+}: {
+ params: Promise<{ popupSn: string }>;
+}) {
+ const { popupSn } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(without-base-layout)/view/survey-article/[srvySn]/page.tsx b/apps/cs/app/(without-base-layout)/view/survey-article/[srvySn]/page.tsx
new file mode 100644
index 000000000..6155852fb
--- /dev/null
+++ b/apps/cs/app/(without-base-layout)/view/survey-article/[srvySn]/page.tsx
@@ -0,0 +1,10 @@
+import { ViewSurveyArticle } from "@/pages/survey";
+
+export default async function ViewSurveyArticlePage({
+ params,
+}: {
+ params: Promise<{ srvySn: string }>;
+}) {
+ const { srvySn } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(without-base-layout)/view/survey-result/[srvySn]/page.tsx b/apps/cs/app/(without-base-layout)/view/survey-result/[srvySn]/page.tsx
new file mode 100644
index 000000000..8ac4b076c
--- /dev/null
+++ b/apps/cs/app/(without-base-layout)/view/survey-result/[srvySn]/page.tsx
@@ -0,0 +1,10 @@
+import { ViewSurveyResult } from "@/pages/survey";
+
+export default async function ViewSurveyResultPage({
+ params,
+}: {
+ params: Promise<{ srvySn: string }>;
+}) {
+ const { srvySn } = await params;
+ return ;
+}
diff --git a/apps/cs/package.json b/apps/cs/package.json
index 6e5f62b96..a072c1d82 100644
--- a/apps/cs/package.json
+++ b/apps/cs/package.json
@@ -1,6 +1,6 @@
{
"name": "cs",
- "version": "0.0.0",
+ "version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
@@ -12,18 +12,27 @@
"@common/assets": "workspace:*",
"@common/components": "workspace:*",
"@common/config": "workspace:*",
+ "@fontsource-variable/noto-sans-kr": "^5.2.5",
"@frontend-opensource/use-react-hooks": "^1.1.4",
+ "@fullcalendar/core": "^6.1.17",
+ "@fullcalendar/daygrid": "^6.1.17",
+ "@fullcalendar/interaction": "^6.1.17",
+ "@fullcalendar/react": "^6.1.17",
+ "@fullcalendar/timegrid": "^6.1.17",
"@hookform/resolvers": "^4.1.3",
"@minoru/react-dnd-treeview": "3.5.1-alpha.1",
+ "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-slot": "^1.1.2",
"@tanstack/react-query": "^5.67.1",
+ "@tanstack/react-query-devtools": "^5.75.5",
"@tanstack/react-table": "^8.21.2",
"@tinymce/tinymce-react": "^6.1.0",
"axios": "^1.8.1",
"chart.js": "^4.4.8",
"dayjs": "^1.11.13",
"js-cookie": "^3.0.5",
+ "lucide-react": "^0.474.0",
"next": "15.3.0",
"react-chartjs-2": "^5.3.0",
"react-dnd": "^16.0.1",
diff --git a/apps/cs/src/app/index.tsx b/apps/cs/src/app/index.tsx
index 5a73f2fdd..692b55ef0 100644
--- a/apps/cs/src/app/index.tsx
+++ b/apps/cs/src/app/index.tsx
@@ -1,5 +1,7 @@
import "./styles/base.css";
import "./styles/components.css";
+import "@fontsource-variable/noto-sans-kr";
+
import { AppProvider } from "./providers";
import { cookies } from "next/headers";
diff --git a/apps/cs/src/app/providers/app-provider.tsx b/apps/cs/src/app/providers/app-provider.tsx
index 713bc172c..1a2189b03 100644
--- a/apps/cs/src/app/providers/app-provider.tsx
+++ b/apps/cs/src/app/providers/app-provider.tsx
@@ -3,34 +3,41 @@
import { DndProvider } from "react-dnd";
import { MultiBackend, getBackendOptions } from "@minoru/react-dnd-treeview";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { ConfirmProvider } from "@frontend-opensource/use-react-hooks";
import { AuthWrapper } from "@/entities/auth";
import { MenuWrapper } from "@/entities/menu";
-import { StoreProvider } from "@/shared/providers";
+import { PromptProvider, StoreProvider } from "@/shared/providers";
import { AlertDialog } from "@/shared/ui/alert-dialog";
+import { PromptDialog } from "@/shared/ui/prompt-dialog";
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
-import { initializeNextClientConfig } from "@common/config";
const AppProvider = ({ children }: Readonly<{ children: React.ReactNode }>) => {
const queryClient = new QueryClient();
-
- initializeNextClientConfig();
-
return (
-
-
-
-
- {children}
-
-
-
-
-
-
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/apps/cs/src/app/styles/base.css b/apps/cs/src/app/styles/base.css
index e24111afe..7a5263bc4 100644
--- a/apps/cs/src/app/styles/base.css
+++ b/apps/cs/src/app/styles/base.css
@@ -1,11 +1,21 @@
@import "@common/assets/styles/base.css";
@import "@common/assets/styles/diveicon.css";
+@import "@common/components/index.css";
@tailwind base;
@tailwind utilities;
-html,
-body {
- font-family: "Noto Sans KR", sans-serif;
- font-size: 10px;
+@layer base {
+ :root {
+ --secondary-background: rgba(0, 0, 0, 0.04);
+ }
+ [data-theme="black"] {
+ --secondary-background: rgba(255, 255, 255, 0.09);
+ }
+
+ html,
+ body {
+ font-family: "Noto Sans KR", sans-serif;
+ font-size: 10px;
+ }
}
diff --git a/apps/cs/src/entities/attachment/api/attachment-service.ts b/apps/cs/src/entities/attachment/api/attachment-service.ts
index f956f6580..fc2dcab05 100644
--- a/apps/cs/src/entities/attachment/api/attachment-service.ts
+++ b/apps/cs/src/entities/attachment/api/attachment-service.ts
@@ -1,3 +1,4 @@
+import type { AxiosResponse } from "axios";
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type {
@@ -25,7 +26,7 @@ export class AttachmentApiService implements AttachmentService {
return response.data;
}
- public async deleteAttachment(atflId: string): Promise {
+ public async deleteAttachmentByAtflId(atflId: string): Promise {
await client.delete(`${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}/${atflId}`);
}
@@ -35,7 +36,7 @@ export class AttachmentApiService implements AttachmentService {
);
}
- public async getImageUrl(atflId: string): Promise {
+ public async getImageUrlByAtflId(atflId: string): Promise {
if (!atflId) return "";
const response = await fetch(`${ENDPOINT.ATTACH_SERVICE.IMAGES}/${atflId}`);
const blob = await response.blob();
@@ -50,6 +51,40 @@ export class AttachmentApiService implements AttachmentService {
const blob = await response.blob();
return URL.createObjectURL(blob);
}
+
+ public async getStreamVideoUrlByAtflId(atflId: string): Promise {
+ const response = await fetch(
+ `${ENDPOINT.ATTACH_SERVICE.STREAM_VIDEO}/${atflId}`,
+ );
+ const blob = await response.blob();
+ return URL.createObjectURL(blob);
+ }
+
+ public async getMovieThumbnailUrlByAtflId(atflId: string): Promise {
+ const response = await fetch(
+ `${ENDPOINT.ATTACH_SERVICE.MOVIE_THUMBNAIL}/${atflId}`,
+ );
+ const blob = await response.blob();
+ return URL.createObjectURL(blob);
+ }
+
+ public async getMovieThumbnailUrlByAtflCd(atflCd: string): Promise {
+ const response = await fetch(
+ `${ENDPOINT.ATTACH_SERVICE.MOVIE_THUMBNAIL}/atflCd/${atflCd}`,
+ );
+ const blob = await response.blob();
+ return URL.createObjectURL(blob);
+ }
+
+ public async downloadAttachmentByAtflCd(
+ atflCd: string,
+ ): Promise {
+ const response = await client.get(
+ `${ENDPOINT.ATTACH_SERVICE.DOWNLOAD}/${atflCd}`,
+ { responseType: "blob" },
+ );
+ return response;
+ }
}
export const AttachmentApi = new AttachmentApiService();
diff --git a/apps/cs/src/entities/attachment/model/attachment-interface.ts b/apps/cs/src/entities/attachment/model/attachment-interface.ts
index 5133e4a72..0f1b5d1ee 100644
--- a/apps/cs/src/entities/attachment/model/attachment-interface.ts
+++ b/apps/cs/src/entities/attachment/model/attachment-interface.ts
@@ -1,3 +1,4 @@
+import type { AxiosResponse } from "axios";
import type { PageableList, PageableParams } from "@/shared/model";
export interface AttachmentParams extends PageableParams {
@@ -35,8 +36,12 @@ export type AttachmentList = PageableList;
export interface AttachmentService {
getAttachmentsList: (params: AttachmentParams) => Promise;
getAttachmentsInfo: (atflCd: string) => Promise;
- deleteAttachment: (atflId: string) => Promise;
+ deleteAttachmentByAtflId: (atflId: string) => Promise;
deleteAttachmentByAtflCd: (atflCd: string) => Promise;
- getImageUrl: (atflId: string) => Promise;
+ getImageUrlByAtflId: (atflId: string) => Promise;
getImageUrlByAtflCd: (atflCd: string) => Promise;
+ getStreamVideoUrlByAtflId: (atflId: string) => Promise;
+ getMovieThumbnailUrlByAtflId: (atflId: string) => Promise;
+ getMovieThumbnailUrlByAtflCd: (atflCd: string) => Promise;
+ downloadAttachmentByAtflCd: (atflCd: string) => Promise;
}
diff --git a/apps/cs/src/entities/auth/lib/auth-wrapper.tsx b/apps/cs/src/entities/auth/lib/auth-wrapper.tsx
index 705c03231..c0be4c2dd 100644
--- a/apps/cs/src/entities/auth/lib/auth-wrapper.tsx
+++ b/apps/cs/src/entities/auth/lib/auth-wrapper.tsx
@@ -19,7 +19,7 @@ const AuthWrapper = ({ children }: { children: React.ReactNode }) => {
}
const response = await client.get(
- `${ENDPOINT.USER_SERVICE.USERS}/${userId}`,
+ `${ENDPOINT.USER_SERVICE.USERS}/info/me`,
);
if (!userInfo) setUserInfo(response.data);
}
diff --git a/apps/cs/src/pages/module/api/authorization-service.ts b/apps/cs/src/entities/authorization/api/authorization-service.ts
similarity index 94%
rename from apps/cs/src/pages/module/api/authorization-service.ts
rename to apps/cs/src/entities/authorization/api/authorization-service.ts
index d68c6920a..fd5f042f5 100644
--- a/apps/cs/src/pages/module/api/authorization-service.ts
+++ b/apps/cs/src/entities/authorization/api/authorization-service.ts
@@ -6,11 +6,11 @@ import type {
AuthorizationsList,
AuthorizationFormData,
WithRoleAuthorizations,
-} from "../model/authorizations-interface";
+} from "../model/authorization-interface";
export class AuthorizationsApiService implements AuthorizationsService {
public async getAuthorizationsList(
- params: AuthorizationsParams,
+ params?: AuthorizationsParams,
): Promise {
const response = await client.get(
`${ENDPOINT.USER_SERVICE.AUTHORIZATIONS}`,
diff --git a/apps/cs/src/entities/authorization/index.ts b/apps/cs/src/entities/authorization/index.ts
new file mode 100644
index 000000000..afb6d2ce4
--- /dev/null
+++ b/apps/cs/src/entities/authorization/index.ts
@@ -0,0 +1,10 @@
+export { AuthorizationsApi } from "./api/authorization-service";
+export {
+ authorizationFormSchema,
+ type Authorizations,
+ type AuthorizationsParams,
+ type AuthorizationFormData,
+ type WithRoleAuthorizations,
+ type AuthorizationsService,
+ type AuthorizationsList,
+} from "./model/authorization-interface";
diff --git a/apps/cs/src/pages/module/model/authorizations-interface.ts b/apps/cs/src/entities/authorization/model/authorization-interface.ts
similarity index 97%
rename from apps/cs/src/pages/module/model/authorizations-interface.ts
rename to apps/cs/src/entities/authorization/model/authorization-interface.ts
index e34d150e0..2230f5226 100644
--- a/apps/cs/src/pages/module/model/authorizations-interface.ts
+++ b/apps/cs/src/entities/authorization/model/authorization-interface.ts
@@ -47,7 +47,7 @@ export type AuthorizationFormData = z.infer;
export interface AuthorizationsService {
getAuthorizationsList: (
- params: AuthorizationsParams,
+ params?: AuthorizationsParams,
) => Promise;
getAuthorizationInfo: (
authorizationNo: string,
diff --git a/apps/cs/src/entities/board/@x/post.ts b/apps/cs/src/entities/board/@x/post.ts
new file mode 100644
index 000000000..9d2b29076
--- /dev/null
+++ b/apps/cs/src/entities/board/@x/post.ts
@@ -0,0 +1 @@
+export { BoardApi } from "../api/board-service";
diff --git a/apps/cs/src/entities/board/api/board-service.ts b/apps/cs/src/entities/board/api/board-service.ts
index 150ff677a..dc474b3ad 100644
--- a/apps/cs/src/entities/board/api/board-service.ts
+++ b/apps/cs/src/entities/board/api/board-service.ts
@@ -11,7 +11,7 @@ import type {
} from "../model/board-interface";
export class BoardApiService implements BoardService {
- public async getBoardList(params: BoardParams): Promise {
+ public async getBoardList(params?: BoardParams): Promise {
const response = await client.get(
`${ENDPOINT.BOARD_SERVICE.BBS}`,
{ params },
diff --git a/apps/cs/src/entities/board/api/board-template-service.ts b/apps/cs/src/entities/board/api/board-template-service.ts
new file mode 100644
index 000000000..be3efde75
--- /dev/null
+++ b/apps/cs/src/entities/board/api/board-template-service.ts
@@ -0,0 +1,17 @@
+import { client } from "@/shared/api";
+import { ENDPOINT } from "@/shared/config";
+import type {
+ BoardTemplate,
+ BoardTemplateService,
+} from "../model/board-template-interface";
+
+export class BoardTemplateApiService implements BoardTemplateService {
+ public async getBoardTemplate(bbsTypeCd: string): Promise {
+ const response = await client.get(
+ `${ENDPOINT.BOARD_SERVICE.BBS_TEMPLATES}/${bbsTypeCd}`,
+ );
+ return response.data;
+ }
+}
+
+export const BoardTemplateApi = new BoardTemplateApiService();
diff --git a/apps/cs/src/entities/board/index.ts b/apps/cs/src/entities/board/index.ts
index f9ef1b610..ddd10f382 100644
--- a/apps/cs/src/entities/board/index.ts
+++ b/apps/cs/src/entities/board/index.ts
@@ -1,8 +1,11 @@
export { BoardApi } from "./api/board-service";
export {
boardFormSchema,
+ BOARD_POSTING_CODE,
type Board,
type BoardFormData,
type BoardParams,
type BoardPopup,
+ type BoardPostingCode,
} from "./model/board-interface";
+export { BoardTemplateApi } from "./api/board-template-service";
diff --git a/apps/cs/src/entities/board/model/board-interface.ts b/apps/cs/src/entities/board/model/board-interface.ts
index 1ed8f1d9f..60ed9f743 100644
--- a/apps/cs/src/entities/board/model/board-interface.ts
+++ b/apps/cs/src/entities/board/model/board-interface.ts
@@ -1,14 +1,15 @@
import { z } from "zod";
import type { PageableList, PageableParams } from "@/shared/model";
+import type { BbsType } from "@/shared/store";
-export const BOARD_TYPE = {
- BBSNORMAL: "BBSNORMAL",
- BBSFAQ: "BBSFAQ",
- BBSIMAGE: "BBSIMAGE",
- BBSMOVIE: "BBSMOVIE",
+export const BOARD_POSTING_CODE = {
+ 팝업게시: "01",
+ 상단게시: "02",
+ 기간게시: "03",
} as const;
-export type BoardType = (typeof BOARD_TYPE)[keyof typeof BOARD_TYPE];
+export type BoardPostingCode =
+ (typeof BOARD_POSTING_CODE)[keyof typeof BOARD_POSTING_CODE];
export interface BoardParams extends PageableParams {
keywordType?: string;
@@ -37,7 +38,7 @@ export interface BoardPopupParams extends PageableParams {
export interface Board {
bbsId: number;
- bbsTypeCd: string;
+ bbsTypeCd: BbsType;
bbsTypeNm: string;
bbsNm: string;
bbsExpln: string;
diff --git a/apps/cs/src/entities/board/model/board-template-interface.ts b/apps/cs/src/entities/board/model/board-template-interface.ts
new file mode 100644
index 000000000..6a7f84fef
--- /dev/null
+++ b/apps/cs/src/entities/board/model/board-template-interface.ts
@@ -0,0 +1,24 @@
+export interface BoardTemplate {
+ bbsTypeCd: string;
+ rfrncUseYn: string;
+ atflUseYn: string;
+ atflMaxCnt: number;
+ atflMaxFileSz: number;
+ ansUseYn: string;
+ cmntUseYn: string;
+ dgstfnEvlUseYn: string;
+ smsUseYn: string;
+ upndFixUseYn: string;
+ pstgPrdUseYn: string;
+ popupUseYn: string;
+ regDt: string;
+ rgtr: string;
+ mdfcnDt: string;
+ mdfr: string;
+ rgtrNm: string;
+ mdfrNm: string;
+}
+
+export interface BoardTemplateService {
+ getBoardTemplate: (bbsTypeCd: string) => Promise;
+}
diff --git a/apps/cs/src/entities/code/api/lwpocode-service.ts b/apps/cs/src/entities/code/api/lwpocode-service.ts
new file mode 100644
index 000000000..b8f11fa22
--- /dev/null
+++ b/apps/cs/src/entities/code/api/lwpocode-service.ts
@@ -0,0 +1,67 @@
+import { client } from "@/shared/api";
+import { ENDPOINT } from "@/shared/config";
+import {
+ LwpoCodeFormSchema,
+ type LwpoCodeService,
+ type LwpoCodeList,
+ type LwpoCodeDetail,
+ type LwpoCodeParams,
+ type LwpoCodeFormData,
+} from "../model/lwpocode-interface";
+
+export class LwpoCodeApiService implements LwpoCodeService {
+ public async getLwpoCodeList(params?: LwpoCodeParams): Promise {
+ const response = await client.get(
+ `${ENDPOINT.CMS_SERVICE.LWPO_CODE}`,
+ { params },
+ );
+ return response.data;
+ }
+
+ public async getUpCodeLwpoCodeList(upCd: string): Promise {
+ const response = await client.get(
+ `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/up-cd/${upCd}`,
+ );
+ return response.data;
+ }
+
+ public async lwpoCodeDetail(
+ upCd: string,
+ lwpoCd: string,
+ ): Promise {
+ const response = await client.get(
+ `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`,
+ );
+ return response.data;
+ }
+
+ public async createLwpoCode(data: LwpoCodeFormData): Promise {
+ const validatedData = LwpoCodeFormSchema.parse(data);
+ const response = await client.post(
+ `${ENDPOINT.CMS_SERVICE.LWPO_CODE}`,
+ validatedData,
+ );
+ return response.data;
+ }
+
+ public async updateLwpoCode(
+ upCd: string,
+ lwpoCd: string,
+ data: LwpoCodeFormData,
+ ): Promise {
+ const validatedData = LwpoCodeFormSchema.parse(data);
+ const response = await client.put(
+ `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`,
+ validatedData,
+ );
+ return response.data;
+ }
+
+ public async deleteLwpoCode(upCd: string, lwpoCd: string): Promise {
+ await client.delete(
+ `${ENDPOINT.CMS_SERVICE.LWPO_CODE}/${lwpoCd}/up-cd/${upCd}`,
+ );
+ }
+}
+
+export const LwpoCodeApi = new LwpoCodeApiService();
diff --git a/apps/cs/src/entities/code/api/upcode-service.ts b/apps/cs/src/entities/code/api/upcode-service.ts
new file mode 100644
index 000000000..dcccd9534
--- /dev/null
+++ b/apps/cs/src/entities/code/api/upcode-service.ts
@@ -0,0 +1,47 @@
+import { client } from "@/shared/api";
+import { ENDPOINT } from "@/shared/config";
+import {
+ upCodeFormSchema,
+ type UpCodeService,
+ type UpCodeList,
+ type UpCodeDetail,
+ type UpCodeParams,
+ type UpCodeFormData,
+} from "../model/upcode-interface";
+
+export class UpCodeApiService implements UpCodeService {
+ public async getUpCodeList(params?: UpCodeParams): Promise {
+ const response = await client.get(
+ `${ENDPOINT.CMS_SERVICE.UP_CODE}`,
+ { params },
+ );
+ return response.data;
+ }
+
+ public async upCodeDetail(upCd: string): Promise {
+ const response = await client.get(
+ `${ENDPOINT.CMS_SERVICE.UP_CODE}/${upCd}`,
+ );
+ return response.data;
+ }
+
+ public async createUpCode(data: UpCodeFormData): Promise {
+ const validatedData = upCodeFormSchema.parse(data);
+ const response = await client.post(
+ `${ENDPOINT.CMS_SERVICE.UP_CODE}`,
+ validatedData,
+ );
+ return response.data;
+ }
+
+ public async updateUpCode(upCd: string, data: UpCodeFormData): Promise {
+ const validatedData = upCodeFormSchema.parse(data);
+ const response = await client.put(
+ `${ENDPOINT.CMS_SERVICE.UP_CODE}/${upCd}`,
+ validatedData,
+ );
+ return response.data;
+ }
+}
+
+export const UpCodeApi = new UpCodeApiService();
diff --git a/apps/cs/src/entities/code/index.ts b/apps/cs/src/entities/code/index.ts
index dc74bbc47..e166e2c29 100644
--- a/apps/cs/src/entities/code/index.ts
+++ b/apps/cs/src/entities/code/index.ts
@@ -1,3 +1,19 @@
export { CodeApi } from "./api/code-service";
export type { ICode } from "./model/code-interface";
export { CodeSelect } from "./ui/code-select";
+
+export { UpCodeApi } from "./api/upcode-service";
+export {
+ upCodeFormSchema,
+ type UpCode,
+ type UpCodeFormData,
+ type UpCodeParams,
+} from "./model/upcode-interface";
+
+export { LwpoCodeApi } from "./api/lwpocode-service";
+export {
+ LwpoCodeFormSchema,
+ type LwpoCode,
+ type LwpoCodeFormData,
+ type LwpoCodeParams,
+} from "./model/lwpocode-interface";
diff --git a/apps/cs/src/entities/code/model/lwpocode-interface.ts b/apps/cs/src/entities/code/model/lwpocode-interface.ts
new file mode 100644
index 000000000..785d86e1e
--- /dev/null
+++ b/apps/cs/src/entities/code/model/lwpocode-interface.ts
@@ -0,0 +1,68 @@
+import { z } from "zod";
+import type { PageableParams, PageableList } from "@/shared/model";
+
+export interface LwpoCodeParams extends PageableParams {
+ upCd?: string;
+ lwpoCd?: string;
+ lwpoCdNm?: string;
+ useYn?: string;
+}
+
+export interface LwpoCode {
+ lwpoCd: string;
+ upCd: string;
+ lwpoCdNm: string;
+ lwpoCdExpln: string;
+ unit: string;
+ prntLwpoCd: string;
+ useYn: string;
+ sortSeq: number;
+ regDt: string;
+ rgTr: string;
+ rgTrNm: string;
+ mdfcnDt: string;
+ mdFr: string;
+}
+
+export interface LwpoCodeDetail extends LwpoCodeFormData {
+ lwpoCd: string;
+ upCd: string;
+ lwpoCdNm: string;
+ lwpoCdExpln: string;
+ unit: string;
+ prntLwpoCd: string;
+ useYn: string;
+ sortSeq: 0;
+}
+
+export const LwpoCodeFormSchema = z.object({
+ lwpoCd: z.string().max(10).nonempty(),
+ upCd: z.string().max(10).nonempty(),
+ lwpoCdNm: z.string().max(100).nonempty(),
+ lwpoCdExpln: z.string().max(1000).nullish(),
+ unit: z.string().max(20).nullish(),
+ prntLwpoCd: z.string().max(10).nullish(),
+ useYn: z.string(),
+ sortSeq: z.number(),
+ delYn: z.string(),
+});
+
+export type LwpoCodeFormData = z.infer;
+export type LwpoCodeList = PageableList;
+
+export interface LwpoCodeService {
+ getLwpoCodeList(params: LwpoCodeParams): Promise;
+ getUpCodeLwpoCodeList(upCd: string): Promise;
+ lwpoCodeDetail(upCd: string, lwpoCd: string): Promise;
+ updateLwpoCode(
+ upCd: string,
+ lwpoCd: string,
+ data: LwpoCodeFormData,
+ ): Promise;
+ createLwpoCode(data: LwpoCodeFormData): Promise;
+ deleteLwpoCode(
+ upCd: string,
+ lwpoCd: string,
+ data: LwpoCodeFormData,
+ ): Promise;
+}
diff --git a/apps/cs/src/entities/code/model/upcode-interface.ts b/apps/cs/src/entities/code/model/upcode-interface.ts
new file mode 100644
index 000000000..73bf4f3ae
--- /dev/null
+++ b/apps/cs/src/entities/code/model/upcode-interface.ts
@@ -0,0 +1,52 @@
+import { z } from "zod";
+import type { PageableParams, PageableList } from "@/shared/model";
+
+export interface UpCodeParams extends PageableParams {
+ keyword?: string;
+ upCd?: string;
+ cdSe?: string;
+ useYn?: string;
+ siteId?: string;
+}
+
+export interface UpCode {
+ upCd: string;
+ upCdNm: string;
+ upCdExpln: string;
+ cdSe: string;
+ siteId: string;
+ useYn: string;
+ regDt: string;
+}
+
+export interface UpCodeDetail extends UpCodeFormData {
+ upCd: string;
+ upCdNm: string;
+ upCdExpln: string;
+ cdSe: string;
+ siteId: string;
+ useYn: string;
+ delYn: string;
+ regDt: string;
+ rgTrNm: string;
+}
+
+export const upCodeFormSchema = z.object({
+ upCd: z.string().max(10).nonempty(),
+ upCdNm: z.string().max(100).nonempty(),
+ upCdExpln: z.string().max(1000).nullish(),
+ cdSe: z.string().max(10).nonempty(),
+ siteId: z.string().max(2).nullish(),
+ useYn: z.string(),
+ delYn: z.string(),
+});
+
+export type UpCodeFormData = z.infer;
+export type UpCodeList = PageableList;
+
+export interface UpCodeService {
+ getUpCodeList(params: UpCodeParams): Promise;
+ upCodeDetail(upCodeId: string): Promise;
+ updateUpCode(upCodeId: string, data: UpCodeFormData): Promise;
+ createUpCode(data: UpCodeFormData): Promise;
+}
diff --git a/apps/cs/src/entities/code/ui/code-select.tsx b/apps/cs/src/entities/code/ui/code-select.tsx
index bd175a8a9..850282375 100644
--- a/apps/cs/src/entities/code/ui/code-select.tsx
+++ b/apps/cs/src/entities/code/ui/code-select.tsx
@@ -1,5 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import {
+ cn,
Select,
SelectContent,
SelectItem,
@@ -11,9 +12,17 @@ import { CodeApi } from "../api/code-service";
type CodeSelectProps = {
upCd: string;
+ placeholder?: string;
+ className?: string;
} & React.ComponentPropsWithoutRef;
-function CodeSelect({ upCd, defaultValue, ...props }: CodeSelectProps) {
+function CodeSelect({
+ upCd,
+ defaultValue,
+ placeholder = "선택",
+ className,
+ ...props
+}: CodeSelectProps) {
const { data: code } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.CODE, upCd],
queryFn: () => CodeApi.getCode(upCd),
@@ -21,11 +30,11 @@ function CodeSelect({ upCd, defaultValue, ...props }: CodeSelectProps) {
});
const defaultValueText =
- code?.find((item) => item.lwpoCd === defaultValue)?.lwpoCdNm ?? "선택";
+ code?.find((item) => item.lwpoCd === defaultValue)?.lwpoCdNm ?? placeholder;
return (