Skip to content

Commit 7d2f978

Browse files
committed
Small refactor
1 parent 2039cfd commit 7d2f978

File tree

5 files changed

+168
-165
lines changed

5 files changed

+168
-165
lines changed

lib/components/pages/new_project_page.dart

Lines changed: 2 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'package:shared/model/participant.dart';
77

88
import '../../model/project.dart';
99
import '../../model/project_data.dart';
10+
import '../../utils/tiles/header_tile.dart';
11+
import '../../utils/tiles/participant_tile.dart';
1012
import 'new_project/local.dart';
1113
import 'new_project/pocketbase.dart';
1214

@@ -127,155 +129,3 @@ class _ParticipantListWidgetState extends State<ParticipantListWidget> {
127129
);
128130
}
129131
}
130-
131-
class HeaderTile extends StatelessWidget {
132-
const HeaderTile(this.text, {super.key});
133-
134-
final String text;
135-
136-
@override
137-
Widget build(BuildContext context) {
138-
return ListTile(
139-
title: Text(
140-
text,
141-
style: const TextStyle(
142-
fontFeatures: [FontFeature.enable('smcp')],
143-
),
144-
),
145-
tileColor: Theme.of(context).splashColor,
146-
dense: false,
147-
);
148-
}
149-
}
150-
151-
class ParticipantTile extends StatefulWidget {
152-
ParticipantTile({
153-
super.key,
154-
required this.project,
155-
required this.participant,
156-
required this.onChange,
157-
required this.setHasNew,
158-
});
159-
160-
final Project project;
161-
Participant? participant;
162-
final Function() onChange;
163-
final void Function(bool v) setHasNew;
164-
165-
@override
166-
State<ParticipantTile> createState() => _ParticipantTileState();
167-
}
168-
169-
class _ParticipantTileState extends State<ParticipantTile> {
170-
late TextEditingController controller;
171-
172-
bool edit = false;
173-
174-
@override
175-
Widget build(BuildContext context) {
176-
bool hasParticipant = widget.participant != null;
177-
if (!hasParticipant) edit = true;
178-
179-
bool isMe = widget.participant == widget.project.currentParticipant;
180-
181-
controller = TextEditingController(
182-
text: hasParticipant
183-
? widget.participant!.pseudo + (isMe && !edit ? ' (me)' : '')
184-
: '',
185-
);
186-
187-
return ListTile(
188-
onTap: () {
189-
widget.project.currentParticipant = widget.participant;
190-
widget.onChange();
191-
},
192-
title: TextField(
193-
autofocus: true,
194-
enabled: edit,
195-
maxLines: 1,
196-
maxLength: 30,
197-
maxLengthEnforcement: MaxLengthEnforcement.enforced,
198-
decoration: InputDecoration(
199-
counterText: "",
200-
border: edit ? null : InputBorder.none,
201-
),
202-
controller: controller,
203-
style: TextStyle(
204-
fontWeight: isMe ? FontWeight.bold : FontWeight.normal,
205-
),
206-
),
207-
trailing: Row(
208-
mainAxisSize: MainAxisSize.min,
209-
children: [
210-
IconButton(
211-
onPressed: () async {
212-
edit = !edit;
213-
if (!edit) {
214-
if (hasParticipant) {
215-
widget.participant!.pseudo = controller.text;
216-
await widget.participant!.conn.save();
217-
} else {
218-
widget.participant = Participant(
219-
pseudo: controller.text,
220-
project: widget.project,
221-
);
222-
await widget.participant!.conn.save();
223-
widget.project.participants.add(widget.participant!);
224-
widget.setHasNew(false);
225-
return;
226-
}
227-
}
228-
setState(() {});
229-
},
230-
icon: Icon(edit ? Icons.done : Icons.edit),
231-
),
232-
IconButton(
233-
icon: const Icon(Icons.close),
234-
onPressed: () async {
235-
if (hasParticipant) {
236-
await confirmBox(
237-
context: context,
238-
title: "Remove ${widget.participant!.pseudo}",
239-
content:
240-
"Are you sure you want to remove ${widget.participant!.pseudo}? You will not be able to undo it.",
241-
onValidate: () async {
242-
await widget.project
243-
.deleteParticipant(widget.participant!);
244-
widget.onChange();
245-
if (context.mounted) Navigator.of(context).pop();
246-
},
247-
);
248-
} else {
249-
widget.setHasNew(false);
250-
}
251-
}),
252-
],
253-
),
254-
);
255-
}
256-
257-
Future<dynamic> confirmBox({
258-
required BuildContext context,
259-
required String title,
260-
required String content,
261-
required Function()? onValidate,
262-
}) {
263-
return showDialog(
264-
context: context,
265-
builder: (context) => AlertDialog(
266-
title: Text(title),
267-
content: Text(content),
268-
actions: [
269-
TextButton(
270-
onPressed: onValidate,
271-
child: const Text("Yes"),
272-
),
273-
TextButton(
274-
onPressed: () => Navigator.of(context).pop(),
275-
child: const Text("No"),
276-
),
277-
],
278-
),
279-
);
280-
}
281-
}

lib/components/pages/refund_page_part.dart

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,19 @@ import 'dart:math';
33
import 'package:flutter/material.dart';
44
import 'package:shared/model/participant.dart';
55
import 'package:shared/model/project.dart';
6+
import 'package:shared/utils/tiles/header_tile.dart';
67

