feat: 다중 도메인 UI 개선 및 컴포넌트 리팩토링
- 게시판, HR, 설정, 차량관리, 건설, 견적 등 전반적 UI 개선 - FormField, TabChip, Select 등 공통 컴포넌트 개선 - 가격배분 edit 페이지 제거 및 상세 페이지 통합 - 체크리스트, 근태, 급여, 권한 관리 등 폼 개선 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,8 @@ import { DynamicBoardEditForm } from '@/components/board/DynamicBoard/DynamicBoa
|
||||
import { useState, useEffect, useCallback, Suspense } from 'react';
|
||||
import { DetailPageSkeleton } from '@/components/ui/skeleton';
|
||||
import { format } from 'date-fns';
|
||||
import { ArrowLeft, Pencil, Trash2, MessageSquare, Eye } from 'lucide-react';
|
||||
import { ArrowLeft, Edit, Trash2, MessageSquare, Eye } from 'lucide-react';
|
||||
import { useMenuStore } from '@/stores/menuStore';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
@@ -100,6 +101,7 @@ function DetailModeRouter() {
|
||||
// 실제 상세 컴포넌트 (자체 hooks 사용)
|
||||
function DynamicBoardDetailContent({ boardCode, postId }: { boardCode: string; postId: string }) {
|
||||
const router = useRouter();
|
||||
const sidebarCollapsed = useMenuStore((state) => state.sidebarCollapsed);
|
||||
|
||||
// 게시판 정보
|
||||
const [boardName, setBoardName] = useState<string>('게시판');
|
||||
@@ -261,6 +263,7 @@ function DynamicBoardDetailContent({ boardCode, postId }: { boardCode: string; p
|
||||
icon={MessageSquare}
|
||||
/>
|
||||
|
||||
<div className="pb-24">
|
||||
{/* 게시글 상세 */}
|
||||
<Card className="mb-6">
|
||||
<CardHeader>
|
||||
@@ -282,9 +285,9 @@ function DynamicBoardDetailContent({ boardCode, postId }: { boardCode: string; p
|
||||
</div>
|
||||
</div>
|
||||
{isAuthor && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="hidden md:flex items-center gap-2">
|
||||
<Button variant="outline" size="sm" onClick={handleEdit}>
|
||||
<Pencil className="h-4 w-4 mr-1" />
|
||||
<Edit className="h-4 w-4 mr-1" />
|
||||
수정
|
||||
</Button>
|
||||
<Button variant="destructive" size="sm" onClick={() => setShowDeleteDialog(true)}>
|
||||
@@ -400,13 +403,33 @@ function DynamicBoardDetailContent({ boardCode, postId }: { boardCode: string; p
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* 하단 버튼 */}
|
||||
<div className="mt-6 flex justify-start">
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
목록으로
|
||||
{/* 하단 액션 버튼 (sticky) */}
|
||||
<div
|
||||
className={`fixed bottom-4 left-4 right-4 px-4 py-3 bg-background/95 backdrop-blur rounded-xl border shadow-lg z-50 transition-all duration-300 md:bottom-6 md:px-6 md:right-[48px] ${sidebarCollapsed ? 'md:left-[156px]' : 'md:left-[316px]'} flex items-center justify-between`}
|
||||
>
|
||||
<Button variant="outline" onClick={handleBack} size="sm" className="md:size-default">
|
||||
<ArrowLeft className="w-4 h-4 md:mr-2" />
|
||||
<span className="hidden md:inline">목록으로</span>
|
||||
</Button>
|
||||
{isAuthor && (
|
||||
<div className="flex items-center gap-1 md:gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setShowDeleteDialog(true)}
|
||||
size="sm"
|
||||
className="text-destructive hover:bg-destructive hover:text-destructive-foreground md:size-default"
|
||||
>
|
||||
<Trash2 className="w-4 h-4 md:mr-2" />
|
||||
<span className="hidden md:inline">삭제</span>
|
||||
</Button>
|
||||
<Button onClick={handleEdit} size="sm" className="md:size-default">
|
||||
<Edit className="w-4 h-4 md:mr-2" />
|
||||
<span className="hidden md:inline">수정</span>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 게시글 삭제 확인 다이얼로그 */}
|
||||
|
||||
@@ -223,7 +223,7 @@ function DynamicBoardListContent({ boardCode }: { boardCode: string }) {
|
||||
|
||||
const handleRowClick = useCallback(
|
||||
(item: BoardPost) => {
|
||||
router.push(`/ko/boards/${boardCode}/${item.id}`);
|
||||
router.push(`/ko/boards/${boardCode}/${item.id}?mode=view`);
|
||||
},
|
||||
[router, boardCode]
|
||||
);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { use } from 'react';
|
||||
import { PriceDistributionDetail } from '@/components/pricing-distribution';
|
||||
|
||||
export default function PriceDistributionEditPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ id: string }>;
|
||||
}) {
|
||||
const { id } = use(params);
|
||||
|
||||
return <PriceDistributionDetail id={id} mode="edit" />;
|
||||
}
|
||||
@@ -10,5 +10,5 @@ export default function PriceDistributionDetailPage({
|
||||
}) {
|
||||
const { id } = use(params);
|
||||
|
||||
return <PriceDistributionDetail id={id} mode="view" />;
|
||||
return <PriceDistributionDetail id={id} />;
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ export default function OrderEditPage() {
|
||||
}, [orderId, router]);
|
||||
|
||||
const handleCancel = () => {
|
||||
router.push(`/sales/order-management-sales/${orderId}`);
|
||||
router.push(`/sales/order-management-sales/${orderId}?mode=view`);
|
||||
};
|
||||
|
||||
// onSubmit wrapper for IntegratedDetailTemplate
|
||||
@@ -247,7 +247,7 @@ export default function OrderEditPage() {
|
||||
|
||||
if (result.success) {
|
||||
toast.success("수주가 수정되었습니다.");
|
||||
router.push(`/sales/order-management-sales/${orderId}`);
|
||||
router.push(`/sales/order-management-sales/${orderId}?mode=view`);
|
||||
return { success: true };
|
||||
} else {
|
||||
toast.error(result.error || "수주 수정에 실패했습니다.");
|
||||
|
||||
@@ -395,11 +395,11 @@ export default function ProductionOrderCreatePage() {
|
||||
}, [fetchData]);
|
||||
|
||||
const handleCancel = () => {
|
||||
router.push(`/ko/sales/order-management-sales/${orderId}`);
|
||||
router.push(`/ko/sales/order-management-sales/${orderId}?mode=view`);
|
||||
};
|
||||
|
||||
const handleBackToDetail = () => {
|
||||
router.push(`/ko/sales/order-management-sales/${orderId}`);
|
||||
router.push(`/ko/sales/order-management-sales/${orderId}?mode=view`);
|
||||
};
|
||||
|
||||
const handleConfirm = async () => {
|
||||
@@ -467,7 +467,7 @@ export default function ProductionOrderCreatePage() {
|
||||
const handleSuccessDialogClose = () => {
|
||||
setShowSuccessDialog(false);
|
||||
// 수주 상세 페이지로 이동 (상태가 변경되었으므로)
|
||||
router.push(`/ko/sales/order-management-sales/${orderId}`);
|
||||
router.push(`/ko/sales/order-management-sales/${orderId}?mode=view`);
|
||||
};
|
||||
|
||||
// 선택된 우선순위 설정 가져오기
|
||||
|
||||
@@ -318,11 +318,11 @@ export default function ProductionOrdersListPage() {
|
||||
};
|
||||
|
||||
const handleRowClick = (item: ProductionOrder) => {
|
||||
router.push(`/sales/order-management-sales/production-orders/${item.id}`);
|
||||
router.push(`/sales/order-management-sales/production-orders/${item.id}?mode=view`);
|
||||
};
|
||||
|
||||
const handleView = (item: ProductionOrder) => {
|
||||
router.push(`/sales/order-management-sales/production-orders/${item.id}`);
|
||||
router.push(`/sales/order-management-sales/production-orders/${item.id}?mode=view`);
|
||||
};
|
||||
|
||||
// 개별 삭제 다이얼로그 열기
|
||||
|
||||
@@ -118,7 +118,7 @@ export default function QuoteDetailPage() {
|
||||
|
||||
// 수주등록 페이지로 이동 핸들러
|
||||
const handleOrderRegister = useCallback(() => {
|
||||
router.push(`/sales/order-management-sales/new?quoteId=${quoteId}`);
|
||||
router.push(`/sales/order-management-sales/new?mode=new"eId=${quoteId}`);
|
||||
}, [router, quoteId]);
|
||||
|
||||
// 기존 수주 보기 핸들러 (이미 수주가 있는 경우)
|
||||
@@ -161,7 +161,7 @@ export default function QuoteDetailPage() {
|
||||
|
||||
if (isEditMode) {
|
||||
// edit 모드에서 저장 후 view 모드로 전환
|
||||
router.push(`/sales/quote-management/${quoteId}`);
|
||||
router.push(`/sales/quote-management/${quoteId}?mode=view`);
|
||||
} else {
|
||||
// view 모드에서 최종저장 후 페이지 새로고침 (데이터 갱신)
|
||||
router.refresh();
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function QuoteNewPage() {
|
||||
|
||||
// 저장 후 상세 페이지로 이동
|
||||
if (result.data?.id) {
|
||||
router.push(`/sales/quote-management/${result.data.id}`);
|
||||
router.push(`/sales/quote-management/${result.data.id}?mode=view`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[QuoteNewPage] 저장 오류:', error);
|
||||
|
||||
Reference in New Issue
Block a user