feat: post 폴더 추가(cs)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import type { AxiosResponse } from "axios";
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
@@ -42,6 +43,10 @@ export class AttachmentApiService implements AttachmentService {
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
public async deleteAttachmentByAtflId(atflId: string): Promise<void> {
|
||||
await client.delete(`${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}/${atflId}`);
|
||||
}
|
||||
|
||||
public async getImageUrlByAtflCd(atflCd: string): Promise<string> {
|
||||
if (!atflCd) return "";
|
||||
const response = await fetch(
|
||||
@@ -50,6 +55,16 @@ export class AttachmentApiService implements AttachmentService {
|
||||
const blob = await response.blob();
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
public async downloadAttachmentByAtflCd(
|
||||
atflCd: string,
|
||||
): Promise<AxiosResponse> {
|
||||
const response = await client.get(
|
||||
`${ENDPOINT.ATTACH_SERVICE.DOWNLOAD}/${atflCd}`,
|
||||
{ responseType: "blob" },
|
||||
);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
export const AttachmentApi = new AttachmentApiService();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { AxiosResponse } from "axios";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface AttachmentParams extends PageableParams {
|
||||
@@ -36,7 +37,9 @@ export interface AttachmentService {
|
||||
getAttachmentsList: (params: AttachmentParams) => Promise<AttachmentList>;
|
||||
getAttachmentsInfo: (atflCd: string) => Promise<Attachment[]>;
|
||||
deleteAttachment: (atflId: string) => Promise<void>;
|
||||
deleteAttachmentByAtflId: (atflId: string) => Promise<void>;
|
||||
deleteAttachmentByAtflCd: (atflCd: string) => Promise<void>;
|
||||
getImageUrl: (atflId: string) => Promise<string>;
|
||||
getImageUrlByAtflCd: (atflCd: string) => Promise<string>;
|
||||
downloadAttachmentByAtflCd: (atflCd: string) => Promise<AxiosResponse>;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
export { BoardApi } from "./api/board-service";
|
||||
export {
|
||||
boardFormSchema,
|
||||
BOARD_POSTING_CODE,
|
||||
type Board,
|
||||
type BoardType,
|
||||
type BoardFormData,
|
||||
type BoardParams,
|
||||
type BoardPopup,
|
||||
type BoardPostingCode,
|
||||
} from "./model/board-interface";
|
||||
export { BoardTemplateApi } from "./api/board-template-service";
|
||||
|
||||
@@ -8,7 +8,15 @@ export const BOARD_TYPE = {
|
||||
BBSMOVIE: "BBSMOVIE",
|
||||
} as const;
|
||||
|
||||
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;
|
||||
|
||||
@@ -11,9 +11,15 @@ import { CodeApi } from "../api/code-service";
|
||||
|
||||
type CodeSelectProps = {
|
||||
upCd: string;
|
||||
placeholder?: string;
|
||||
} & React.ComponentPropsWithoutRef<typeof Select>;
|
||||
|
||||
function CodeSelect({ upCd, defaultValue, ...props }: CodeSelectProps) {
|
||||
function CodeSelect({
|
||||
upCd,
|
||||
defaultValue,
|
||||
placeholder = "선택",
|
||||
...props
|
||||
}: CodeSelectProps) {
|
||||
const { data: code } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CODE, upCd],
|
||||
queryFn: () => CodeApi.getCode(upCd),
|
||||
@@ -21,7 +27,7 @@ function CodeSelect({ upCd, defaultValue, ...props }: CodeSelectProps) {
|
||||
});
|
||||
|
||||
const defaultValueText =
|
||||
code?.find((item) => item.lwpoCd === defaultValue)?.lwpoCdNm ?? "선택";
|
||||
code?.find((item) => item.lwpoCd === defaultValue)?.lwpoCdNm ?? placeholder;
|
||||
|
||||
return (
|
||||
<Select {...props}>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import {
|
||||
commentFormSchema,
|
||||
commentUpdateFormSchema,
|
||||
type Comment,
|
||||
type CommentService,
|
||||
type CommentList,
|
||||
type CommentParams,
|
||||
type CommentFormData,
|
||||
type CommentUpdateFormData,
|
||||
} from "../model/comment-interface";
|
||||
|
||||
export class CommentApiService implements CommentService {
|
||||
public async getComments(params: CommentParams): Promise<CommentList> {
|
||||
const response = await client.get<CommentList>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createComment(data: CommentFormData): Promise<Comment> {
|
||||
const validatedData = commentFormSchema.parse(data);
|
||||
const response = await client.post<Comment>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async updateComment(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
cmntNo: number,
|
||||
data: CommentUpdateFormData,
|
||||
): Promise<Comment> {
|
||||
const validatedData = commentUpdateFormSchema.parse(data);
|
||||
const response = await client.put<Comment>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS}/${bbsId}/${pstNo}/${cmntNo}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async deleteComment(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
cmntNo: number,
|
||||
cmntPswd: string,
|
||||
): Promise<Comment> {
|
||||
const response = await client.delete<Comment>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS}/${bbsId}/${pstNo}/${cmntNo}`,
|
||||
{ params: { cmntPswd } },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const CommentApi = new CommentApiService();
|
||||
@@ -0,0 +1,10 @@
|
||||
export { CommentApi } from "./api/comment-service";
|
||||
export {
|
||||
commentFormSchema,
|
||||
commentUpdateFormSchema,
|
||||
type Comment,
|
||||
type CommentList,
|
||||
type CommentParams,
|
||||
type CommentFormData,
|
||||
type CommentUpdateFormData,
|
||||
} from "./model/comment-interface";
|
||||
@@ -0,0 +1,55 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface CommentParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
pstNo: number;
|
||||
delYn?: string;
|
||||
}
|
||||
|
||||
export interface Comment {
|
||||
cmntEvl: number;
|
||||
pstNo: number;
|
||||
cmntNo: number;
|
||||
cmntCn: string;
|
||||
wrtrNm: string;
|
||||
regDt: string;
|
||||
rgtr: string;
|
||||
mdfcnDt: string;
|
||||
mdfr: string;
|
||||
delYn: string;
|
||||
}
|
||||
|
||||
export const commentFormSchema = z.object({
|
||||
pstNo: z.number(),
|
||||
cmntCn: z.string(),
|
||||
wrtrNm: z.string().nullish(),
|
||||
cmntPswd: z.string(),
|
||||
cmntEvl: z.number().nullish(),
|
||||
});
|
||||
|
||||
export const commentUpdateFormSchema = commentFormSchema.omit({
|
||||
pstNo: true,
|
||||
});
|
||||
|
||||
export type CommentList = PageableList<Comment>;
|
||||
export type CommentFormData = z.infer<typeof commentFormSchema>;
|
||||
export type CommentUpdateFormData = z.infer<typeof commentUpdateFormSchema>;
|
||||
|
||||
export interface CommentService {
|
||||
getComments(params: CommentParams): Promise<CommentList>;
|
||||
createComment(data: CommentFormData): Promise<Comment>;
|
||||
updateComment(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
cmntNo: number,
|
||||
data: CommentUpdateFormData,
|
||||
): Promise<Comment>;
|
||||
deleteComment(
|
||||
bbsId: number,
|
||||
pstNo: number,
|
||||
cmntNo: number,
|
||||
cmntPswd: string,
|
||||
): Promise<Comment>;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import {
|
||||
postFormSchema,
|
||||
postUpdateFormSchema,
|
||||
type Post,
|
||||
type PostInfo,
|
||||
type PostList,
|
||||
type PostParams,
|
||||
type PostService,
|
||||
type PostFormData,
|
||||
type PostUpdateFormData,
|
||||
} from "../model/post-interface";
|
||||
|
||||
export class PostApiService implements PostService {
|
||||
public async getPostList(
|
||||
bbsId: string,
|
||||
params: PostParams,
|
||||
): Promise<PostList> {
|
||||
const response = await client.get<PostList>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_USER}/${bbsId}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getPostInfo(bbsId: string, pstNo: string): Promise<PostInfo> {
|
||||
const response = await client.get<PostInfo>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_USER}/${bbsId}/${pstNo}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async createPost(data: PostFormData): Promise<Post> {
|
||||
const validatedData = postFormSchema.parse(data);
|
||||
const response = await client.post<Post>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_USER}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async updatePost(
|
||||
bbsId: string,
|
||||
pstNo: string,
|
||||
data: PostUpdateFormData,
|
||||
): Promise<Post> {
|
||||
const validatedData = postUpdateFormSchema.parse(data);
|
||||
const response = await client.put<Post>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_USER}/${bbsId}/${pstNo}`,
|
||||
validatedData,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async deletePost(
|
||||
bbsId: string,
|
||||
pstNo: string,
|
||||
pstPswd?: string,
|
||||
): Promise<void> {
|
||||
await client.delete(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS_USER}/${bbsId}/${pstNo}`,
|
||||
{ params: { pstPswd } },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const PostApi = new PostApiService();
|
||||
@@ -0,0 +1,11 @@
|
||||
export { PostApi } from "./api/post-service";
|
||||
export {
|
||||
postFormSchema,
|
||||
postUpdateFormSchema,
|
||||
type Post,
|
||||
type PostList,
|
||||
type PostParams,
|
||||
type PostService,
|
||||
type PostFormData,
|
||||
type PostUpdateFormData,
|
||||
} from "./model/post-interface";
|
||||
@@ -0,0 +1,85 @@
|
||||
import { z } from "zod";
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface PostParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
popupYn?: string;
|
||||
upndFixYn?: string;
|
||||
prdPstgYn?: string;
|
||||
siteId?: string;
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
bbsId: number;
|
||||
rowNo: number;
|
||||
pstNo: number;
|
||||
pstTtl: string;
|
||||
inqNocs: number;
|
||||
rfrncUrl: string;
|
||||
popupYn: string;
|
||||
upndFixYn: string;
|
||||
prdPstgYn: string;
|
||||
rootPath: string;
|
||||
pstPath: string;
|
||||
ansPstn: number;
|
||||
wrtrNm: string;
|
||||
wrtrCplc: string;
|
||||
atflCd: string;
|
||||
regDt: string;
|
||||
rgtrNm: string;
|
||||
cmntCnt: number;
|
||||
}
|
||||
|
||||
export interface PostInfo extends Post {
|
||||
pstCn: string;
|
||||
rgtr: string;
|
||||
mdfcnDt: string;
|
||||
mdfr: string;
|
||||
}
|
||||
|
||||
const postEtcSchema = z.object({
|
||||
bbsPstgTypeCd: z.string(),
|
||||
pstgPrdSeCd: z.string(),
|
||||
pstgBgngDt: z.string().nullish(),
|
||||
pstgEndDt: z.string().nullish(),
|
||||
});
|
||||
|
||||
export const postFormSchema = z.object({
|
||||
bbsId: z.number(),
|
||||
pstTtl: z.string().nonempty(),
|
||||
pstCn: z.string().nullish(),
|
||||
rfrncUrl: z.string().nullish(),
|
||||
popupYn: z.string().nullish(),
|
||||
popupYnEtc: z.array(postEtcSchema).nullish(),
|
||||
upndFixYn: z.string().nullish(),
|
||||
upndFixYnEtc: z.array(postEtcSchema).nullish(),
|
||||
prdPstgYn: z.string().nullish(),
|
||||
prdPstgYnEtc: z.array(postEtcSchema).nullish(),
|
||||
pstPswd: z.string(),
|
||||
wrtrNm: z.string().nullish(),
|
||||
wrtrCplc: z.string().nullish(),
|
||||
atflCd: z.string().nullish(),
|
||||
parentPstNo: z.number().nullish(),
|
||||
});
|
||||
|
||||
export const postUpdateFormSchema = postFormSchema.omit({
|
||||
bbsId: true,
|
||||
parentPstNo: true,
|
||||
});
|
||||
|
||||
export type PostList = PageableList<Post>;
|
||||
export type PostFormData = z.infer<typeof postFormSchema>;
|
||||
export type PostUpdateFormData = z.infer<typeof postUpdateFormSchema>;
|
||||
|
||||
export interface PostService {
|
||||
getPostList(bbsId: string, params: PostParams): Promise<PostList>;
|
||||
getPostInfo(bbsId: string, pstNo: string): Promise<PostInfo>;
|
||||
createPost(data: PostFormData): Promise<Post>;
|
||||
updatePost(
|
||||
bbsId: string,
|
||||
pstNo: string,
|
||||
data: PostUpdateFormData,
|
||||
): Promise<Post>;
|
||||
deletePost(bbsId: string, pstNo: string, pstPswd?: string): Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { handleTusUpload } from "./lib/utils";
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Upload, type HttpResponse } from "tus-js-client";
|
||||
import { getCookie, setCookie } from "@/shared/lib";
|
||||
import { AUTH_USER_ID, CLAIM_NAME, ENDPOINT } from "@/shared/config";
|
||||
|
||||
type UploadOptions = {
|
||||
handleUploadStart?: (upload: Upload) => void;
|
||||
handleProgress?: (percentage: string) => void;
|
||||
handleSuccess?: (upload: Upload) => void;
|
||||
handleResponse?: (res: HttpResponse, upload: Upload) => void;
|
||||
};
|
||||
|
||||
export const handleTusUpload = (file: File, options?: UploadOptions) => {
|
||||
let metadata = {};
|
||||
|
||||
if (!file) return;
|
||||
metadata = {
|
||||
filename: file.name,
|
||||
filetype: file.type,
|
||||
};
|
||||
|
||||
const atflCd = getCookie("atfl-cd-key");
|
||||
if (atflCd) {
|
||||
metadata = {
|
||||
...metadata,
|
||||
atflCd,
|
||||
};
|
||||
}
|
||||
|
||||
const upload = new Upload(file, {
|
||||
endpoint: `${ENDPOINT.ATTACH_SERVICE.TUS_UPLOAD}`,
|
||||
chunkSize: 10 * 1024 * 1024,
|
||||
headers: {
|
||||
[CLAIM_NAME]: getCookie(CLAIM_NAME) ?? "",
|
||||
[AUTH_USER_ID]: getCookie(AUTH_USER_ID) ?? "",
|
||||
},
|
||||
metadata,
|
||||
onError(error) {
|
||||
console.error(`Failed because: ${error}`);
|
||||
},
|
||||
onProgress(bytesUploaded, bytesTotal) {
|
||||
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
|
||||
options?.handleProgress?.(percentage);
|
||||
},
|
||||
onAfterResponse(req, res) {
|
||||
const fileInfo = res.getHeader("X-File-Info");
|
||||
if (fileInfo === undefined || fileInfo === null) return;
|
||||
|
||||
setCookie("atfl-cd-key", JSON.parse(fileInfo)?.atflCd ?? "");
|
||||
options?.handleResponse?.(res, upload);
|
||||
},
|
||||
onSuccess() {
|
||||
options?.handleSuccess?.(upload);
|
||||
},
|
||||
});
|
||||
|
||||
upload.start();
|
||||
options?.handleUploadStart?.(upload);
|
||||
|
||||
console.log("upload start >>>>>", upload);
|
||||
};
|
||||
Reference in New Issue
Block a user