Skip to content

Commit

Permalink
chore: update text fields (#61)
Browse files Browse the repository at this point in the history
* add `InputDecorationTheme`

* use theme's `InputDecoration`

* add `useFocusNode()` in `SearchPaymentMethodsPage`

* add `didPrefix` localization

* add `invalidDid` localization

* refactor `SendDidPage` with `useFocusNode()`

* update test after refactoring `SendDidPage`
  • Loading branch information
ethan-tbd authored Feb 12, 2024
1 parent 87f1584 commit a1c7eda
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 112 deletions.
9 changes: 8 additions & 1 deletion lib/features/payments/search_payment_methods_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SearchPaymentMethodsPage extends HookWidget {
@override
Widget build(BuildContext context) {
final searchText = useState('');
final focusNode = useFocusNode();

return Scaffold(
appBar: AppBar(scrolledUnderElevation: 0),
Expand All @@ -33,9 +34,15 @@ class SearchPaymentMethodsPage extends HookWidget {
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
focusNode: focusNode,
onTapOutside: (_) => focusNode.unfocus(),
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: Loc.of(context).search,
prefixIcon: const Icon(Icons.search),
prefixIcon: const Padding(
padding: EdgeInsets.only(top: Grid.xs),
child: Icon(Icons.search)),
),
onChanged: (value) => searchText.value = value,
),
Expand Down
156 changes: 85 additions & 71 deletions lib/features/send/send_did_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,99 +5,113 @@ import 'package:didpay/shared/theme/grid.dart';
import 'package:didpay/shared/success_page.dart';

class SendDidPage extends HookWidget {
final _formKey = GlobalKey<FormState>();

final String sendAmount;
const SendDidPage({super.key, required this.sendAmount});
SendDidPage({super.key, required this.sendAmount});

@override
Widget build(BuildContext context) {
final sendDid = useState<String>('');
final focusNode = useFocusNode();
final controller = useTextEditingController();

return Scaffold(
appBar: AppBar(
title: Column(
children: [
Text(
'\$$sendAmount',
style: Theme.of(context).textTheme.headlineMedium,
textAlign: TextAlign.center,
),
Text(
Loc.of(context).accountBalance,
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
)
],
)),
appBar: AppBar(),
body: SafeArea(
child:
Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: Grid.side),
child: Column(
children: [
Column(children: [
const SizedBox(height: Grid.lg),
GestureDetector(
child: Row(
children: [
const Icon(Icons.qr_code_scanner,
size: Grid.sm),
const SizedBox(width: Grid.xs),
Expanded(
child: Text(
Loc.of(context).scanQrCode,
softWrap: true,
),
)
],
),
),
]),
const SizedBox(height: Grid.lg),
Row(
children: [
Text(Loc.of(context).to,
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(width: Grid.xs),
Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
floatingLabelBehavior:
FloatingLabelBehavior.never,
labelText: Loc.of(context).didTag),
enableSuggestions: false,
autocorrect: false,
onChanged: (value) => sendDid.value = value),
)
],
)
],
),
),
],
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: Grid.xxs),
_buildScanQrTile(context, controller),
const SizedBox(height: Grid.xxs),
_buildForm(context, focusNode, controller),
],
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: Grid.side),
child: FilledButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SuccessPage(
text: Loc.of(context).yourPaymentWasSent,
if (_formKey.currentState?.validate() ?? false) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SuccessPage(
text: Loc.of(context).yourPaymentWasSent),
),
),
);
);
}
},
child: Text('${Loc.of(context).pay} \$$sendAmount'),
),
),
]),
));
}

Widget _buildForm(BuildContext context, FocusNode focusNode,
TextEditingController controller) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: Grid.side),
child: Form(
key: _formKey,
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Padding(
padding: const EdgeInsets.only(right: Grid.xs),
child: Text(
Loc.of(context).to,
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: Theme.of(context).colorScheme.primary),
),
),
Expanded(
child: TextFormField(
focusNode: focusNode,
controller: controller,
onTapOutside: (event) => focusNode.unfocus(),
maxLines: null,
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: Loc.of(context).didPrefix,
),
validator: (value) {
if (value == null ||
!value.startsWith(Loc.of(context).didPrefix)) {
return Loc.of(context).invalidDid;
}
return null;
}),
),
],
)),
);
}

