diff options
| -rw-r--r-- | app/[lng]/evcp/(evcp)/information/page.tsx | 4 | ||||
| -rw-r--r-- | app/[lng]/evcp/(evcp)/rfq-last/page.tsx | 2 | ||||
| -rw-r--r-- | app/[lng]/partners/(partners)/bid/page.tsx | 7 | ||||
| -rw-r--r-- | app/[lng]/partners/(partners)/rfq-last/page.tsx | 2 | ||||
| -rw-r--r-- | components/information/information-button.tsx | 29 | ||||
| -rw-r--r-- | components/information/information-client.tsx | 36 | ||||
| -rw-r--r-- | components/notice/notice-create-dialog.tsx | 107 | ||||
| -rw-r--r-- | db/schema/information.ts | 5 | ||||
| -rw-r--r-- | i18n/locales/ko/menu.json | 2 | ||||
| -rw-r--r-- | lib/bidding/list/biddings-page-header.tsx | 7 | ||||
| -rw-r--r-- | lib/information/repository.ts | 40 | ||||
| -rw-r--r-- | lib/information/service.ts | 36 | ||||
| -rw-r--r-- | lib/information/table/update-information-dialog.tsx | 27 |
13 files changed, 220 insertions, 84 deletions
diff --git a/app/[lng]/evcp/(evcp)/information/page.tsx b/app/[lng]/evcp/(evcp)/information/page.tsx index c87471ae..8a6d348b 100644 --- a/app/[lng]/evcp/(evcp)/information/page.tsx +++ b/app/[lng]/evcp/(evcp)/information/page.tsx @@ -9,7 +9,7 @@ import { InformationButton } from "@/components/information/information-button" import { useTranslation } from "@/i18n" export const metadata: Metadata = { - title: "인포메이션 관리", + title: "안내사항 관리", description: "페이지별 도움말 및 첨부파일을 관리합니다.", } @@ -39,7 +39,7 @@ export default async function InformationPage({ params }: InformationPageProps) <div> <div className="flex items-center gap-2"> <h2 className="text-2xl font-bold tracking-tight"> - 인포메이션 관리 + 안내사항 관리 </h2> <InformationButton pagePath="/evcp/information" /> </div> diff --git a/app/[lng]/evcp/(evcp)/rfq-last/page.tsx b/app/[lng]/evcp/(evcp)/rfq-last/page.tsx index 0297c4f9..af5a8d95 100644 --- a/app/[lng]/evcp/(evcp)/rfq-last/page.tsx +++ b/app/[lng]/evcp/(evcp)/rfq-last/page.tsx @@ -84,7 +84,7 @@ export default async function RfqPage(props: RfqPageProps) { <h2 className="text-2xl font-bold tracking-tight"> 견적목록관리 </h2> - <InformationButton pagePath="rfq" /> + <InformationButton pagePath="evcp/rfq-last" /> </div> </div> diff --git a/app/[lng]/partners/(partners)/bid/page.tsx b/app/[lng]/partners/(partners)/bid/page.tsx index a09dec72..05081c3a 100644 --- a/app/[lng]/partners/(partners)/bid/page.tsx +++ b/app/[lng]/partners/(partners)/bid/page.tsx @@ -5,7 +5,7 @@ import { authOptions } from "@/app/api/auth/[...nextauth]/route" import { getBiddingListForPartners } from '@/lib/bidding/detail/service' import { Shell } from '@/components/shell' import { DataTableSkeleton } from '@/components/data-table/data-table-skeleton' - +import { InformationButton } from '@/components/information/information-button' export default async function PartnersBidPage() { // 세션에서 companyId 가져오기 const session = await getServerSession(authOptions) @@ -31,7 +31,10 @@ export default async function PartnersBidPage() { <div className="container mx-auto py-6 space-y-6"> <div className="flex items-center justify-between"> <div> - <h1 className="text-3xl font-bold">입찰 참여</h1> + <div className="flex items-center gap-2"> + <h1 className="text-3xl font-bold">입찰 참여</h1> + <InformationButton pagePath="partners/bid" /> + </div> <p className="text-muted-foreground mt-2"> 참여 가능한 입찰 목록을 확인하고 응찰하실 수 있습니다. </p> diff --git a/app/[lng]/partners/(partners)/rfq-last/page.tsx b/app/[lng]/partners/(partners)/rfq-last/page.tsx index cddb45dd..a49ed648 100644 --- a/app/[lng]/partners/(partners)/rfq-last/page.tsx +++ b/app/[lng]/partners/(partners)/rfq-last/page.tsx @@ -43,7 +43,7 @@ export default async function IndexPage(props: IndexPageProps) { <h2 className="text-2xl font-bold tracking-tight"> 견적 목록 </h2> - <InformationButton pagePath="partners/rfq-ship" /> + <InformationButton pagePath="partners/rfq-last" /> </div> {/* <p className="text-muted-foreground"> 진행 중인 견적서 목록을 확인하고 관리합니다. diff --git a/components/information/information-button.tsx b/components/information/information-button.tsx index 2cff96d0..e9163093 100644 --- a/components/information/information-button.tsx +++ b/components/information/information-button.tsx @@ -18,6 +18,11 @@ import { UpdateInformationDialog } from "@/lib/information/table/update-informat import { NoticeViewDialog } from "@/components/notice/notice-view-dialog"
// import { PDFTronViewerDialog } from "@/components/document-viewer/pdftron-viewer-dialog" // 주석 처리 - 브라우저 내장 뷰어 사용
import type { PageInformation, InformationAttachment } from "@/db/schema/information"
+
+type PageInformationWithUpdatedBy = PageInformation & {
+ updatedByName?: string | null
+ updatedByEmail?: string | null
+}
import type { Notice } from "@/db/schema/notice"
import { useSession } from "next-auth/react"
import { formatDate } from "@/lib/utils"
@@ -44,7 +49,7 @@ export function InformationButton({ }: InformationButtonProps) {
const { data: session } = useSession()
const [isOpen, setIsOpen] = useState(false)
- const [information, setInformation] = useState<(PageInformation & { attachments: InformationAttachment[] }) | null>(null)
+ const [information, setInformation] = useState<PageInformationWithUpdatedBy & { attachments: InformationAttachment[] } | null>(null)
const [notices, setNotices] = useState<NoticeWithAuthor[]>([])
const [hasEditPermission, setHasEditPermission] = useState(false)
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
@@ -211,10 +216,10 @@ export function InformationButton({ variant={variant}
size={size}
className={className}
- title="인포메이션"
+ title="안내사항"
>
<Info className="h-4 w-4" />
- {size !== "icon" && <span className="ml-1">정보</span>}
+ {size !== "icon" && <span className="ml-1">안내사항</span>}
</Button>
</DialogTrigger>
<DialogContent className="max-w-4xl max-h-[80vh] overflow-y-auto">
@@ -277,7 +282,7 @@ export function InformationButton({ )}
</div>
- {/* 인포메이션 컨텐츠 */}
+ {/* 안내사항 컨텐츠 */}
<div className="space-y-3">
<div className="flex items-center justify-between">
<h4 className="font-semibold">안내사항</h4>
@@ -295,8 +300,20 @@ export function InformationButton({ </div>
<div className="bg-muted/50 border rounded-lg p-4">
{information?.informationContent ? (
- <div className="text-sm text-muted-foreground whitespace-pre-wrap max-h-40 overflow-y-auto">
- {information.informationContent}
+ <div className="space-y-3">
+ <div className="text-sm text-muted-foreground whitespace-pre-wrap max-h-40 overflow-y-auto">
+ {information.informationContent}
+ </div>
+ <div className="flex items-center justify-between text-xs text-muted-foreground border-t pt-2">
+ <div className="flex items-center gap-4">
+ <span>
+ <strong>수정자:</strong> {information.updatedByName || '시스템'}
+ </span>
+ <span>
+ <strong>수정일:</strong> {formatDate(information.updatedAt, "KR")}
+ </span>
+ </div>
+ </div>
</div>
) : (
<div className="text-center text-muted-foreground">
diff --git a/components/information/information-client.tsx b/components/information/information-client.tsx index 48bb683d..53350d13 100644 --- a/components/information/information-client.tsx +++ b/components/information/information-client.tsx @@ -28,13 +28,18 @@ import { toast } from "sonner" import { formatDate } from "@/lib/utils"
import { getInformationLists, syncInformationFromMenuAssignments, getInformationDetail } from "@/lib/information/service"
import type { PageInformation } from "@/db/schema/information"
+
+type PageInformationWithUpdatedBy = PageInformation & {
+ updatedByName?: string | null
+ updatedByEmail?: string | null
+}
import { UpdateInformationDialog } from "@/lib/information/table/update-information-dialog"
interface InformationClientProps {
initialData?: PageInformation[]
}
-type SortField = "pageName" | "pagePath" | "createdAt"
+type SortField = "pageName" | "pagePath" | "updatedAt"
type SortDirection = "asc" | "desc"
export function InformationClient({ initialData = [] }: InformationClientProps) {
@@ -58,12 +63,12 @@ export function InformationClient({ initialData = [] }: InformationClientProps) }
}
- const [informations, setInformations] = useState<PageInformation[]>(initialData)
+ const [informations, setInformations] = useState<PageInformationWithUpdatedBy[]>(initialData)
const [loading, setLoading] = useState(false)
const [searchQuery, setSearchQuery] = useState("")
const [sortField, setSortField] = useState<SortField>("createdAt")
const [sortDirection, setSortDirection] = useState<SortDirection>("desc")
- const [editingInformation, setEditingInformation] = useState<PageInformation | null>(null)
+ const [editingInformation, setEditingInformation] = useState<PageInformationWithUpdatedBy | null>(null)
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
const [isSyncing, setIsSyncing] = useState(false)
const [, startTransition] = useTransition()
@@ -327,13 +332,14 @@ export function InformationClient({ initialData = [] }: InformationClientProps) </TableHead>
<TableHead>정보 내용</TableHead>
<TableHead>상태</TableHead>
+ <TableHead>수정자</TableHead>
<TableHead>
<button
className="flex items-center gap-1 hover:text-foreground"
- onClick={() => handleSort("createdAt")}
+ onClick={() => handleSort("updatedAt")}
>
- 생성일
- {sortField === "createdAt" && (
+ 수정일
+ {sortField === "updatedAt" && (
sortDirection === "asc" ? (
<ChevronUp className="h-4 w-4" />
) : (
@@ -342,20 +348,21 @@ export function InformationClient({ initialData = [] }: InformationClientProps) )}
</button>
</TableHead>
+ <TableHead>수정일</TableHead>
<TableHead className="text-right">작업</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{loading ? (
<TableRow>
- <TableCell colSpan={7} className="text-center py-8">
+ <TableCell colSpan={8} className="text-center py-8">
로딩 중...
</TableCell>
</TableRow>
) : filteredAndSortedInformations.length === 0 ? (
<TableRow>
- <TableCell colSpan={7} className="text-center py-8 text-muted-foreground">
- 정보가 없습니다.
+ <TableCell colSpan={8} className="text-center py-8 text-muted-foreground">
+ 안내사항이 없습니다.
</TableCell>
</TableRow>
) : (
@@ -388,7 +395,16 @@ export function InformationClient({ initialData = [] }: InformationClientProps) </Badge>
</TableCell>
<TableCell>
- {formatDate(information.createdAt, "KR")}
+ {information.updatedByName || '시스템'}
+ </TableCell>
+ <TableCell>
+ {formatDate(information.updatedAt, "KR")}
+ </TableCell>
+ <TableCell>
+ {information.updatedAt && information.updatedAt !== information.createdAt
+ ? formatDate(information.updatedAt, "KR")
+ : '-'
+ }
</TableCell>
<TableCell className="text-right">
<Button
diff --git a/components/notice/notice-create-dialog.tsx b/components/notice/notice-create-dialog.tsx index 591b2bc7..98c66c99 100644 --- a/components/notice/notice-create-dialog.tsx +++ b/components/notice/notice-create-dialog.tsx @@ -7,7 +7,7 @@ import { useForm } from "react-hook-form" import { useParams } from "next/navigation"
import { useTranslation } from "@/i18n/client"
import { toast } from "sonner"
-import { Loader } from "lucide-react"
+import { Loader, Check, ChevronsUpDown } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Dialog,
@@ -25,13 +25,9 @@ import { } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Switch } from "@/components/ui/switch"
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
+import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
+import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "@/components/ui/command"
+import { cn } from "@/lib/utils"
import TiptapEditor from "@/components/qna/tiptap-editor"
import { createNotice } from "@/lib/notice/service"
import { createNoticeSchema, type CreateNoticeSchema } from "@/lib/notice/validations"
@@ -135,26 +131,81 @@ export function NoticeCreateDialog({ <FormField
control={form.control}
name="pagePath"
- render={({ field }) => (
- <FormItem>
- <FormLabel>페이지 경로 *</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="페이지를 선택하세요" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {pagePathOptions.map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {safeTranslate(option.label)} - {option.value}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
+ render={({ field }) => {
+ const [open, setOpen] = useState(false)
+ const [searchTerm, setSearchTerm] = useState("")
+
+ const filteredOptions = React.useMemo(() => {
+ if (!searchTerm.trim()) return pagePathOptions
+
+ const lowerSearch = searchTerm.toLowerCase()
+ return pagePathOptions.filter(
+ (option) =>
+ safeTranslate(option.label).toLowerCase().includes(lowerSearch) ||
+ option.value.toLowerCase().includes(lowerSearch)
+ )
+ }, [pagePathOptions, searchTerm])
+
+ const selectedOption = pagePathOptions.find(option => option.value === field.value)
+
+ return (
+ <FormItem>
+ <FormLabel>페이지 경로 *</FormLabel>
+ <Popover open={open} onOpenChange={setOpen}>
+ <PopoverTrigger asChild>
+ <FormControl>
+ <Button
+ variant="outline"
+ role="combobox"
+ aria-expanded={open}
+ className="w-full justify-between"
+ >
+ {selectedOption
+ ? `${safeTranslate(selectedOption.label)} - ${selectedOption.value}`
+ : "페이지를 선택하세요"}
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+ </Button>
+ </FormControl>
+ </PopoverTrigger>
+ <PopoverContent className="w-full p-0" align="start">
+ <Command>
+ <CommandInput
+ placeholder="페이지명 또는 경로 검색..."
+ onValueChange={setSearchTerm}
+ />
+ <CommandList className="max-h-[300px]">
+ <CommandEmpty>검색 결과가 없습니다</CommandEmpty>
+ <CommandGroup>
+ {filteredOptions.map((option) => (
+ <CommandItem
+ key={option.value}
+ value={`${safeTranslate(option.label)} ${option.value}`}
+ onSelect={() => {
+ field.onChange(option.value)
+ setOpen(false)
+ }}
+ >
+ <Check
+ className={cn(
+ "mr-2 h-4 w-4",
+ field.value === option.value
+ ? "opacity-100"
+ : "opacity-0"
+ )}
+ />
+ <span className="font-medium">{safeTranslate(option.label)}</span>
+ <span className="ml-2 text-gray-500 truncate">- {option.value}</span>
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </PopoverContent>
+ </Popover>
+ <FormMessage />
+ </FormItem>
+ )
+ }}
/>
<FormField
diff --git a/db/schema/information.ts b/db/schema/information.ts index f20723d5..325f02a6 100644 --- a/db/schema/information.ts +++ b/db/schema/information.ts @@ -1,5 +1,6 @@ import { pgTable, varchar, timestamp, serial, boolean, text as textArea, integer } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
+import { users } from "./users";
// 페이지별 인포메이션 관리 테이블
export const pageInformation = pgTable("page_information", {
@@ -13,9 +14,11 @@ export const pageInformation = pgTable("page_information", { // 활성화 여부
isActive: boolean("is_active").default(true).notNull(), // 활성화 여부
-
+
+ createdBy: integer("created_by").references(() => users.id), // 생성자
// 메타데이터
createdAt: timestamp("created_at").defaultNow().notNull(),
+ updatedBy: integer("updated_by").references(() => users.id), // 수정자
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
diff --git a/i18n/locales/ko/menu.json b/i18n/locales/ko/menu.json index f81719fc..7b563bcb 100644 --- a/i18n/locales/ko/menu.json +++ b/i18n/locales/ko/menu.json @@ -180,7 +180,7 @@ }, "information_system": { "title": "정보시스템", - "information": "인포메이션 관리", + "information": "안내사항 관리", "notice": "공지사항 관리", "menu_list": "메뉴 리스트", "menu_access": "메뉴 접근제어", diff --git a/lib/bidding/list/biddings-page-header.tsx b/lib/bidding/list/biddings-page-header.tsx index 64e588c3..0be2172b 100644 --- a/lib/bidding/list/biddings-page-header.tsx +++ b/lib/bidding/list/biddings-page-header.tsx @@ -3,7 +3,7 @@ import { Button } from "@/components/ui/button" import { Plus, FileText, TrendingUp } from "lucide-react" import { useRouter } from "next/navigation" - +import { InformationButton } from "@/components/information/information-button" export function BiddingsPageHeader() { const router = useRouter() @@ -11,7 +11,10 @@ export function BiddingsPageHeader() { <div className="flex items-center justify-between"> {/* 좌측: 제목과 설명 */} <div className="space-y-1"> - <h2 className="text-3xl font-bold tracking-tight">입찰 목록 관리</h2> + <div className="flex items-center gap-2"> + <h2 className="text-3xl font-bold tracking-tight">입찰 목록 관리</h2> + <InformationButton pagePath="evcp/bid" /> + </div> <p className="text-muted-foreground"> 입찰 공고를 생성하고 진행 상황을 관리할 수 있습니다. </p> diff --git a/lib/information/repository.ts b/lib/information/repository.ts index c7c000b1..c3b82d4a 100644 --- a/lib/information/repository.ts +++ b/lib/information/repository.ts @@ -1,13 +1,14 @@ import { asc, desc, eq, and } from "drizzle-orm"
import db from "@/db/db"
-import {
- pageInformation,
+import {
+ pageInformation,
informationAttachments,
- type PageInformation,
+ type PageInformation,
type NewPageInformation,
type InformationAttachment,
type NewInformationAttachment
} from "@/db/schema/information"
+import { users } from "@/db/schema/users"
@@ -22,10 +23,22 @@ export async function updateInformation(id: number, data: Partial<NewPageInforma return result[0] || null
}
-// 인포메이션과 첨부파일 함께 조회
+// 인포메이션과 첨부파일 함께 조회 (사용자 정보 포함)
export async function getInformationWithAttachments(id: number) {
const information = await db
- .select()
+ .select({
+ id: pageInformation.id,
+ pagePath: pageInformation.pagePath,
+ pageName: pageInformation.pageName,
+ informationContent: pageInformation.informationContent,
+ isActive: pageInformation.isActive,
+ createdBy: pageInformation.createdBy,
+ createdAt: pageInformation.createdAt,
+ updatedBy: pageInformation.updatedBy,
+ updatedAt: pageInformation.updatedAt,
+ updatedByName: users.name,
+ updatedByEmail: users.email,
+ })
.from(pageInformation)
.where(eq(pageInformation.id, id))
.limit(1)
@@ -44,11 +57,24 @@ export async function getInformationWithAttachments(id: number) { }
}
-// 페이지 경로로 인포메이션과 첨부파일 함께 조회
+// 페이지 경로로 인포메이션과 첨부파일 함께 조회 (사용자 정보 포함)
export async function getInformationByPagePathWithAttachments(pagePath: string) {
const information = await db
- .select()
+ .select({
+ id: pageInformation.id,
+ pagePath: pageInformation.pagePath,
+ pageName: pageInformation.pageName,
+ informationContent: pageInformation.informationContent,
+ isActive: pageInformation.isActive,
+ createdBy: pageInformation.createdBy,
+ createdAt: pageInformation.createdAt,
+ updatedBy: pageInformation.updatedBy,
+ updatedAt: pageInformation.updatedAt,
+ updatedByName: users.name,
+ updatedByEmail: users.email,
+ })
.from(pageInformation)
+ .leftJoin(users, eq(pageInformation.updatedBy, users.id))
.where(and(
eq(pageInformation.pagePath, pagePath),
eq(pageInformation.isActive, true)
diff --git a/lib/information/service.ts b/lib/information/service.ts index 2d3ad079..02efe616 100644 --- a/lib/information/service.ts +++ b/lib/information/service.ts @@ -3,7 +3,7 @@ import { getErrorMessage } from "@/lib/handle-error" import { desc, or, eq } from "drizzle-orm" import db from "@/db/db" -import { pageInformation, menuAssignments } from "@/db/schema" +import { pageInformation, menuAssignments, users } from "@/db/schema" import { saveDRMFile } from "@/lib/file-stroage" import { decryptWithServerAction } from "@/components/drm/drmUtils" @@ -25,10 +25,23 @@ import type { PageInformation, InformationAttachment } from "@/db/schema/informa // 간단한 인포메이션 목록 조회 (페이지네이션 없이 전체 조회) export async function getInformationLists() { try { - // 전체 데이터 조회 (클라이언트에서 검색 처리) + // 전체 데이터 조회 (클라이언트에서 검색 처리, 생성자/수정자 정보 포함) const data = await db - .select() + .select({ + id: pageInformation.id, + pagePath: pageInformation.pagePath, + pageName: pageInformation.pageName, + informationContent: pageInformation.informationContent, + isActive: pageInformation.isActive, + createdBy: pageInformation.createdBy, + createdAt: pageInformation.createdAt, + updatedBy: pageInformation.updatedBy, + updatedAt: pageInformation.updatedAt, + updatedByName: users.name, + updatedByEmail: users.email, + }) .from(pageInformation) + .leftJoin(users, eq(pageInformation.updatedBy, users.id)) .orderBy(desc(pageInformation.createdAt)) return { data } @@ -68,28 +81,29 @@ export async function getPageInformationDirect(pagePath: string) { } // 인포메이션 수정 (내용과 첨부파일만) -export async function updateInformationData(input: UpdateInformationSchema) { +export async function updateInformationData(input: UpdateInformationSchema, userId?: string) { try { const { id, ...updateData } = input - + // 수정 가능한 필드만 허용 const allowedFields = { informationContent: updateData.informationContent, isActive: updateData.isActive, + updatedBy: userId ? parseInt(userId) : null, updatedAt: new Date() } - + const result = await updateInformation(id, allowedFields) - + if (!result) { return { success: false, message: "인포메이션을 찾을 수 없거나 수정에 실패했습니다." } } - + // 캐시 무효화 제거됨 - + return { success: true, message: "인포메이션이 성공적으로 수정되었습니다." @@ -174,8 +188,8 @@ export async function syncInformationFromMenuAssignments() { for (const menu of menuItems) { try { // 맨 앞의 / 제거하여 pagePath 정규화 - const normalizedPagePath = menu.menuPath.startsWith('/') - ? menu.menuPath.slice(1) + const normalizedPagePath = menu.menuPath.startsWith('/') + ? menu.menuPath.slice(1) : menu.menuPath; await db.insert(pageInformation) diff --git a/lib/information/table/update-information-dialog.tsx b/lib/information/table/update-information-dialog.tsx index 370eb763..147dc2ab 100644 --- a/lib/information/table/update-information-dialog.tsx +++ b/lib/information/table/update-information-dialog.tsx @@ -46,13 +46,14 @@ import { import type { PageInformation, InformationAttachment } from "@/db/schema/information"
// downloadFile은 동적으로 import
import prettyBytes from "pretty-bytes"
+import { useSession } from "next-auth/react"
const MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB
// 폼 스키마
const updateInformationSchema = z.object({
id: z.number(),
- informationContent: z.string().min(1, "인포메이션 내용을 입력해주세요"),
+ informationContent: z.string().min(1, "안내사항 내용을 입력해주세요"),
isActive: z.boolean(),
newFiles: z.array(z.any()).optional(),
})
@@ -79,6 +80,8 @@ export function UpdateInformationDialog({ const [isLoading, setIsLoading] = React.useState(false)
const [isUploadingFiles, setIsUploadingFiles] = React.useState(false)
const [existingAttachments, setExistingAttachments] = React.useState<InformationAttachment[]>([])
+ const session = useSession()
+ const userId = session.data?.user?.id
const form = useForm<UpdateInformationSchema>({
resolver: zodResolver(updateInformationSchema),
@@ -95,7 +98,7 @@ export function UpdateInformationDialog({ name: "newFiles",
})
- // 인포메이션 데이터가 변경되면 폼 업데이트
+ // 안내사항 데이터가 변경되면 폼 업데이트
React.useEffect(() => {
if (information && open) {
form.reset({
@@ -160,12 +163,12 @@ export function UpdateInformationDialog({ const onSubmit = async (values: UpdateInformationSchema) => {
setIsLoading(true)
try {
- // 1. 인포메이션 정보 업데이트
+ // 1. 안내사항 정보 업데이트
const updateResult = await updateInformationData({
id: values.id,
informationContent: values.informationContent,
isActive: values.isActive,
- })
+ }, userId)
if (!updateResult.success) {
toast.error(updateResult.message)
@@ -189,13 +192,13 @@ export function UpdateInformationDialog({ setIsUploadingFiles(false)
}
- toast.success("인포메이션이 성공적으로 수정되었습니다.")
+ toast.success("안내사항이 성공적으로 수정되었습니다.")
if (onSuccess) onSuccess()
onOpenChange(false)
router.refresh()
} catch (error) {
- console.error("인포메이션 수정 오류:", error)
- toast.error("인포메이션 수정에 실패했습니다.")
+ console.error("안내사항 수정 오류:", error)
+ toast.error("안내사항 수정에 실패했습니다.")
} finally {
setIsLoading(false)
setIsUploadingFiles(false)
@@ -212,9 +215,9 @@ export function UpdateInformationDialog({ <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
- <DialogTitle>{t('information.edit.title', '인포메이션 수정')}</DialogTitle>
+ <DialogTitle>{t('information.edit.title', '안내사항 수정')}</DialogTitle>
<DialogDescription>
- {t('information.edit.description', '페이지 인포메이션 정보를 수정합니다.')}
+ {t('information.edit.description', '페이지 안내사항 정보를 수정합니다.')}
</DialogDescription>
</DialogHeader>
@@ -237,10 +240,10 @@ export function UpdateInformationDialog({ name="informationContent"
render={({ field }) => (
<FormItem>
- <FormLabel>{t('information.content.label', '인포메이션 내용')}</FormLabel>
+ <FormLabel>{t('information.content.label', '안내사항')}</FormLabel>
<FormControl>
<Textarea
- placeholder={t('information.content.placeholder', '인포메이션 내용을 입력하세요')}
+ placeholder={t('information.content.placeholder', '안내사항을 입력하세요')}
rows={6}
{...field}
/>
@@ -355,7 +358,7 @@ export function UpdateInformationDialog({ <div className="space-y-0.5">
<FormLabel className="text-base">{t('information.status.label', '활성 상태')}</FormLabel>
<div className="text-sm text-muted-foreground">
- {t('information.status.description', '활성화하면 해당 페이지에서 인포메이션 버튼이 표시됩니다.')}
+ {t('information.status.description', '활성화하면 해당 페이지에서 안내사항 버튼이 표시됩니다.')}
</div>
</div>
<FormControl>
|
