CommunityAPP/lib/new_resident_step.dart

502 lines
16 KiB
Dart
Raw Normal View History

2025-05-09 11:46:02 +08:00
import 'package:flutter/material.dart';
import 'login_page.dart';
2025-05-09 11:46:02 +08:00
class NewResidentStepPage extends StatefulWidget {
const NewResidentStepPage({super.key});
@override
State<NewResidentStepPage> createState() => _NewResidentStepPageState();
}
class _NewResidentStepPageState extends State<NewResidentStepPage> {
int currentStep = 1;
final TextEditingController _emailController = TextEditingController();
final List<TextEditingController> _codeControllers = List.generate(
6,
(_) => TextEditingController(),
);
String? statusMessage;
bool isSuccess = false;
void sendVerification() {
final email = _emailController.text.trim();
if (email.contains("@")) {
setState(() {
isSuccess = true;
statusMessage = '📧 驗證碼已寄出至 $email';
currentStep = 2;
});
} else {
setState(() {
isSuccess = false;
statusMessage = '❌ 請輸入有效的 Email';
});
}
}
void verifyCode() {
final code = _codeControllers.map((c) => c.text).join();
if (RegExp(r'^\d{6}$').hasMatch(code)) {
setState(() {
isSuccess = true;
statusMessage = '✅ 驗證成功!';
currentStep = 3;
});
} else {
setState(() {
isSuccess = false;
statusMessage = '❌ 請輸入正確的 6 位數驗證碼';
});
}
}
Widget buildStep1() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'步驟 1 之 3',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.grey),
),
const SizedBox(height: 10),
const Text(
'輸入電子郵件',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 24),
TextField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
labelText: '電子郵件',
border: OutlineInputBorder(),
hintText: 'example@mail.com',
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: sendVerification,
style: ElevatedButton.styleFrom(backgroundColor: Colors.indigo),
child: const Text('發送驗證碼', style: TextStyle(color: Colors.white)),
),
],
);
}
Widget buildStep2() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'步驟 2 之 3',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.grey),
),
const SizedBox(height: 10),
const Text(
'請輸入驗證碼',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
const Text(
'我們已將 6 位數驗證碼寄至您的 Email',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(6, (i) {
return Container(
width: 40,
margin: const EdgeInsets.symmetric(horizontal: 4),
child: TextField(
controller: _codeControllers[i],
maxLength: 1,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
decoration: const InputDecoration(counterText: ''),
onChanged: (val) {
if (val.length == 1 && i < 5) {
FocusScope.of(context).nextFocus();
}
},
),
);
}),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: verifyCode,
style: ElevatedButton.styleFrom(backgroundColor: Colors.indigo),
child: const Text('驗證並繼續', style: TextStyle(color: Colors.white)),
),
TextButton(
onPressed: () {
setState(() {
statusMessage = '📨 驗證碼已重新寄出,請再次查收 Email。';
});
},
child: const Text('重新發送驗證碼'),
),
],
);
}
// 在 State 裡新增這些 controller 和變數:
final nameController = TextEditingController();
final birthdayController = TextEditingController();
final phoneController = TextEditingController();
final roomController = TextEditingController();
final plateController = TextEditingController();
final passwordController = TextEditingController();
final confirmPasswordController = TextEditingController();
String? selectedGender;
// 表單驗證 function
bool validateStep3Fields() {
return true;
/*
nameController.text.isNotEmpty &&
selectedGender != null &&
birthdayController.text.isNotEmpty &&
phoneController.text.isNotEmpty &&
roomController.text.isNotEmpty &&
plateController.text.isNotEmpty &&
passwordController.text.isNotEmpty &&
confirmPasswordController.text.isNotEmpty &&
passwordController.text == confirmPasswordController.text;
*/
}
// buildStep3 widget
Widget buildStep3() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'步驟 3 之 3',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.grey),
),
const SizedBox(height: 10),
const Text(
'填寫基本資料',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
const Text(
'請輸入您的基本資訊以完成註冊',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey),
),
const SizedBox(height: 20),
TextField(
controller: nameController,
decoration: const InputDecoration(
labelText: '姓名',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
DropdownButtonFormField<String>(
value: selectedGender,
items: const [
DropdownMenuItem(value: '', child: Text('')),
DropdownMenuItem(value: '', child: Text('')),
DropdownMenuItem(value: '其他', child: Text('其他')),
],
onChanged: (value) {
setState(() {
selectedGender = value;
});
},
decoration: const InputDecoration(
labelText: '性別',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: birthdayController,
decoration: const InputDecoration(
labelText: '生日',
hintText: 'YYYY-MM-DD',
border: OutlineInputBorder(),
),
keyboardType: TextInputType.datetime,
),
const SizedBox(height: 16),
TextField(
controller: phoneController,
decoration: const InputDecoration(
labelText: '手機號碼',
hintText: '例如0912345678',
border: OutlineInputBorder(),
),
keyboardType: TextInputType.phone,
),
const SizedBox(height: 16),
TextField(
controller: roomController,
decoration: const InputDecoration(
labelText: '房號 / 室別',
hintText: '例如A棟 5F-2',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: plateController,
decoration: const InputDecoration(
labelText: '車牌號碼',
hintText: '例如ABC-1234',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: passwordController,
obscureText: true,
decoration: const InputDecoration(
labelText: '密碼',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
TextField(
controller: confirmPasswordController,
obscureText: true,
decoration: const InputDecoration(
labelText: '確認密碼',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () {
if (validateStep3Fields()) {
setState(() {
currentStep = 4;
statusMessage = null;
isSuccess = true;
});
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('✅ 註冊完成!歡迎加入社區!')));
} else {
setState(() {
isSuccess = false;
statusMessage = '❌ 請完整填寫所有欄位,並確認密碼一致';
});
}
},
style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
child: const Text('完成註冊', style: TextStyle(color: Colors.white)),
),
],
);
}
Widget buildStep4() {
return Column(
children: [
// Body content
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min, // 讓 Column 的高度根據內容來調整
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'親愛的用戶您好',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color: Color(0xFF333333),
),
),
const SizedBox(height: 20),
const Text(
'您的新用戶申請已送至管理室,請您拿手機至管理室由管理員掃描開通。',
style: TextStyle(fontSize: 16, color: Color(0xFF666666)),
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
setState(() {
currentStep = 5;
statusMessage = null;
isSuccess = true;
});
2025-05-09 11:46:02 +08:00
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF4CAF50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
padding: const EdgeInsets.symmetric(vertical: 12),
),
child: const Text(
'掃描開通',
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
),
],
),
),
],
);
}
Widget buildStep5() {
return Column(
children: [
// Body content
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
mainAxisSize: MainAxisSize.min, // 讓 Column 的高度根據內容來調整
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'掃描QR Code 來開通',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color: Color(0xFF333333),
),
),
const SizedBox(height: 20),
const Text(
'請掃描下面的 QR Code 開通此住戶。',
style: TextStyle(fontSize: 16, color: Color(0xFF666666)),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
// 塞入QR CODE 圖片
Image.network(
'https://docs.lightburnsoftware.com/legacy/img/QRCode/ExampleCode.png',
width: 200,
height: 200,
),
const SizedBox(height: 40),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const LoginPage(),
),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF4CAF50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
padding: const EdgeInsets.symmetric(vertical: 12),
),
child: const Text(
'掃描完畢,返回登入介面',
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
),
const Text(
'如果無法掃描,請調整螢幕亮度。',
style: TextStyle(
fontSize: 14,
color: Color.fromARGB(255, 129, 129, 129),
),
textAlign: TextAlign.center,
),
],
),
),
],
);
}
2025-05-09 11:46:02 +08:00
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF7F8FA),
appBar: AppBar(
backgroundColor: const Color(0xFF9EAF9F),
foregroundColor: Colors.white,
title: const Text('新住戶註冊'),
leading:
currentStep > 1
? IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
setState(() {
currentStep--;
});
},
)
: null,
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 3)],
),
child: SingleChildScrollView(
child: Column(
children: [
buildStepContent(),
const SizedBox(height: 20),
if (statusMessage != null)
Text(
statusMessage!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: isSuccess ? Colors.green : Colors.red,
),
),
],
),
),
),
),
);
}
Widget buildStepContent() {
switch (currentStep) {
case 1:
return buildStep1();
case 2:
return buildStep2();
case 3:
return buildStep3();
case 4:
return buildStep4();
case 5:
return buildStep5();
2025-05-09 11:46:02 +08:00
default:
return const Text('未知步驟');
}
}
}