7-
List<ListTile> getRefundPageTiles({
8+
List<Widget> getRefundPageTiles({
89
required final Project project,
910
required final Map<Participant, double> parts,
1011
required final List<Participant> sortedParticipants,
1112
required final BuildContext context,
1213
}) {
1314
bool hasMe = project.currentParticipant != null;
1415

15-
List<ListTile> tiles = [];
16+
List<Widget> tiles = [];
1617

17-
tiles.add(
18-
ListTile(
19-
title: const Padding(
20-
padding: EdgeInsets.only(left: 8.0),
21-
child: Text(
22-
"How to refund ?",
23-
),
24-
),
25-
tileColor: Theme.of(context).splashColor,
26-
),
27-
);
18+
tiles.add(const HeaderTile("How to refund ?"));
2819

2920
if (hasMe) {
3021
tiles.add(

lib/utils/dialogs/confirm_box.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import 'package:flutter/material.dart';
2+
3+
Future<dynamic> confirmBox({
4+
required BuildContext context,
5+
required String title,
6+
required String content,
7+
required Function()? onValidate,
8+
}) {
9+
return showDialog(
10+
context: context,
11+
builder: (context) => AlertDialog(
12+
title: Text(title),
13+
content: Text(content),
14+
actions: [
15+
TextButton(
16+
onPressed: onValidate,
17+
child: const Text("Yes"),
18+
),
19+
TextButton(
20+
onPressed: () => Navigator.of(context).pop(),
21+
child: const Text("No"),
22+
),
23+
],
24+
),
25+
);
26+
}

lib/utils/tiles/header_tile.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'dart:ui';
2+
3+
import 'package:flutter/material.dart';
4+
5+
class HeaderTile extends StatelessWidget {
6+
const HeaderTile(this.text, {super.key});
7+
8+
final String text;
9+
10+
@override
11+
Widget build(BuildContext context) {
12+
return ListTile(
13+
title: Text(
14+
text,
15+
style: const TextStyle(
16+
fontFeatures: [FontFeature.enable('smcp')],
17+
),
18+
),
19+
tileColor: Theme.of(context).splashColor,
20+
dense: false,
21+
);
22+
}
23+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
3+
4+
import '../../model/participant.dart';
5+
import '../../model/project.dart';
6+
import '../dialogs/confirm_box.dart';
7+
8+
class ParticipantTile extends StatefulWidget {
9+
ParticipantTile({
10+
super.key,
11+
required this.project,
12+
required this.participant,
13+
required this.onChange,
14+
required this.setHasNew,
15+
});
16+
17+
final Project project;
18+
Participant? participant;
19+
final Function() onChange;
20+
final void Function(bool v) setHasNew;
21+
22+
@override
23+
State<ParticipantTile> createState() => _ParticipantTileState();
24+
}
25+
26+
class _ParticipantTileState extends State<ParticipantTile> {
27+
late TextEditingController controller;
28+
29+
bool edit = false;
30+
31+
@override
32+
Widget build(BuildContext context) {
33+
bool hasParticipant = widget.participant != null;
34+
if (!hasParticipant) edit = true;
35+
36+
bool isMe = widget.participant == widget.project.currentParticipant;
37+
38+
controller = TextEditingController(
39+
text: hasParticipant
40+
? widget.participant!.pseudo + (isMe && !edit ? ' (me)' : '')
41+
: '',
42+
);
43+
44+
return ListTile(
45+
onTap: () {
46+
widget.project.currentParticipant = widget.participant;
47+
widget.onChange();
48+
},
49+
title: TextField(
50+
autofocus: true,
51+
enabled: edit,
52+
maxLines: 1,
53+
maxLength: 30,
54+
maxLengthEnforcement: MaxLengthEnforcement.enforced,
55+
decoration: InputDecoration(
56+
counterText: "",
57+
border: edit ? null : InputBorder.none,
58+
),
59+
controller: controller,
60+
style: TextStyle(
61+
fontWeight: isMe ? FontWeight.bold : FontWeight.normal,
62+
),
63+
),
64+
trailing: Row(
65+
mainAxisSize: MainAxisSize.min,
66+
children: [
67+
IconButton(
68+
onPressed: () async {
69+
edit = !edit;
70+
if (!edit) {
71+
if (hasParticipant) {
72+
widget.participant!.pseudo = controller.text;
73+
await widget.participant!.conn.save();
74+
} else {
75+
widget.participant = Participant(
76+
pseudo: controller.text,
77+
project: widget.project,
78+
);
79+
await widget.participant!.conn.save();
80+
widget.project.participants.add(widget.participant!);
81+
widget.setHasNew(false);
82+
return;
83+
}
84+
}
85+
setState(() {});
86+
},
87+
icon: Icon(edit ? Icons.done : Icons.edit),
88+
),
89+
IconButton(
90+
icon: const Icon(Icons.close),
91+
onPressed: () async {
92+
if (hasParticipant) {
93+
await confirmBox(
94+
context: context,
95+
title: "Remove ${widget.participant!.pseudo}",
96+
content:
97+
"Are you sure you want to remove ${widget.participant!.pseudo}? You will not be able to undo it.",
98+
onValidate: () async {
99+
await widget.project
100+
.deleteParticipant(widget.participant!);
101+
widget.onChange();
102+
if (context.mounted) Navigator.of(context).pop();
103+
},
104+
);
105+
} else {
106+
widget.setHasNew(false);
107+
}
108+
}),
109+
],
110+
),
111+
);
112+
}
113+
}

0 commit comments

Comments
 (0)