Skip to content

Commit

Permalink
Merge pull request #90 from DevKor-github/78-multipage-form-for-sched…
Browse files Browse the repository at this point in the history
…ule-creation

78 multipage form for schedule creation
  • Loading branch information
SeoHyeonSim authored Jan 20, 2025
2 parents 29a275f + 7265d3e commit 6b7f96b
Show file tree
Hide file tree
Showing 11 changed files with 827 additions and 30 deletions.
19 changes: 1 addition & 18 deletions lib/presentation/home/screens/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,24 +176,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
),
floatingActionButton: FloatingActionButton(
onPressed: () {
final scheduleRepository = getIt.get<ScheduleRepository>();
scheduleRepository.createSchedule(
ScheduleEntity(
id: Uuid().v7(),
scheduleTime: dateOfToday.add(Duration(days: -2, hours: 10)),
scheduleName: 'ㅇㅇㅇㅇㅇ',
moveTime: Duration(minutes: 10),
isChanged: false,
isStarted: false,
scheduleSpareTime: Duration(minutes: 10),
scheduleNote: '',
userId: '1',
place: PlaceEntity(
id: Uuid().v7(),
placeName: '장소',
),
),
);
context.go('/scheduleCreate');
},
child: Icon(Icons.add),
),
Expand Down
4 changes: 2 additions & 2 deletions lib/presentation/onboarding/mutly_page_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ class MultiPageFormField extends Form {
super.canPop,
required super.child,
super.onPopInvokedWithResult,
this.onSaved,
required this.onSaved,
});

final VoidCallback? onSaved;
final VoidCallback onSaved;

@override
// ignore: library_private_types_in_public_api
Expand Down
16 changes: 6 additions & 10 deletions lib/presentation/onboarding/onboarding_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class _OnboardingScreenState extends State<OnboardingScreen>
late List<GlobalKey<FormState>> formKeys;
PreparationFormData preparationFormData = PreparationFormData();
Duration spareTime = const Duration(minutes: 0);
int _currentPageIndex = 0;
final int _numberOfPages = 4;

