diff --git a/app/Http/Controllers/ESign/EsignApiController.php b/app/Http/Controllers/ESign/EsignApiController.php index 9996b7c9..b39441bb 100644 --- a/app/Http/Controllers/ESign/EsignApiController.php +++ b/app/Http/Controllers/ESign/EsignApiController.php @@ -818,6 +818,62 @@ public function destroyTemplateItem(int $templateId, int $itemId): JsonResponse ]); } + /** + * 템플릿 필드 아이템 일괄 저장 (에디터에서 사용) + */ + public function updateTemplateItems(Request $request, int $templateId): JsonResponse + { + $request->validate([ + 'items' => 'present|array', + 'items.*.signer_order' => 'required|integer|min:1', + 'items.*.page_number' => 'required|integer|min:1', + 'items.*.position_x' => 'required|numeric', + 'items.*.position_y' => 'required|numeric', + 'items.*.width' => 'required|numeric', + 'items.*.height' => 'required|numeric', + 'items.*.field_type' => 'required|in:signature,stamp,text,date,checkbox', + 'items.*.field_label' => 'nullable|string|max:100', + 'items.*.is_required' => 'nullable|boolean', + ]); + + $tenantId = session('selected_tenant_id', 1); + $template = EsignFieldTemplate::forTenant($tenantId)->findOrFail($templateId); + + $items = $request->input('items', []); + + DB::transaction(function () use ($template, $items) { + // 기존 아이템 삭제 + EsignFieldTemplateItem::where('template_id', $template->id)->delete(); + + // 새 아이템 생성 + foreach ($items as $i => $itemData) { + EsignFieldTemplateItem::create([ + 'template_id' => $template->id, + 'signer_order' => $itemData['signer_order'], + 'page_number' => $itemData['page_number'], + 'position_x' => round($itemData['position_x'], 2), + 'position_y' => round($itemData['position_y'], 2), + 'width' => round($itemData['width'], 2), + 'height' => round($itemData['height'], 2), + 'field_type' => $itemData['field_type'], + 'field_label' => $itemData['field_label'] ?? '', + 'is_required' => $itemData['is_required'] ?? true, + 'sort_order' => $i, + ]); + } + + // signer_count 업데이트 + $maxOrder = collect($items)->max('signer_order') ?: 0; + $template->update(['signer_count' => $maxOrder]); + }); + + return response()->json([ + 'success' => true, + 'message' => '템플릿 필드가 저장되었습니다.', + 'data' => $template->fresh()->load('items'), + ]); + } + /** * 템플릿 복제 */ diff --git a/app/Http/Controllers/ESign/EsignController.php b/app/Http/Controllers/ESign/EsignController.php index 5dcc5e6c..95ed5179 100644 --- a/app/Http/Controllers/ESign/EsignController.php +++ b/app/Http/Controllers/ESign/EsignController.php @@ -54,6 +54,15 @@ public function send(Request $request, int $id): View|Response return view('esign.send', ['contractId' => $id]); } + public function templateFields(Request $request, int $templateId): View|Response + { + if ($request->header('HX-Request')) { + return response('', 200)->header('HX-Redirect', route('esign.template-fields', $templateId)); + } + + return view('esign.template-fields', ['templateId' => $templateId]); + } + public function templates(Request $request): View|Response { if ($request->header('HX-Request')) { diff --git a/resources/views/esign/template-fields.blade.php b/resources/views/esign/template-fields.blade.php new file mode 100644 index 00000000..7520d46e --- /dev/null +++ b/resources/views/esign/template-fields.blade.php @@ -0,0 +1,790 @@ +@extends('layouts.app') + +@section('title', 'SAM E-Sign - 템플릿 필드 편집') + +@section('content') + +
+@endsection + +@push('scripts') +@include('partials.react-cdn') + + + +@verbatim + +@endverbatim +@endpush diff --git a/resources/views/esign/templates.blade.php b/resources/views/esign/templates.blade.php index 408b45a8..7869e8b6 100644 --- a/resources/views/esign/templates.blade.php +++ b/resources/views/esign/templates.blade.php @@ -236,10 +236,24 @@ className="px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 {/* 서식 필드 탭 */} {tab === 'fields' && (PDF에서 시각적으로 필드를 편집할 수 있습니다
+드래그 앤 드롭으로 서명 위치를 설정하세요
+서식 필드가 없습니다.
-계약의 필드 에디터에서 "템플릿으로 저장" 시 필드가 포함됩니다.
+{tpl.file_path ? '위의 "비주얼 편집" 버튼으로 PDF에서 필드를 추가하세요.' : '계약의 필드 에디터에서 "템플릿으로 저장" 시 필드가 포함됩니다.'}