This commit is contained in:
2025-07-01 10:51:57 +09:00
90 changed files with 4706 additions and 2209 deletions
+3
View File
@@ -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,
+1
View File
@@ -58,6 +58,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",
},
};
+1
View File
@@ -5,3 +5,4 @@ export { useDataTable } from "./use-data-table";
export { useMenuStore } from "./use-menu-store";
export { useUserStore } from "./use-user-store";
export { usePrompt } from "./use-prompt";
export { useSelectPrompt } from "./use-select-prompt";
@@ -0,0 +1,48 @@
import { useContext, useEffect } from "react";
import { PromptContext } from "../providers/prompt-provider";
type SelectData = {
label: string;
value: string;
};
export const useSelectPrompt = (data?: SelectData[]) => {
const {
selectData,
selectionGuide,
resolve,
setResolve,
setSelectData,
setSelectionGuide,
} = useContext(PromptContext);
const prompt = (message: string) => {
setSelectionGuide(message);
return new Promise<{ resolved: boolean; value?: string }>((resolve) => {
setResolve(() => resolve);
});
};
const onSubmit = (value: string) => {
resolve?.({ resolved: true, value });
setSelectionGuide("");
};
const onCancel = () => {
resolve?.({ resolved: false });
setSelectionGuide("");
};
useEffect(() => {
if (data) setSelectData(data);
}, [data]);
return {
selectData,
selectionGuide,
isOpen: !!selectionGuide,
prompt,
onSubmit,
onCancel,
};
};
@@ -1,7 +1,14 @@
import { createContext, useState } from "react";
type SelectData = {
label: string;
value: string;
};
interface PromptContext {
message?: string;
selectData?: SelectData[];
selectionGuide?: string;
resolve?: ({
resolved,
value,
@@ -10,18 +17,26 @@ interface PromptContext {
value?: string;
}) => void;
setMessage: (message: string) => void;
setSelectData: (selectData: SelectData[]) => void;
setSelectionGuide: (message: string) => void;
setResolve: (resolve: () => void) => void;
}
export const PromptContext = createContext<PromptContext>({
message: "",
selectData: [],
selectionGuide: "",
resolve() {},
setMessage() {},
setSelectData() {},
setSelectionGuide() {},
setResolve() {},
});
export const PromptProvider = ({ children }: { children: React.ReactNode }) => {
const [message, setMessage] = useState<string>();
const [selectData, setSelectData] = useState<SelectData[]>([]);
const [selectionGuide, setSelectionGuide] = useState<string>();
const [resolve, setResolve] =
useState<
({ resolved, value }: { resolved: boolean; value?: string }) => void
@@ -29,7 +44,16 @@ export const PromptProvider = ({ children }: { children: React.ReactNode }) => {
return (
<PromptContext.Provider
value={{ message, resolve, setMessage, setResolve }}
value={{
message,
selectData,
selectionGuide,
resolve,
setMessage,
setSelectData,
setSelectionGuide,
setResolve,
}}
>
{children}
</PromptContext.Provider>
+5 -1
View File
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import {
Button,
Dialog,
@@ -13,6 +13,10 @@ function PromptDialog() {
const { message, isOpen, onSubmit, onCancel } = usePrompt();
const [value, setValue] = useState("");
useEffect(() => {
if (isOpen) setValue("");
}, [isOpen]);
return (
<Dialog open={isOpen} onOpenChange={onCancel}>
<DialogContent aria-describedby={undefined}>
@@ -0,0 +1,68 @@
import { useEffect, useState } from "react";
import {
Button,
Dialog,
DialogContent,
DialogFooter,
DialogClose,
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
Textarea,
} from "@common/components";
import { useSelectPrompt } from "../lib/use-select-prompt";
function SelectPromptDialog() {
const { selectData, selectionGuide, isOpen, onSubmit, onCancel } =
useSelectPrompt();
const [value, setValue] = useState("");
useEffect(() => {
if (isOpen) setValue("");
}, [isOpen]);
return (
<Dialog open={isOpen} onOpenChange={onCancel}>
<DialogContent aria-describedby={undefined}>
<div className="flex flex-col gap-6 pb-4 pt-8">
<p className="whitespace-pre-line text-center text-[1.4rem] text-foreground">
{selectionGuide}
</p>
<div className="flex flex-col gap-2">
<Select onValueChange={setValue}>
<SelectTrigger>
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
{selectData?.map((data) => (
<SelectItem key={data.value} value={data.value}>
{data.label}
</SelectItem>
))}
</SelectContent>
</Select>
<Textarea
value={value}
className="!text-[1.3rem] !leading-6"
onChange={(e) => setValue(e.target.value)}
/>
</div>
</div>
<DialogFooter className="!justify-center">
<DialogClose asChild>
<Button onClick={() => onSubmit(value)}>확인</Button>
</DialogClose>
<DialogClose asChild>
<Button onClick={onCancel} color="white">
취소
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
export { SelectPromptDialog };