2025-03-11 21:17:14 +08:00

214 lines
6.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:lamiter/Class/Question/question.dart';
import 'package:lamiter/Class/Question/question_layout_attributes.dart';
import 'package:lamiter/Extension/build_context.dart';
import 'package:lamiter/Extension/string.dart';
import 'package:lamiter/Component/q_title.dart';
import 'package:lamiter/Provider/Form/form_provider.dart';
import 'package:lamiter/Provider/Language/language_provider.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class SDQ<T extends FormProvider> extends Question<String> {
final GlobalKey<SDQLayoutState> SDQKey = GlobalKey<SDQLayoutState>();
final TextEditingController controller = TextEditingController();
final SDQLayoutAttributes attributes;
final SDQValidator validator;
SDQ({
super.key,
required super.id,
required super.required,
super.answer,
required this.attributes,
required this.validator,
});
@override
void setAnswerLayout(String? _answer) {
if (_answer == null) return;
answer = _answer;
controller.text = _answer;
}
@override
void lockAnswerLayouot() {
SDQKey.currentState?.lockAnswer();
}
@override
Widget build(BuildContext context) {
void layoutSetAnswer(String? layoutAnswer) {
if (validator.validator(layoutAnswer) != null) {
answer = null;
} else {
answer = layoutAnswer;
}
context.read<T>().refresh();
}
return _Layout(
key: SDQKey,
controller: controller,
attributes: attributes,
validator: validator,
setAnswer: layoutSetAnswer,
);
}
}
enum SDQValidator {
none,
nonNull,
email,
phoneNumber,
positiveNumber;
const SDQValidator();
String? validator(value) {
switch (this) {
case SDQValidator.none:
return null;
case SDQValidator.nonNull:
if (value == null || value.isEmpty) return '此欄位為必填。';
return null;
case SDQValidator.email:
if (value == null || value.isEmpty) return '此欄位為必填。';
value as String;
if (!value.validateEmail()) return '請輸入正確的電子郵件格式。';
return null;
case SDQValidator.phoneNumber:
if (value == null || value.isEmpty) return '此欄位為必填。';
value as String;
if (!value.validatePhoneNumber()) return '請輸入正確的電話號碼。';
return null;
case SDQValidator.positiveNumber:
if (value == null || value.isEmpty) return '此欄位為必填。';
value as String;
try {
if (double.parse(value) <= 0) return '請輸入大於零的數字。';
} catch (e) {
return '請輸入有效數字。';
}
return null;
default:
return null;
}
}
}
class SDQLayoutAttributes extends QuestionLayoutAttributes<String> {
final String? hintText;
final int maxLines;
final bool obscureText;
final TextInputType keyboardType;
final TextCapitalization textCapitalization;
SDQLayoutAttributes({
super.title,
required super.required,
this.hintText,
this.maxLines = 1,
this.obscureText = false,
this.keyboardType = TextInputType.text,
this.textCapitalization = TextCapitalization.none,
});
}
class _Layout extends StatefulWidget {
// Short description question
final TextEditingController controller;
final SDQLayoutAttributes attributes;
final SDQValidator validator;
final Function(String?) setAnswer;
const _Layout({
super.key,
required this.controller,
required this.attributes,
required this.validator,
required this.setAnswer,
});
@override
State<_Layout> createState() => SDQLayoutState();
}
class SDQLayoutState extends State<_Layout> {
bool _readOnly = false;
late bool _obscureText;
@override
void initState() {
super.initState();
_obscureText = widget.attributes.obscureText;
setState(() {});
}
void lockAnswer() {
_readOnly = true;
setState(() {});
}
@override
Widget build(BuildContext context) {
final languageProvider = Provider.of<LanguageProvider>(context);
return Form(
child: Column(
children: [
// question title
widget.attributes.title != null && widget.attributes.title!.isNotEmpty
? QTitle(
title: languageProvider
.getLocaleString(widget.attributes.title!),
readOnly: _readOnly,
required: widget.attributes.required,
)
: const SizedBox.shrink(),
// answer TextField
TextFormField(
controller: widget.controller,
minLines: 1,
maxLines:
widget.attributes.obscureText ? 1 : widget.attributes.maxLines,
obscureText: _obscureText,
autocorrect: false,
readOnly: _readOnly,
keyboardType: widget.attributes.keyboardType,
textCapitalization: widget.attributes.textCapitalization,
// textInputAction: TextInputAction.done,
decoration: InputDecoration(
isDense: false,
contentPadding: REdgeInsets.only(top: 9.sp, bottom: 6.sp),
hintText: languageProvider
.getLocaleString(widget.attributes.hintText ?? ''),
hintStyle: context.bL!.copyWith(color: context.primary),
enabledBorder:
UnderlineInputBorder(borderSide: context.QBorderSide),
suffixIcon: widget.attributes.obscureText
? GestureDetector(
onTap: () => setState(
() {
_obscureText = !_obscureText;
},
),
child: Icon(
_obscureText ? Icons.visibility : Icons.visibility_off,
),
)
: null,
),
validator: widget.validator.validator,
autovalidateMode: AutovalidateMode.onUserInteraction,
onChanged: widget.setAnswer,
),
],
),
);
}
}