- 모델 6개 (Equipment, InspectionTemplate, Inspection, InspectionDetail, Repair, Process) - 서비스 3개 (Equipment, Inspection, Repair) - API 컨트롤러 3개 + FormRequest 4개 - Blade 컨트롤러 + 라우트 등록 - 뷰: 대시보드, 등록대장(CRUD), 일상점검표(캘린더 그리드), 수리이력
231 lines
12 KiB
PHP
231 lines
12 KiB
PHP
@extends('layouts.app')
|
|
@section('title', '설비 수정')
|
|
@section('content')
|
|
|
|
<div class="max-w-4xl mx-auto">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h1 class="text-2xl font-bold text-gray-800">설비 수정</h1>
|
|
<a href="{{ route('equipment.index') }}" class="text-gray-600 hover:text-gray-800">
|
|
← 목록으로
|
|
</a>
|
|
</div>
|
|
|
|
<!-- 로딩 상태 -->
|
|
<div id="loadingState" class="bg-white rounded-lg shadow-sm p-6">
|
|
<div class="flex justify-center items-center p-12">
|
|
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 폼 -->
|
|
<div id="formContainer" style="display: none;">
|
|
<form id="equipmentForm" class="space-y-6">
|
|
@csrf
|
|
|
|
<!-- 기본정보 -->
|
|
<div class="bg-white rounded-lg shadow-sm p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4 pb-2 border-b">기본정보</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">
|
|
설비코드 <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="text" name="equipment_code" id="equipment_code" required
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">
|
|
설비명 <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="text" name="name" id="name" required
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">설비유형</label>
|
|
<select name="equipment_type" id="equipment_type"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">선택</option>
|
|
<option value="포밍기">포밍기</option>
|
|
<option value="미싱기">미싱기</option>
|
|
<option value="샤링기">샤링기</option>
|
|
<option value="V컷팅기">V컷팅기</option>
|
|
<option value="절곡기">절곡기</option>
|
|
<option value="프레스">프레스</option>
|
|
<option value="드릴">드릴</option>
|
|
<option value="기타">기타</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">규격</label>
|
|
<input type="text" name="specification" id="specification"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 제조사 정보 -->
|
|
<div class="bg-white rounded-lg shadow-sm p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4 pb-2 border-b">제조사 정보</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">제조사</label>
|
|
<input type="text" name="manufacturer" id="manufacturer"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">모델명</label>
|
|
<input type="text" name="model_name" id="model_name"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">제조번호</label>
|
|
<input type="text" name="serial_no" id="serial_no"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 설치 정보 -->
|
|
<div class="bg-white rounded-lg shadow-sm p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4 pb-2 border-b">설치 정보</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">위치</label>
|
|
<input type="text" name="location" id="location"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">생산라인</label>
|
|
<select name="production_line" id="production_line"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">선택</option>
|
|
<option value="스라트">스라트</option>
|
|
<option value="스크린">스크린</option>
|
|
<option value="절곡">절곡</option>
|
|
<option value="기타">기타</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">구입일</label>
|
|
<input type="date" name="purchase_date" id="purchase_date"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">설치일</label>
|
|
<input type="date" name="install_date" id="install_date"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">구입가격 (원)</label>
|
|
<input type="number" name="purchase_price" id="purchase_price" min="0" step="1"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">내용연수 (년)</label>
|
|
<input type="number" name="useful_life" id="useful_life" min="0"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 담당자/비고 -->
|
|
<div class="bg-white rounded-lg shadow-sm p-6">
|
|
<h2 class="text-lg font-semibold text-gray-800 mb-4 pb-2 border-b">담당자 / 비고</h2>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">담당자</label>
|
|
<select name="manager_id" id="manager_id"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="">선택</option>
|
|
@foreach($users as $user)
|
|
<option value="{{ $user->id }}">{{ $user->name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">상태</label>
|
|
<select name="status" id="status"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
|
|
<option value="active">가동</option>
|
|
<option value="idle">유휴</option>
|
|
<option value="disposed">폐기</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="mt-4">
|
|
<label class="block text-sm font-semibold text-gray-700 mb-2">비고</label>
|
|
<textarea name="memo" id="memo" rows="3"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 버튼 -->
|
|
<div class="flex gap-3">
|
|
<button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-2 rounded-lg transition">
|
|
수정
|
|
</button>
|
|
<a href="{{ route('equipment.index') }}"
|
|
class="bg-gray-200 hover:bg-gray-300 text-gray-800 px-6 py-2 rounded-lg transition">
|
|
취소
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<script>
|
|
const equipmentId = {{ $id }};
|
|
const fields = ['equipment_code', 'name', 'equipment_type', 'specification', 'manufacturer',
|
|
'model_name', 'serial_no', 'location', 'production_line', 'purchase_date', 'install_date',
|
|
'purchase_price', 'useful_life', 'status', 'manager_id', 'memo'];
|
|
|
|
fetch(`/admin/equipment/${equipmentId}`, {
|
|
headers: { 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
|
})
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
const eq = data.data;
|
|
fields.forEach(f => {
|
|
const el = document.getElementById(f);
|
|
if (el && eq[f] != null) el.value = eq[f];
|
|
});
|
|
document.getElementById('loadingState').style.display = 'none';
|
|
document.getElementById('formContainer').style.display = 'block';
|
|
} else {
|
|
showToast('설비 정보를 불러올 수 없습니다.', 'error');
|
|
window.location.href = '{{ route("equipment.index") }}';
|
|
}
|
|
});
|
|
|
|
document.getElementById('equipmentForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
const formData = new FormData(this);
|
|
const data = Object.fromEntries(formData.entries());
|
|
|
|
fetch(`/admin/equipment/${equipmentId}`, {
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
|
'Accept': 'application/json',
|
|
},
|
|
body: JSON.stringify(data)
|
|
})
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
showToast(data.message, 'success');
|
|
window.location.href = '{{ route("equipment.index") }}';
|
|
} else {
|
|
showToast(data.message || '수정에 실패했습니다.', 'error');
|
|
}
|
|
})
|
|
.catch(() => showToast('서버 오류가 발생했습니다.', 'error'));
|
|
});
|
|
</script>
|
|
@endpush
|