feat(WEB): Phase 6 IntegratedDetailTemplate 마이그레이션 완료
Phase 6 마이그레이션 (41개 컴포넌트 완료): - 건설/시공: 협력업체, 시공관리, 기성관리, 발주관리, 계약관리 등 - 영업: 견적관리(V2), 고객관리(V2), 수주관리 - 회계: 청구관리, 매입관리, 매출관리, 거래처관리, 악성채권 등 - 생산: 작업지시, 검수관리 - 출고: 출하관리 - 자재: 입고관리, 재고현황 - 고객센터: 문의관리, 이벤트관리, 공지관리 - 인사: 직원관리 - 설정: 권한관리 주요 변경사항: - 34개 xxxConfig.ts 파일 생성 (설정 기반 페이지 구성) - PageLayout/PageHeader → IntegratedDetailTemplate 통합 - 일관된 타이틀/버튼 영역 (목록, 상세, 수정, 삭제) - 1112줄 코드 감소 (중복 제거) 프로젝트 공통화 현황 분석 문서 추가: - 상세 페이지 62%, 목록 페이지 82% 공통화 달성 - 추가 공통화 기회 및 로드맵 정리 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,23 +2,19 @@
|
||||
|
||||
/**
|
||||
* 이벤트 상세 컴포넌트
|
||||
* IntegratedDetailTemplate 마이그레이션 완료 (2026-01-20)
|
||||
*
|
||||
* 디자인 스펙:
|
||||
* - 페이지 타이틀: 이벤트 상세
|
||||
* - 이벤트 / 제목
|
||||
* - 작성자 | 기간 | 조회수
|
||||
* - 이미지 영역
|
||||
* - 내용
|
||||
* - 첨부파일
|
||||
* 특이사항:
|
||||
* - view 모드만 지원 (수정/삭제 없음)
|
||||
* - 이미지, 첨부파일 표시
|
||||
*/
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Calendar, ArrowLeft, Download } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { Download } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
|
||||
import { eventConfig } from './eventConfig';
|
||||
import { type Event } from './types';
|
||||
|
||||
interface EventDetailProps {
|
||||
@@ -26,21 +22,9 @@ interface EventDetailProps {
|
||||
}
|
||||
|
||||
export function EventDetail({ event }: EventDetailProps) {
|
||||
const router = useRouter();
|
||||
|
||||
const handleBack = () => {
|
||||
router.push('/ko/customer-center/events');
|
||||
};
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
<PageHeader
|
||||
title="이벤트 상세"
|
||||
description="이벤트를 조회합니다"
|
||||
icon={Calendar}
|
||||
/>
|
||||
|
||||
<Card>
|
||||
// 폼 콘텐츠 렌더링
|
||||
const renderFormContent = useCallback(() => (
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
{/* 헤더: 이벤트 / 제목 */}
|
||||
<div className="border-b pb-4 mb-4">
|
||||
@@ -101,15 +85,17 @@ export function EventDetail({ event }: EventDetailProps) {
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
), [event]);
|
||||
|
||||
{/* 목록으로 버튼 */}
|
||||
<div className="flex items-center">
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
목록으로
|
||||
</Button>
|
||||
</div>
|
||||
</PageLayout>
|
||||
return (
|
||||
<IntegratedDetailTemplate
|
||||
config={eventConfig}
|
||||
mode="view"
|
||||
initialData={event}
|
||||
itemId={event.id}
|
||||
renderView={() => renderFormContent()}
|
||||
renderForm={() => renderFormContent()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Calendar } from 'lucide-react';
|
||||
import type { DetailConfig } from '@/components/templates/IntegratedDetailTemplate/types';
|
||||
|
||||
/**
|
||||
* 이벤트 상세 페이지 Config
|
||||
*
|
||||
* 참고: 이 config는 타이틀/버튼 영역만 정의
|
||||
* 폼 내용은 renderView/renderForm에서 처리
|
||||
*
|
||||
* 특이사항:
|
||||
* - view 모드만 지원 (수정/삭제 없음)
|
||||
* - 이미지, 첨부파일 표시
|
||||
*/
|
||||
export const eventConfig: DetailConfig = {
|
||||
title: '이벤트 상세',
|
||||
description: '이벤트를 조회합니다',
|
||||
icon: Calendar,
|
||||
basePath: '/customer-center/events',
|
||||
fields: [], // renderView/renderForm 사용으로 필드 정의 불필요
|
||||
gridColumns: 1,
|
||||
actions: {
|
||||
showBack: true,
|
||||
showDelete: false,
|
||||
showEdit: false,
|
||||
backLabel: '목록으로',
|
||||
},
|
||||
};
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
/**
|
||||
* 1:1 문의 상세 컴포넌트
|
||||
* IntegratedDetailTemplate 마이그레이션 완료 (2026-01-20)
|
||||
*
|
||||
* 디자인 스펙:
|
||||
* - 페이지 타이틀: 1:1 문의 상세
|
||||
* - 페이지 설명: 1:1 문의를 조회합니다.
|
||||
* 특이사항:
|
||||
* - 삭제/수정 버튼 (답변완료 후에는 수정 버튼 비활성화)
|
||||
* - 문의 영역 (제목, 작성자|날짜, 내용, 첨부파일)
|
||||
* - 답변 영역 (작성자|날짜, 내용, 첨부파일)
|
||||
@@ -13,28 +12,18 @@
|
||||
* - 댓글 목록 (프로필, 이름, 내용, 날짜, 수정/삭제)
|
||||
*/
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { format } from 'date-fns';
|
||||
import { MessageSquare, Download, ArrowLeft, Edit, Trash2, User } from 'lucide-react';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { Download, Edit, Trash2, User } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
} from '@/components/ui/card';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
|
||||
import { inquiryConfig } from './inquiryConfig';
|
||||
import type { Inquiry, Reply, Comment, Attachment } from './types';
|
||||
|
||||
interface InquiryDetailProps {
|
||||
@@ -59,7 +48,6 @@ export function InquiryDetail({
|
||||
onDeleteInquiry,
|
||||
}: InquiryDetailProps) {
|
||||
const router = useRouter();
|
||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||
const [newComment, setNewComment] = useState('');
|
||||
const [editingCommentId, setEditingCommentId] = useState<string | null>(null);
|
||||
const [editingContent, setEditingContent] = useState('');
|
||||
@@ -68,28 +56,30 @@ export function InquiryDetail({
|
||||
const isMyInquiry = inquiry.authorId === currentUserId;
|
||||
const canEdit = isMyInquiry && inquiry.status !== 'completed';
|
||||
|
||||
// ===== 액션 핸들러 =====
|
||||
const handleBack = useCallback(() => {
|
||||
router.push('/ko/customer-center/qna');
|
||||
}, [router]);
|
||||
// 동적 config (작성자/상태에 따라 버튼 표시)
|
||||
const dynamicConfig = useMemo(() => ({
|
||||
...inquiryConfig,
|
||||
actions: {
|
||||
...inquiryConfig.actions,
|
||||
showDelete: isMyInquiry,
|
||||
showEdit: canEdit,
|
||||
},
|
||||
}), [isMyInquiry, canEdit]);
|
||||
|
||||
const handleEdit = useCallback(() => {
|
||||
// 수정 버튼 클릭 시 수정 페이지로 이동
|
||||
const handleEditClick = useCallback(() => {
|
||||
router.push(`/ko/customer-center/qna/${inquiry.id}?mode=edit`);
|
||||
}, [router, inquiry.id]);
|
||||
|
||||
const handleConfirmDelete = useCallback(async () => {
|
||||
if (isSubmitting) return;
|
||||
setIsSubmitting(true);
|
||||
try {
|
||||
const success = await onDeleteInquiry();
|
||||
if (success) {
|
||||
setShowDeleteDialog(false);
|
||||
router.push('/ko/customer-center/qna');
|
||||
}
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
// onDelete 핸들러 (Promise 반환)
|
||||
const handleFormDelete = useCallback(async () => {
|
||||
const success = await onDeleteInquiry();
|
||||
if (success) {
|
||||
router.push('/ko/customer-center/qna');
|
||||
return { success: true };
|
||||
}
|
||||
}, [onDeleteInquiry, router, isSubmitting]);
|
||||
return { success: false, error: '삭제에 실패했습니다.' };
|
||||
}, [onDeleteInquiry, router]);
|
||||
|
||||
// ===== 댓글 핸들러 =====
|
||||
const handleAddComment = useCallback(async () => {
|
||||
@@ -168,39 +158,11 @@ export function InquiryDetail({
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
{/* 헤더 */}
|
||||
<PageHeader
|
||||
title="1:1 문의 상세"
|
||||
description="1:1 문의를 조회합니다."
|
||||
icon={MessageSquare}
|
||||
actions={
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
목록
|
||||
</Button>
|
||||
{isMyInquiry && (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="text-red-500 border-red-200 hover:bg-red-50 hover:text-red-600"
|
||||
onClick={() => setShowDeleteDialog(true)}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
<Button onClick={handleEdit} disabled={!canEdit}>
|
||||
수정
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
// 폼 콘텐츠 렌더링
|
||||
const renderFormContent = useCallback(() => (
|
||||
<div className="space-y-6">
|
||||
{/* 문의 카드 */}
|
||||
<Card className="mb-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
{/* 섹션 타이틀 */}
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -231,7 +193,7 @@ export function InquiryDetail({
|
||||
|
||||
{/* 답변 카드 */}
|
||||
{reply && (
|
||||
<Card className="mb-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
{/* 섹션 타이틀 */}
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -259,7 +221,7 @@ export function InquiryDetail({
|
||||
)}
|
||||
|
||||
{/* 댓글 등록 */}
|
||||
<Card className="mb-6">
|
||||
<Card>
|
||||
<CardContent className="pt-6 space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-2 h-2 bg-red-500 rounded-full" />
|
||||
@@ -360,28 +322,36 @@ export function InquiryDetail({
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
), [
|
||||
inquiry,
|
||||
reply,
|
||||
comments,
|
||||
currentUserId,
|
||||
newComment,
|
||||
editingCommentId,
|
||||
editingContent,
|
||||
isSubmitting,
|
||||
renderAttachments,
|
||||
handleAddComment,
|
||||
handleStartEdit,
|
||||
handleCancelEdit,
|
||||
handleSaveEdit,
|
||||
handleDeleteComment,
|
||||
]);
|
||||
|
||||
{/* 삭제 확인 다이얼로그 */}
|
||||
<AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>문의 삭제</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
정말 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>취소</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={handleConfirmDelete}
|
||||
className="bg-red-600 hover:bg-red-700"
|
||||
>
|
||||
삭제
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</PageLayout>
|
||||
return (
|
||||
<IntegratedDetailTemplate
|
||||
config={dynamicConfig}
|
||||
mode="view"
|
||||
initialData={inquiry}
|
||||
itemId={inquiry.id}
|
||||
isLoading={isSubmitting}
|
||||
onDelete={handleFormDelete}
|
||||
onEdit={handleEditClick}
|
||||
renderView={() => renderFormContent()}
|
||||
renderForm={() => renderFormContent()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { MessageSquare } from 'lucide-react';
|
||||
import type { DetailConfig } from '@/components/templates/IntegratedDetailTemplate/types';
|
||||
|
||||
/**
|
||||
* 1:1 문의 상세 페이지 Config
|
||||
*
|
||||
* 참고: 이 config는 타이틀/버튼 영역만 정의
|
||||
* 폼 내용은 renderView/renderForm에서 처리
|
||||
*
|
||||
* 특이사항:
|
||||
* - view 모드만 지원 (수정은 별도 InquiryForm 사용)
|
||||
* - 댓글 CRUD 기능
|
||||
* - 작성자만 삭제/수정 가능
|
||||
* - 답변완료 후 수정 불가
|
||||
*/
|
||||
export const inquiryConfig: DetailConfig = {
|
||||
title: '1:1 문의 상세',
|
||||
description: '1:1 문의를 조회합니다.',
|
||||
icon: MessageSquare,
|
||||
basePath: '/customer-center/qna',
|
||||
fields: [], // renderView/renderForm 사용으로 필드 정의 불필요
|
||||
gridColumns: 1,
|
||||
actions: {
|
||||
showBack: true,
|
||||
showDelete: true,
|
||||
showEdit: true,
|
||||
backLabel: '목록',
|
||||
editLabel: '수정',
|
||||
deleteLabel: '삭제',
|
||||
},
|
||||
};
|
||||
@@ -2,23 +2,19 @@
|
||||
|
||||
/**
|
||||
* 공지사항 상세 컴포넌트
|
||||
* IntegratedDetailTemplate 마이그레이션 완료 (2026-01-20)
|
||||
*
|
||||
* 디자인 스펙:
|
||||
* - 페이지 타이틀: 공지사항 상세
|
||||
* - 공지사항 / 제목
|
||||
* - 작성자 | 날짜 | 조회수
|
||||
* - 이미지 영역
|
||||
* - 내용
|
||||
* - 첨부파일
|
||||
* 특이사항:
|
||||
* - view 모드만 지원 (수정/삭제 없음)
|
||||
* - 이미지, 첨부파일 표시
|
||||
*/
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Bell, ArrowLeft, Download } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { Download } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
|
||||
import { noticeConfig } from './noticeConfig';
|
||||
import { type Notice } from './types';
|
||||
|
||||
interface NoticeDetailProps {
|
||||
@@ -26,90 +22,80 @@ interface NoticeDetailProps {
|
||||
}
|
||||
|
||||
export function NoticeDetail({ notice }: NoticeDetailProps) {
|
||||
const router = useRouter();
|
||||
// 폼 콘텐츠 렌더링
|
||||
const renderFormContent = useCallback(() => (
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
{/* 헤더: 공지사항 / 제목 */}
|
||||
<div className="border-b pb-4 mb-4">
|
||||
<div className="text-sm text-muted-foreground mb-1">공지사항</div>
|
||||
<h2 className="text-xl font-semibold">{notice.title}</h2>
|
||||
</div>
|
||||
|
||||
const handleBack = () => {
|
||||
router.push('/ko/customer-center/notices');
|
||||
};
|
||||
{/* 메타 정보: 작성자 | 날짜 | 조회수 */}
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground mb-6">
|
||||
<span>{notice.author}</span>
|
||||
<span>|</span>
|
||||
<span>{notice.createdAt}</span>
|
||||
<span className="ml-auto">조회수 {notice.viewCount}</span>
|
||||
</div>
|
||||
|
||||
{/* 이미지 영역 */}
|
||||
{notice.imageUrl ? (
|
||||
<div className="border rounded-md p-4 mb-4 bg-muted/30">
|
||||
<div className="relative w-full aspect-video">
|
||||
<Image
|
||||
src={notice.imageUrl}
|
||||
alt={notice.title}
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="border rounded-md p-4 mb-4 bg-muted/30 flex items-center justify-center min-h-[200px]">
|
||||
<span className="text-muted-foreground">IMG</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 내용 */}
|
||||
<div className="mb-6">
|
||||
<div className="text-sm text-muted-foreground mb-2">내용</div>
|
||||
<div className="prose prose-sm max-w-none">
|
||||
{notice.content}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 첨부파일 */}
|
||||
{notice.attachments && notice.attachments.length > 0 && (
|
||||
<div className="border-t pt-4">
|
||||
{notice.attachments.map((file) => (
|
||||
<div key={file.id} className="flex items-center gap-2">
|
||||
<Download className="h-4 w-4 text-muted-foreground" />
|
||||
<a
|
||||
href={file.url}
|
||||
className="text-sm text-blue-600 hover:underline"
|
||||
download
|
||||
>
|
||||
{file.name}
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
), [notice]);
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
<PageHeader
|
||||
title="공지사항 상세"
|
||||
description="공지사항을 조회합니다"
|
||||
icon={Bell}
|
||||
/>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
{/* 헤더: 공지사항 / 제목 */}
|
||||
<div className="border-b pb-4 mb-4">
|
||||
<div className="text-sm text-muted-foreground mb-1">공지사항</div>
|
||||
<h2 className="text-xl font-semibold">{notice.title}</h2>
|
||||
</div>
|
||||
|
||||
{/* 메타 정보: 작성자 | 날짜 | 조회수 */}
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground mb-6">
|
||||
<span>{notice.author}</span>
|
||||
<span>|</span>
|
||||
<span>{notice.createdAt}</span>
|
||||
<span className="ml-auto">조회수 {notice.viewCount}</span>
|
||||
</div>
|
||||
|
||||
{/* 이미지 영역 */}
|
||||
{notice.imageUrl ? (
|
||||
<div className="border rounded-md p-4 mb-4 bg-muted/30">
|
||||
<div className="relative w-full aspect-video">
|
||||
<Image
|
||||
src={notice.imageUrl}
|
||||
alt={notice.title}
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="border rounded-md p-4 mb-4 bg-muted/30 flex items-center justify-center min-h-[200px]">
|
||||
<span className="text-muted-foreground">IMG</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 내용 */}
|
||||
<div className="mb-6">
|
||||
<div className="text-sm text-muted-foreground mb-2">내용</div>
|
||||
<div className="prose prose-sm max-w-none">
|
||||
{notice.content}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 첨부파일 */}
|
||||
{notice.attachments && notice.attachments.length > 0 && (
|
||||
<div className="border-t pt-4">
|
||||
{notice.attachments.map((file) => (
|
||||
<div key={file.id} className="flex items-center gap-2">
|
||||
<Download className="h-4 w-4 text-muted-foreground" />
|
||||
<a
|
||||
href={file.url}
|
||||
className="text-sm text-blue-600 hover:underline"
|
||||
download
|
||||
>
|
||||
{file.name}
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 목록으로 버튼 */}
|
||||
<div className="flex items-center">
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="w-4 h-4 mr-2" />
|
||||
목록으로
|
||||
</Button>
|
||||
</div>
|
||||
</PageLayout>
|
||||
<IntegratedDetailTemplate
|
||||
config={noticeConfig}
|
||||
mode="view"
|
||||
initialData={notice}
|
||||
itemId={notice.id}
|
||||
renderView={() => renderFormContent()}
|
||||
renderForm={() => renderFormContent()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Bell } from 'lucide-react';
|
||||
import type { DetailConfig } from '@/components/templates/IntegratedDetailTemplate/types';
|
||||
|
||||
/**
|
||||
* 공지사항 상세 페이지 Config
|
||||
*
|
||||
* 참고: 이 config는 타이틀/버튼 영역만 정의
|
||||
* 폼 내용은 renderView/renderForm에서 처리
|
||||
*
|
||||
* 특이사항:
|
||||
* - view 모드만 지원 (수정/삭제 없음)
|
||||
* - 이미지, 첨부파일 표시
|
||||
*/
|
||||
export const noticeConfig: DetailConfig = {
|
||||
title: '공지사항 상세',
|
||||
description: '공지사항을 조회합니다',
|
||||
icon: Bell,
|
||||
basePath: '/customer-center/notices',
|
||||
fields: [], // renderView/renderForm 사용으로 필드 정의 불필요
|
||||
gridColumns: 1,
|
||||
actions: {
|
||||
showBack: true,
|
||||
showDelete: false,
|
||||
showEdit: false,
|
||||
backLabel: '목록으로',
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user