사용하지 않는 파일 정리 전 백업 (Phase 10 완료 후 상태)
This commit is contained in:
705
lib/screens/maintenance/maintenance_schedule_screen.dart
Normal file
705
lib/screens/maintenance/maintenance_schedule_screen.dart
Normal file
@@ -0,0 +1,705 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../data/models/maintenance_dto.dart';
|
||||
import '../../domain/entities/maintenance_schedule.dart';
|
||||
import 'controllers/maintenance_controller.dart';
|
||||
import 'maintenance_form_dialog.dart';
|
||||
import 'components/maintenance_calendar.dart';
|
||||
|
||||
class MaintenanceScheduleScreen extends StatefulWidget {
|
||||
const MaintenanceScheduleScreen({super.key});
|
||||
|
||||
@override
|
||||
State<MaintenanceScheduleScreen> createState() =>
|
||||
_MaintenanceScheduleScreenState();
|
||||
}
|
||||
|
||||
class _MaintenanceScheduleScreenState extends State<MaintenanceScheduleScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late TabController _tabController;
|
||||
bool _isCalendarView = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabController = TabController(length: 3, vsync: this);
|
||||
|
||||
// 초기 데이터 로드
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final controller = context.read<MaintenanceController>();
|
||||
controller.loadMaintenances(refresh: true);
|
||||
controller.loadAlerts();
|
||||
controller.loadStatistics();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey[100],
|
||||
body: Column(
|
||||
children: [
|
||||
_buildHeader(),
|
||||
_buildFilterBar(),
|
||||
Expanded(
|
||||
child: Consumer<MaintenanceController>(
|
||||
builder: (context, controller, child) {
|
||||
if (controller.isLoading && controller.maintenances.isEmpty) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (controller.error != null) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'오류 발생',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(controller.error!),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed:
|
||||
() => controller.loadMaintenances(refresh: true),
|
||||
child: const Text('다시 시도'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return _isCalendarView
|
||||
? MaintenanceCalendar(
|
||||
maintenances: controller.maintenances,
|
||||
onDateSelected: (date) {
|
||||
// 날짜 선택시 해당 날짜의 유지보수 표시
|
||||
_showMaintenancesForDate(date, controller.maintenances);
|
||||
},
|
||||
)
|
||||
: _buildListView(controller);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: _showCreateMaintenanceDialog,
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('유지보수 등록'),
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHeader() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withValues(alpha: 0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 3,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'유지보수 일정 관리',
|
||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Consumer<MaintenanceController>(
|
||||
builder: (context, controller, child) {
|
||||
return Text(
|
||||
'총 ${controller.totalCount}건 | '
|
||||
'예정 ${controller.upcomingCount}건 | '
|
||||
'지연 ${controller.overdueCount}건',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
_isCalendarView ? Icons.list : Icons.calendar_month,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isCalendarView = !_isCalendarView;
|
||||
});
|
||||
},
|
||||
tooltip: _isCalendarView ? '리스트 보기' : '캘린더 보기',
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
context.read<MaintenanceController>().loadMaintenances(
|
||||
refresh: true,
|
||||
);
|
||||
},
|
||||
tooltip: '새로고침',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildStatisticsCards(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatisticsCards() {
|
||||
return Consumer<MaintenanceController>(
|
||||
builder: (context, controller, child) {
|
||||
final stats = controller.statistics;
|
||||
if (stats == null) return const SizedBox.shrink();
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
'전체 유지보수',
|
||||
(stats['total'] ?? 0).toString(),
|
||||
Icons.build_circle,
|
||||
Colors.blue,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
'예정된 항목',
|
||||
(stats['upcoming'] ?? 0).toString(),
|
||||
Icons.schedule,
|
||||
Colors.orange,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
'지연된 항목',
|
||||
(stats['overdue'] ?? 0).toString(),
|
||||
Icons.warning,
|
||||
Colors.red,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
'진행 중',
|
||||
(stats['inProgress'] ?? 0).toString(),
|
||||
Icons.schedule_outlined,
|
||||
Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatCard(
|
||||
String title,
|
||||
String value,
|
||||
IconData icon,
|
||||
Color color,
|
||||
) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: color, size: 32),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFilterBar() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(bottom: BorderSide(color: Colors.grey[300]!)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: '장비명, 일련번호로 검색',
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: Colors.grey[300]!),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
),
|
||||
onChanged: (value) {
|
||||
context.read<MaintenanceController>().setSearchQuery(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
PopupMenuButton<String>(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey[300]!),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.filter_list),
|
||||
SizedBox(width: 8),
|
||||
Text('상태 필터'),
|
||||
],
|
||||
),
|
||||
),
|
||||
onSelected: (status) {
|
||||
context.read<MaintenanceController>().setMaintenanceFilter(status);
|
||||
},
|
||||
itemBuilder:
|
||||
(context) => [
|
||||
const PopupMenuItem(value: null, child: Text('전체')),
|
||||
const PopupMenuItem(
|
||||
value: 'active',
|
||||
child: Text('진행중 (시작됨, 완료되지 않음)'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
value: 'completed',
|
||||
child: Text('완료됨'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
value: 'upcoming',
|
||||
child: Text('예정됨'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
PopupMenuButton<String>(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey[300]!),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.sort),
|
||||
SizedBox(width: 8),
|
||||
Text('정렬'),
|
||||
],
|
||||
),
|
||||
),
|
||||
onSelected: (value) {
|
||||
final parts = value.split('_');
|
||||
context.read<MaintenanceController>().setSorting(
|
||||
parts[0],
|
||||
parts[1] == 'asc',
|
||||
);
|
||||
},
|
||||
itemBuilder:
|
||||
(context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'started_at_asc',
|
||||
child: Text('시작일 오름차순'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
value: 'started_at_desc',
|
||||
child: Text('시작일 내림차순'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
value: 'registered_at_desc',
|
||||
child: Text('최신 등록순'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
value: 'period_month_desc',
|
||||
child: Text('주기 긴 순'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildListView(MaintenanceController controller) {
|
||||
if (controller.maintenances.isEmpty) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.build_circle_outlined,
|
||||
size: 64,
|
||||
color: Colors.grey[400],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'등록된 유지보수가 없습니다',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(color: Colors.grey[600]),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text('새로운 유지보수를 등록해주세요', style: TextStyle(color: Colors.grey[500])),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(24),
|
||||
itemCount: controller.maintenances.length,
|
||||
itemBuilder: (context, index) {
|
||||
final maintenance = controller.maintenances[index];
|
||||
return _buildMaintenanceCard(maintenance);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMaintenanceCard(MaintenanceDto maintenance) {
|
||||
final schedule = context
|
||||
.read<MaintenanceController>()
|
||||
.getScheduleForMaintenance(maintenance.startedAt);
|
||||
// generateAlert is not available, using null for now
|
||||
final alert = null; // schedule?.generateAlert();
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
child: InkWell(
|
||||
onTap: () => _showMaintenanceDetails(maintenance),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
_buildStatusChip(maintenance),
|
||||
const SizedBox(width: 8),
|
||||
_buildTypeChip(maintenance.maintenanceType),
|
||||
const SizedBox(width: 8),
|
||||
if (alert != null) _buildAlertChip(alert),
|
||||
const Spacer(),
|
||||
PopupMenuButton<String>(
|
||||
onSelected:
|
||||
(value) => _handleMaintenanceAction(value, maintenance),
|
||||
itemBuilder:
|
||||
(context) => [
|
||||
const PopupMenuItem(value: 'edit', child: Text('수정')),
|
||||
const PopupMenuItem(
|
||||
value: 'toggle',
|
||||
child: Text('상태 변경'),
|
||||
),
|
||||
const PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Text('삭제'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Equipment History #${maintenance.equipmentHistoryId}',
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.calendar_today, size: 16, color: Colors.grey[600]),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'시작일: ${maintenance.startedAt ?? "미정"}',
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Icon(Icons.check_circle, size: 16, color: Colors.grey[600]),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'완료일: ${maintenance.endedAt ?? "미완료"}',
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.repeat, size: 16, color: Colors.grey[600]),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'주기: ${maintenance.periodMonth ?? 0}개월',
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Icon(Icons.settings, size: 16, color: Colors.grey[600]),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'유형: ${maintenance.maintenanceType == 'O' ? '현장' : '원격'}',
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.schedule, size: 16, color: Colors.grey[600]),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'등록일: ${DateFormat('yyyy-MM-dd').format(maintenance.registeredAt)}',
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatusChip(MaintenanceDto maintenance) {
|
||||
Color color;
|
||||
String label;
|
||||
|
||||
// 백엔드 스키마 기준으로 상태 판단
|
||||
if (maintenance.endedAt != null) {
|
||||
// 완료됨
|
||||
color = Colors.green;
|
||||
label = '완료';
|
||||
} else if (maintenance.startedAt != null) {
|
||||
// 시작됐지만 완료되지 않음 (진행중)
|
||||
color = Colors.orange;
|
||||
label = '진행중';
|
||||
} else {
|
||||
// 아직 시작되지 않음 (예정)
|
||||
color = Colors.blue;
|
||||
label = '예정';
|
||||
}
|
||||
|
||||
return Chip(
|
||||
label: Text(label, style: const TextStyle(fontSize: 12)),
|
||||
backgroundColor: color.withValues(alpha: 0.2),
|
||||
side: BorderSide(color: color),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTypeChip(String type) {
|
||||
return Chip(
|
||||
label: Text(
|
||||
type == 'O' ? '현장' : '원격',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
backgroundColor: Colors.grey[200],
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAlertChip(MaintenanceAlert alert) {
|
||||
Color color;
|
||||
switch (alert.priority) {
|
||||
case AlertPriority.critical:
|
||||
color = Colors.red;
|
||||
break;
|
||||
case AlertPriority.high:
|
||||
color = Colors.orange;
|
||||
break;
|
||||
case AlertPriority.medium:
|
||||
color = Colors.yellow[700]!;
|
||||
break;
|
||||
case AlertPriority.low:
|
||||
color = Colors.blue;
|
||||
break;
|
||||
}
|
||||
|
||||
return Chip(
|
||||
label: Text(
|
||||
'${alert.daysUntilDue < 0 ? "지연 " : ""}${alert.daysUntilDue.abs()}일',
|
||||
style: TextStyle(fontSize: 12, color: Colors.white),
|
||||
),
|
||||
backgroundColor: color,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
);
|
||||
}
|
||||
|
||||
void _showCreateMaintenanceDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const MaintenanceFormDialog(),
|
||||
).then((result) {
|
||||
if (result == true) {
|
||||
context.read<MaintenanceController>().loadMaintenances(refresh: true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _showMaintenanceDetails(MaintenanceDto maintenance) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => MaintenanceFormDialog(maintenance: maintenance),
|
||||
).then((result) {
|
||||
if (result == true) {
|
||||
context.read<MaintenanceController>().loadMaintenances(refresh: true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _handleMaintenanceAction(
|
||||
String action,
|
||||
MaintenanceDto maintenance,
|
||||
) async {
|
||||
final controller = context.read<MaintenanceController>();
|
||||
|
||||
switch (action) {
|
||||
case 'edit':
|
||||
_showMaintenanceDetails(maintenance);
|
||||
break;
|
||||
case 'toggle':
|
||||
// TODO: 백엔드 스키마에 맞는 상태 변경 로직 구현 필요
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('상태 변경 기능은 준비 중입니다')),
|
||||
);
|
||||
break;
|
||||
case 'delete':
|
||||
final confirm = await showDialog<bool>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: const Text('유지보수 삭제'),
|
||||
content: const Text('정말로 이 유지보수를 삭제하시겠습니까?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('취소'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: const Text(
|
||||
'삭제',
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirm == true && maintenance.id != null) {
|
||||
await controller.deleteMaintenance(maintenance.id!);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _showMaintenancesForDate(
|
||||
DateTime date,
|
||||
List<MaintenanceDto> maintenances,
|
||||
) {
|
||||
final dateMaintenances =
|
||||
maintenances.where((m) {
|
||||
// nextMaintenanceDate 필드가 백엔드에 없으므로 startedAt~endedAt 기간으로 확인
|
||||
final targetDate = DateTime(date.year, date.month, date.day);
|
||||
final startDate = DateTime(m.startedAt.year, m.startedAt.month, m.startedAt.day);
|
||||
final endDate = DateTime(m.endedAt.year, m.endedAt.month, m.endedAt.day);
|
||||
|
||||
return (targetDate.isAfter(startDate) || targetDate.isAtSameMomentAs(startDate)) &&
|
||||
(targetDate.isBefore(endDate) || targetDate.isAtSameMomentAs(endDate));
|
||||
}).toList();
|
||||
|
||||
if (dateMaintenances.isEmpty) return;
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${DateFormat('yyyy년 MM월 dd일').format(date)} 유지보수',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
...dateMaintenances.map(
|
||||
(m) => ListTile(
|
||||
title: Text('Equipment History #${m.equipmentHistoryId}'),
|
||||
subtitle: Text(
|
||||
'${m.maintenanceType == "O" ? "현장" : "원격"} | ${m.periodMonth}개월 주기',
|
||||
),
|
||||
trailing: Text(
|
||||
'${DateFormat('yyyy-MM-dd').format(m.endedAt)}', // 종료일로 대체
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
_showMaintenanceDetails(m);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user