- show/edit 뷰에서 bf_{id} 조회 실패 시 bf_{label} 레거시 호환 추가
- 기존 bf_납품명 형식으로 저장된 문서도 정상 표시
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
955 lines
67 KiB
PHP
955 lines
67 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', $isCreate ? '새 문서 작성' : '문서 수정')
|
|
|
|
@section('content')
|
|
<div class="max-w-7xl mx-auto">
|
|
<!-- 헤더 -->
|
|
<div class="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-4 mb-6">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-gray-800">{{ $isCreate ? '새 문서 작성' : '문서 수정' }}</h1>
|
|
<p class="text-sm text-gray-500 mt-1 hidden sm:block">
|
|
@if($document)
|
|
{{ $document->document_no }} - {{ $document->title }}
|
|
@else
|
|
템플릿을 선택하여 문서를 작성합니다.
|
|
@endif
|
|
</p>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<a href="{{ route('documents.index') }}"
|
|
class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-4 py-2 rounded-lg transition">
|
|
목록
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 템플릿 선택 (생성 시) --}}
|
|
@if($isCreate && !$template)
|
|
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4">템플릿 선택</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
@forelse($templates as $tpl)
|
|
<a href="{{ route('documents.create', ['template_id' => $tpl->id]) }}"
|
|
class="block p-4 border border-gray-200 rounded-lg hover:border-blue-500 hover:bg-blue-50 transition-colors">
|
|
<h3 class="font-medium text-gray-900">{{ $tpl->name }}</h3>
|
|
<p class="text-sm text-gray-500 mt-1">{{ $tpl->category }}</p>
|
|
</a>
|
|
@empty
|
|
<p class="text-gray-500 col-span-3">사용 가능한 템플릿이 없습니다.</p>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- 문서 폼 --}}
|
|
@if($template)
|
|
<form id="documentForm" class="space-y-6">
|
|
@csrf
|
|
<input type="hidden" name="template_id" value="{{ $template->id }}">
|
|
|
|
{{-- 기본 정보 --}}
|
|
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4">기본 정보</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">템플릿</label>
|
|
<input type="text" value="{{ $template->name }}" disabled
|
|
class="w-full rounded-lg border-gray-300 bg-gray-50 text-sm">
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">
|
|
제목 <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="text" name="title" value="{{ $document->title ?? '' }}" required
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500"
|
|
placeholder="문서 제목을 입력하세요">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- 기본 필드 --}}
|
|
@if($template->basicFields && $template->basicFields->count() > 0)
|
|
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4">{{ $template->title ?? '문서 정보' }}</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
@foreach($template->basicFields as $field)
|
|
@php
|
|
$fieldKey = 'bf_' . $field->id;
|
|
$fieldData = $document?->data->where('field_key', $fieldKey)->first();
|
|
// 레거시 호환: bf_{label} 형식으로 저장된 데이터도 조회
|
|
if (!$fieldData) {
|
|
$fieldData = $document?->data->where('field_key', 'bf_' . $field->label)->first();
|
|
}
|
|
$savedValue = $fieldData?->field_value ?? $field->default_value ?? '';
|
|
@endphp
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">
|
|
{{ $field->label }}
|
|
</label>
|
|
@if($field->field_type === 'textarea')
|
|
<textarea name="data[{{ $fieldKey }}]"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500"
|
|
rows="3">{{ $savedValue }}</textarea>
|
|
@elseif($field->field_type === 'date')
|
|
<input type="date" name="data[{{ $fieldKey }}]"
|
|
value="{{ $savedValue }}"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@elseif($field->field_type === 'number')
|
|
<input type="number" name="data[{{ $fieldKey }}]"
|
|
value="{{ $savedValue }}"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@elseif($field->field_type === 'item_search')
|
|
<div class="relative" x-data="itemSearch('{{ $fieldKey }}', '{{ $savedValue }}')" x-init="init()">
|
|
<input type="text" name="data[{{ $fieldKey }}]"
|
|
x-model="searchText"
|
|
@input.debounce.300ms="search()"
|
|
@focus="showResults = results.length > 0"
|
|
@click.away="showResults = false"
|
|
placeholder="품명 또는 코드로 검색"
|
|
autocomplete="off"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<div x-show="showResults" x-cloak
|
|
class="absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg max-h-60 overflow-y-auto">
|
|
<template x-for="item in results" :key="item.id">
|
|
<div @click="selectItem(item)"
|
|
class="px-3 py-2 cursor-pointer hover:bg-blue-50 flex justify-between items-center">
|
|
<span class="text-sm" x-text="item.name"></span>
|
|
<span class="text-xs text-gray-400" x-text="item.code"></span>
|
|
</div>
|
|
</template>
|
|
<div x-show="results.length === 0 && searchText.length > 0"
|
|
class="px-3 py-2 text-sm text-gray-400">검색 결과 없음</div>
|
|
</div>
|
|
</div>
|
|
@else
|
|
<input type="text" name="data[{{ $fieldKey }}]"
|
|
value="{{ $savedValue }}"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500">
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- 섹션 (검사 데이터 테이블) --}}
|
|
@if($template->sections && $template->sections->count() > 0)
|
|
@foreach($template->sections as $sectionIndex => $section)
|
|
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4">{{ $section->title }}</h2>
|
|
@if($section->image_path)
|
|
<img src="{{ asset('storage/' . $section->image_path) }}" alt="{{ $section->title }}" class="max-w-full h-auto mb-4 rounded">
|
|
@endif
|
|
|
|
{{-- 연결 품목 규격 정보 --}}
|
|
@if(!empty($linkedItemSpecs))
|
|
<div class="mb-3 flex flex-wrap gap-2 items-center text-xs">
|
|
<span class="text-gray-500">연결 품목 규격:</span>
|
|
@foreach($linkedItemSpecs as $spec)
|
|
<span class="inline-flex items-center gap-1 bg-yellow-50 border border-yellow-200 rounded px-2 py-0.5">
|
|
<span class="font-medium">{{ $spec['name'] }}</span>
|
|
@if($spec['thickness'])<span class="text-gray-500">t={{ $spec['thickness'] }}</span>@endif
|
|
@if($spec['width'])<span class="text-gray-500">w={{ $spec['width'] }}</span>@endif
|
|
@if($spec['length'])<span class="text-gray-500">l={{ $spec['length'] }}</span>@endif
|
|
</span>
|
|
@endforeach
|
|
<span class="text-gray-400 ml-1">← 해당 범위 행이 노란색으로 표시됩니다</span>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- 검사 데이터 테이블 --}}
|
|
@if($section->items->count() > 0 && $template->columns->count() > 0)
|
|
@php
|
|
// 정규화 데이터 조회 헬퍼
|
|
$getData = function($sectionId, $colId, $rowIdx, $fieldKey) use ($document) {
|
|
if (!$document) return '';
|
|
return $document->data
|
|
->where('section_id', $sectionId)
|
|
->where('column_id', $colId)
|
|
->where('row_index', $rowIdx)
|
|
->where('field_key', $fieldKey)
|
|
->first()?->field_value ?? '';
|
|
};
|
|
// 레거시 fallback
|
|
$getLegacy = function($legacyKey) use ($document) {
|
|
if (!$document) return '';
|
|
return $document->data->where('field_key', $legacyKey)->first()?->field_value ?? '';
|
|
};
|
|
|
|
// 검사방식 코드→한글 매핑
|
|
$methodNames = [
|
|
'visual' => '육안검사',
|
|
'check' => '체크검사',
|
|
'mill_sheet' => '공급업체 밀시트',
|
|
'certified_agency' => '공인시험기관',
|
|
'substitute_cert' => '공급업체 성적서 대체',
|
|
'other' => '기타',
|
|
];
|
|
|
|
// 공차 포맷 함수
|
|
$formatTolerance = function($tol) {
|
|
if (!$tol || !is_array($tol) || !isset($tol['type'])) {
|
|
// 레거시 문자열 지원
|
|
return is_string($tol) && $tol !== '' ? $tol : '-';
|
|
}
|
|
switch ($tol['type']) {
|
|
case 'symmetric':
|
|
return isset($tol['value']) ? "±{$tol['value']}" : '-';
|
|
case 'asymmetric':
|
|
$p = $tol['plus'] ?? 0;
|
|
$m = $tol['minus'] ?? 0;
|
|
return ($p || $m) ? "+{$p} / -{$m}" : '-';
|
|
case 'range':
|
|
$min = $tol['min'] ?? '';
|
|
$max = $tol['max'] ?? '';
|
|
return ($min !== '' || $max !== '') ? "{$min} ~ {$max}" : '-';
|
|
case 'limit':
|
|
$opSymbol = ['lte' => '≤', 'lt' => '<', 'gte' => '≥', 'gt' => '>'];
|
|
$op = $opSymbol[$tol['op'] ?? 'lte'] ?? '≤';
|
|
return isset($tol['value']) ? "{$op}{$tol['value']}" : '-';
|
|
default:
|
|
return '-';
|
|
}
|
|
};
|
|
|
|
// standard_criteria 포맷 함수 (getFieldValue 사용)
|
|
$formatStandard = function($item) use ($formatTolerance) {
|
|
$c = $item->getFieldValue('standard_criteria');
|
|
if ($c && is_array($c) && (isset($c['min']) || isset($c['max']))) {
|
|
$opLabel = ['gte' => '이상', 'gt' => '초과', 'lte' => '이하', 'lt' => '미만'];
|
|
$parts = [];
|
|
if (isset($c['min'])) $parts[] = $c['min'] . ' ' . ($opLabel[$c['min_op'] ?? 'gte'] ?? '이상');
|
|
if (isset($c['max'])) $parts[] = $c['max'] . ' ' . ($opLabel[$c['max_op'] ?? 'lte'] ?? '이하');
|
|
return implode(' ~ ', $parts);
|
|
}
|
|
$std = $item->getFieldValue('standard') ?: '-';
|
|
$tolStr = $formatTolerance($item->getFieldValue('tolerance'));
|
|
if ($tolStr !== '-') $std .= ' (' . $tolStr . ')';
|
|
return $std;
|
|
};
|
|
|
|
// 검사주기 포맷 함수 (getFieldValue 사용)
|
|
$formatFrequency = function($item) {
|
|
$parts = [];
|
|
$freqN = $item->getFieldValue('frequency_n');
|
|
$freqC = $item->getFieldValue('frequency_c');
|
|
$freq = $item->getFieldValue('frequency');
|
|
if ($freqN) {
|
|
$nc = "n={$freqN}";
|
|
if ($freqC !== null) $nc .= ", c={$freqC}";
|
|
$parts[] = $nc;
|
|
}
|
|
if ($freq) $parts[] = $freq;
|
|
return $parts ? implode(' / ', $parts) : '-';
|
|
};
|
|
|
|
// 카테고리별 그룹핑 (getFieldValue 사용)
|
|
$groupedRows = [];
|
|
$allItems = $section->items->values();
|
|
$idx = 0;
|
|
while ($idx < $allItems->count()) {
|
|
$item = $allItems[$idx];
|
|
$cat = trim($item->getFieldValue('category') ?? '');
|
|
if ($cat) {
|
|
$grouped = [$item];
|
|
while ($idx + 1 < $allItems->count() && trim($allItems[$idx + 1]->getFieldValue('category') ?? '') === $cat) {
|
|
$idx++;
|
|
$grouped[] = $allItems[$idx];
|
|
}
|
|
$groupedRows[] = ['type' => 'group', 'category' => $cat, 'items' => $grouped];
|
|
} else {
|
|
$groupedRows[] = ['type' => 'single', 'item' => $item];
|
|
}
|
|
$idx++;
|
|
}
|
|
|
|
// 연결 품목 규격 정보 (자동 하이라이트용)
|
|
$itemSpecs = $linkedItemSpecs ?? [];
|
|
$matchRow = function($item) use ($itemSpecs) {
|
|
$c = $item->getFieldValue('standard_criteria');
|
|
if (!$c || !is_array($c) || (!isset($c['min']) && !isset($c['max']))) {
|
|
return false;
|
|
}
|
|
|
|
// 검사항목명에서 비교 대상 결정 (두께→thickness, 너비→width, 길이→length)
|
|
$itemName = mb_strtolower(trim($item->getFieldValue('item') ?? ''));
|
|
$specKey = 'thickness'; // 기본값
|
|
if (str_contains($itemName, '너비') || str_contains($itemName, 'width')) {
|
|
$specKey = 'width';
|
|
} elseif (str_contains($itemName, '길이') || str_contains($itemName, 'length')) {
|
|
$specKey = 'length';
|
|
}
|
|
|
|
foreach ($itemSpecs as $spec) {
|
|
$val = $spec[$specKey] ?? null;
|
|
if ($val === null) continue;
|
|
|
|
$min = isset($c['min']) ? (float)$c['min'] : null;
|
|
$max = isset($c['max']) ? (float)$c['max'] : null;
|
|
$minOp = $c['min_op'] ?? 'gte';
|
|
$maxOp = $c['max_op'] ?? 'lte';
|
|
|
|
$minOk = $min === null || ($minOp === 'gt' ? $val > $min : $val >= $min);
|
|
$maxOk = $max === null || ($maxOp === 'lt' ? $val < $max : $val <= $max);
|
|
if ($minOk && $maxOk) return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
// 측정치 컬럼 정보
|
|
$hasComplex = $template->columns->contains(fn($c) => $c->column_type === 'complex' && $c->sub_labels);
|
|
$maxFreqN = $allItems->max(fn($i) => $i->getFieldValue('frequency_n')) ?: 0;
|
|
$complexCol = $template->columns->first(fn($c) => $c->column_type === 'complex' && $c->sub_labels);
|
|
$totalMeasCols = $complexCol ? max(count($complexCol->sub_labels), $maxFreqN) : 0;
|
|
@endphp
|
|
<div class="overflow-x-auto mt-4">
|
|
<table class="min-w-full border border-gray-300 text-sm" data-section-id="{{ $section->id }}">
|
|
{{-- colgroup: 컬럼 너비 제어 --}}
|
|
<colgroup>
|
|
@foreach($template->columns as $col)
|
|
@php $colLabel = trim($col->label); @endphp
|
|
@if($col->column_type === 'complex' && $col->sub_labels)
|
|
@for($ci = 0; $ci < $totalMeasCols; $ci++)
|
|
<col style="width:60px">
|
|
@endfor
|
|
@elseif(str_contains(strtolower($colLabel), 'no') && strlen($colLabel) <= 4)
|
|
<col style="width:40px">
|
|
@elseif(in_array($colLabel, ['검사항목', '항목']))
|
|
<col style="width:60px">
|
|
<col style="width:100px">
|
|
@elseif(in_array($colLabel, ['검사기준', '기준']))
|
|
<col style="width:120px">
|
|
<col style="width:60px">
|
|
@elseif(str_contains($colLabel, '판정'))
|
|
<col style="width:40px">
|
|
@else
|
|
<col style="width:80px">
|
|
@endif
|
|
@endforeach
|
|
</colgroup>
|
|
{{-- 테이블 헤더 --}}
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
@foreach($template->columns as $col)
|
|
@if($col->column_type === 'complex' && $col->sub_labels)
|
|
<th colspan="{{ $totalMeasCols }}"
|
|
class="px-2 py-2 text-center text-xs font-medium text-gray-600 uppercase border border-gray-300">
|
|
{{ $col->label }}
|
|
</th>
|
|
@else
|
|
@php
|
|
$colLabel = trim($col->label);
|
|
$isItemOrStd = in_array($colLabel, ['검사항목', '항목']) || in_array($colLabel, ['검사기준', '기준']);
|
|
@endphp
|
|
<th {{ $isItemOrStd ? 'colspan=2' : '' }}
|
|
{{ $hasComplex ? 'rowspan=2' : '' }}
|
|
class="px-2 py-2 text-center text-xs font-medium text-gray-600 uppercase border border-gray-300">
|
|
{{ $col->label }}
|
|
</th>
|
|
@endif
|
|
@endforeach
|
|
</tr>
|
|
@if($hasComplex)
|
|
<tr>
|
|
@for($si = 1; $si <= $totalMeasCols; $si++)
|
|
<th class="px-2 py-1 text-center text-xs font-medium text-gray-500 border border-gray-300 bg-gray-50">
|
|
n{{ $si }}
|
|
</th>
|
|
@endfor
|
|
</tr>
|
|
@endif
|
|
</thead>
|
|
{{-- 테이블 바디 --}}
|
|
<tbody>
|
|
@php $rowNum = 0; $globalRowIndex = 0; @endphp
|
|
@foreach($groupedRows as $row)
|
|
@php $rowNum++; @endphp
|
|
@if($row['type'] === 'single')
|
|
{{-- 단일 항목 --}}
|
|
@php $item = $row['item']; $rowIndex = $globalRowIndex; $globalRowIndex++; $isMatch = $matchRow($item); @endphp
|
|
<tr class="{{ $isMatch ? 'bg-yellow-50 border-l-4 border-l-yellow-400' : 'hover:bg-blue-50' }}" data-row-index="{{ $rowIndex }}" @if($isMatch) title="연결 품목 규격 범위에 해당" @endif>
|
|
@foreach($template->columns as $col)
|
|
@if($col->column_type === 'complex' && $col->sub_labels)
|
|
{{-- 측정치: measurement_type에 따라 분기 (getFieldValue 사용) --}}
|
|
@php
|
|
$mType = $item->getFieldValue('measurement_type') ?? '';
|
|
$freqN = $item->getFieldValue('frequency_n') ?: $totalMeasCols;
|
|
$remainder = $totalMeasCols - $freqN;
|
|
@endphp
|
|
@if($mType === 'checkbox')
|
|
@for($nIdx = 1; $nIdx <= $freqN; $nIdx++)
|
|
@php
|
|
$savedOK = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}_ok");
|
|
if (!$savedOK) $savedOK = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}_ok");
|
|
$savedNG = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}_ng");
|
|
if (!$savedNG) $savedNG = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}_ng");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<label class="inline-flex items-center gap-0.5 text-xs">
|
|
<input type="checkbox" name="section_data[n{{ $nIdx }}_ok]" value="OK" {{ $savedOK === 'OK' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}_ok"
|
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 w-3 h-3">OK
|
|
</label><br>
|
|
<label class="inline-flex items-center gap-0.5 text-xs">
|
|
<input type="checkbox" name="section_data[n{{ $nIdx }}_ng]" value="NG" {{ $savedNG === 'NG' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}_ng"
|
|
class="rounded border-gray-300 text-red-600 focus:ring-red-500 w-3 h-3">NG
|
|
</label>
|
|
</td>
|
|
@endfor
|
|
@if($remainder > 0)
|
|
<td class="border border-gray-300" colspan="{{ $remainder }}"></td>
|
|
@endif
|
|
@elseif($mType === 'numeric')
|
|
@for($nIdx = 1; $nIdx <= $freqN; $nIdx++)
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}");
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="number" step="any" name="section_data[n{{ $nIdx }}]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="n{{ $nIdx }}">
|
|
</td>
|
|
@endfor
|
|
@if($remainder > 0)
|
|
<td class="border border-gray-300" colspan="{{ $remainder }}"></td>
|
|
@endif
|
|
@elseif($mType === 'single_value')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center" colspan="{{ $totalMeasCols }}">
|
|
<input type="text" name="section_data[value]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="입력">
|
|
</td>
|
|
@elseif($mType === 'substitute')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center text-gray-400 text-xs" colspan="{{ $totalMeasCols }}">
|
|
<input type="text" name="section_data[value]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="(입력)">
|
|
</td>
|
|
@else
|
|
@for($nIdx = 1; $nIdx <= $totalMeasCols; $nIdx++)
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}");
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="text" name="section_data[n{{ $nIdx }}]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="n{{ $nIdx }}">
|
|
</td>
|
|
@endfor
|
|
@endif
|
|
@elseif($col->column_type === 'select')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
$options = $template->footer_judgement_options ?? ['적합', '부적합'];
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<select name="section_data[value]"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1">
|
|
<option value="">-</option>
|
|
@foreach($options as $opt)
|
|
<option value="{{ $opt }}" {{ $savedVal === $opt ? 'selected' : '' }}>{{ $opt }}</option>
|
|
@endforeach
|
|
</select>
|
|
</td>
|
|
@elseif($col->column_type === 'check')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="checkbox" name="section_data[value]" value="OK" {{ $savedVal === 'OK' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
</td>
|
|
@else
|
|
{{-- text: 정적 데이터 --}}
|
|
@php
|
|
$label = trim($col->label);
|
|
$isNoCol = str_contains(strtolower($label), 'no') && strlen($label) <= 4;
|
|
$isItemCol = in_array($label, ['검사항목', '항목']);
|
|
$isStdCol = in_array($label, ['검사기준', '기준']);
|
|
$isMethodCol = str_contains($label, '검사방') || in_array($label, ['방식', '검사방법']);
|
|
$isFreqCol = str_contains($label, '주기') || in_array($label, ['검사주기']);
|
|
$isJudgeCol = str_contains($label, '판정');
|
|
@endphp
|
|
@if($isNoCol)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $rowNum }}</td>
|
|
@elseif($isItemCol)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center" colspan="2">{{ $item->getFieldValue('item') ?: '-' }}</td>
|
|
@elseif($isStdCol)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center" colspan="2">{{ $formatStandard($item) }}</td>
|
|
@elseif($isMethodCol)
|
|
@php $methodVal = $item->getFieldValue('method'); @endphp
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $methodNames[$methodVal] ?? ($methodVal ?: '-') }}</td>
|
|
@elseif($isFreqCol)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $formatFrequency($item) }}</td>
|
|
@elseif($isJudgeCol)
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="checkbox" name="section_data[value]" value="OK" {{ $savedVal === 'OK' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
</td>
|
|
@else
|
|
@php
|
|
$staticValue = match(true) {
|
|
in_array($label, ['규격', '적용규격', '관련규정']) => $item->getFieldValue('regulation'),
|
|
in_array($label, ['분류', '카테고리']) => $item->getFieldValue('category'),
|
|
default => null,
|
|
};
|
|
@endphp
|
|
@if($staticValue !== null)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm">{{ $staticValue }}</td>
|
|
@else
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="text" name="section_data[value]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1">
|
|
</td>
|
|
@endif
|
|
@endif
|
|
@endif
|
|
@endforeach
|
|
</tr>
|
|
@else
|
|
{{-- 그룹 항목 --}}
|
|
@php $groupItems = $row['items']; $groupCount = count($groupItems); @endphp
|
|
@foreach($groupItems as $itemIdx => $item)
|
|
@php $rowIndex = $globalRowIndex; $globalRowIndex++; $isMatch = $matchRow($item); @endphp
|
|
<tr class="{{ $isMatch ? 'bg-yellow-50 border-l-4 border-l-yellow-400' : 'hover:bg-blue-50' }}" data-row-index="{{ $rowIndex }}" @if($isMatch) title="연결 품목 규격 범위에 해당" @endif>
|
|
@foreach($template->columns as $col)
|
|
@if($col->column_type === 'complex' && $col->sub_labels)
|
|
{{-- 측정치: 각 행 개별 렌더링 (getFieldValue 사용) --}}
|
|
@php
|
|
$mType = $item->getFieldValue('measurement_type') ?? '';
|
|
$freqN = $item->getFieldValue('frequency_n') ?: $totalMeasCols;
|
|
$remainder = $totalMeasCols - $freqN;
|
|
@endphp
|
|
@if($mType === 'checkbox')
|
|
@for($nIdx = 1; $nIdx <= $freqN; $nIdx++)
|
|
@php
|
|
$savedOK = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}_ok");
|
|
if (!$savedOK) $savedOK = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}_ok");
|
|
$savedNG = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}_ng");
|
|
if (!$savedNG) $savedNG = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}_ng");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<label class="inline-flex items-center gap-0.5 text-xs">
|
|
<input type="checkbox" name="section_data[n{{ $nIdx }}_ok]" value="OK" {{ $savedOK === 'OK' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}_ok"
|
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 w-3 h-3">OK
|
|
</label><br>
|
|
<label class="inline-flex items-center gap-0.5 text-xs">
|
|
<input type="checkbox" name="section_data[n{{ $nIdx }}_ng]" value="NG" {{ $savedNG === 'NG' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}_ng"
|
|
class="rounded border-gray-300 text-red-600 focus:ring-red-500 w-3 h-3">NG
|
|
</label>
|
|
</td>
|
|
@endfor
|
|
@if($remainder > 0)
|
|
<td class="border border-gray-300" colspan="{{ $remainder }}"></td>
|
|
@endif
|
|
@elseif($mType === 'numeric')
|
|
@for($nIdx = 1; $nIdx <= $freqN; $nIdx++)
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}");
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="number" step="any" name="section_data[n{{ $nIdx }}]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="n{{ $nIdx }}">
|
|
</td>
|
|
@endfor
|
|
@if($remainder > 0)
|
|
<td class="border border-gray-300" colspan="{{ $remainder }}"></td>
|
|
@endif
|
|
@elseif($mType === 'single_value')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center" colspan="{{ $totalMeasCols }}">
|
|
<input type="text" name="section_data[value]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="입력">
|
|
</td>
|
|
@elseif($mType === 'substitute')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center text-gray-400 text-xs" colspan="{{ $totalMeasCols }}">
|
|
<input type="text" name="section_data[value]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="(입력)">
|
|
</td>
|
|
@else
|
|
@for($nIdx = 1; $nIdx <= $totalMeasCols; $nIdx++)
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, "n{$nIdx}");
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}_n{$nIdx}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="text" name="section_data[n{{ $nIdx }}]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="n{{ $nIdx }}"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1"
|
|
placeholder="n{{ $nIdx }}">
|
|
</td>
|
|
@endfor
|
|
@endif
|
|
@elseif($col->column_type === 'select')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
$options = $template->footer_judgement_options ?? ['적합', '부적합'];
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<select name="section_data[value]"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1">
|
|
<option value="">-</option>
|
|
@foreach($options as $opt)
|
|
<option value="{{ $opt }}" {{ $savedVal === $opt ? 'selected' : '' }}>{{ $opt }}</option>
|
|
@endforeach
|
|
</select>
|
|
</td>
|
|
@elseif($col->column_type === 'check')
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="checkbox" name="section_data[value]" value="OK" {{ $savedVal === 'OK' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
</td>
|
|
@else
|
|
{{-- text: 정적 데이터 (그룹) --}}
|
|
@php
|
|
$label = trim($col->label);
|
|
$isNoCol = str_contains(strtolower($label), 'no') && strlen($label) <= 4;
|
|
$isItemCol = in_array($label, ['검사항목', '항목']);
|
|
$isStdCol = in_array($label, ['검사기준', '기준']);
|
|
$isMethodCol = str_contains($label, '검사방') || in_array($label, ['방식', '검사방법']);
|
|
$isFreqCol = str_contains($label, '주기') || in_array($label, ['검사주기']);
|
|
$isJudgeCol = str_contains($label, '판정');
|
|
@endphp
|
|
@if($isNoCol)
|
|
@if($itemIdx === 0)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center" rowspan="{{ $groupCount }}">{{ $rowNum }}</td>
|
|
@endif
|
|
@elseif($isItemCol)
|
|
{{-- 구분(rowspan) + 항목명(각 행) --}}
|
|
@if($itemIdx === 0)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center font-medium" rowspan="{{ $groupCount }}">{{ $row['category'] }}</td>
|
|
@endif
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $item->getFieldValue('item') ?: '-' }}</td>
|
|
@elseif($isStdCol)
|
|
{{-- 기준 + 공차 (각 행 개별) --}}
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $formatStandard($item) }}</td>
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $formatTolerance($item->getFieldValue('tolerance')) }}</td>
|
|
@elseif($isMethodCol)
|
|
@php $methodVal = $item->getFieldValue('method'); @endphp
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $methodNames[$methodVal] ?? ($methodVal ?: '-') }}</td>
|
|
@elseif($isFreqCol)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm text-center">{{ $formatFrequency($item) }}</td>
|
|
@elseif($isJudgeCol)
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="checkbox" name="section_data[value]" value="OK" {{ $savedVal === 'OK' ? 'checked' : '' }}
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="rounded border-gray-300 text-blue-600 focus:ring-blue-500">
|
|
</td>
|
|
@else
|
|
@php
|
|
$staticValue = match(true) {
|
|
in_array($label, ['규격', '적용규격', '관련규정']) => $item->getFieldValue('regulation'),
|
|
in_array($label, ['분류', '카테고리']) => $item->getFieldValue('category'),
|
|
default => null,
|
|
};
|
|
@endphp
|
|
@if($staticValue !== null)
|
|
<td class="px-2 py-2 border border-gray-300 text-sm">{{ $staticValue }}</td>
|
|
@else
|
|
@php
|
|
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
|
|
if (!$savedVal) $savedVal = $getLegacy("s{$section->id}_r{$rowIndex}_c{$col->id}");
|
|
@endphp
|
|
<td class="px-1 py-1 border border-gray-300 text-center">
|
|
<input type="text" name="section_data[value]" value="{{ $savedVal }}"
|
|
data-section-id="{{ $section->id }}" data-column-id="{{ $col->id }}" data-row-index="{{ $rowIndex }}"
|
|
data-field-key="value"
|
|
class="w-full text-center text-sm border-0 focus:ring-1 focus:ring-blue-400 rounded py-1">
|
|
</td>
|
|
@endif
|
|
@endif
|
|
@endif
|
|
@endforeach
|
|
</tr>
|
|
@endforeach
|
|
@endif
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- 종합판정 / 비고 --}}
|
|
@if($loop->last && $template->footer_judgement_label)
|
|
<div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-4 pt-4 border-t border-gray-200">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">
|
|
{{ $template->footer_remark_label ?? '비고' }}
|
|
</label>
|
|
@php
|
|
$remarkVal = $document?->data->where('field_key', 'remark')->first()?->field_value
|
|
?? $document?->data->where('field_key', 'footer_remark')->first()?->field_value
|
|
?? '';
|
|
@endphp
|
|
<textarea name="data[remark]" rows="3"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500">{{ $remarkVal }}</textarea>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">
|
|
{{ $template->footer_judgement_label ?? '종합판정' }}
|
|
</label>
|
|
@php
|
|
$judgementVal = $document?->data->where('field_key', 'overall_result')->first()?->field_value
|
|
?? $document?->data->where('field_key', 'footer_judgement')->first()?->field_value
|
|
?? '';
|
|
$judgementOptions = $template->footer_judgement_options ?? ['적합', '부적합'];
|
|
@endphp
|
|
<select name="data[overall_result]"
|
|
class="w-full rounded-lg border-gray-300 text-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<option value="">선택하세요</option>
|
|
@foreach($judgementOptions as $opt)
|
|
<option value="{{ $opt }}" {{ $judgementVal === $opt ? 'selected' : '' }}>{{ $opt }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
@endif
|
|
|
|
{{-- 버튼 --}}
|
|
<div class="flex justify-end gap-3">
|
|
<a href="{{ route('documents.index') }}"
|
|
class="px-6 py-2 bg-gray-100 text-gray-700 text-sm font-medium rounded-lg hover:bg-gray-200 transition-colors">
|
|
취소
|
|
</a>
|
|
<button type="submit"
|
|
class="px-6 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 transition-colors">
|
|
{{ $isCreate ? '저장' : '저장' }}
|
|
</button>
|
|
@if(!$isCreate && $document && $document->canEdit())
|
|
<button type="button" onclick="submitForApproval()"
|
|
class="px-6 py-2 bg-green-600 text-white text-sm font-medium rounded-lg hover:bg-green-700 transition-colors">
|
|
결재 제출
|
|
</button>
|
|
@endif
|
|
</div>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
function itemSearch(fieldKey, savedValue) {
|
|
return {
|
|
searchText: savedValue,
|
|
results: [],
|
|
showResults: false,
|
|
init() {},
|
|
async search() {
|
|
if (this.searchText.length < 1) {
|
|
this.results = [];
|
|
this.showResults = false;
|
|
return;
|
|
}
|
|
try {
|
|
const res = await fetch(`/api/admin/items/search?q=${encodeURIComponent(this.searchText)}`, {
|
|
headers: { 'Accept': 'application/json' }
|
|
});
|
|
const json = await res.json();
|
|
this.results = json.data || [];
|
|
this.showResults = this.results.length > 0;
|
|
} catch (e) {
|
|
this.results = [];
|
|
}
|
|
},
|
|
selectItem(item) {
|
|
this.searchText = item.name;
|
|
this.showResults = false;
|
|
}
|
|
};
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const form = document.getElementById('documentForm');
|
|
if (!form) return;
|
|
|
|
form.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
const formData = new FormData(form);
|
|
const data = {
|
|
template_id: formData.get('template_id'),
|
|
title: formData.get('title'),
|
|
data: []
|
|
};
|
|
|
|
// 기본 필드 수집 (data[field_key])
|
|
for (const [key, value] of formData.entries()) {
|
|
if (key.startsWith('data[') && key.endsWith(']')) {
|
|
const fieldKey = key.slice(5, -1);
|
|
data.data.push({
|
|
field_key: fieldKey,
|
|
field_value: value
|
|
});
|
|
}
|
|
}
|
|
|
|
// 섹션 테이블 데이터 수집 (data-field-key 기반)
|
|
form.querySelectorAll('[data-field-key]').forEach(el => {
|
|
const fieldKey = el.dataset.fieldKey;
|
|
const sectionId = el.dataset.sectionId ? parseInt(el.dataset.sectionId) : null;
|
|
const columnId = el.dataset.columnId ? parseInt(el.dataset.columnId) : null;
|
|
const rowIndex = el.dataset.rowIndex ? parseInt(el.dataset.rowIndex) : 0;
|
|
|
|
let fieldValue;
|
|
if (el.type === 'checkbox') {
|
|
fieldValue = el.checked ? el.value : '';
|
|
} else if (el.tagName === 'SELECT') {
|
|
fieldValue = el.value;
|
|
} else {
|
|
fieldValue = el.value;
|
|
}
|
|
|
|
data.data.push({
|
|
field_key: fieldKey,
|
|
field_value: fieldValue,
|
|
section_id: sectionId,
|
|
column_id: columnId,
|
|
row_index: rowIndex,
|
|
});
|
|
});
|
|
|
|
const isCreate = {{ $isCreate ? 'true' : 'false' }};
|
|
const url = isCreate ? '/api/admin/documents' : '/api/admin/documents/{{ $document?->id }}';
|
|
const method = isCreate ? 'POST' : 'PATCH';
|
|
|
|
fetch(url, {
|
|
method: method,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
|
},
|
|
body: JSON.stringify(data)
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result.success) {
|
|
showToast(isCreate ? '문서가 저장되었습니다.' : '문서가 수정되었습니다.', 'success');
|
|
if (isCreate && result.data?.id) {
|
|
window.location.href = '/documents/' + result.data.id + '/edit';
|
|
} else {
|
|
window.location.href = '/documents';
|
|
}
|
|
} else {
|
|
showToast(result.message || '오류가 발생했습니다.', 'error');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
showToast('오류가 발생했습니다.', 'error');
|
|
});
|
|
});
|
|
});
|
|
|
|
@if(!$isCreate && $document)
|
|
window.submitForApproval = function() {
|
|
if (!confirm('결재를 제출하시겠습니까? 제출 후에는 수정이 불가합니다.')) return;
|
|
|
|
fetch('/api/admin/documents/{{ $document->id }}/submit', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result.success) {
|
|
showToast(result.message, 'success');
|
|
window.location.href = '/documents/{{ $document->id }}';
|
|
} else {
|
|
showToast(result.message || '오류가 발생했습니다.', 'error');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Submit error:', error);
|
|
showToast('결재 제출 중 오류가 발생했습니다.', 'error');
|
|
});
|
|
};
|
|
@endif
|
|
</script>
|
|
@endpush
|