Widget _buildScanQrTile(
BuildContext context, TextEditingController controller) {
return ListTile(
leading: const Icon(Icons.qr_code),
title: Text(
Loc.of(context).scanQrCode,
style: Theme.of(context).textTheme.bodyMedium,
),
contentPadding: const EdgeInsets.symmetric(horizontal: Grid.side),
trailing: const Icon(Icons.chevron_right),
onTap: () => {
//TODO: complete in #55 using TextEditingController
},
);
}
}
6 changes: 4 additions & 2 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"done": "Done",
"deposit": "Deposit",
"send": "Send",
"to": "To",
"to": "To:",
"pay": "Pay",
"scanQrCode": "Don't know the recipient's DID tag? Scan their QR code",
"didTag": "DID tag",
Expand Down Expand Up @@ -64,5 +64,7 @@
},
"search": "Search",
"serviceFeesMayApply": "Service fees may apply",
"selectPaymentMethod": "Select a payment method"
"selectPaymentMethod": "Select a payment method",
"didPrefix": "did:jwk:",
"invalidDid": "Invalid DID"
}
14 changes: 13 additions & 1 deletion lib/l10n/app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ abstract class Loc {
/// No description provided for @to.
///
/// In en, this message translates to:
/// **'To'**
/// **'To:'**
String get to;

/// No description provided for @pay.
Expand Down Expand Up @@ -336,6 +336,18 @@ abstract class Loc {
/// In en, this message translates to:
/// **'Select a payment method'**
String get selectPaymentMethod;

/// No description provided for @didPrefix.
///
/// In en, this message translates to:
/// **'did:jwk:'**
String get didPrefix;

/// No description provided for @invalidDid.
///
/// In en, this message translates to:
/// **'Invalid DID'**
String get invalidDid;
}

class _LocDelegate extends LocalizationsDelegate<Loc> {
Expand Down
8 changes: 7 additions & 1 deletion lib/l10n/app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class LocEn extends Loc {
String get send => 'Send';

@override
String get to => 'To';
String get to => 'To:';

@override
String get pay => 'Pay';
Expand Down Expand Up @@ -132,4 +132,10 @@ class LocEn extends Loc {

@override
String get selectPaymentMethod => 'Select a payment method';

@override
String get didPrefix => 'did:jwk:';

@override
String get invalidDid => 'Invalid DID';
}
40 changes: 22 additions & 18 deletions lib/shared/json_schema_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ class JsonSchemaForm extends HookWidget {
@override
Widget build(BuildContext context) {
final jsonSchema = json.decode(schema);

List<Widget> formFields = [];
jsonSchema['properties']?.forEach((key, value) {
formFields.add(TextFormField(
decoration: InputDecoration(
labelText: value['title'] ?? key,
labelStyle: TextStyle(
color: Theme.of(context).colorScheme.outlineVariant,
jsonSchema['properties']?.forEach(
(key, value) {
final focusNode = useFocusNode();

formFields.add(
TextFormField(
focusNode: focusNode,
onTapOutside: (_) => focusNode.unfocus(),
enableSuggestions: false,
autocorrect: false,
decoration: InputDecoration(
labelText: value['title'] ?? key,
),
textInputAction: TextInputAction.next,
validator: (value) => _validateField(key, value, jsonSchema),
onSaved: (value) => formData[key] = value ?? '',
),
border: InputBorder.none,
),
validator: (value) => _validateField(key, value, jsonSchema),
onSaved: (value) => formData[key] = value ?? '',
));
});
);
},
);

return Form(
key: _formKey,
Expand All @@ -41,12 +49,8 @@ class JsonSchemaForm extends HookWidget {
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: Grid.side,
),
child: Column(
children: formFields,
),
padding: const EdgeInsets.symmetric(horizontal: Grid.side),
child: Column(children: formFields),
),
),
),
Expand Down
16 changes: 16 additions & 0 deletions lib/shared/theme/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ ThemeData lightTheme(BuildContext context) => ThemeData(
),
),
),
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
floatingLabelBehavior: FloatingLabelBehavior.never,
alignLabelWithHint: true,
labelStyle: TextStyle(
color: lightColorScheme.outlineVariant,
),
),
);

ThemeData darkTheme(BuildContext context) => ThemeData(
Expand Down Expand Up @@ -65,4 +73,12 @@ ThemeData darkTheme(BuildContext context) => ThemeData(
),
),
),
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
floatingLabelBehavior: FloatingLabelBehavior.never,
alignLabelWithHint: true,
labelStyle: TextStyle(
color: darkColorScheme.outlineVariant,
),
),
);
Loading

0 comments on commit a1c7eda

Please sign in to comment.