프로젝트 최초 커밋
This commit is contained in:
805
lib/screens/equipment/equipment_out_form.dart
Normal file
805
lib/screens/equipment/equipment_out_form.dart
Normal file
@@ -0,0 +1,805 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:superport/models/equipment_unified_model.dart';
|
||||
import 'package:superport/models/company_model.dart';
|
||||
import 'package:superport/models/address_model.dart';
|
||||
import 'package:superport/screens/common/custom_widgets.dart';
|
||||
import 'package:superport/screens/common/theme_tailwind.dart';
|
||||
import 'package:superport/services/mock_data_service.dart';
|
||||
import 'package:superport/screens/equipment/controllers/equipment_out_form_controller.dart';
|
||||
import 'package:superport/screens/equipment/widgets/equipment_summary_card.dart';
|
||||
import 'package:superport/screens/equipment/widgets/equipment_summary_row.dart';
|
||||
import 'package:superport/screens/common/widgets/remark_input.dart';
|
||||
|
||||
class EquipmentOutFormScreen extends StatefulWidget {
|
||||
final int? equipmentOutId;
|
||||
final Equipment? selectedEquipment;
|
||||
final int? selectedEquipmentInId;
|
||||
final List<Map<String, dynamic>>? selectedEquipments;
|
||||
|
||||
const EquipmentOutFormScreen({
|
||||
Key? key,
|
||||
this.equipmentOutId,
|
||||
this.selectedEquipment,
|
||||
this.selectedEquipmentInId,
|
||||
this.selectedEquipments,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<EquipmentOutFormScreen> createState() => _EquipmentOutFormScreenState();
|
||||
}
|
||||
|
||||
class _EquipmentOutFormScreenState extends State<EquipmentOutFormScreen> {
|
||||
late final EquipmentOutFormController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = EquipmentOutFormController(dataService: MockDataService());
|
||||
_controller.isEditMode = widget.equipmentOutId != null;
|
||||
_controller.equipmentOutId = widget.equipmentOutId;
|
||||
_controller.selectedEquipment = widget.selectedEquipment;
|
||||
_controller.selectedEquipmentInId = widget.selectedEquipmentInId;
|
||||
_controller.selectedEquipments = widget.selectedEquipments;
|
||||
_controller.loadDropdownData();
|
||||
if (_controller.isEditMode) {
|
||||
// 수정 모드: 기존 출고 정보 로드
|
||||
// (이 부분은 실제 서비스에서 컨트롤러에 메서드 추가 필요)
|
||||
} else if (widget.selectedEquipments != null &&
|
||||
widget.selectedEquipments!.isNotEmpty) {
|
||||
// 다중 선택 장비 있음: 별도 초기화 필요시 컨트롤러에서 처리
|
||||
} else if (widget.selectedEquipment != null) {
|
||||
_controller.initializeWithSelectedEquipment(widget.selectedEquipment!);
|
||||
}
|
||||
}
|
||||
|
||||
// 요약 테이블 위젯 - 다중 선택 장비에 대한 요약 테이블
|
||||
Widget _buildSummaryTable() {
|
||||
if (_controller.selectedEquipments == null ||
|
||||
_controller.selectedEquipments!.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// 각 장비별로 전체 폭을 사용하는 리스트로 구현
|
||||
return Container(
|
||||
width: double.infinity, // 전체 폭 사용
|
||||
child: Card(
|
||||
elevation: 2,
|
||||
margin: EdgeInsets.zero, // margin 제거
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'선택된 장비 목록 (${_controller.selectedEquipments!.length}개)',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 리스트 헤더
|
||||
Row(
|
||||
children: const [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'제조사',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'장비명',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Text(
|
||||
'수량',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'워런티 시작일',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Text(
|
||||
'워런티 종료일',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
// 리스트 본문
|
||||
Column(
|
||||
children: List.generate(_controller.selectedEquipments!.length, (
|
||||
index,
|
||||
) {
|
||||
final equipmentData = _controller.selectedEquipments![index];
|
||||
final equipment = equipmentData['equipment'] as Equipment;
|
||||
// 워런티 날짜를 임시로 저장할 수 있도록 상태를 관리(컨트롤러에 리스트로 추가하거나, 여기서 임시로 관리)
|
||||
// 여기서는 equipment 객체의 필드를 직접 수정(실제 서비스에서는 별도 상태 관리 필요)
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(flex: 2, child: Text(equipment.manufacturer)),
|
||||
Expanded(flex: 2, child: Text(equipment.name)),
|
||||
Expanded(flex: 1, child: Text('${equipment.quantity}')),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
final picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate:
|
||||
equipment.warrantyStartDate ??
|
||||
DateTime.now(),
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
equipment.warrantyStartDate = picked;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
_formatDate(equipment.warrantyStartDate),
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
final picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate:
|
||||
equipment.warrantyEndDate ?? DateTime.now(),
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
equipment.warrantyEndDate = picked;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
_formatDate(equipment.warrantyEndDate),
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 날짜 포맷 유틸리티
|
||||
String _formatDate(DateTime? date) {
|
||||
if (date == null) return '정보 없음';
|
||||
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 담당자가 없거나 첫 번째 회사에 대한 담당자가 '없음'인 경우 등록 버튼 비활성화 조건
|
||||
final bool canSubmit =
|
||||
_controller.selectedCompanies.isNotEmpty &&
|
||||
_controller.selectedCompanies[0] != null &&
|
||||
_controller.hasManagersPerCompany[0] &&
|
||||
_controller.filteredManagersPerCompany[0].first != '없음';
|
||||
final int totalSelectedEquipments =
|
||||
_controller.selectedEquipments?.length ?? 0;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
_controller.isEditMode
|
||||
? '장비 출고 수정'
|
||||
: totalSelectedEquipments > 0
|
||||
? '장비 출고 등록 (${totalSelectedEquipments}개)'
|
||||
: '장비 출고 등록',
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Form(
|
||||
key: _controller.formKey,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 장비 정보 요약 섹션
|
||||
if (_controller.selectedEquipments != null &&
|
||||
_controller.selectedEquipments!.isNotEmpty)
|
||||
_buildSummaryTable()
|
||||
else if (_controller.selectedEquipment != null)
|
||||
// 단일 장비 요약 카드도 전체 폭으로 맞춤
|
||||
Container(
|
||||
width: double.infinity,
|
||||
child: EquipmentSingleSummaryCard(
|
||||
equipment: _controller.selectedEquipment!,
|
||||
),
|
||||
)
|
||||
else
|
||||
const SizedBox.shrink(),
|
||||
// 요약 카드 아래 라디오 버튼 추가
|
||||
const SizedBox(height: 12),
|
||||
// 전체 폭을 사용하는 라디오 버튼
|
||||
Container(width: double.infinity, child: _buildOutTypeRadio()),
|
||||
const SizedBox(height: 16),
|
||||
// 출고 정보 입력 섹션 (수정/등록)
|
||||
_buildOutgoingInfoSection(context),
|
||||
// 비고 입력란 추가
|
||||
const SizedBox(height: 16),
|
||||
FormFieldWrapper(
|
||||
label: '비고',
|
||||
isRequired: false,
|
||||
child: RemarkInput(
|
||||
controller: _controller.remarkController,
|
||||
hint: '비고를 입력하세요',
|
||||
minLines: 4,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// 담당자 없음 경고 메시지
|
||||
if (_controller.selectedCompanies.isNotEmpty &&
|
||||
_controller.selectedCompanies[0] != null &&
|
||||
(!_controller.hasManagersPerCompany[0] ||
|
||||
_controller.filteredManagersPerCompany[0].first ==
|
||||
'없음'))
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red.shade100,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(color: Colors.red.shade300),
|
||||
),
|
||||
child: const Row(
|
||||
children: [
|
||||
Icon(Icons.warning, color: Colors.red),
|
||||
SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'선택한 회사에 등록된 담당자가 없습니다. 담당자를 먼저 등록해야 합니다.',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 저장 버튼
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed:
|
||||
canSubmit
|
||||
? () {
|
||||
// 각 회사별 담당자를 첫 번째 항목으로 설정
|
||||
for (
|
||||
int i = 0;
|
||||
i < _controller.selectedCompanies.length;
|
||||
i++
|
||||
) {
|
||||
if (_controller.selectedCompanies[i] != null &&
|
||||
_controller.hasManagersPerCompany[i] &&
|
||||
_controller
|
||||
.filteredManagersPerCompany[i]
|
||||
.isNotEmpty &&
|
||||
_controller
|
||||
.filteredManagersPerCompany[i]
|
||||
.first !=
|
||||
'없음') {
|
||||
_controller.selectedManagersPerCompany[i] =
|
||||
_controller
|
||||
.filteredManagersPerCompany[i]
|
||||
.first;
|
||||
}
|
||||
}
|
||||
|
||||
_controller.saveEquipmentOut(
|
||||
(msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(msg),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
Navigator.pop(context, true);
|
||||
},
|
||||
(err) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(err),
|
||||
duration: const Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
: null,
|
||||
style:
|
||||
canSubmit
|
||||
? AppThemeTailwind.primaryButtonStyle
|
||||
: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey.shade300,
|
||||
foregroundColor: Colors.grey.shade700,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Text(
|
||||
_controller.isEditMode ? '수정하기' : '등록하기',
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 출고 정보 입력 섹션 위젯 (등록/수정 공통)
|
||||
Widget _buildOutgoingInfoSection(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('출고 정보', style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(height: 12),
|
||||
// 출고일
|
||||
_buildDateField(
|
||||
context,
|
||||
label: '출고일',
|
||||
date: _controller.outDate,
|
||||
onDateChanged: (picked) {
|
||||
setState(() {
|
||||
_controller.outDate = picked;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
// 출고 회사 영역 헤더
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('출고 회사', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextButton.icon(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_controller.addCompany();
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add_circle_outline, size: 18),
|
||||
label: const Text('출고 회사 추가'),
|
||||
style: TextButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
minimumSize: Size.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
||||
// 동적 출고 회사 드롭다운 목록
|
||||
...List.generate(_controller.selectedCompanies.length, (index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12.0),
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: _controller.selectedCompanies[index],
|
||||
decoration: InputDecoration(
|
||||
hintText: index == 0 ? '출고할 회사를 선택하세요' : '추가된 출고할 회사를 선택하세요',
|
||||
// 이전 드롭다운에 값이 선택되지 않았으면 비활성화
|
||||
enabled:
|
||||
index == 0 ||
|
||||
_controller.selectedCompanies[index - 1] != null,
|
||||
),
|
||||
items:
|
||||
_controller.availableCompaniesPerDropdown[index]
|
||||
.map(
|
||||
(item) => DropdownMenuItem<String>(
|
||||
value: item,
|
||||
child: _buildCompanyDropdownItem(item),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
validator: (value) {
|
||||
if (index == 0 && (value == null || value.isEmpty)) {
|
||||
return '출고 회사를 선택해주세요';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged:
|
||||
(index == 0 ||
|
||||
_controller.selectedCompanies[index - 1] != null)
|
||||
? (value) {
|
||||
setState(() {
|
||||
_controller.selectedCompanies[index] = value;
|
||||
_controller.filterManagersByCompanyAtIndex(
|
||||
value,
|
||||
index,
|
||||
);
|
||||
_controller.updateAvailableCompanies();
|
||||
});
|
||||
}
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
// 각 회사별 담당자 선택 목록
|
||||
...List.generate(_controller.selectedCompanies.length, (index) {
|
||||
// 회사가 선택된 경우에만 담당자 표시
|
||||
if (_controller.selectedCompanies[index] != null) {
|
||||
// 회사 정보 가져오기
|
||||
final companyInfo = _controller.companiesWithBranches.firstWhere(
|
||||
(info) => info.name == _controller.selectedCompanies[index],
|
||||
orElse:
|
||||
() => CompanyBranchInfo(
|
||||
id: 0,
|
||||
name: _controller.selectedCompanies[index]!,
|
||||
originalName: _controller.selectedCompanies[index]!,
|
||||
isMainCompany: true,
|
||||
companyId: 0,
|
||||
branchId: null,
|
||||
),
|
||||
);
|
||||
|
||||
// 실제 회사/지점 정보를 ID로 가져오기
|
||||
Company? company;
|
||||
Branch? branch;
|
||||
|
||||
if (companyInfo.companyId != null) {
|
||||
company = _controller.dataService.getCompanyById(
|
||||
companyInfo.companyId!,
|
||||
);
|
||||
if (!companyInfo.isMainCompany &&
|
||||
companyInfo.branchId != null &&
|
||||
company != null) {
|
||||
final branches = company.branches;
|
||||
if (branches != null) {
|
||||
branch = branches.firstWhere(
|
||||
(b) => b.id == companyInfo.branchId,
|
||||
orElse:
|
||||
() => Branch(
|
||||
companyId: companyInfo.companyId!,
|
||||
name: companyInfo.originalName,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'담당자 정보 (${_controller.selectedCompanies[index]})',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 15,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade400),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child:
|
||||
company != null
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 본사/지점 정보 표시
|
||||
if (companyInfo.isMainCompany &&
|
||||
company.contactName != null &&
|
||||
company.contactName!.isNotEmpty)
|
||||
Text(
|
||||
'${company.contactName} ${company.contactPosition ?? ""} ${company.contactPhone ?? ""} ${company.contactEmail ?? ""}',
|
||||
style: AppThemeTailwind.bodyStyle,
|
||||
),
|
||||
if (!companyInfo.isMainCompany &&
|
||||
branch != null &&
|
||||
branch.contactName != null &&
|
||||
branch.contactName!.isNotEmpty)
|
||||
Text(
|
||||
'${branch.contactName} ${branch.contactPosition ?? ""} ${branch.contactPhone ?? ""} ${branch.contactEmail ?? ""}',
|
||||
style: AppThemeTailwind.bodyStyle,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 담당자 목록에서 실제 담당자 정보만 표시하는 부분은 제거
|
||||
],
|
||||
)
|
||||
: Text(
|
||||
'회사 정보를 불러올 수 없습니다.',
|
||||
style: TextStyle(
|
||||
color: Colors.red.shade400,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
|
||||
// 유지 보수(라이센스) 선택
|
||||
_buildDropdownField(
|
||||
label: '유지 보수', // 텍스트 변경
|
||||
value: _controller.selectedLicense,
|
||||
items: _controller.licenses,
|
||||
hint: '유지 보수를 선택하세요', // 텍스트 변경
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_controller.selectedLicense = value;
|
||||
});
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '유지 보수를 선택해주세요'; // 텍스트 변경
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 날짜 선택 필드 위젯
|
||||
Widget _buildDateField(
|
||||
BuildContext context, {
|
||||
required String label,
|
||||
required DateTime date,
|
||||
required ValueChanged<DateTime> onDateChanged,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 4),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: date,
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
if (picked != null && picked != date) {
|
||||
onDateChanged(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.formatDate(date),
|
||||
style: AppThemeTailwind.bodyStyle,
|
||||
),
|
||||
const Icon(Icons.calendar_today, size: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 드롭다운 필드 위젯
|
||||
Widget _buildDropdownField({
|
||||
required String label,
|
||||
required String? value,
|
||||
required List<String> items,
|
||||
required String hint,
|
||||
required ValueChanged<String?>? onChanged,
|
||||
required String? Function(String?) validator,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 4),
|
||||
DropdownButtonFormField<String>(
|
||||
value: value,
|
||||
decoration: InputDecoration(hintText: hint),
|
||||
items:
|
||||
items
|
||||
.map(
|
||||
(item) => DropdownMenuItem<String>(
|
||||
value: item,
|
||||
child: Text(item),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
validator: validator,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 회사 이름을 표시하는 위젯 (지점 포함)
|
||||
Widget _buildCompanyDropdownItem(String item) {
|
||||
final TextStyle defaultStyle = TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
);
|
||||
|
||||
// 컨트롤러에서 해당 항목에 대한 정보 확인
|
||||
final companyInfoList =
|
||||
_controller.companiesWithBranches
|
||||
.where((info) => info.name == item)
|
||||
.toList();
|
||||
|
||||
// 회사 정보가 존재하고 지점인 경우
|
||||
if (companyInfoList.isNotEmpty && !companyInfoList[0].isMainCompany) {
|
||||
final companyInfo = companyInfoList[0];
|
||||
final parentCompanyName = companyInfo.parentCompanyName ?? '';
|
||||
final branchName = companyInfo.displayName ?? companyInfo.originalName;
|
||||
|
||||
// Row 대신 RichText 사용 - 지점 표시
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: defaultStyle, // 기본 스타일 설정
|
||||
children: [
|
||||
WidgetSpan(
|
||||
child: Icon(
|
||||
Icons.subdirectory_arrow_right,
|
||||
size: 16,
|
||||
color: Colors.grey,
|
||||
),
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
),
|
||||
TextSpan(text: ' ', style: defaultStyle),
|
||||
TextSpan(
|
||||
text: parentCompanyName, // 회사명
|
||||
style: defaultStyle,
|
||||
),
|
||||
TextSpan(text: ' ', style: defaultStyle),
|
||||
TextSpan(
|
||||
text: branchName, // 지점명
|
||||
style: const TextStyle(
|
||||
color: Colors.indigo,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
);
|
||||
}
|
||||
|
||||
// 일반 회사명 (본사)
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: defaultStyle, // 기본 스타일 설정
|
||||
children: [
|
||||
WidgetSpan(
|
||||
child: Icon(Icons.business, size: 16, color: Colors.black54),
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
),
|
||||
TextSpan(text: ' ', style: defaultStyle),
|
||||
TextSpan(
|
||||
text: item,
|
||||
style: defaultStyle.copyWith(fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
);
|
||||
}
|
||||
|
||||
// 회사 ID에 따른 담당자 정보를 가져와 표시하는 위젯 목록 생성
|
||||
List<Widget> _getUsersForCompany(CompanyBranchInfo companyInfo) {
|
||||
final List<Widget> userWidgets = [];
|
||||
|
||||
// 판교지점 특별 처리
|
||||
if (companyInfo.originalName == "판교지점" &&
|
||||
companyInfo.parentCompanyName == "LG전자") {
|
||||
userWidgets.add(
|
||||
Text(
|
||||
'정수진 사원 010-4567-8901 jung.soojin@lg.com',
|
||||
style: AppThemeTailwind.bodyStyle,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return userWidgets;
|
||||
}
|
||||
|
||||
// 출고/대여/폐기 라디오 버튼 위젯
|
||||
Widget _buildOutTypeRadio() {
|
||||
// 출고 유형 리스트
|
||||
final List<String> outTypes = ['출고', '대여', '폐기'];
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children:
|
||||
outTypes.map((type) {
|
||||
return Row(
|
||||
children: [
|
||||
Radio<String>(
|
||||
value: type,
|
||||
groupValue: _controller.outType, // 컨트롤러에서 현재 선택값 관리
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_controller.outType = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
Text(type),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user