Compare commits
5 Commits
50e2e98fcb
...
8d9f204a44
Author | SHA1 | Date | |
---|---|---|---|
8d9f204a44 | |||
a6123b506f | |||
8fe8e7113c | |||
2bd6731f9c | |||
1f349f2887 |
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'activity_submit.dart';
|
||||
|
||||
class ActivityListPage extends StatefulWidget {
|
||||
const ActivityListPage({Key? key}) : super(key: key);
|
||||
@ -93,7 +94,7 @@ class _ActivityListPageState extends State<ActivityListPage> {
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// TODO: 導向詳情頁
|
||||
// TODO : 查看詳情
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
@ -110,20 +111,27 @@ class _ActivityListPageState extends State<ActivityListPage> {
|
||||
),
|
||||
child: const Text('查看詳情'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
if (canRegister && id != null)
|
||||
if (canRegister && id != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
ElevatedButton(
|
||||
onPressed: () => openRegisterModal(id),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
shadowColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 12,
|
||||
),
|
||||
),
|
||||
child: const Text('我要報名'),
|
||||
child: const Text(
|
||||
'我要報名',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
@ -188,7 +196,13 @@ class _ActivityListPageState extends State<ActivityListPage> {
|
||||
alignment: Alignment.centerRight,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// TODO: 導向提交活動頁
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder:
|
||||
(context) => const ActivitySubmitPage(),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('提交活動申請'),
|
||||
|
224
lib/activity_submit.dart
Normal file
224
lib/activity_submit.dart
Normal file
@ -0,0 +1,224 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'dart:io';
|
||||
|
||||
class ActivitySubmitPage extends StatefulWidget {
|
||||
const ActivitySubmitPage({super.key});
|
||||
|
||||
@override
|
||||
State<ActivitySubmitPage> createState() => _ActivitySubmitPageState();
|
||||
}
|
||||
|
||||
class _ActivitySubmitPageState extends State<ActivitySubmitPage> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _titleController = TextEditingController();
|
||||
final _locationController = TextEditingController();
|
||||
final _descriptionController = TextEditingController();
|
||||
DateTime? _startDate;
|
||||
DateTime? _endDate;
|
||||
String _needRegister = '否';
|
||||
String _repeatOption = 'none';
|
||||
int _repeatCount = 1;
|
||||
File? _poster;
|
||||
|
||||
Future<void> _selectDateTime(bool isStart) async {
|
||||
final now = DateTime.now();
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: now,
|
||||
firstDate: now,
|
||||
lastDate: DateTime(now.year + 2),
|
||||
);
|
||||
if (date == null) return;
|
||||
|
||||
final time = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.fromDateTime(now),
|
||||
);
|
||||
if (time == null) return;
|
||||
|
||||
final selected = DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
date.day,
|
||||
time.hour,
|
||||
time.minute,
|
||||
);
|
||||
setState(() {
|
||||
if (isStart) {
|
||||
_startDate = selected;
|
||||
} else {
|
||||
_endDate = selected;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _submitForm() {
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
|
||||
if (_startDate == null || _endDate == null) {
|
||||
_showAlert('請選擇開始與結束時間');
|
||||
return;
|
||||
}
|
||||
|
||||
if (_endDate!.isBefore(_startDate!)) {
|
||||
_showAlert('結束時間必須晚於開始時間!');
|
||||
return;
|
||||
}
|
||||
|
||||
final formatter = DateFormat('yyyy-MM-dd HH:mm');
|
||||
final message =
|
||||
StringBuffer()
|
||||
..writeln('活動申請已送出')
|
||||
..writeln('名稱:${_titleController.text}')
|
||||
..writeln('開始時間:${formatter.format(_startDate!)}')
|
||||
..writeln('結束時間:${formatter.format(_endDate!)}')
|
||||
..writeln('地點:${_locationController.text}')
|
||||
..writeln('描述:${_descriptionController.text}')
|
||||
..writeln('需報名統計:$_needRegister');
|
||||
|
||||
if (_repeatOption != 'none') {
|
||||
final map = {'weekly': '每週', 'biweekly': '每兩週', 'monthly': '每月'};
|
||||
message.writeln('重複設定:${map[_repeatOption]},共重複 $_repeatCount 次');
|
||||
}
|
||||
|
||||
if (_poster != null) {
|
||||
message.writeln('檔案名稱:${_poster!.path.split('/').last}');
|
||||
}
|
||||
|
||||
_showAlert(message.toString());
|
||||
}
|
||||
|
||||
void _showAlert(String text) {
|
||||
// print('Submit button pressed'); // ← Debug 用
|
||||
showDialog(
|
||||
context: context,
|
||||
builder:
|
||||
(_) => AlertDialog(
|
||||
title: const Text('訊息'),
|
||||
content: Text(text),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('確定'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('提交活動申請'),
|
||||
backgroundColor: const Color(0xFF9eaf9f),
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _titleController,
|
||||
decoration: const InputDecoration(labelText: '活動名稱'),
|
||||
validator: (value) => value!.isEmpty ? '必填' : null,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_buildDateField('開始時間', _startDate, () => _selectDateTime(true)),
|
||||
const SizedBox(height: 12),
|
||||
_buildDateField('結束時間', _endDate, () => _selectDateTime(false)),
|
||||
const SizedBox(height: 12),
|
||||
TextFormField(
|
||||
controller: _locationController,
|
||||
decoration: const InputDecoration(labelText: '地點'),
|
||||
validator: (value) => value!.isEmpty ? '必填' : null,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
TextFormField(
|
||||
controller: _descriptionController,
|
||||
decoration: const InputDecoration(labelText: '活動描述'),
|
||||
maxLines: 4,
|
||||
validator: (value) => value!.isEmpty ? '必填' : null,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
DropdownButtonFormField<String>(
|
||||
value: _needRegister,
|
||||
decoration: const InputDecoration(labelText: '是否需統計報名人數?'),
|
||||
items:
|
||||
['否', '是']
|
||||
.map((v) => DropdownMenuItem(value: v, child: Text(v)))
|
||||
.toList(),
|
||||
onChanged: (v) => setState(() => _needRegister = v!),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
DropdownButtonFormField<String>(
|
||||
value: _repeatOption,
|
||||
decoration: const InputDecoration(labelText: '是否重複舉辦'),
|
||||
items: const [
|
||||
DropdownMenuItem(value: 'none', child: Text('否')),
|
||||
DropdownMenuItem(value: 'weekly', child: Text('每週一次')),
|
||||
DropdownMenuItem(value: 'biweekly', child: Text('每兩週一次')),
|
||||
DropdownMenuItem(value: 'monthly', child: Text('每月一次')),
|
||||
],
|
||||
onChanged: (v) => setState(() => _repeatOption = v!),
|
||||
),
|
||||
if (_repeatOption != 'none') ...[
|
||||
const SizedBox(height: 12),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: '重複次數(不含首次)'),
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: '1',
|
||||
onChanged:
|
||||
(v) =>
|
||||
_repeatCount =
|
||||
int.tryParse(v) != null ? int.parse(v) : 1,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// 檔案選取功能:日後可整合 `file_picker` 套件
|
||||
_showAlert('尚未實作檔案選擇功能,請整合 file_picker 或 image_picker');
|
||||
},
|
||||
icon: const Icon(Icons.upload_file),
|
||||
label: const Text('上傳活動海報'),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: _submitForm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 32,
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'送出申請',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDateField(String label, DateTime? value, VoidCallback onTap) {
|
||||
final formatter = DateFormat('yyyy-MM-dd HH:mm');
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'$label:${value != null ? formatter.format(value) : '未選擇'}',
|
||||
),
|
||||
),
|
||||
TextButton(onPressed: onTap, child: const Text('選擇')),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
181
lib/announcement.dart
Normal file
181
lib/announcement.dart
Normal file
@ -0,0 +1,181 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Announcement {
|
||||
final String date;
|
||||
final String title;
|
||||
final String preview;
|
||||
final String full;
|
||||
|
||||
Announcement({
|
||||
required this.date,
|
||||
required this.title,
|
||||
required this.preview,
|
||||
required this.full,
|
||||
});
|
||||
|
||||
factory Announcement.fromJson(Map<String, dynamic> json) {
|
||||
return Announcement(
|
||||
date: json['date'],
|
||||
title: json['title'],
|
||||
preview: json['preview'],
|
||||
full: json['full'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AnnouncementWrapper extends StatefulWidget {
|
||||
const AnnouncementWrapper({super.key});
|
||||
|
||||
@override
|
||||
State<AnnouncementWrapper> createState() => _AnnouncementWrapperState();
|
||||
}
|
||||
|
||||
class _AnnouncementWrapperState extends State<AnnouncementWrapper> {
|
||||
List<Announcement> _announcements = [];
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchAnnouncements();
|
||||
}
|
||||
|
||||
Future<void> _fetchAnnouncements() async {
|
||||
// 模擬 API 延遲
|
||||
//await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
// 模擬 API 回傳資料
|
||||
final mockData = [
|
||||
{
|
||||
'date': '2025/04/28',
|
||||
'title': '水塔清洗通知',
|
||||
'preview': '本社區將於 2025/05/05 進行水塔清洗作業,請住戶提前儲水...',
|
||||
'full': '本社區將於 2025/05/05 進行水塔清洗作業,請住戶提前儲水,造成不便敬請見諒。',
|
||||
},
|
||||
{
|
||||
'date': '2025/04/25',
|
||||
'title': '停電通知',
|
||||
'preview': '台電預計於 5/1 上午進行電路維修,期間將暫時停電,請提前準備...',
|
||||
'full': '台電預計於 2025/05/01 08:00~12:00 進行電路維修,期間將暫時停電,請提前準備。',
|
||||
},
|
||||
{
|
||||
'date': '2025/04/20',
|
||||
'title': '消防演練公告',
|
||||
'preview': '消防演練將於 5/10 下午舉行,請住戶配合參與並聆聽安全說明...',
|
||||
'full': '消防演練將於 2025/05/10 下午 3 點舉行,請各位住戶配合參與。',
|
||||
},
|
||||
];
|
||||
|
||||
setState(() {
|
||||
_announcements =
|
||||
mockData.map((json) => Announcement.fromJson(json)).toList();
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
void _showDetailModal(BuildContext context, String title, String content) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder:
|
||||
(_) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(content),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('關閉'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
|
||||
child:
|
||||
_isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
const Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'公告列表',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 48),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text('📢 最新公告', style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
..._announcements.map(
|
||||
(item) => Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
item.date,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black54,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.title,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.only(top: 6.0),
|
||||
child: Text(
|
||||
item.preview,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.black45,
|
||||
),
|
||||
),
|
||||
),
|
||||
onTap:
|
||||
() => _showDetailModal(
|
||||
context,
|
||||
item.title,
|
||||
item.full,
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -108,22 +108,6 @@ class _EditProfilePageState extends State<EditProfilePage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
items: const [
|
||||
BottomNavigationBarItem(icon: Icon(Icons.home), label: '首頁'),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.door_front_door),
|
||||
label: '出入',
|
||||
),
|
||||
BottomNavigationBarItem(icon: Icon(Icons.message), label: '訊息'),
|
||||
BottomNavigationBarItem(icon: Icon(Icons.person), label: '住戶'),
|
||||
],
|
||||
currentIndex: 3,
|
||||
onTap: (index) {
|
||||
// Add navigation logic here if needed
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import 'package:communityapp/visitor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'reapair.dart';
|
||||
import 'activity.dart';
|
||||
import 'announcement.dart';
|
||||
|
||||
class HomeContentPage extends StatelessWidget {
|
||||
const HomeContentPage({super.key});
|
||||
@ -59,7 +60,7 @@ class HomeContentPage extends StatelessWidget {
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
_announcementSection(),
|
||||
_announcementSection(context),
|
||||
_quickMenuSection(context),
|
||||
_adCarousel(),
|
||||
_marqueeNotice(),
|
||||
@ -71,21 +72,56 @@ class HomeContentPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
// 📢 重要公告區塊
|
||||
static Widget _announcementSection() {
|
||||
static Widget _announcementSection(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'📢 重要公告',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
Row(
|
||||
children: [
|
||||
const Text(
|
||||
'📢 重要公告',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Spacer(),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (_) => const AnnouncementWrapper(),
|
||||
);
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: Colors.blue,
|
||||
side: const BorderSide(color: Colors.blue), // 藍色外框
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20), // 更小的圓角
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
), // 更小的內距
|
||||
minimumSize: const Size(0, 0), // 取消預設最小尺寸限制
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // 點擊範圍不外擴
|
||||
),
|
||||
child: const Text(
|
||||
'更多',
|
||||
style: TextStyle(fontSize: 14), // 更小字體
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Card(
|
||||
child: ListTile(
|
||||
title: const Text('4/20 水塔清洗通知'),
|
||||
subtitle: const Text('本週六早上9:00至下午3:00進行清洗,請提前儲水。'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
title: const Text('4/20 水塔清洗通知'),
|
||||
subtitle: const Text('本週六早上9:00至下午3:00進行清洗,請提前儲水。'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -153,7 +153,10 @@ class _MessagePageState extends State<MessagePage> {
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
child: const Text('發送'),
|
||||
child: const Text(
|
||||
'發送',
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -157,7 +157,6 @@ class PersonalPage extends StatelessWidget {
|
||||
right: 0,
|
||||
child: OutlinedButton(
|
||||
onPressed: () {
|
||||
// TODO: 意見箱按鈕
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const FeedbackPage()),
|
||||
|
@ -208,6 +208,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -34,6 +34,7 @@ dependencies:
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.8
|
||||
intl: ^0.18.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -1,30 +0,0 @@
|
||||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:communityapp/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user