CommunityAPP/lib/new_resident_step.dart

502 lines
16 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 'login_page.dart';
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;
});
},
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,
),
],
),
),
],
);
}
@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();
default:
return const Text('未知步驟');
}
}
}