feat: 견적서 모달 회사정보 API 연동
- getCompanyInfo() API 함수 추가 (GET /api/v1/tenants) - EstimateDocumentModal에 회사정보 API 연동 - 하드코딩된 회사명/주소/연락처 제거 - 결재란 견적자명 동적 표시 - constants.ts 모듈 유효성 수정
This commit is contained in:
@@ -1138,4 +1138,78 @@ export async function getEstimateOptions(): Promise<{
|
|||||||
console.error('견적서 옵션 일괄 조회 오류:', error);
|
console.error('견적서 옵션 일괄 조회 오류:', error);
|
||||||
return { success: false, error: '견적서 옵션을 불러오는데 실패했습니다.' };
|
return { success: false, error: '견적서 옵션을 불러오는데 실패했습니다.' };
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 회사 정보 조회 (Tenant API)
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회사 정보 타입 (견적서용)
|
||||||
|
*/
|
||||||
|
export interface CompanyInfo {
|
||||||
|
companyName: string;
|
||||||
|
representativeName: string;
|
||||||
|
address: string;
|
||||||
|
phone: string;
|
||||||
|
fax: string;
|
||||||
|
email: string;
|
||||||
|
managerName: string;
|
||||||
|
managerPhone: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 회사 정보 조회 (견적서 모달용)
|
||||||
|
* GET /api/v1/tenants
|
||||||
|
*/
|
||||||
|
export async function getCompanyInfo(): Promise<{
|
||||||
|
success: boolean;
|
||||||
|
data?: CompanyInfo;
|
||||||
|
error?: string;
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
const response = await apiClient.get<{
|
||||||
|
success: boolean;
|
||||||
|
message: string;
|
||||||
|
data: {
|
||||||
|
id: number;
|
||||||
|
company_name: string;
|
||||||
|
ceo_name?: string;
|
||||||
|
email?: string;
|
||||||
|
phone?: string;
|
||||||
|
fax?: string;
|
||||||
|
address?: string;
|
||||||
|
options?: {
|
||||||
|
manager_name?: string;
|
||||||
|
address_detail?: string;
|
||||||
|
zip_code?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}>('/tenants');
|
||||||
|
|
||||||
|
const tenant = response.data;
|
||||||
|
const opts = tenant.options || {};
|
||||||
|
|
||||||
|
// 주소 조합: 우편번호 + 주소 + 상세주소
|
||||||
|
const fullAddress = [opts.zip_code, tenant.address, opts.address_detail]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
companyName: tenant.company_name || '',
|
||||||
|
representativeName: tenant.ceo_name || '',
|
||||||
|
address: fullAddress || tenant.address || '',
|
||||||
|
phone: tenant.phone || '',
|
||||||
|
fax: tenant.fax || '',
|
||||||
|
email: tenant.email || '',
|
||||||
|
managerName: opts.manager_name || '',
|
||||||
|
managerPhone: tenant.phone || '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('회사 정보 조회 오류:', error);
|
||||||
|
return { success: false, error: '회사 정보를 불러오는데 실패했습니다.' };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { Printer, Pencil, Send, X as XIcon } from 'lucide-react';
|
import { Printer, Pencil, Send, X as XIcon } from 'lucide-react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import { printArea } from '@/lib/print-utils';
|
import { printArea } from '@/lib/print-utils';
|
||||||
import type { EstimateDetailFormData } from '../types';
|
import type { EstimateDetailFormData } from '../types';
|
||||||
|
import { getCompanyInfo, type CompanyInfo } from '../actions';
|
||||||
|
|
||||||
// 금액 포맷팅
|
// 금액 포맷팅
|
||||||
function formatAmount(amount: number): string {
|
function formatAmount(amount: number): string {
|
||||||
@@ -65,6 +66,20 @@ export function EstimateDocumentModal({
|
|||||||
}: EstimateDocumentModalProps) {
|
}: EstimateDocumentModalProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 회사 정보 상태
|
||||||
|
const [companyInfo, setCompanyInfo] = useState<CompanyInfo | null>(null);
|
||||||
|
|
||||||
|
// 회사 정보 로드
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen) {
|
||||||
|
getCompanyInfo().then((result) => {
|
||||||
|
if (result.success && result.data) {
|
||||||
|
setCompanyInfo(result.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
// 인쇄
|
// 인쇄
|
||||||
const handlePrint = useCallback(() => {
|
const handlePrint = useCallback(() => {
|
||||||
printArea({ title: '견적서 인쇄' });
|
printArea({ title: '견적서 인쇄' });
|
||||||
@@ -78,22 +93,22 @@ export function EstimateDocumentModal({
|
|||||||
}
|
}
|
||||||
}, [estimateId, onClose, router]);
|
}, [estimateId, onClose, router]);
|
||||||
|
|
||||||
// 견적서 문서 데이터
|
// 견적서 문서 데이터 (회사 정보는 API에서 로드)
|
||||||
const documentData = {
|
const documentData = {
|
||||||
documentNo: formData.estimateCode || 'ABC123',
|
documentNo: formData.estimateCode || '',
|
||||||
createdDate: formData.siteBriefing.briefingDate || '2025년 11월 11일',
|
createdDate: formData.siteBriefing.briefingDate || '',
|
||||||
recipient: formData.siteBriefing.partnerName || '',
|
recipient: formData.siteBriefing.partnerName || '',
|
||||||
companyName: formData.siteBriefing.companyName || '(주) 주일기업',
|
companyName: companyInfo?.companyName || formData.siteBriefing.companyName || '',
|
||||||
projectName: formData.bidInfo.projectName || '',
|
projectName: formData.bidInfo.projectName || '',
|
||||||
address: '주소',
|
address: companyInfo?.address || '',
|
||||||
amount: formData.summaryItems.reduce((sum, item) => sum + item.totalCost, 0),
|
amount: formData.summaryItems.reduce((sum, item) => sum + item.totalCost, 0),
|
||||||
date: formData.bidInfo.bidDate || '2025년 12월 12일',
|
date: formData.bidInfo.bidDate || '',
|
||||||
manager: formData.estimateCompanyManager || '',
|
manager: companyInfo?.managerName || formData.estimateCompanyManager || '',
|
||||||
managerContact: formData.estimateCompanyManagerContact || '',
|
managerContact: companyInfo?.managerPhone || formData.estimateCompanyManagerContact || '',
|
||||||
contact: {
|
contact: {
|
||||||
hp: '010-3679-2188',
|
hp: companyInfo?.managerPhone || '',
|
||||||
tel: '(02) 849-5130',
|
tel: companyInfo?.phone || '',
|
||||||
fax: '(02) 6911-6315',
|
fax: companyInfo?.fax || '',
|
||||||
},
|
},
|
||||||
note: '하기와 같이 보내합니다.',
|
note: '하기와 같이 보내합니다.',
|
||||||
};
|
};
|
||||||
@@ -160,13 +175,13 @@ export function EstimateDocumentModal({
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="border border-gray-400 px-2 py-3 text-center whitespace-nowrap">결재</td>
|
<td className="border border-gray-400 px-2 py-3 text-center whitespace-nowrap">결재</td>
|
||||||
<td className="border border-gray-400 px-4 py-3 text-center whitespace-nowrap">홍길동</td>
|
<td className="border border-gray-400 px-4 py-3 text-center whitespace-nowrap">{formData.estimatorName || ''}</td>
|
||||||
<td className="border border-gray-400 px-4 py-3 text-center whitespace-nowrap">이름</td>
|
<td className="border border-gray-400 px-4 py-3 text-center whitespace-nowrap"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="border border-gray-400"></td>
|
<td className="border border-gray-400"></td>
|
||||||
<td className="border border-gray-400 px-4 py-1 text-center whitespace-nowrap">부서명</td>
|
<td className="border border-gray-400 px-4 py-1 text-center whitespace-nowrap"></td>
|
||||||
<td className="border border-gray-400 px-4 py-1 text-center whitespace-nowrap">부서명</td>
|
<td className="border border-gray-400 px-4 py-1 text-center whitespace-nowrap"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
// 견적서 상수 정의
|
/**
|
||||||
// 모든 MOCK 데이터는 API로 대체됨:
|
* 견적서 상수 정의
|
||||||
// - 재료(material_type): getCommonCodeOptions('material_type')
|
*
|
||||||
// - 공과 품목: getExpenseItemOptions()
|
* 모든 MOCK 데이터는 API로 대체됨:
|
||||||
// - 도장/모터/제어기/시공비: getCommonCodeOptions('{group}')
|
* - 재료(material_type): getCommonCodeOptions('material_type')
|
||||||
// - 거래처/견적자: getClientOptions(), getUserOptions()
|
* - 공과 품목: getExpenseItemOptions()
|
||||||
|
* - 도장/모터/제어기/시공비: getCommonCodeOptions('{group}')
|
||||||
|
* - 거래처/견적자: getClientOptions(), getUserOptions()
|
||||||
|
* - 회사 정보: getCompanyInfo()
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 빈 export로 모듈 유효성 유지
|
||||||
|
export {};
|
||||||
Reference in New Issue
Block a user