@override
Expand Down Expand Up @@ -48,7 +47,6 @@ class _OnboardingScreenState extends State<OnboardingScreen>
children: <Widget>[
PageIndicator(
tabController: _tabController,
currentPageIndex: _currentPageIndex,
onUpdateCurrentPageIndex: _updateCurrentPageIndex,
),
Expanded(
Expand Down Expand Up @@ -152,9 +150,9 @@ class _OnboardingScreenState extends State<OnboardingScreen>
}

void _onNextPageButtonClicked() {
formKeys[_currentPageIndex].currentState!.save();
if (_currentPageIndex < _numberOfPages - 1) {
_updateCurrentPageIndex(_currentPageIndex + 1);
formKeys[_tabController.index].currentState!.save();
if (_tabController.index < _numberOfPages - 1) {
_updateCurrentPageIndex(_tabController.index + 1);
} else {
context.go('/home');
}
Expand All @@ -163,7 +161,7 @@ class _OnboardingScreenState extends State<OnboardingScreen>
void _handlePageViewChanged(int currentPageIndex) {
_tabController.index = currentPageIndex;
setState(() {
_currentPageIndex = currentPageIndex;
_tabController.index = currentPageIndex;
});
}

Expand All @@ -181,11 +179,9 @@ class PageIndicator extends StatelessWidget {
const PageIndicator({
super.key,
required this.tabController,
required this.currentPageIndex,
required this.onUpdateCurrentPageIndex,
});

final int currentPageIndex;
final TabController tabController;
final void Function(int) onUpdateCurrentPageIndex;

Expand All @@ -203,10 +199,10 @@ class PageIndicator extends StatelessWidget {
child: IconButton(
padding: EdgeInsets.zero,
onPressed: () {
if (currentPageIndex == 0) {
if (tabController.index == 0) {
return;
}
onUpdateCurrentPageIndex(currentPageIndex - 1);
onUpdateCurrentPageIndex(tabController.index - 1);
},
icon: const Icon(
Icons.arrow_left_rounded,
Expand Down
39 changes: 39 additions & 0 deletions lib/presentation/schedule_create/compoenent/top_bar.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';

class TopBar extends StatelessWidget {
const TopBar(
{super.key,
required this.tabController,
required this.onNextPAgeButtonClicked,
required this.onPreviousPageButtonClicked});

final TabController tabController;
final void Function() onNextPAgeButtonClicked;
final void Function() onPreviousPageButtonClicked;

@override
Widget build(BuildContext context) {
return Row(
children: [
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
onPreviousPageButtonClicked();
},
),
Expanded(
child: Center(
child: Text('약속 추가하기',
style: Theme.of(context).textTheme.titleMedium)),
),
TextButton(
child: const Text('다음'),
onPressed: () {
// Save the schedule
onNextPAgeButtonClicked();
},
),
],
);
}
}
166 changes: 166 additions & 0 deletions lib/presentation/schedule_create/screens/schedule_create_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:on_time_front/presentation/schedule_create/compoenent/top_bar.dart';
import 'package:on_time_front/presentation/schedule_create/screens/schedule_name_form.dart';
import 'package:on_time_front/presentation/schedule_create/screens/schedule_place_moving_time_form.dart';
import 'package:on_time_front/presentation/schedule_create/screens/schedule_spare_and_preparing_time_form.dart';
import 'package:on_time_front/presentation/schedule_create/screens/schedule_time_form.dart';
import 'package:on_time_front/presentation/shared/components/progress_bar.dart';

class ScheduleCreateScreen extends StatefulWidget {
const ScheduleCreateScreen({super.key});

@override
State<ScheduleCreateScreen> createState() => _ScheduleCreateScreenState();
}

class _ScheduleCreateScreenState extends State<ScheduleCreateScreen>
with TickerProviderStateMixin {
late PageController _pageViewController;
late TabController _tabController;
late List<GlobalKey<FormState>> formKeys;
ScheduleFormData _scheduleFormData = ScheduleFormData();

@override
void initState() {
_pageViewController = PageController();
_tabController = TabController(length: 4, vsync: this);
formKeys =
List.generate(_tabController.length, (index) => GlobalKey<FormState>());
super.initState();
}

@override
Widget build(BuildContext context) {
return Material(
child: SafeArea(
child: Column(
children: [
TopBar(
tabController: _tabController,
onNextPAgeButtonClicked: _onNextPageButtonClicked,
onPreviousPageButtonClicked: _onPreviousPageButtonClicked,
),
ProgressBar(
tabController: _tabController,
),
Expanded(
child: PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _pageViewController,
onPageChanged: _handlePageViewChanged,
children: [
ScheduleNameForm(
formKey: formKeys[0],
initalValue: _scheduleFormData,
onSaved: (value) {
_scheduleFormData = value;
}),
ScheduleTimeForm(
formKey: formKeys[1],
initalValue: _scheduleFormData,
onSaved: (value) {
_scheduleFormData = value;
}),
SchedulePlaceMovingTimeForm(
formKey: formKeys[2],
initalValue: _scheduleFormData,
onSaved: (value) {
_scheduleFormData = value;
}),
ScheduleSpareAndPreparingTimeForm(
formKey: formKeys[3],
initalValue: _scheduleFormData,
onSaved: (value) {
_scheduleFormData = value;
}),
],
),
),
],
),
),
);
}

void _onNextPageButtonClicked() {
formKeys[_tabController.index].currentState?.save();
if (_tabController.index < _tabController.length - 1) {
_updateCurrentPageIndex(_tabController.index + 1);
} else {
context.go('/home');
}
}

void _onPreviousPageButtonClicked() {
if (_tabController.index > 0) {
_updateCurrentPageIndex(_tabController.index - 1);
}
}

void _handlePageViewChanged(int currentPageIndex) {
_tabController.index = currentPageIndex;
setState(() {
_tabController.index = currentPageIndex;
});
}

void _updateCurrentPageIndex(int index) {
_tabController.index = index;
_pageViewController.animateToPage(
index,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
);
}
}

class ScheduleFormData {
final String? id;
final String? placeName;
final String? scheduleName;
final DateTime? scheduleTime;
final Duration? moveTime;
final bool? isChanged;
final Duration? scheduleSpareTime;
final String? scheduleNote;
final Duration? spareTime;

ScheduleFormData({
this.id,
this.placeName,
this.scheduleName,
this.scheduleTime,
this.moveTime,
this.isChanged,
this.scheduleSpareTime,
this.scheduleNote,
this.spareTime,
});

ScheduleFormData copyWith({
String? id,
String? userId,
String? placeName,
String? scheduleName,
DateTime? scheduleTime,
Duration? moveTime,
bool? isChanged,
bool? isStarted,
Duration? scheduleSpareTime,
String? scheduleNote,
Duration? spareTime,
}) {
return ScheduleFormData(
id: id ?? this.id,
placeName: placeName ?? this.placeName,
scheduleName: scheduleName ?? this.scheduleName,
scheduleTime: scheduleTime ?? this.scheduleTime,
moveTime: moveTime ?? this.moveTime,
isChanged: isChanged ?? this.isChanged,
scheduleSpareTime: scheduleSpareTime ?? this.scheduleSpareTime,
scheduleNote: scheduleNote ?? this.scheduleNote,
spareTime: spareTime ?? this.spareTime,
);
}
}
41 changes: 41 additions & 0 deletions lib/presentation/schedule_create/screens/schedule_name_form.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:on_time_front/presentation/onboarding/mutly_page_form.dart';
import 'package:on_time_front/presentation/schedule_create/screens/schedule_create_screen.dart';

class ScheduleNameForm extends StatefulWidget {
const ScheduleNameForm(
{super.key,
required this.formKey,
required this.initalValue,
this.onSaved});

final GlobalKey<FormState> formKey;
final ScheduleFormData initalValue;
final Function(ScheduleFormData)? onSaved;

@override
State<ScheduleNameForm> createState() => _ScheduleNameFormState();
}

class _ScheduleNameFormState extends State<ScheduleNameForm> {
ScheduleFormData _scheduleFormData = ScheduleFormData();

@override
Widget build(BuildContext context) {
return MultiPageFormField(
key: widget.formKey,
onSaved: () {
widget.onSaved?.call(_scheduleFormData);
},
child: TextFormField(
initialValue: widget.initalValue.scheduleName,
decoration: InputDecoration(labelText: '약속 이름'),
textInputAction: TextInputAction.done,
onSaved: (newValue) {
_scheduleFormData =
_scheduleFormData.copyWith(scheduleName: newValue!);
},
),
);
}
}
Loading

0 comments on commit 6b7f96b

Please sign in to comment.