refactor: 회사 폼 UI 개선 및 코드 정리
- 담당자 연락처 필드를 드롭다운 + 입력 방식으로 분리 - 사용자 폼과 동일한 전화번호 UI 패턴 적용 - 미사용 위젯 파일 4개 정리 (branch_card, contact_info_* 등) - 파일명 통일성 확보 (branch_edit_screen → branch_form, company_form_simplified → company_form) - 네이밍 일관성 개선으로 유지보수성 향상
This commit is contained in:
@@ -71,6 +71,13 @@ class EquipmentInFormController extends ChangeNotifier {
|
||||
List<String> warehouseLocations = [];
|
||||
List<String> partnerCompanies = [];
|
||||
|
||||
// 새로운 필드들 (백엔드 API 구조 변경 대응)
|
||||
int? currentCompanyId;
|
||||
int? currentBranchId;
|
||||
DateTime? lastInspectionDate;
|
||||
DateTime? nextInspectionDate;
|
||||
String? equipmentStatus;
|
||||
|
||||
final TextEditingController remarkController = TextEditingController();
|
||||
|
||||
EquipmentInFormController({this.equipmentInId}) {
|
||||
@@ -234,6 +241,13 @@ class EquipmentInFormController extends ChangeNotifier {
|
||||
warrantyStartDate = equipment.warrantyStartDate ?? DateTime.now();
|
||||
warrantyEndDate = equipment.warrantyEndDate ?? DateTime.now().add(const Duration(days: 365));
|
||||
|
||||
// 새로운 필드들 설정 (백엔드 API에서 제공되면 사용, 아니면 기본값)
|
||||
currentCompanyId = equipment.currentCompanyId;
|
||||
currentBranchId = equipment.currentBranchId;
|
||||
lastInspectionDate = equipment.lastInspectionDate;
|
||||
nextInspectionDate = equipment.nextInspectionDate;
|
||||
equipmentStatus = equipment.equipmentStatus ?? 'available'; // 기본값: 사용 가능
|
||||
|
||||
// 입고 관련 정보는 현재 API에서 제공하지 않으므로 기본값 사용
|
||||
inDate = equipment.inDate ?? DateTime.now();
|
||||
equipmentType = EquipmentType.new_;
|
||||
@@ -337,6 +351,12 @@ class EquipmentInFormController extends ChangeNotifier {
|
||||
warrantyLicense: warrantyLicense,
|
||||
warrantyStartDate: warrantyStartDate,
|
||||
warrantyEndDate: warrantyEndDate,
|
||||
// 새로운 필드들 추가
|
||||
currentCompanyId: currentCompanyId,
|
||||
currentBranchId: currentBranchId,
|
||||
lastInspectionDate: lastInspectionDate,
|
||||
nextInspectionDate: nextInspectionDate,
|
||||
equipmentStatus: equipmentStatus,
|
||||
// 워런티 코드 저장 필요시 여기에 추가
|
||||
);
|
||||
|
||||
|
||||
@@ -2374,6 +2374,184 @@ class _EquipmentInFormScreenState extends State<EquipmentInFormScreen> {
|
||||
),
|
||||
),
|
||||
|
||||
// 현재 위치 및 상태 정보 섹션
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// 현재 회사 및 지점 정보
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FormFieldWrapper(
|
||||
label: '현재 회사',
|
||||
required: false,
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: _controller.currentCompanyId?.toString(),
|
||||
decoration: const InputDecoration(
|
||||
hintText: '현재 배치된 회사를 선택하세요',
|
||||
),
|
||||
items: const [
|
||||
DropdownMenuItem(value: null, child: Text('선택하지 않음')),
|
||||
// TODO: 실제 회사 목록으로 대체 필요
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_controller.currentCompanyId = value != null ? int.tryParse(value) : null;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: FormFieldWrapper(
|
||||
label: '현재 지점',
|
||||
required: false,
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: _controller.currentBranchId?.toString(),
|
||||
decoration: const InputDecoration(
|
||||
hintText: '현재 배치된 지점을 선택하세요',
|
||||
),
|
||||
items: const [
|
||||
DropdownMenuItem(value: null, child: Text('선택하지 않음')),
|
||||
// TODO: 실제 지점 목록으로 대체 필요
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_controller.currentBranchId = value != null ? int.tryParse(value) : null;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// 점검 날짜 정보
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FormFieldWrapper(
|
||||
label: '최근 점검일',
|
||||
required: false,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: _controller.lastInspectionDate ?? DateTime.now(),
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime.now(),
|
||||
);
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
_controller.lastInspectionDate = picked;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 15,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade400),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
_controller.lastInspectionDate != null
|
||||
? '${_controller.lastInspectionDate!.year}-${_controller.lastInspectionDate!.month.toString().padLeft(2, '0')}-${_controller.lastInspectionDate!.day.toString().padLeft(2, '0')}'
|
||||
: '날짜를 선택하세요',
|
||||
style: TextStyle(
|
||||
color: _controller.lastInspectionDate != null
|
||||
? Colors.black87
|
||||
: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.calendar_today, size: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: FormFieldWrapper(
|
||||
label: '다음 점검일',
|
||||
required: false,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: _controller.nextInspectionDate ?? DateTime.now().add(const Duration(days: 365)),
|
||||
firstDate: DateTime.now(),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
_controller.nextInspectionDate = picked;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 15,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade400),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
_controller.nextInspectionDate != null
|
||||
? '${_controller.nextInspectionDate!.year}-${_controller.nextInspectionDate!.month.toString().padLeft(2, '0')}-${_controller.nextInspectionDate!.day.toString().padLeft(2, '0')}'
|
||||
: '날짜를 선택하세요',
|
||||
style: TextStyle(
|
||||
color: _controller.nextInspectionDate != null
|
||||
? Colors.black87
|
||||
: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
const Icon(Icons.calendar_today, size: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// 장비 상태
|
||||
const SizedBox(height: 16),
|
||||
FormFieldWrapper(
|
||||
label: '장비 상태',
|
||||
required: false,
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: _controller.equipmentStatus,
|
||||
decoration: const InputDecoration(
|
||||
hintText: '장비 상태를 선택하세요',
|
||||
),
|
||||
items: const [
|
||||
DropdownMenuItem(value: 'available', child: Text('사용 가능')),
|
||||
DropdownMenuItem(value: 'inuse', child: Text('사용 중')),
|
||||
DropdownMenuItem(value: 'maintenance', child: Text('유지보수')),
|
||||
DropdownMenuItem(value: 'disposed', child: Text('폐기')),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_controller.equipmentStatus = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// 비고 입력란 추가
|
||||
const SizedBox(height: 16),
|
||||
FormFieldWrapper(
|
||||
|
||||
@@ -759,12 +759,9 @@ class _EquipmentListState extends State<EquipmentList> {
|
||||
if (_showDetailedColumns) {
|
||||
totalWidth += 120; // 시리얼번호
|
||||
totalWidth += 120; // 바코드
|
||||
|
||||
// 출고 정보 (조건부)
|
||||
if (pagedEquipments.any((e) => e.status == EquipmentStatus.out || e.status == EquipmentStatus.rent)) {
|
||||
totalWidth += 120; // 회사
|
||||
totalWidth += 80; // 담당자
|
||||
}
|
||||
totalWidth += 120; // 현재 위치
|
||||
totalWidth += 100; // 창고 위치
|
||||
totalWidth += 100; // 점검일
|
||||
}
|
||||
|
||||
// padding 추가 (좌우 각 16px)
|
||||
@@ -865,10 +862,11 @@ class _EquipmentListState extends State<EquipmentList> {
|
||||
_buildHeaderCell('상태', flex: 2, useExpanded: useExpanded, minWidth: 70),
|
||||
// 날짜
|
||||
_buildHeaderCell('날짜', flex: 2, useExpanded: useExpanded, minWidth: 80),
|
||||
// 출고 정보 (조건부)
|
||||
if (_showDetailedColumns && hasOutOrRent) ...[
|
||||
_buildHeaderCell('회사', flex: 3, useExpanded: useExpanded, minWidth: 120),
|
||||
_buildHeaderCell('담당자', flex: 2, useExpanded: useExpanded, minWidth: 80),
|
||||
// 상세 정보 (조건부)
|
||||
if (_showDetailedColumns) ...[
|
||||
_buildHeaderCell('현재 위치', flex: 3, useExpanded: useExpanded, minWidth: 120),
|
||||
_buildHeaderCell('창고 위치', flex: 2, useExpanded: useExpanded, minWidth: 100),
|
||||
_buildHeaderCell('점검일', flex: 2, useExpanded: useExpanded, minWidth: 100),
|
||||
],
|
||||
// 관리
|
||||
_buildHeaderCell('관리', flex: 2, useExpanded: useExpanded, minWidth: 90),
|
||||
@@ -989,25 +987,34 @@ class _EquipmentListState extends State<EquipmentList> {
|
||||
useExpanded: useExpanded,
|
||||
minWidth: 80,
|
||||
),
|
||||
// 출고 정보 (조건부)
|
||||
if (_showDetailedColumns && hasOutOrRent) ...[
|
||||
// 상세 정보 (조건부)
|
||||
if (_showDetailedColumns) ...[
|
||||
// 현재 위치 (회사 + 지점)
|
||||
_buildDataCell(
|
||||
_buildTextWithTooltip(
|
||||
'-', // TODO: 출고 정보 추가 필요
|
||||
'-',
|
||||
_buildCurrentLocationText(equipment),
|
||||
_buildCurrentLocationText(equipment),
|
||||
),
|
||||
flex: 3,
|
||||
useExpanded: useExpanded,
|
||||
minWidth: 120,
|
||||
),
|
||||
// 창고 위치
|
||||
_buildDataCell(
|
||||
Text(
|
||||
'-', // TODO: 담당자 정보 추가 필요
|
||||
equipment.warehouseLocation ?? '-',
|
||||
style: ShadcnTheme.bodySmall,
|
||||
),
|
||||
flex: 2,
|
||||
useExpanded: useExpanded,
|
||||
minWidth: 80,
|
||||
minWidth: 100,
|
||||
),
|
||||
// 점검일 (최근/다음)
|
||||
_buildDataCell(
|
||||
_buildInspectionDateWidget(equipment),
|
||||
flex: 2,
|
||||
useExpanded: useExpanded,
|
||||
minWidth: 100,
|
||||
),
|
||||
],
|
||||
// 관리
|
||||
@@ -1325,4 +1332,50 @@ class _EquipmentListState extends State<EquipmentList> {
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/// 현재 위치 텍스트 생성 (회사명 + 지점명)
|
||||
String _buildCurrentLocationText(UnifiedEquipment equipment) {
|
||||
final currentCompany = equipment.currentCompany ?? '-';
|
||||
final currentBranch = equipment.currentBranch ?? '';
|
||||
|
||||
if (currentBranch.isNotEmpty) {
|
||||
return '$currentCompany ($currentBranch)';
|
||||
} else {
|
||||
return currentCompany;
|
||||
}
|
||||
}
|
||||
|
||||
/// 점검일 위젯 생성 (최근 점검일/다음 점검일)
|
||||
Widget _buildInspectionDateWidget(UnifiedEquipment equipment) {
|
||||
final lastInspection = equipment.lastInspectionDate;
|
||||
final nextInspection = equipment.nextInspectionDate;
|
||||
|
||||
String displayText = '-';
|
||||
Color? textColor;
|
||||
|
||||
if (nextInspection != null) {
|
||||
final now = DateTime.now();
|
||||
final difference = nextInspection.difference(now).inDays;
|
||||
|
||||
if (difference < 0) {
|
||||
displayText = '점검 필요';
|
||||
textColor = Colors.red;
|
||||
} else if (difference <= 30) {
|
||||
displayText = '${difference}일 후';
|
||||
textColor = Colors.orange;
|
||||
} else {
|
||||
displayText = '${nextInspection.month}/${nextInspection.day}';
|
||||
textColor = Colors.green;
|
||||
}
|
||||
} else if (lastInspection != null) {
|
||||
displayText = '${lastInspection.month}/${lastInspection.day}';
|
||||
}
|
||||
|
||||
return Text(
|
||||
displayText,
|
||||
style: ShadcnTheme.bodySmall.copyWith(
|
||||
color: textColor ?? ShadcnTheme.bodySmall.color,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,11 +467,36 @@ class _EquipmentOutFormScreenState extends State<EquipmentOutFormScreen> {
|
||||
},
|
||||
),
|
||||
|
||||
// 장비 상태 변경 (출고 시 'inuse'로 자동 설정)
|
||||
const Text('장비 상태 설정', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 4),
|
||||
DropdownButtonFormField<String>(
|
||||
value: 'inuse', // 출고 시 기본값
|
||||
decoration: const InputDecoration(
|
||||
hintText: '출고 후 장비 상태',
|
||||
labelText: '출고 후 상태 *',
|
||||
),
|
||||
items: const [
|
||||
DropdownMenuItem(value: 'inuse', child: Text('사용 중')),
|
||||
DropdownMenuItem(value: 'maintenance', child: Text('유지보수')),
|
||||
],
|
||||
onChanged: (value) {
|
||||
// controller.equipmentStatus = value; // TODO: 컨트롤러에 추가 필요
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '출고 후 상태를 선택해주세요';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// 출고 회사 영역 헤더
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('출고 회사', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
const Text('출고 회사 *', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextButton.icon(
|
||||
onPressed: () {
|
||||
controller.addCompany();
|
||||
|
||||
Reference in New Issue
Block a user