CommunityAPP/lib/reapair.dart

251 lines
8.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class RepairPage extends StatefulWidget {
const RepairPage({super.key, required this.scrollController});
final ScrollController scrollController;
@override
State<RepairPage> createState() => _RepairPageState();
}
class _RepairPageState extends State<RepairPage> {
final _formKey = GlobalKey<FormState>();
String? _repairType;
final _locationController = TextEditingController();
final _descriptionController = TextEditingController();
XFile? _photo;
final List<Map<String, String>> _repairRecords = [
{
"date": "2025/04/20",
"type": "水管漏水",
"location": "A棟 2F",
"status": "處理中",
},
{
"date": "2025/04/18",
"type": "網路異常",
"location": "C棟 5F",
"status": "已完成",
},
{
"date": "2025/04/15",
"type": "電力問題",
"location": "B棟 6F",
"status": "待處理",
},
];
Future<void> _pickImage() async {
final picker = ImagePicker();
final picked = await picker.pickImage(source: ImageSource.gallery);
if (picked != null) {
setState(() {
_photo = picked;
});
}
}
void _submitForm() {
if (_formKey.currentState!.validate() && _repairType != null) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('報修已提交!')));
// 這裡可以擴充送出資料到伺服器的邏輯
}
}
@override
void dispose() {
_locationController.dispose();
_descriptionController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: Color(0xFFF7F8FA),
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Column(
children: [
// 標題列
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: const BoxDecoration(
color: Color(0xFF9EAF9F),
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Row(
children: [
IconButton(
icon: const Icon(Icons.close, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
const SizedBox(width: 8),
const Text(
'水電網路報修',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.white,
),
),
],
),
),
Expanded(
child: ListView(
controller: widget.scrollController,
padding: const EdgeInsets.all(16),
children: [
const Text('🛠️ 填寫報修單', style: TextStyle(fontSize: 16)),
const SizedBox(height: 12),
Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'報修類別',
style: TextStyle(fontWeight: FontWeight.bold),
),
DropdownButtonFormField<String>(
value: _repairType,
items: const [
DropdownMenuItem(value: '電力問題', child: Text('電力問題')),
DropdownMenuItem(value: '水管漏水', child: Text('水管漏水')),
DropdownMenuItem(value: '網路異常', child: Text('網路異常')),
DropdownMenuItem(value: '其他', child: Text('其他')),
],
hint: const Text('請選擇'),
onChanged: (value) {
setState(() {
_repairType = value;
});
},
validator: (value) => value == null ? '請選擇報修類別' : null,
),
const SizedBox(height: 12),
const Text(
'地點/房號',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextFormField(
controller: _locationController,
decoration: const InputDecoration(hintText: 'B棟 3F'),
validator:
(value) =>
value == null || value.isEmpty ? '請輸入地點' : null,
),
const SizedBox(height: 12),
const Text(
'問題描述',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextFormField(
controller: _descriptionController,
maxLines: 3,
decoration: const InputDecoration(
hintText: '請簡要描述問題...',
border: OutlineInputBorder(),
),
validator:
(value) =>
value == null || value.isEmpty
? '請輸入問題描述'
: null,
),
const SizedBox(height: 12),
const Text(
'照片上傳(選填)',
style: TextStyle(fontWeight: FontWeight.bold),
),
Row(
children: [
ElevatedButton(
onPressed: _pickImage,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
),
child: const Text(
'選擇照片',
style: TextStyle(color: Colors.purple),
),
),
const SizedBox(width: 8),
if (_photo != null)
const Text(
'已選擇圖片',
style: TextStyle(color: Colors.green),
),
],
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _submitForm,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
minimumSize: const Size.fromHeight(48),
),
child: const Text(
'送出報修',
style: TextStyle(color: Colors.white),
),
),
],
),
),
const SizedBox(height: 24),
const Text('📋 已申報紀錄', style: TextStyle(fontSize: 16)),
const SizedBox(height: 12),
..._repairRecords.map(
(record) => Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${record["date"]} - ${record["type"]}',
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text('地點:${record["location"]}|狀態:${record["status"]}'),
],
),
),
),
],
),
),
],
),
);
}
}
// 浮層包裝元件,給 showModalBottomSheet 使用
class RepairPageWrapper extends StatelessWidget {
const RepairPageWrapper({super.key});
@override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
initialChildSize: 0.95,
minChildSize: 0.5,
maxChildSize: 1.0,
expand: false,
builder: (_, scrollController) {
return Container(
color: Colors.transparent,
child: RepairPage(scrollController: scrollController),
);
},
);
}
}