From 16226ea11cb32584c8990698d26e8e34444fd986 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Mon, 10 Jul 2023 22:42:55 -0400 Subject: [PATCH 01/35] Refactor major folder structure --- lib/main.dart | 12 ++++----- ...r_view_model.dart => user_view.model.dart} | 0 .../signin.page.dart} | 2 +- ...orrower_model.dart => borrower.model.dart} | 0 ...wers_view_model.dart => borrowers.vm.dart} | 2 +- .../borrowers/data/borrowers_mapper.dart | 2 +- .../borrower_details.widget.dart} | 4 +-- .../borrower_issues.widget.dart} | 6 ++--- .../borrower_search_delegate.widget.dart} | 6 ++--- ...s_list.dart => borrowers_list.widget.dart} | 2 +- .../borrowers_view.widget.dart} | 6 ++--- .../connected_borrowers_list.widget.dart} | 6 ++--- .../borrower_details_pane.widget.dart} | 6 ++--- .../borrowers_desktop_layout.widget.dart} | 6 ++--- .../borrowers_list_pane.widget.dart} | 8 +++--- ...es_dialog.dart => dues_dialog.widget.dart} | 2 +- ....dart => needs_attention_view.widget.dart} | 2 +- ...dart => record_payment_dialog.widget.dart} | 0 .../searchable_borrowers_list.widget.dart} | 6 ++--- ...ne_header.dart => pane_header.widget.dart} | 0 ...tion.dart => input_decoration.widget.dart} | 0 ...ch_field.dart => search_field.widget.dart} | 0 ...eld.dart => submit_text_field.widget.dart} | 0 .../dashboard.page.dart} | 26 +++++++++---------- .../desktop_dashboard.widget.dart} | 0 ...g_model.dart => detailed_thing.model.dart} | 0 ...ry_repository.dart => inventory.repo.dart} | 4 +-- ...tory_view_model.dart => inventory.vm.dart} | 6 ++--- .../{thing_model.dart => thing.model.dart} | 0 .../inventory_details.page.dart} | 4 +-- ....dart => add_inventory_dialog.widget.dart} | 2 +- ...g.dart => create_thing_dialog.widget.dart} | 2 +- .../inventory_desktop_layout.widget.dart} | 10 +++---- .../inventory_details_pane.widget.dart} | 10 +++---- ...r.dart => details_card_header.widget.dart} | 0 ...ils.dart => inventory_details.widget.dart} | 8 +++--- .../inventory_details_view.widget.dart} | 4 +-- ...y_list.dart => inventory_list.widget.dart} | 2 +- .../inventory_view.widget.dart} | 6 ++--- .../searchable_inventory_list.widget.dart} | 6 ++--- .../data/{loan_model.dart => loan.model.dart} | 4 +-- .../{loans_view_model.dart => loans.vm.dart} | 2 +- lib/src/features/loans/data/loans_mapper.dart | 6 ++--- .../{thing_model.dart => thing.model.dart} | 0 ...{things_view_model.dart => things.vm.dart} | 2 +- .../checkout.page.dart} | 2 +- .../loan_details.page.dart} | 6 ++--- .../open_loan.page.dart} | 14 +++++----- ...dialog.dart => checkin_dialog.widget.dart} | 0 .../checkout/checkout_controller.dart | 2 +- .../checkout/checkout_stepper.widget.dart} | 16 ++++++------ .../connected_thing_search_field.widget.dart} | 4 +-- .../connected_loans_list.widget.dart} | 6 ++--- .../dashboard/loan_details_pane.widget.dart} | 10 +++---- .../loans_desktop_layout.widget.dart} | 10 +++---- ..._details.dart => loan_details.widget.dart} | 4 +-- ...loans_list.dart => loans_list.widget.dart} | 2 +- .../loans_view.widget.dart} | 6 ++--- .../pick_things.widget.dart} | 8 +++--- .../searchable_loans_list.widget.dart} | 6 ++--- ..._tile.dart => thing_list_tile.widget.dart} | 0 ...g_number.dart => thing_number.widget.dart} | 0 .../things_list.widget.dart} | 6 ++--- .../splash.page.dart} | 4 +-- 64 files changed, 144 insertions(+), 144 deletions(-) rename lib/src/features/authentication/data/{user_view_model.dart => user_view.model.dart} (100%) rename lib/src/features/authentication/{views/signin_page.dart => pages/signin.page.dart} (96%) rename lib/src/features/borrowers/data/{borrower_model.dart => borrower.model.dart} (100%) rename lib/src/features/borrowers/data/{borrowers_view_model.dart => borrowers.vm.dart} (98%) rename lib/src/features/borrowers/{views/borrower_details.dart => widgets/borrower_details.widget.dart} (95%) rename lib/src/features/borrowers/{views/borrower_issues.dart => widgets/borrower_issues.widget.dart} (94%) rename lib/src/features/borrowers/{views/borrower_search_delegate.dart => widgets/borrower_search_delegate.widget.dart} (90%) rename lib/src/features/borrowers/widgets/{borrowers_list.dart => borrowers_list.widget.dart} (96%) rename lib/src/features/borrowers/{views/borrowers_view.dart => widgets/borrowers_view.widget.dart} (90%) rename lib/src/features/borrowers/{views/connected_borrowers_list.dart => widgets/connected_borrowers_list.widget.dart} (81%) rename lib/src/features/borrowers/{views/dashboard/borrower_details_pane.dart => widgets/dashboard/borrower_details_pane.widget.dart} (88%) rename lib/src/features/borrowers/{views/dashboard/borrowers_desktop_layout.dart => widgets/dashboard/borrowers_desktop_layout.widget.dart} (74%) rename lib/src/features/borrowers/{views/dashboard/borrowers_list_pane.dart => widgets/dashboard/borrowers_list_pane.widget.dart} (92%) rename lib/src/features/borrowers/widgets/{dues_dialog.dart => dues_dialog.widget.dart} (97%) rename lib/src/features/borrowers/widgets/{needs_attention_view.dart => needs_attention_view.widget.dart} (98%) rename lib/src/features/borrowers/widgets/{record_payment_dialog.dart => record_payment_dialog.widget.dart} (100%) rename lib/src/features/borrowers/{views/searchable_borrowers_list.dart => widgets/searchable_borrowers_list.widget.dart} (88%) rename lib/src/features/common/widgets/dashboard/{pane_header.dart => pane_header.widget.dart} (100%) rename lib/src/features/common/widgets/{input_decoration.dart => input_decoration.widget.dart} (100%) rename lib/src/features/common/widgets/{search_field.dart => search_field.widget.dart} (100%) rename lib/src/features/common/widgets/{submit_text_field.dart => submit_text_field.widget.dart} (100%) rename lib/src/features/dashboard/{views/dashboard_page.dart => pages/dashboard.page.dart} (85%) rename lib/src/features/dashboard/{views/desktop_dashboard.dart => widgets/desktop_dashboard.widget.dart} (100%) rename lib/src/features/inventory/data/{detailed_thing_model.dart => detailed_thing.model.dart} (100%) rename lib/src/features/inventory/data/{inventory_repository.dart => inventory.repo.dart} (95%) rename lib/src/features/inventory/data/{inventory_view_model.dart => inventory.vm.dart} (96%) rename lib/src/features/inventory/data/{thing_model.dart => thing.model.dart} (100%) rename lib/src/features/inventory/{views/inventory_details_page.dart => pages/inventory_details.page.dart} (94%) rename lib/src/features/inventory/widgets/{add_inventory_dialog.dart => add_inventory_dialog.widget.dart} (99%) rename lib/src/features/inventory/widgets/{create_thing_dialog.dart => create_thing_dialog.widget.dart} (99%) rename lib/src/features/inventory/{views/dashboard/inventory_desktop_layout.dart => widgets/dashboard/inventory_desktop_layout.widget.dart} (88%) rename lib/src/features/inventory/{views/dashboard/inventory_details_pane.dart => widgets/dashboard/inventory_details_pane.widget.dart} (97%) rename lib/src/features/inventory/widgets/{details_card_header.dart => details_card_header.widget.dart} (100%) rename lib/src/features/inventory/widgets/{inventory_details.dart => inventory_details.widget.dart} (97%) rename lib/src/features/inventory/{views/inventory_details_view.dart => widgets/inventory_details_view.widget.dart} (97%) rename lib/src/features/inventory/widgets/{inventory_list.dart => inventory_list.widget.dart} (95%) rename lib/src/features/inventory/{views/inventory_view.dart => widgets/inventory_view.widget.dart} (87%) rename lib/src/features/inventory/{views/searchable_inventory_list.dart => widgets/searchable_inventory_list.widget.dart} (87%) rename lib/src/features/loans/data/{loan_model.dart => loan.model.dart} (93%) rename lib/src/features/loans/data/{loans_view_model.dart => loans.vm.dart} (99%) rename lib/src/features/loans/data/{thing_model.dart => thing.model.dart} (100%) rename lib/src/features/loans/data/{things_view_model.dart => things.vm.dart} (95%) rename lib/src/features/loans/{views/checkout/checkout_page.dart => pages/checkout.page.dart} (81%) rename lib/src/features/loans/{views/loan_details_page.dart => pages/loan_details.page.dart} (96%) rename lib/src/features/loans/{views/open_loan_page.dart => pages/open_loan.page.dart} (91%) rename lib/src/features/loans/widgets/{checkin_dialog.dart => checkin_dialog.widget.dart} (100%) rename lib/src/features/loans/{views => widgets}/checkout/checkout_controller.dart (89%) rename lib/src/features/loans/{views/checkout/checkout_stepper.dart => widgets/checkout/checkout_stepper.widget.dart} (92%) rename lib/src/features/loans/{views/checkout/connected_thing_search_field.dart => widgets/checkout/connected_thing_search_field.widget.dart} (94%) rename lib/src/features/loans/{views/connected_loans_list.dart => widgets/connected_loans_list.widget.dart} (79%) rename lib/src/features/loans/{views/dashboard/loan_details_pane.dart => widgets/dashboard/loan_details_pane.widget.dart} (95%) rename lib/src/features/loans/{views/dashboard/loans_desktop_layout.dart => widgets/dashboard/loans_desktop_layout.widget.dart} (90%) rename lib/src/features/loans/widgets/{loan_details.dart => loan_details.widget.dart} (97%) rename lib/src/features/loans/widgets/{loans_list.dart => loans_list.widget.dart} (98%) rename lib/src/features/loans/{views/loans_view.dart => widgets/loans_view.widget.dart} (88%) rename lib/src/features/loans/{views/pick_things_view.dart => widgets/pick_things.widget.dart} (94%) rename lib/src/features/loans/{views/searchable_loans_list.dart => widgets/searchable_loans_list.widget.dart} (87%) rename lib/src/features/loans/widgets/{thing_list_tile.dart => thing_list_tile.widget.dart} (100%) rename lib/src/features/loans/widgets/{thing_number.dart => thing_number.widget.dart} (100%) rename lib/src/features/loans/{views/things_list_view.dart => widgets/things_list.widget.dart} (92%) rename lib/src/features/splash/{views/splash_page.dart => pages/splash.page.dart} (88%) diff --git a/lib/main.dart b/lib/main.dart index c4e7108..1f18728 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/constants.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers_view_model.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory_view_model.dart'; -import 'package:librarian_app/src/features/loans/data/loans_view_model.dart'; -import 'package:librarian_app/src/features/authentication/data/user_view_model.dart'; -import 'package:librarian_app/src/features/splash/views/splash_page.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; +import 'package:librarian_app/src/features/authentication/data/user_view.model.dart'; +import 'package:librarian_app/src/features/splash/pages/splash.page.dart'; import 'package:provider/provider.dart'; import 'package:supabase_flutter/supabase_flutter.dart' as supabase; -import 'src/features/loans/data/things_view_model.dart'; +import 'src/features/loans/data/things.vm.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/src/features/authentication/data/user_view_model.dart b/lib/src/features/authentication/data/user_view.model.dart similarity index 100% rename from lib/src/features/authentication/data/user_view_model.dart rename to lib/src/features/authentication/data/user_view.model.dart diff --git a/lib/src/features/authentication/views/signin_page.dart b/lib/src/features/authentication/pages/signin.page.dart similarity index 96% rename from lib/src/features/authentication/views/signin_page.dart rename to lib/src/features/authentication/pages/signin.page.dart index e61f636..9e69bad 100644 --- a/lib/src/features/authentication/views/signin_page.dart +++ b/lib/src/features/authentication/pages/signin.page.dart @@ -1,6 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/dashboard/views/dashboard_page.dart'; +import 'package:librarian_app/src/features/dashboard/pages/dashboard.page.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; class SignInPage extends StatefulWidget { diff --git a/lib/src/features/borrowers/data/borrower_model.dart b/lib/src/features/borrowers/data/borrower.model.dart similarity index 100% rename from lib/src/features/borrowers/data/borrower_model.dart rename to lib/src/features/borrowers/data/borrower.model.dart diff --git a/lib/src/features/borrowers/data/borrowers_view_model.dart b/lib/src/features/borrowers/data/borrowers.vm.dart similarity index 98% rename from lib/src/features/borrowers/data/borrowers_view_model.dart rename to lib/src/features/borrowers/data/borrowers.vm.dart index ba67fad..dc3dc87 100644 --- a/lib/src/features/borrowers/data/borrowers_view_model.dart +++ b/lib/src/features/borrowers/data/borrowers.vm.dart @@ -2,7 +2,7 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/data/lending_api.dart'; -import 'borrower_model.dart'; +import 'borrower.model.dart'; import 'borrowers_mapper.dart'; class BorrowersViewModel extends ChangeNotifier { diff --git a/lib/src/features/borrowers/data/borrowers_mapper.dart b/lib/src/features/borrowers/data/borrowers_mapper.dart index 6b83656..48b99bf 100644 --- a/lib/src/features/borrowers/data/borrowers_mapper.dart +++ b/lib/src/features/borrowers/data/borrowers_mapper.dart @@ -1,4 +1,4 @@ -import 'borrower_model.dart'; +import 'borrower.model.dart'; class BorrowersMapper { static Iterable map(Iterable data) { diff --git a/lib/src/features/borrowers/views/borrower_details.dart b/lib/src/features/borrowers/widgets/borrower_details.widget.dart similarity index 95% rename from lib/src/features/borrowers/views/borrower_details.dart rename to lib/src/features/borrowers/widgets/borrower_details.widget.dart index 74b516e..3e35dad 100644 --- a/lib/src/features/borrowers/views/borrower_details.dart +++ b/lib/src/features/borrowers/widgets/borrower_details.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/views/borrower_issues.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_issues.widget.dart'; -import '../data/borrower_model.dart'; +import '../data/borrower.model.dart'; class BorrowerDetails extends StatefulWidget { final BorrowerModel borrower; diff --git a/lib/src/features/borrowers/views/borrower_issues.dart b/lib/src/features/borrowers/widgets/borrower_issues.widget.dart similarity index 94% rename from lib/src/features/borrowers/views/borrower_issues.dart rename to lib/src/features/borrowers/widgets/borrower_issues.widget.dart index 524dada..3847ccd 100644 --- a/lib/src/features/borrowers/views/borrower_issues.dart +++ b/lib/src/features/borrowers/widgets/borrower_issues.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../data/borrower_model.dart'; -import '../data/borrowers_view_model.dart'; -import '../widgets/dues_dialog.dart'; +import '../data/borrower.model.dart'; +import '../data/borrowers.vm.dart'; +import '../widgets/dues_dialog.widget.dart'; class BorrowerIssues extends StatelessWidget { final String borrowerId; diff --git a/lib/src/features/borrowers/views/borrower_search_delegate.dart b/lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart similarity index 90% rename from lib/src/features/borrowers/views/borrower_search_delegate.dart rename to lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart index b210e68..5de69c5 100644 --- a/lib/src/features/borrowers/views/borrower_search_delegate.dart +++ b/lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import '../data/borrower_model.dart'; -import '../data/borrowers_view_model.dart'; -import 'borrowers_view.dart'; +import '../data/borrower.model.dart'; +import '../data/borrowers.vm.dart'; +import 'borrowers_view.widget.dart'; class BorrowerSearchDelegate extends SearchDelegate { BorrowerSearchDelegate({required this.model}); diff --git a/lib/src/features/borrowers/widgets/borrowers_list.dart b/lib/src/features/borrowers/widgets/borrowers_list.widget.dart similarity index 96% rename from lib/src/features/borrowers/widgets/borrowers_list.dart rename to lib/src/features/borrowers/widgets/borrowers_list.widget.dart index b7b3551..0c3d26f 100644 --- a/lib/src/features/borrowers/widgets/borrowers_list.dart +++ b/lib/src/features/borrowers/widgets/borrowers_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/borrower_model.dart'; +import '../data/borrower.model.dart'; class BorrowersList extends StatefulWidget { final List borrowers; diff --git a/lib/src/features/borrowers/views/borrowers_view.dart b/lib/src/features/borrowers/widgets/borrowers_view.widget.dart similarity index 90% rename from lib/src/features/borrowers/views/borrowers_view.dart rename to lib/src/features/borrowers/widgets/borrowers_view.widget.dart index dc3d2a0..8952e5c 100644 --- a/lib/src/features/borrowers/views/borrowers_view.dart +++ b/lib/src/features/borrowers/widgets/borrowers_view.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers_view_model.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; -import '../data/borrower_model.dart'; -import '../widgets/borrowers_list.dart'; +import '../data/borrower.model.dart'; +import '../widgets/borrowers_list.widget.dart'; class BorrowersView extends StatelessWidget { const BorrowersView({ diff --git a/lib/src/features/borrowers/views/connected_borrowers_list.dart b/lib/src/features/borrowers/widgets/connected_borrowers_list.widget.dart similarity index 81% rename from lib/src/features/borrowers/views/connected_borrowers_list.dart rename to lib/src/features/borrowers/widgets/connected_borrowers_list.widget.dart index ace87bd..af35bb4 100644 --- a/lib/src/features/borrowers/views/connected_borrowers_list.dart +++ b/lib/src/features/borrowers/widgets/connected_borrowers_list.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers_view_model.dart'; -import 'package:librarian_app/src/features/borrowers/views/borrowers_view.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrowers_view.widget.dart'; import 'package:provider/provider.dart'; -import '../data/borrower_model.dart'; +import '../data/borrower.model.dart'; class ConnectedBorrowersList extends StatelessWidget { final void Function(BorrowerModel)? onTap; diff --git a/lib/src/features/borrowers/views/dashboard/borrower_details_pane.dart b/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart similarity index 88% rename from lib/src/features/borrowers/views/dashboard/borrower_details_pane.dart rename to lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart index bfe8661..b24ceb1 100644 --- a/lib/src/features/borrowers/views/dashboard/borrower_details_pane.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/views/borrower_details.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_details.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; -import '../../data/borrower_model.dart'; +import '../../data/borrower.model.dart'; class BorrowerDetailsPane extends StatelessWidget { final BorrowerModel? borrower; diff --git a/lib/src/features/borrowers/views/dashboard/borrowers_desktop_layout.dart b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart similarity index 74% rename from lib/src/features/borrowers/views/dashboard/borrowers_desktop_layout.dart rename to lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart index 4ded468..3989d71 100644 --- a/lib/src/features/borrowers/views/dashboard/borrowers_desktop_layout.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers_view_model.dart'; -import 'package:librarian_app/src/features/borrowers/views/dashboard/borrower_details_pane.dart'; -import 'package:librarian_app/src/features/borrowers/views/dashboard/borrowers_list_pane.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart'; import 'package:provider/provider.dart'; class BorrowersDesktopLayout extends StatelessWidget { diff --git a/lib/src/features/borrowers/views/dashboard/borrowers_list_pane.dart b/lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart similarity index 92% rename from lib/src/features/borrowers/views/dashboard/borrowers_list_pane.dart rename to lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart index 363883b..242afd4 100644 --- a/lib/src/features/borrowers/views/dashboard/borrowers_list_pane.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers_view_model.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.dart'; -import 'package:librarian_app/src/features/common/widgets/search_field.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; -import '../borrowers_view.dart'; +import '../borrowers_view.widget.dart'; class BorrowersListPane extends StatefulWidget { const BorrowersListPane({super.key, required this.model}); diff --git a/lib/src/features/borrowers/widgets/dues_dialog.dart b/lib/src/features/borrowers/widgets/dues_dialog.widget.dart similarity index 97% rename from lib/src/features/borrowers/widgets/dues_dialog.dart rename to lib/src/features/borrowers/widgets/dues_dialog.widget.dart index a51eb47..651cf7d 100644 --- a/lib/src/features/borrowers/widgets/dues_dialog.dart +++ b/lib/src/features/borrowers/widgets/dues_dialog.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'record_payment_dialog.dart'; +import 'record_payment_dialog.widget.dart'; class DuesNotPaidDialog extends StatefulWidget { final String instructions; diff --git a/lib/src/features/borrowers/widgets/needs_attention_view.dart b/lib/src/features/borrowers/widgets/needs_attention_view.widget.dart similarity index 98% rename from lib/src/features/borrowers/widgets/needs_attention_view.dart rename to lib/src/features/borrowers/widgets/needs_attention_view.widget.dart index f4eaa0c..80cf580 100644 --- a/lib/src/features/borrowers/widgets/needs_attention_view.dart +++ b/lib/src/features/borrowers/widgets/needs_attention_view.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrower_model.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; class NeedsAttentionView extends StatelessWidget { final BorrowerModel borrower; diff --git a/lib/src/features/borrowers/widgets/record_payment_dialog.dart b/lib/src/features/borrowers/widgets/record_payment_dialog.widget.dart similarity index 100% rename from lib/src/features/borrowers/widgets/record_payment_dialog.dart rename to lib/src/features/borrowers/widgets/record_payment_dialog.widget.dart diff --git a/lib/src/features/borrowers/views/searchable_borrowers_list.dart b/lib/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart similarity index 88% rename from lib/src/features/borrowers/views/searchable_borrowers_list.dart rename to lib/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart index 8578392..09ec9aa 100644 --- a/lib/src/features/borrowers/views/searchable_borrowers_list.dart +++ b/lib/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrower_model.dart'; -import 'package:librarian_app/src/features/borrowers/views/connected_borrowers_list.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/connected_borrowers_list.widget.dart'; -import '../../common/widgets/submit_text_field.dart'; +import '../../common/widgets/submit_text_field.widget.dart'; class SearchableBorrowersList extends StatefulWidget { final void Function(BorrowerModel borrower)? onTapBorrower; diff --git a/lib/src/features/common/widgets/dashboard/pane_header.dart b/lib/src/features/common/widgets/dashboard/pane_header.widget.dart similarity index 100% rename from lib/src/features/common/widgets/dashboard/pane_header.dart rename to lib/src/features/common/widgets/dashboard/pane_header.widget.dart diff --git a/lib/src/features/common/widgets/input_decoration.dart b/lib/src/features/common/widgets/input_decoration.widget.dart similarity index 100% rename from lib/src/features/common/widgets/input_decoration.dart rename to lib/src/features/common/widgets/input_decoration.widget.dart diff --git a/lib/src/features/common/widgets/search_field.dart b/lib/src/features/common/widgets/search_field.widget.dart similarity index 100% rename from lib/src/features/common/widgets/search_field.dart rename to lib/src/features/common/widgets/search_field.widget.dart diff --git a/lib/src/features/common/widgets/submit_text_field.dart b/lib/src/features/common/widgets/submit_text_field.widget.dart similarity index 100% rename from lib/src/features/common/widgets/submit_text_field.dart rename to lib/src/features/common/widgets/submit_text_field.widget.dart diff --git a/lib/src/features/dashboard/views/dashboard_page.dart b/lib/src/features/dashboard/pages/dashboard.page.dart similarity index 85% rename from lib/src/features/dashboard/views/dashboard_page.dart rename to lib/src/features/dashboard/pages/dashboard.page.dart index 589949f..8c15ae2 100644 --- a/lib/src/features/dashboard/views/dashboard_page.dart +++ b/lib/src/features/dashboard/pages/dashboard.page.dart @@ -1,20 +1,20 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/views/dashboard/borrowers_desktop_layout.dart'; -import 'package:librarian_app/src/features/borrowers/views/searchable_borrowers_list.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory_view_model.dart'; -import 'package:librarian_app/src/features/inventory/views/dashboard/inventory_desktop_layout.dart'; -import 'package:librarian_app/src/features/inventory/views/inventory_details_page.dart'; -import 'package:librarian_app/src/features/inventory/views/searchable_inventory_list.dart'; -import 'package:librarian_app/src/features/inventory/widgets/create_thing_dialog.dart'; -import 'package:librarian_app/src/features/loans/views/checkout/checkout_page.dart'; -import 'package:librarian_app/src/features/loans/views/loan_details_page.dart'; -import 'package:librarian_app/src/features/loans/views/searchable_loans_list.dart'; -import 'package:librarian_app/src/features/loans/views/dashboard/loans_desktop_layout.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; +import 'package:librarian_app/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart'; +import 'package:librarian_app/src/features/inventory/pages/inventory_details.page.dart'; +import 'package:librarian_app/src/features/inventory/widgets/searchable_inventory_list.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/create_thing_dialog.widget.dart'; +import 'package:librarian_app/src/features/loans/pages/checkout.page.dart'; +import 'package:librarian_app/src/features/loans/pages/loan_details.page.dart'; +import 'package:librarian_app/src/features/loans/widgets/searchable_loans_list.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart'; import 'package:librarian_app/src/utils/media_query.dart'; import 'package:provider/provider.dart'; -import 'desktop_dashboard.dart'; +import '../widgets/desktop_dashboard.widget.dart'; class DashboardPage extends StatefulWidget { const DashboardPage({super.key}); diff --git a/lib/src/features/dashboard/views/desktop_dashboard.dart b/lib/src/features/dashboard/widgets/desktop_dashboard.widget.dart similarity index 100% rename from lib/src/features/dashboard/views/desktop_dashboard.dart rename to lib/src/features/dashboard/widgets/desktop_dashboard.widget.dart diff --git a/lib/src/features/inventory/data/detailed_thing_model.dart b/lib/src/features/inventory/data/detailed_thing.model.dart similarity index 100% rename from lib/src/features/inventory/data/detailed_thing_model.dart rename to lib/src/features/inventory/data/detailed_thing.model.dart diff --git a/lib/src/features/inventory/data/inventory_repository.dart b/lib/src/features/inventory/data/inventory.repo.dart similarity index 95% rename from lib/src/features/inventory/data/inventory_repository.dart rename to lib/src/features/inventory/data/inventory.repo.dart index 71f5990..98e6211 100644 --- a/lib/src/features/inventory/data/inventory_repository.dart +++ b/lib/src/features/inventory/data/inventory.repo.dart @@ -1,7 +1,7 @@ import 'package:librarian_app/src/features/common/data/lending_api.dart'; -import 'detailed_thing_model.dart'; -import 'thing_model.dart'; +import 'detailed_thing.model.dart'; +import 'thing.model.dart'; class InventoryRepository { List things = []; diff --git a/lib/src/features/inventory/data/inventory_view_model.dart b/lib/src/features/inventory/data/inventory.vm.dart similarity index 96% rename from lib/src/features/inventory/data/inventory_view_model.dart rename to lib/src/features/inventory/data/inventory.vm.dart index 4662026..adf97d9 100644 --- a/lib/src/features/inventory/data/inventory_view_model.dart +++ b/lib/src/features/inventory/data/inventory.vm.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/inventory/data/detailed_thing_model.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory_repository.dart'; +import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.repo.dart'; -import 'thing_model.dart'; +import 'thing.model.dart'; class InventoryViewModel extends ChangeNotifier { InventoryViewModel() { diff --git a/lib/src/features/inventory/data/thing_model.dart b/lib/src/features/inventory/data/thing.model.dart similarity index 100% rename from lib/src/features/inventory/data/thing_model.dart rename to lib/src/features/inventory/data/thing.model.dart diff --git a/lib/src/features/inventory/views/inventory_details_page.dart b/lib/src/features/inventory/pages/inventory_details.page.dart similarity index 94% rename from lib/src/features/inventory/views/inventory_details_page.dart rename to lib/src/features/inventory/pages/inventory_details.page.dart index 861b2ff..08513cd 100644 --- a/lib/src/features/inventory/views/inventory_details_page.dart +++ b/lib/src/features/inventory/pages/inventory_details.page.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../data/inventory_view_model.dart'; -import 'inventory_details_view.dart'; +import '../data/inventory.vm.dart'; +import '../widgets/inventory_details_view.widget.dart'; class InventoryDetailsPage extends StatelessWidget { const InventoryDetailsPage({super.key}); diff --git a/lib/src/features/inventory/widgets/add_inventory_dialog.dart b/lib/src/features/inventory/widgets/add_inventory_dialog.widget.dart similarity index 99% rename from lib/src/features/inventory/widgets/add_inventory_dialog.dart rename to lib/src/features/inventory/widgets/add_inventory_dialog.widget.dart index 985902f..4294655 100644 --- a/lib/src/features/inventory/widgets/add_inventory_dialog.dart +++ b/lib/src/features/inventory/widgets/add_inventory_dialog.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/input_decoration.dart'; +import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; class AddInventoryDialog extends StatelessWidget { AddInventoryDialog({super.key, this.onCreate}); diff --git a/lib/src/features/inventory/widgets/create_thing_dialog.dart b/lib/src/features/inventory/widgets/create_thing_dialog.widget.dart similarity index 99% rename from lib/src/features/inventory/widgets/create_thing_dialog.dart rename to lib/src/features/inventory/widgets/create_thing_dialog.widget.dart index dc08b21..115263e 100644 --- a/lib/src/features/inventory/widgets/create_thing_dialog.dart +++ b/lib/src/features/inventory/widgets/create_thing_dialog.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/input_decoration.dart'; +import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; class CreateThingDialog extends StatelessWidget { CreateThingDialog({super.key, this.onCreate}); diff --git a/lib/src/features/inventory/views/dashboard/inventory_desktop_layout.dart b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart similarity index 88% rename from lib/src/features/inventory/views/dashboard/inventory_desktop_layout.dart rename to lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart index 5db854d..6f0d31f 100644 --- a/lib/src/features/inventory/views/dashboard/inventory_desktop_layout.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.dart'; -import 'package:librarian_app/src/features/common/widgets/search_field.dart'; -import 'package:librarian_app/src/features/inventory/views/dashboard/inventory_details_pane.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart'; import 'package:provider/provider.dart'; -import '../../data/inventory_view_model.dart'; -import '../inventory_view.dart'; +import '../../data/inventory.vm.dart'; +import '../inventory_view.widget.dart'; class InventoryDesktopLayout extends StatefulWidget { const InventoryDesktopLayout({super.key}); diff --git a/lib/src/features/inventory/views/dashboard/inventory_details_pane.dart b/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart similarity index 97% rename from lib/src/features/inventory/views/dashboard/inventory_details_pane.dart rename to lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart index 0f4445c..53e5a0f 100644 --- a/lib/src/features/inventory/views/dashboard/inventory_details_pane.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.dart'; -import 'package:librarian_app/src/features/inventory/data/detailed_thing_model.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory_view_model.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; -import '../../data/thing_model.dart'; -import '../../widgets/inventory_details.dart'; +import '../../data/thing.model.dart'; +import '../../widgets/inventory_details.widget.dart'; class InventoryDetailsPane extends StatefulWidget { final ThingModel? thing; diff --git a/lib/src/features/inventory/widgets/details_card_header.dart b/lib/src/features/inventory/widgets/details_card_header.widget.dart similarity index 100% rename from lib/src/features/inventory/widgets/details_card_header.dart rename to lib/src/features/inventory/widgets/details_card_header.widget.dart diff --git a/lib/src/features/inventory/widgets/inventory_details.dart b/lib/src/features/inventory/widgets/inventory_details.widget.dart similarity index 97% rename from lib/src/features/inventory/widgets/inventory_details.dart rename to lib/src/features/inventory/widgets/inventory_details.widget.dart index bc39a39..9538a43 100644 --- a/lib/src/features/inventory/widgets/inventory_details.dart +++ b/lib/src/features/inventory/widgets/inventory_details.widget.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/input_decoration.dart'; -import 'package:librarian_app/src/features/inventory/data/detailed_thing_model.dart'; -import 'package:librarian_app/src/features/inventory/widgets/add_inventory_dialog.dart'; +import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; +import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; +import 'package:librarian_app/src/features/inventory/widgets/add_inventory_dialog.widget.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import 'details_card_header.dart'; +import 'details_card_header.widget.dart'; class InventoryDetails extends StatelessWidget { const InventoryDetails({ diff --git a/lib/src/features/inventory/views/inventory_details_view.dart b/lib/src/features/inventory/widgets/inventory_details_view.widget.dart similarity index 97% rename from lib/src/features/inventory/views/inventory_details_view.dart rename to lib/src/features/inventory/widgets/inventory_details_view.widget.dart index 4ae8d7c..b17c457 100644 --- a/lib/src/features/inventory/views/inventory_details_view.dart +++ b/lib/src/features/inventory/widgets/inventory_details_view.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory_view_model.dart'; -import 'package:librarian_app/src/features/inventory/widgets/inventory_details.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details.widget.dart'; import 'package:provider/provider.dart'; class InventoryDetailsView extends StatelessWidget { diff --git a/lib/src/features/inventory/widgets/inventory_list.dart b/lib/src/features/inventory/widgets/inventory_list.widget.dart similarity index 95% rename from lib/src/features/inventory/widgets/inventory_list.dart rename to lib/src/features/inventory/widgets/inventory_list.widget.dart index 2472d57..e2d907a 100644 --- a/lib/src/features/inventory/widgets/inventory_list.dart +++ b/lib/src/features/inventory/widgets/inventory_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/thing_model.dart'; +import '../data/thing.model.dart'; class InventoryList extends StatelessWidget { const InventoryList({ diff --git a/lib/src/features/inventory/views/inventory_view.dart b/lib/src/features/inventory/widgets/inventory_view.widget.dart similarity index 87% rename from lib/src/features/inventory/views/inventory_view.dart rename to lib/src/features/inventory/widgets/inventory_view.widget.dart index eeeadd7..59ca92e 100644 --- a/lib/src/features/inventory/views/inventory_view.dart +++ b/lib/src/features/inventory/widgets/inventory_view.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../data/inventory_view_model.dart'; -import '../data/thing_model.dart'; -import '../widgets/inventory_list.dart'; +import '../data/inventory.vm.dart'; +import '../data/thing.model.dart'; +import '../widgets/inventory_list.widget.dart'; class InventoryView extends StatelessWidget { const InventoryView({ diff --git a/lib/src/features/inventory/views/searchable_inventory_list.dart b/lib/src/features/inventory/widgets/searchable_inventory_list.widget.dart similarity index 87% rename from lib/src/features/inventory/views/searchable_inventory_list.dart rename to lib/src/features/inventory/widgets/searchable_inventory_list.widget.dart index 70688ef..e3ec83d 100644 --- a/lib/src/features/inventory/views/searchable_inventory_list.dart +++ b/lib/src/features/inventory/widgets/searchable_inventory_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/submit_text_field.dart'; -import 'package:librarian_app/src/features/inventory/data/thing_model.dart'; -import 'package:librarian_app/src/features/inventory/views/inventory_view.dart'; +import 'package:librarian_app/src/features/common/widgets/submit_text_field.widget.dart'; +import 'package:librarian_app/src/features/inventory/data/thing.model.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_view.widget.dart'; class SearchableInventoryList extends StatefulWidget { final Function(ThingModel)? onThingTapped; diff --git a/lib/src/features/loans/data/loan_model.dart b/lib/src/features/loans/data/loan.model.dart similarity index 93% rename from lib/src/features/loans/data/loan_model.dart rename to lib/src/features/loans/data/loan.model.dart index 6b8f177..8bcd699 100644 --- a/lib/src/features/loans/data/loan_model.dart +++ b/lib/src/features/loans/data/loan.model.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrower_model.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; -import 'thing_model.dart'; +import 'thing.model.dart'; class LoanModel { final String id; diff --git a/lib/src/features/loans/data/loans_view_model.dart b/lib/src/features/loans/data/loans.vm.dart similarity index 99% rename from lib/src/features/loans/data/loans_view_model.dart rename to lib/src/features/loans/data/loans.vm.dart index 210bcf2..f0dd018 100644 --- a/lib/src/features/loans/data/loans_view_model.dart +++ b/lib/src/features/loans/data/loans.vm.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:librarian_app/src/features/common/data/lending_api.dart'; -import 'loan_model.dart'; +import 'loan.model.dart'; import 'loans_mapper.dart'; class LoansViewModel extends ChangeNotifier { diff --git a/lib/src/features/loans/data/loans_mapper.dart b/lib/src/features/loans/data/loans_mapper.dart index 00fe0b1..ec20212 100644 --- a/lib/src/features/loans/data/loans_mapper.dart +++ b/lib/src/features/loans/data/loans_mapper.dart @@ -1,6 +1,6 @@ -import '../../borrowers/data/borrower_model.dart'; -import 'loan_model.dart'; -import 'thing_model.dart'; +import '../../borrowers/data/borrower.model.dart'; +import 'loan.model.dart'; +import 'thing.model.dart'; class LoansMapper { static Iterable map(Iterable data) { diff --git a/lib/src/features/loans/data/thing_model.dart b/lib/src/features/loans/data/thing.model.dart similarity index 100% rename from lib/src/features/loans/data/thing_model.dart rename to lib/src/features/loans/data/thing.model.dart diff --git a/lib/src/features/loans/data/things_view_model.dart b/lib/src/features/loans/data/things.vm.dart similarity index 95% rename from lib/src/features/loans/data/things_view_model.dart rename to lib/src/features/loans/data/things.vm.dart index 9f9a59d..df477f8 100644 --- a/lib/src/features/loans/data/things_view_model.dart +++ b/lib/src/features/loans/data/things.vm.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/data/lending_api.dart'; -import 'thing_model.dart'; +import 'thing.model.dart'; class ThingsViewModel extends ChangeNotifier { Future getOne({required int number}) async { diff --git a/lib/src/features/loans/views/checkout/checkout_page.dart b/lib/src/features/loans/pages/checkout.page.dart similarity index 81% rename from lib/src/features/loans/views/checkout/checkout_page.dart rename to lib/src/features/loans/pages/checkout.page.dart index 8ec9bff..3a0a4a8 100644 --- a/lib/src/features/loans/views/checkout/checkout_page.dart +++ b/lib/src/features/loans/pages/checkout.page.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/views/checkout/checkout_stepper.dart'; +import 'package:librarian_app/src/features/loans/widgets/checkout/checkout_stepper.widget.dart'; class CheckoutPage extends StatelessWidget { const CheckoutPage({super.key}); diff --git a/lib/src/features/loans/views/loan_details_page.dart b/lib/src/features/loans/pages/loan_details.page.dart similarity index 96% rename from lib/src/features/loans/views/loan_details_page.dart rename to lib/src/features/loans/pages/loan_details.page.dart index e1620e4..f00216c 100644 --- a/lib/src/features/loans/views/loan_details_page.dart +++ b/lib/src/features/loans/pages/loan_details.page.dart @@ -1,10 +1,10 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/data/loans_view_model.dart'; -import 'package:librarian_app/src/features/loans/widgets/loan_details.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details.widget.dart'; import 'package:provider/provider.dart'; -import '../data/loan_model.dart'; +import '../data/loan.model.dart'; class LoanDetailsPage extends StatefulWidget { const LoanDetailsPage(this.loan, {super.key}); diff --git a/lib/src/features/loans/views/open_loan_page.dart b/lib/src/features/loans/pages/open_loan.page.dart similarity index 91% rename from lib/src/features/loans/views/open_loan_page.dart rename to lib/src/features/loans/pages/open_loan.page.dart index ae1c1ad..c92c19d 100644 --- a/lib/src/features/loans/views/open_loan_page.dart +++ b/lib/src/features/loans/pages/open_loan.page.dart @@ -1,14 +1,14 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrower_model.dart'; -import 'package:librarian_app/src/features/loans/data/loans_view_model.dart'; -import 'package:librarian_app/src/features/loans/views/pick_things_view.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.dart'; -import 'package:librarian_app/src/features/loans/widgets/loan_details.dart'; -import 'package:librarian_app/src/features/borrowers/views/searchable_borrowers_list.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; +import 'package:librarian_app/src/features/loans/widgets/pick_things.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart'; import 'package:provider/provider.dart'; -import '../data/thing_model.dart'; +import '../data/thing.model.dart'; class OpenLoanPage extends StatefulWidget { const OpenLoanPage({super.key}); diff --git a/lib/src/features/loans/widgets/checkin_dialog.dart b/lib/src/features/loans/widgets/checkin_dialog.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/checkin_dialog.dart rename to lib/src/features/loans/widgets/checkin_dialog.widget.dart diff --git a/lib/src/features/loans/views/checkout/checkout_controller.dart b/lib/src/features/loans/widgets/checkout/checkout_controller.dart similarity index 89% rename from lib/src/features/loans/views/checkout/checkout_controller.dart rename to lib/src/features/loans/widgets/checkout/checkout_controller.dart index 5313789..bd54d83 100644 --- a/lib/src/features/loans/views/checkout/checkout_controller.dart +++ b/lib/src/features/loans/widgets/checkout/checkout_controller.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import 'package:librarian_app/src/features/loans/data/loans_view_model.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; import 'package:provider/provider.dart'; class CheckoutController { diff --git a/lib/src/features/loans/views/checkout/checkout_stepper.dart b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart similarity index 92% rename from lib/src/features/loans/views/checkout/checkout_stepper.dart rename to lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart index 6bdc7a1..005875a 100644 --- a/lib/src/features/loans/views/checkout/checkout_stepper.dart +++ b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrower_model.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers_view_model.dart'; -import 'package:librarian_app/src/features/borrowers/views/borrower_issues.dart'; -import 'package:librarian_app/src/features/borrowers/views/borrower_search_delegate.dart'; -import 'package:librarian_app/src/features/loans/data/thing_model.dart'; -import 'package:librarian_app/src/features/loans/views/checkout/checkout_controller.dart'; -import 'package:librarian_app/src/features/loans/views/checkout/connected_thing_search_field.dart'; -import 'package:librarian_app/src/features/loans/widgets/loan_details.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_issues.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_search_delegate.widget.dart'; +import 'package:librarian_app/src/features/loans/data/thing.model.dart'; +import 'package:librarian_app/src/features/loans/widgets/checkout/checkout_controller.dart'; +import 'package:librarian_app/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details.widget.dart'; import 'package:provider/provider.dart'; class CheckoutStepper extends StatefulWidget { diff --git a/lib/src/features/loans/views/checkout/connected_thing_search_field.dart b/lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart similarity index 94% rename from lib/src/features/loans/views/checkout/connected_thing_search_field.dart rename to lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart index ea9fe5a..1107ebf 100644 --- a/lib/src/features/loans/views/checkout/connected_thing_search_field.dart +++ b/lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/data/thing_model.dart'; -import 'package:librarian_app/src/features/loans/data/things_view_model.dart'; +import 'package:librarian_app/src/features/loans/data/thing.model.dart'; +import 'package:librarian_app/src/features/loans/data/things.vm.dart'; import 'package:provider/provider.dart'; class ConnectedThingSearchField extends StatelessWidget { diff --git a/lib/src/features/loans/views/connected_loans_list.dart b/lib/src/features/loans/widgets/connected_loans_list.widget.dart similarity index 79% rename from lib/src/features/loans/views/connected_loans_list.dart rename to lib/src/features/loans/widgets/connected_loans_list.widget.dart index 7a68667..c973125 100644 --- a/lib/src/features/loans/views/connected_loans_list.dart +++ b/lib/src/features/loans/widgets/connected_loans_list.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/views/loans_view.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_view.widget.dart'; import 'package:provider/provider.dart'; -import '../data/loan_model.dart'; -import '../data/loans_view_model.dart'; +import '../data/loan.model.dart'; +import '../data/loans.vm.dart'; class ConnectedLoansList extends StatelessWidget { final void Function(LoanModel loan)? onTap; diff --git a/lib/src/features/loans/views/dashboard/loan_details_pane.dart b/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart similarity index 95% rename from lib/src/features/loans/views/dashboard/loan_details_pane.dart rename to lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart index ce8d8a2..d2332d0 100644 --- a/lib/src/features/loans/views/dashboard/loan_details_pane.dart +++ b/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; -import '../../data/loan_model.dart'; -import '../../widgets/checkin_dialog.dart'; -import '../../widgets/loan_details.dart'; -import '../../widgets/thing_number.dart'; +import '../../data/loan.model.dart'; +import '../../widgets/checkin_dialog.widget.dart'; +import '../../widgets/loan_details.widget.dart'; +import '../../widgets/thing_number.widget.dart'; class LoanDetailsPane extends StatefulWidget { final LoanModel? loan; diff --git a/lib/src/features/loans/views/dashboard/loans_desktop_layout.dart b/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart similarity index 90% rename from lib/src/features/loans/views/dashboard/loans_desktop_layout.dart rename to lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart index aee4d3a..7e5c615 100644 --- a/lib/src/features/loans/views/dashboard/loans_desktop_layout.dart +++ b/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.dart'; -import 'package:librarian_app/src/features/common/widgets/search_field.dart'; -import 'package:librarian_app/src/features/loans/views/dashboard/loan_details_pane.dart'; -import 'package:librarian_app/src/features/loans/views/loans_view.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_view.widget.dart'; import 'package:provider/provider.dart'; -import '../../data/loans_view_model.dart'; +import '../../data/loans.vm.dart'; class LoansDesktopLayout extends StatefulWidget { const LoansDesktopLayout({super.key}); diff --git a/lib/src/features/loans/widgets/loan_details.dart b/lib/src/features/loans/widgets/loan_details.widget.dart similarity index 97% rename from lib/src/features/loans/widgets/loan_details.dart rename to lib/src/features/loans/widgets/loan_details.widget.dart index 6d147c2..cb7feb6 100644 --- a/lib/src/features/loans/widgets/loan_details.dart +++ b/lib/src/features/loans/widgets/loan_details.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrower_model.dart'; -import 'package:librarian_app/src/features/loans/data/thing_model.dart'; +import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; +import 'package:librarian_app/src/features/loans/data/thing.model.dart'; class LoanDetails extends StatelessWidget { const LoanDetails({ diff --git a/lib/src/features/loans/widgets/loans_list.dart b/lib/src/features/loans/widgets/loans_list.widget.dart similarity index 98% rename from lib/src/features/loans/widgets/loans_list.dart rename to lib/src/features/loans/widgets/loans_list.widget.dart index 91ee262..6e4a902 100644 --- a/lib/src/features/loans/widgets/loans_list.dart +++ b/lib/src/features/loans/widgets/loans_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/loan_model.dart'; +import '../data/loan.model.dart'; class LoansList extends StatelessWidget { final List loans; diff --git a/lib/src/features/loans/views/loans_view.dart b/lib/src/features/loans/widgets/loans_view.widget.dart similarity index 88% rename from lib/src/features/loans/views/loans_view.dart rename to lib/src/features/loans/widgets/loans_view.widget.dart index 506e803..d8a1a45 100644 --- a/lib/src/features/loans/views/loans_view.dart +++ b/lib/src/features/loans/widgets/loans_view.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import '../data/loan_model.dart'; -import '../data/loans_view_model.dart'; -import '../widgets/loans_list.dart'; +import '../data/loan.model.dart'; +import '../data/loans.vm.dart'; +import '../widgets/loans_list.widget.dart'; class LoansView extends StatelessWidget { const LoansView({ diff --git a/lib/src/features/loans/views/pick_things_view.dart b/lib/src/features/loans/widgets/pick_things.widget.dart similarity index 94% rename from lib/src/features/loans/views/pick_things_view.dart rename to lib/src/features/loans/widgets/pick_things.widget.dart index c01de32..2d9256c 100644 --- a/lib/src/features/loans/views/pick_things_view.dart +++ b/lib/src/features/loans/widgets/pick_things.widget.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:librarian_app/src/features/loans/data/things_view_model.dart'; +import 'package:librarian_app/src/features/loans/data/things.vm.dart'; import 'package:provider/provider.dart'; -import '../../common/widgets/submit_text_field.dart'; -import '../data/thing_model.dart'; -import '../widgets/thing_list_tile.dart'; +import '../../common/widgets/submit_text_field.widget.dart'; +import '../data/thing.model.dart'; +import '../widgets/thing_list_tile.widget.dart'; class PickThingsView extends StatefulWidget { const PickThingsView({ diff --git a/lib/src/features/loans/views/searchable_loans_list.dart b/lib/src/features/loans/widgets/searchable_loans_list.widget.dart similarity index 87% rename from lib/src/features/loans/views/searchable_loans_list.dart rename to lib/src/features/loans/widgets/searchable_loans_list.widget.dart index 93ca137..fe77a6c 100644 --- a/lib/src/features/loans/views/searchable_loans_list.dart +++ b/lib/src/features/loans/widgets/searchable_loans_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/submit_text_field.dart'; -import 'package:librarian_app/src/features/loans/data/loan_model.dart'; -import 'package:librarian_app/src/features/loans/views/connected_loans_list.dart'; +import 'package:librarian_app/src/features/common/widgets/submit_text_field.widget.dart'; +import 'package:librarian_app/src/features/loans/data/loan.model.dart'; +import 'package:librarian_app/src/features/loans/widgets/connected_loans_list.widget.dart'; class SearchableLoansList extends StatefulWidget { final Function(LoanModel)? onLoanTapped; diff --git a/lib/src/features/loans/widgets/thing_list_tile.dart b/lib/src/features/loans/widgets/thing_list_tile.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/thing_list_tile.dart rename to lib/src/features/loans/widgets/thing_list_tile.widget.dart diff --git a/lib/src/features/loans/widgets/thing_number.dart b/lib/src/features/loans/widgets/thing_number.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/thing_number.dart rename to lib/src/features/loans/widgets/thing_number.widget.dart diff --git a/lib/src/features/loans/views/things_list_view.dart b/lib/src/features/loans/widgets/things_list.widget.dart similarity index 92% rename from lib/src/features/loans/views/things_list_view.dart rename to lib/src/features/loans/widgets/things_list.widget.dart index 8b957a0..d143102 100644 --- a/lib/src/features/loans/views/things_list_view.dart +++ b/lib/src/features/loans/widgets/things_list.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/data/things_view_model.dart'; -import 'package:librarian_app/src/features/loans/widgets/thing_list_tile.dart'; +import 'package:librarian_app/src/features/loans/data/things.vm.dart'; +import 'package:librarian_app/src/features/loans/widgets/thing_list_tile.widget.dart'; import 'package:provider/provider.dart'; -import '../data/thing_model.dart'; +import '../data/thing.model.dart'; class ThingsListView extends StatefulWidget { const ThingsListView({ diff --git a/lib/src/features/splash/views/splash_page.dart b/lib/src/features/splash/pages/splash.page.dart similarity index 88% rename from lib/src/features/splash/views/splash_page.dart rename to lib/src/features/splash/pages/splash.page.dart index 9a48ca5..5cc19fb 100644 --- a/lib/src/features/splash/views/splash_page.dart +++ b/lib/src/features/splash/pages/splash.page.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/authentication/views/signin_page.dart'; -import 'package:librarian_app/src/features/dashboard/views/dashboard_page.dart'; +import 'package:librarian_app/src/features/authentication/pages/signin.page.dart'; +import 'package:librarian_app/src/features/dashboard/pages/dashboard.page.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; class SplashPage extends StatefulWidget { From b67edeb4f7e617a469d19f4acafa99b5cbdf1f12 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 08:50:32 -0400 Subject: [PATCH 02/35] Refactor signin/splash logic --- lib/main.dart | 2 +- .../authentication/data/user.model.dart | 15 +++ .../features/authentication/data/user.vm.dart | 21 ++++ .../authentication/data/user_view.model.dart | 24 ----- .../authentication/pages/signin.page.dart | 98 ++++++++++--------- .../services/authentication.service.dart | 20 ++++ .../features/splash/pages/splash.page.dart | 38 ++++--- 7 files changed, 125 insertions(+), 93 deletions(-) create mode 100644 lib/src/features/authentication/data/user.model.dart create mode 100644 lib/src/features/authentication/data/user.vm.dart delete mode 100644 lib/src/features/authentication/data/user_view.model.dart create mode 100644 lib/src/features/authentication/services/authentication.service.dart diff --git a/lib/main.dart b/lib/main.dart index 1f18728..7c7aa40 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,7 +3,7 @@ import 'package:librarian_app/constants.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; -import 'package:librarian_app/src/features/authentication/data/user_view.model.dart'; +import 'package:librarian_app/src/features/authentication/data/user.vm.dart'; import 'package:librarian_app/src/features/splash/pages/splash.page.dart'; import 'package:provider/provider.dart'; import 'package:supabase_flutter/supabase_flutter.dart' as supabase; diff --git a/lib/src/features/authentication/data/user.model.dart b/lib/src/features/authentication/data/user.model.dart new file mode 100644 index 0000000..2331bc0 --- /dev/null +++ b/lib/src/features/authentication/data/user.model.dart @@ -0,0 +1,15 @@ +import 'package:supabase_flutter/supabase_flutter.dart'; + +class UserModel { + final String name; + + const UserModel({required this.name}); + + factory UserModel.from(User? supabaseUser) { + final name = supabaseUser?.userMetadata?['full_name'] ?? + supabaseUser?.email ?? + 'Alice'; + + return UserModel(name: name); + } +} diff --git a/lib/src/features/authentication/data/user.vm.dart b/lib/src/features/authentication/data/user.vm.dart new file mode 100644 index 0000000..d53cd78 --- /dev/null +++ b/lib/src/features/authentication/data/user.vm.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/authentication/data/user.model.dart'; +import 'package:librarian_app/src/features/authentication/services/authentication.service.dart'; + +class UserViewModel extends ChangeNotifier { + final service = AuthenticationService(); + + bool get signedIn => service.hasValidSession; + + UserModel get user => service.currentUser; + + Future signIn() async { + await service.signIn(); + notifyListeners(); + } + + Future signOut() async { + await service.signOut(); + notifyListeners(); + } +} diff --git a/lib/src/features/authentication/data/user_view.model.dart b/lib/src/features/authentication/data/user_view.model.dart deleted file mode 100644 index f090488..0000000 --- a/lib/src/features/authentication/data/user_view.model.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:supabase_flutter/supabase_flutter.dart'; - -class UserViewModel extends ChangeNotifier { - static SupabaseClient get _supabase => Supabase.instance.client; - static User? get _currentUser => _supabase.auth.currentUser; - - bool get signedIn => _supabase.auth.currentSession != null; - - String get name => - _currentUser?.userMetadata?['full_name'] ?? - _currentUser?.email ?? - 'Alice'; - - void signIn() { - _supabase.auth - .signInWithOAuth(Provider.discord) - .whenComplete(() => notifyListeners()); - } - - void signOut() { - _supabase.auth.signOut().whenComplete(() => notifyListeners()); - } -} diff --git a/lib/src/features/authentication/pages/signin.page.dart b/lib/src/features/authentication/pages/signin.page.dart index 9e69bad..5a1fe01 100644 --- a/lib/src/features/authentication/pages/signin.page.dart +++ b/lib/src/features/authentication/pages/signin.page.dart @@ -1,6 +1,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/authentication/data/user.vm.dart'; import 'package:librarian_app/src/features/dashboard/pages/dashboard.page.dart'; +import 'package:provider/provider.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; class SignInPage extends StatefulWidget { @@ -15,23 +17,6 @@ class SignInPage extends StatefulWidget { class _SignInPageState extends State { String? _errorMessage; - Future _signIn() async { - if (kDebugMode) { - _navigateToDashboard(); - return; - } - - try { - await Supabase.instance.client.auth - .signInWithOAuth(Provider.discord) - .whenComplete(_navigateToDashboard); - } on AuthException catch (error) { - setState(() => _errorMessage = error.message); - } catch (error) { - setState(() => _errorMessage = "An unexpected error occurred."); - } - } - void _navigateToDashboard() { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const DashboardPage()), @@ -45,36 +30,55 @@ class _SignInPageState extends State { body: Padding( padding: const EdgeInsets.all(16), child: Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - "pvd_things.png", - isAntiAlias: true, - width: 160, - ), - const SizedBox(height: 32), - ElevatedButton.icon( - icon: const Icon(Icons.discord_rounded), - label: const Text('Sign in with Discord'), - onPressed: _signIn, - style: ElevatedButton.styleFrom( - textStyle: const TextStyle(fontSize: 20), - padding: const EdgeInsets.all(16), - ), - ), - if (_errorMessage != null) const SizedBox(height: 16), - if (_errorMessage != null) Text(_errorMessage!), - const SizedBox(height: 32), - const Card( - child: Padding( - padding: EdgeInsets.all(16), - child: Text( - 'Only authorized users can sign in.\nPlease ask the PVD Things Digital Team for volunteer access.'), - ), - ), - ], + child: Consumer( + builder: (context, viewModel, child) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + "pvd_things.png", + isAntiAlias: true, + width: 160, + ), + const SizedBox(height: 32), + ElevatedButton.icon( + icon: const Icon(Icons.discord_rounded), + label: const Text('Sign in with Discord'), + onPressed: () async { + if (kDebugMode) { + _navigateToDashboard(); + return; + } + + try { + await viewModel.signIn(); + _navigateToDashboard(); + } on AuthException catch (error) { + setState(() => _errorMessage = error.message); + } catch (error) { + setState(() => + _errorMessage = "An unexpected error occurred."); + } + }, + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20), + padding: const EdgeInsets.all(16), + ), + ), + if (_errorMessage != null) const SizedBox(height: 16), + if (_errorMessage != null) Text(_errorMessage!), + const SizedBox(height: 32), + const Card( + child: Padding( + padding: EdgeInsets.all(16), + child: Text( + 'Only authorized users can sign in.\nPlease ask the PVD Things Digital Team for volunteer access.'), + ), + ), + ], + ); + }, ), ), ), diff --git a/lib/src/features/authentication/services/authentication.service.dart b/lib/src/features/authentication/services/authentication.service.dart new file mode 100644 index 0000000..255d6b9 --- /dev/null +++ b/lib/src/features/authentication/services/authentication.service.dart @@ -0,0 +1,20 @@ +import 'package:supabase_flutter/supabase_flutter.dart'; + +import '../data/user.model.dart'; + +class AuthenticationService { + static SupabaseClient get _supabase => Supabase.instance.client; + static User? get _currentUser => _supabase.auth.currentUser; + + bool get hasValidSession => _supabase.auth.currentSession != null; + + UserModel get currentUser => UserModel.from(_currentUser); + + Future signIn() async { + await _supabase.auth.signInWithOAuth(Provider.discord); + } + + Future signOut() async { + await _supabase.auth.signOut(); + } +} diff --git a/lib/src/features/splash/pages/splash.page.dart b/lib/src/features/splash/pages/splash.page.dart index 5cc19fb..81bb90b 100644 --- a/lib/src/features/splash/pages/splash.page.dart +++ b/lib/src/features/splash/pages/splash.page.dart @@ -1,8 +1,9 @@ -import 'package:flutter/foundation.dart'; +import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/authentication/data/user.vm.dart'; import 'package:librarian_app/src/features/authentication/pages/signin.page.dart'; import 'package:librarian_app/src/features/dashboard/pages/dashboard.page.dart'; -import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:provider/provider.dart'; class SplashPage extends StatefulWidget { const SplashPage({super.key}); @@ -15,27 +16,22 @@ class _SplashPageState extends State { @override void initState() { super.initState(); - _redirect(); - } - Future _redirect() async { - // await for for the widget to mount - await Future.delayed(Duration.zero); + Timer(const Duration(seconds: 2), () { + final viewModel = Provider.of(context, listen: false); - final session = Supabase.instance.client.auth.currentSession; - if (session == null && !kDebugMode) { - // ignore: use_build_context_synchronously - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute(builder: (_) => const SignInPage()), - (route) => false, - ); - } else { - // ignore: use_build_context_synchronously - Navigator.of(context).pushAndRemoveUntil( - MaterialPageRoute(builder: (_) => const DashboardPage()), - (route) => false, - ); - } + if (!viewModel.signedIn) { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (_) => const SignInPage()), + (route) => false, + ); + } else { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (_) => const DashboardPage()), + (route) => false, + ); + } + }); } @override From 27e98d3c0c8b076b08cf78d481f8b5940ae68f7c Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 08:51:54 -0400 Subject: [PATCH 03/35] Update README re pages --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cc4f026..592daf4 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ Without a `SUPABASE_URL`, attempting signin will result in a 404 error. ## Project Structure -The app is broken down into features or modules, each containing directories for `data`, `widgets`, and `views`. +The app is broken down into features or modules, each containing directories for `data`, `widgets`, and `pages`. - `data` contains Models, ViewModels, Repostories, or any other business logic. -- `widgets` contains UI components that have no knowledge of the ViewModel. -- `views` contains UI components that _do_ have knowledge of the ViewModel. Pages are the most common, but there may be smaller views that compose a page. +- `widgets` contains UI components that compose larger widgets or pages. +- `pages` contains UI components that represent pages. Generally wrapped in a `Scaffold` widget. ## Background From db3db82cf90e7d0759ce78d1c8cb0d8cdb87bc92 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 09:07:29 -0400 Subject: [PATCH 04/35] Pull out DiscordSigninButton --- .../authentication/pages/signin/index.dart | 1 + .../pages/{ => signin}/signin.page.dart | 30 +++---------- .../signin/widgets/discord_button.widget.dart | 43 +++++++++++++++++++ .../features/splash/pages/splash.page.dart | 2 +- 4 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 lib/src/features/authentication/pages/signin/index.dart rename lib/src/features/authentication/pages/{ => signin}/signin.page.dart (64%) create mode 100644 lib/src/features/authentication/pages/signin/widgets/discord_button.widget.dart diff --git a/lib/src/features/authentication/pages/signin/index.dart b/lib/src/features/authentication/pages/signin/index.dart new file mode 100644 index 0000000..470f5d3 --- /dev/null +++ b/lib/src/features/authentication/pages/signin/index.dart @@ -0,0 +1 @@ +export 'signin.page.dart'; diff --git a/lib/src/features/authentication/pages/signin.page.dart b/lib/src/features/authentication/pages/signin/signin.page.dart similarity index 64% rename from lib/src/features/authentication/pages/signin.page.dart rename to lib/src/features/authentication/pages/signin/signin.page.dart index 5a1fe01..f87959a 100644 --- a/lib/src/features/authentication/pages/signin.page.dart +++ b/lib/src/features/authentication/pages/signin/signin.page.dart @@ -1,9 +1,8 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/authentication/data/user.vm.dart'; +import 'package:librarian_app/src/features/authentication/pages/signin/widgets/discord_button.widget.dart'; import 'package:librarian_app/src/features/dashboard/pages/dashboard.page.dart'; import 'package:provider/provider.dart'; -import 'package:supabase_flutter/supabase_flutter.dart'; class SignInPage extends StatefulWidget { const SignInPage({super.key}); @@ -42,29 +41,12 @@ class _SignInPageState extends State { width: 160, ), const SizedBox(height: 32), - ElevatedButton.icon( - icon: const Icon(Icons.discord_rounded), - label: const Text('Sign in with Discord'), - onPressed: () async { - if (kDebugMode) { - _navigateToDashboard(); - return; - } - - try { - await viewModel.signIn(); - _navigateToDashboard(); - } on AuthException catch (error) { - setState(() => _errorMessage = error.message); - } catch (error) { - setState(() => - _errorMessage = "An unexpected error occurred."); - } + DiscordSigninButton( + signIn: viewModel.signIn, + onSignedIn: _navigateToDashboard, + onError: (error) { + setState(() => _errorMessage = error); }, - style: ElevatedButton.styleFrom( - textStyle: const TextStyle(fontSize: 20), - padding: const EdgeInsets.all(16), - ), ), if (_errorMessage != null) const SizedBox(height: 16), if (_errorMessage != null) Text(_errorMessage!), diff --git a/lib/src/features/authentication/pages/signin/widgets/discord_button.widget.dart b/lib/src/features/authentication/pages/signin/widgets/discord_button.widget.dart new file mode 100644 index 0000000..8e7c069 --- /dev/null +++ b/lib/src/features/authentication/pages/signin/widgets/discord_button.widget.dart @@ -0,0 +1,43 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:supabase_flutter/supabase_flutter.dart'; + +class DiscordSigninButton extends StatelessWidget { + final Future Function()? signIn; + final void Function()? onSignedIn; + final void Function(String)? onError; + + const DiscordSigninButton({ + super.key, + this.signIn, + this.onSignedIn, + this.onError, + }); + + @override + Widget build(BuildContext context) { + return ElevatedButton.icon( + icon: const Icon(Icons.discord_rounded), + label: const Text('Sign in with Discord'), + onPressed: () async { + if (kDebugMode) { + onSignedIn?.call(); + return; + } + + try { + await signIn?.call(); + onSignedIn?.call(); + } on AuthException catch (error) { + onError?.call(error.toString()); + } catch (error) { + onError?.call("An unexpected error occurred."); + } + }, + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20), + padding: const EdgeInsets.all(16), + ), + ); + } +} diff --git a/lib/src/features/splash/pages/splash.page.dart b/lib/src/features/splash/pages/splash.page.dart index 81bb90b..e4c9be1 100644 --- a/lib/src/features/splash/pages/splash.page.dart +++ b/lib/src/features/splash/pages/splash.page.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/authentication/data/user.vm.dart'; -import 'package:librarian_app/src/features/authentication/pages/signin.page.dart'; +import 'package:librarian_app/src/features/authentication/pages/signin/index.dart'; import 'package:librarian_app/src/features/dashboard/pages/dashboard.page.dart'; import 'package:provider/provider.dart'; From b2c92673db2d584405661841291dd81e14a2ddc5 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 14:59:01 -0400 Subject: [PATCH 05/35] Pull out ItemModel --- .../inventory/data/detailed_thing.model.dart | 28 ++----------------- .../features/inventory/data/item.model.dart | 25 +++++++++++++++++ .../widgets/inventory_details.widget.dart | 2 +- 3 files changed, 28 insertions(+), 27 deletions(-) create mode 100644 lib/src/features/inventory/data/item.model.dart diff --git a/lib/src/features/inventory/data/detailed_thing.model.dart b/lib/src/features/inventory/data/detailed_thing.model.dart index 2f4e061..66db1de 100644 --- a/lib/src/features/inventory/data/detailed_thing.model.dart +++ b/lib/src/features/inventory/data/detailed_thing.model.dart @@ -1,3 +1,5 @@ +import 'item.model.dart'; + class DetailedThingModel { DetailedThingModel({ required this.id, @@ -26,29 +28,3 @@ class DetailedThingModel { ); } } - -class ItemModel { - ItemModel({ - required this.id, - required this.number, - required this.available, - required this.totalLoans, - this.brand, - }); - - final String id; - final int number; - final String? brand; - final bool available; - final int totalLoans; - - factory ItemModel.fromJson(Map json) { - return ItemModel( - id: json['id'] as String, - number: json['number'] as int, - available: json['available'] as bool, - totalLoans: json['totalLoans'] as int, - brand: json['brand'] as String?, - ); - } -} diff --git a/lib/src/features/inventory/data/item.model.dart b/lib/src/features/inventory/data/item.model.dart new file mode 100644 index 0000000..7a48ed6 --- /dev/null +++ b/lib/src/features/inventory/data/item.model.dart @@ -0,0 +1,25 @@ +class ItemModel { + ItemModel({ + required this.id, + required this.number, + required this.available, + required this.totalLoans, + this.brand, + }); + + final String id; + final int number; + final String? brand; + final bool available; + final int totalLoans; + + factory ItemModel.fromJson(Map json) { + return ItemModel( + id: json['id'] as String, + number: json['number'] as int, + available: json['available'] as bool, + totalLoans: json['totalLoans'] as int, + brand: json['brand'] as String?, + ); + } +} diff --git a/lib/src/features/inventory/widgets/inventory_details.widget.dart b/lib/src/features/inventory/widgets/inventory_details.widget.dart index 9538a43..5bc42b2 100644 --- a/lib/src/features/inventory/widgets/inventory_details.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; -import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; import 'package:librarian_app/src/features/inventory/widgets/add_inventory_dialog.widget.dart'; import 'package:librarian_app/src/utils/media_query.dart'; +import '../data/item.model.dart'; import 'details_card_header.widget.dart'; class InventoryDetails extends StatelessWidget { From 03034046c8c6c0181f32f4e8483856f6d24006b4 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 15:21:05 -0400 Subject: [PATCH 06/35] Reorganize inventory widgets --- lib/src/features/dashboard/pages/dashboard.page.dart | 4 ++-- .../inventory/pages/inventory_details.page.dart | 2 +- .../dashboard/inventory_desktop_layout.widget.dart | 4 ++-- .../dashboard/inventory_details_pane.widget.dart | 2 +- .../{ => dialogs}/add_inventory_dialog.widget.dart | 0 .../{ => dialogs}/create_thing_dialog.widget.dart | 0 .../details_card_header.widget.dart | 0 .../inventory_details.widget.dart | 4 ++-- .../inventory_details_view.widget.dart | 2 +- .../{ => inventory_list}/inventory_list.widget.dart | 2 +- .../inventory_list_view.widget.dart} | 10 +++++----- .../searchable_inventory_list.widget.dart | 4 ++-- 12 files changed, 17 insertions(+), 17 deletions(-) rename lib/src/features/inventory/widgets/{ => dialogs}/add_inventory_dialog.widget.dart (100%) rename lib/src/features/inventory/widgets/{ => dialogs}/create_thing_dialog.widget.dart (100%) rename lib/src/features/inventory/widgets/{ => inventory_details}/details_card_header.widget.dart (100%) rename lib/src/features/inventory/widgets/{ => inventory_details}/inventory_details.widget.dart (96%) rename lib/src/features/inventory/widgets/{ => inventory_details}/inventory_details_view.widget.dart (97%) rename lib/src/features/inventory/widgets/{ => inventory_list}/inventory_list.widget.dart (95%) rename lib/src/features/inventory/widgets/{inventory_view.widget.dart => inventory_list/inventory_list_view.widget.dart} (79%) rename lib/src/features/inventory/widgets/{ => inventory_list}/searchable_inventory_list.widget.dart (94%) diff --git a/lib/src/features/dashboard/pages/dashboard.page.dart b/lib/src/features/dashboard/pages/dashboard.page.dart index 8c15ae2..3b0273d 100644 --- a/lib/src/features/dashboard/pages/dashboard.page.dart +++ b/lib/src/features/dashboard/pages/dashboard.page.dart @@ -5,8 +5,8 @@ import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_vie import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; import 'package:librarian_app/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart'; import 'package:librarian_app/src/features/inventory/pages/inventory_details.page.dart'; -import 'package:librarian_app/src/features/inventory/widgets/searchable_inventory_list.widget.dart'; -import 'package:librarian_app/src/features/inventory/widgets/create_thing_dialog.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_list/searchable_inventory_list.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/dialogs/create_thing_dialog.widget.dart'; import 'package:librarian_app/src/features/loans/pages/checkout.page.dart'; import 'package:librarian_app/src/features/loans/pages/loan_details.page.dart'; import 'package:librarian_app/src/features/loans/widgets/searchable_loans_list.widget.dart'; diff --git a/lib/src/features/inventory/pages/inventory_details.page.dart b/lib/src/features/inventory/pages/inventory_details.page.dart index 08513cd..f7e9505 100644 --- a/lib/src/features/inventory/pages/inventory_details.page.dart +++ b/lib/src/features/inventory/pages/inventory_details.page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../data/inventory.vm.dart'; -import '../widgets/inventory_details_view.widget.dart'; +import '../widgets/inventory_details/inventory_details_view.widget.dart'; class InventoryDetailsPage extends StatelessWidget { const InventoryDetailsPage({super.key}); diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart index 6f0d31f..af5aa6f 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart @@ -5,7 +5,7 @@ import 'package:librarian_app/src/features/inventory/widgets/dashboard/inventory import 'package:provider/provider.dart'; import '../../data/inventory.vm.dart'; -import '../inventory_view.widget.dart'; +import '../inventory_list/inventory_list_view.widget.dart'; class InventoryDesktopLayout extends StatefulWidget { const InventoryDesktopLayout({super.key}); @@ -41,7 +41,7 @@ class _InventoryDesktopLayoutState extends State { ), ), Expanded( - child: InventoryView( + child: InventoryListView( searchFilter: _searchFilter, ), ), diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart b/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart index 53e5a0f..d281ce4 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart @@ -4,7 +4,7 @@ import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.d import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; import '../../data/thing.model.dart'; -import '../../widgets/inventory_details.widget.dart'; +import '../inventory_details/inventory_details.widget.dart'; class InventoryDetailsPane extends StatefulWidget { final ThingModel? thing; diff --git a/lib/src/features/inventory/widgets/add_inventory_dialog.widget.dart b/lib/src/features/inventory/widgets/dialogs/add_inventory_dialog.widget.dart similarity index 100% rename from lib/src/features/inventory/widgets/add_inventory_dialog.widget.dart rename to lib/src/features/inventory/widgets/dialogs/add_inventory_dialog.widget.dart diff --git a/lib/src/features/inventory/widgets/create_thing_dialog.widget.dart b/lib/src/features/inventory/widgets/dialogs/create_thing_dialog.widget.dart similarity index 100% rename from lib/src/features/inventory/widgets/create_thing_dialog.widget.dart rename to lib/src/features/inventory/widgets/dialogs/create_thing_dialog.widget.dart diff --git a/lib/src/features/inventory/widgets/details_card_header.widget.dart b/lib/src/features/inventory/widgets/inventory_details/details_card_header.widget.dart similarity index 100% rename from lib/src/features/inventory/widgets/details_card_header.widget.dart rename to lib/src/features/inventory/widgets/inventory_details/details_card_header.widget.dart diff --git a/lib/src/features/inventory/widgets/inventory_details.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart similarity index 96% rename from lib/src/features/inventory/widgets/inventory_details.widget.dart rename to lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart index 5bc42b2..804c484 100644 --- a/lib/src/features/inventory/widgets/inventory_details.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; -import 'package:librarian_app/src/features/inventory/widgets/add_inventory_dialog.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/dialogs/add_inventory_dialog.widget.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/item.model.dart'; +import '../../data/item.model.dart'; import 'details_card_header.widget.dart'; class InventoryDetails extends StatelessWidget { diff --git a/lib/src/features/inventory/widgets/inventory_details_view.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart similarity index 97% rename from lib/src/features/inventory/widgets/inventory_details_view.widget.dart rename to lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart index b17c457..c0c03f3 100644 --- a/lib/src/features/inventory/widgets/inventory_details_view.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; -import 'package:librarian_app/src/features/inventory/widgets/inventory_details.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart'; import 'package:provider/provider.dart'; class InventoryDetailsView extends StatelessWidget { diff --git a/lib/src/features/inventory/widgets/inventory_list.widget.dart b/lib/src/features/inventory/widgets/inventory_list/inventory_list.widget.dart similarity index 95% rename from lib/src/features/inventory/widgets/inventory_list.widget.dart rename to lib/src/features/inventory/widgets/inventory_list/inventory_list.widget.dart index e2d907a..7f63138 100644 --- a/lib/src/features/inventory/widgets/inventory_list.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_list/inventory_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/thing.model.dart'; +import '../../data/thing.model.dart'; class InventoryList extends StatelessWidget { const InventoryList({ diff --git a/lib/src/features/inventory/widgets/inventory_view.widget.dart b/lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart similarity index 79% rename from lib/src/features/inventory/widgets/inventory_view.widget.dart rename to lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart index 59ca92e..ae8dbdd 100644 --- a/lib/src/features/inventory/widgets/inventory_view.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../data/inventory.vm.dart'; -import '../data/thing.model.dart'; -import '../widgets/inventory_list.widget.dart'; +import '../../data/inventory.vm.dart'; +import '../../data/thing.model.dart'; +import 'inventory_list.widget.dart'; -class InventoryView extends StatelessWidget { - const InventoryView({ +class InventoryListView extends StatelessWidget { + const InventoryListView({ super.key, required this.searchFilter, this.onTap, diff --git a/lib/src/features/inventory/widgets/searchable_inventory_list.widget.dart b/lib/src/features/inventory/widgets/inventory_list/searchable_inventory_list.widget.dart similarity index 94% rename from lib/src/features/inventory/widgets/searchable_inventory_list.widget.dart rename to lib/src/features/inventory/widgets/inventory_list/searchable_inventory_list.widget.dart index e3ec83d..68102b2 100644 --- a/lib/src/features/inventory/widgets/searchable_inventory_list.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_list/searchable_inventory_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/submit_text_field.widget.dart'; import 'package:librarian_app/src/features/inventory/data/thing.model.dart'; -import 'package:librarian_app/src/features/inventory/widgets/inventory_view.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart'; class SearchableInventoryList extends StatefulWidget { final Function(ThingModel)? onThingTapped; @@ -40,7 +40,7 @@ class _SearchableInventoryListState extends State { ), ), Expanded( - child: InventoryView( + child: InventoryListView( searchFilter: _searchText, onTap: widget.onThingTapped, ), From ee48115599580683f56afc23f8a3b5045b0b31a9 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 15:52:07 -0400 Subject: [PATCH 07/35] Pull out ItemsCard --- .../inventory_details.widget.dart | 78 +++---------------- .../details_card_header.widget.dart | 0 .../items_card/items_card.widget.dart | 77 ++++++++++++++++++ 3 files changed, 89 insertions(+), 66 deletions(-) rename lib/src/features/inventory/widgets/inventory_details/{ => items_card}/details_card_header.widget.dart (100%) create mode 100644 lib/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart index 804c484..b86f086 100644 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; import 'package:librarian_app/src/features/inventory/widgets/dialogs/add_inventory_dialog.widget.dart'; -import 'package:librarian_app/src/utils/media_query.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart'; import '../../data/item.model.dart'; -import 'details_card_header.widget.dart'; class InventoryDetails extends StatelessWidget { const InventoryDetails({ @@ -54,72 +53,19 @@ class InventoryDetails extends StatelessWidget { ), ), const SizedBox(height: 32), - Card( - elevation: isMobile(context) ? 1 : 0, - margin: EdgeInsets.zero, - clipBehavior: Clip.antiAlias, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - children: [ - DetailsCardHeader( - title: 'Inventory', - trailing: TextButton.icon( - onPressed: () { - showDialog( - context: context, - builder: (context) => AddInventoryDialog( - onCreate: onAddItems, - ), - ); - }, - icon: const Icon(Icons.add), - label: const Text('Add items'), - ), - children: [ - Row( - children: [ - Text('Available: $availableItems'), - const SizedBox(width: 16), - Text('Total: ${items.length}'), - ], - ), - ], - ), - if (items.isNotEmpty) const Divider(), - if (items.isNotEmpty) - ListView.separated( - shrinkWrap: true, - itemCount: items.length, - itemBuilder: (context, index) { - final item = items[index]; - - return ListTile( - leading: - item.available ? checkedInIcon : checkedOutIcon, - title: Text('#${item.number}'), - trailing: Text(item.brand ?? 'Generic'), - ); - }, - separatorBuilder: (BuildContext context, int index) { - return const Divider(); - }, - ), - ], - ), - ), + ItemsCard( + items: items, + availableItemsCount: availableItems, + onAddItemsPressed: () { + showDialog( + context: context, + builder: (context) => AddInventoryDialog( + onCreate: onAddItems, + ), + ); + }, ), ], ); } } - -const checkedInIcon = Tooltip( - message: 'Available', - child: Icon(Icons.circle, color: Colors.green, size: 16), -); - -const checkedOutIcon = Tooltip( - message: 'Checked out', - child: Icon(Icons.circle, color: Colors.amber, size: 16), -); diff --git a/lib/src/features/inventory/widgets/inventory_details/details_card_header.widget.dart b/lib/src/features/inventory/widgets/inventory_details/items_card/details_card_header.widget.dart similarity index 100% rename from lib/src/features/inventory/widgets/inventory_details/details_card_header.widget.dart rename to lib/src/features/inventory/widgets/inventory_details/items_card/details_card_header.widget.dart diff --git a/lib/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart b/lib/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart new file mode 100644 index 0000000..1b0af71 --- /dev/null +++ b/lib/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:librarian_app/src/utils/media_query.dart'; + +import '../../../data/item.model.dart'; +import 'details_card_header.widget.dart'; + +class ItemsCard extends StatelessWidget { + const ItemsCard({ + super.key, + required this.items, + required this.availableItemsCount, + required this.onAddItemsPressed, + }); + + final List items; + final int availableItemsCount; + final void Function() onAddItemsPressed; + + @override + Widget build(BuildContext context) { + return Card( + elevation: isMobile(context) ? 1 : 0, + margin: EdgeInsets.zero, + clipBehavior: Clip.antiAlias, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + children: [ + DetailsCardHeader( + title: 'Inventory', + trailing: TextButton.icon( + onPressed: onAddItemsPressed, + icon: const Icon(Icons.add), + label: const Text('Add items'), + ), + children: [ + Row( + children: [ + Text('Available: $availableItemsCount'), + const SizedBox(width: 16), + Text('Total: ${items.length}'), + ], + ), + ], + ), + if (items.isNotEmpty) const Divider(), + if (items.isNotEmpty) + ListView.separated( + shrinkWrap: true, + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + + return ListTile( + leading: item.available ? checkedInIcon : checkedOutIcon, + title: Text('#${item.number}'), + trailing: Text(item.brand ?? 'Generic'), + ); + }, + separatorBuilder: (c, i) => const Divider(), + ), + ], + ), + ), + ); + } +} + +const checkedInIcon = Tooltip( + message: 'Available', + child: Icon(Icons.circle, color: Colors.green, size: 16), +); + +const checkedOutIcon = Tooltip( + message: 'Checked out', + child: Icon(Icons.circle, color: Colors.amber, size: 16), +); From f672355c2e1734c12407ca45be4bd246849e836a Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 11 Jul 2023 17:35:41 -0400 Subject: [PATCH 08/35] Refactor list panes --- .../borrowers_desktop_layout.widget.dart | 59 ++++++++++++++----- .../dashboard/borrowers_list_pane.widget.dart | 50 ---------------- .../widgets/dashboard/list_pane.widget.dart | 30 ++++++++++ .../inventory_desktop_layout.widget.dart | 51 +++++++--------- .../loans_desktop_layout.widget.dart | 51 +++++++--------- 5 files changed, 116 insertions(+), 125 deletions(-) delete mode 100644 lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart create mode 100644 lib/src/features/common/widgets/dashboard/list_pane.widget.dart diff --git a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart index 3989d71..aa74baf 100644 --- a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart @@ -1,27 +1,58 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/list_pane.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; import 'package:provider/provider.dart'; -class BorrowersDesktopLayout extends StatelessWidget { +import '../borrowers_view.widget.dart'; + +class BorrowersDesktopLayout extends StatefulWidget { const BorrowersDesktopLayout({super.key}); + @override + State createState() => _BorrowersDesktopLayoutState(); +} + +class _BorrowersDesktopLayoutState extends State { + String _searchFilter = ''; + @override Widget build(BuildContext context) { - return Consumer( - builder: (context, borrowers, child) { - return Row( - children: [ - BorrowersListPane(model: borrowers), - Expanded( - child: BorrowerDetailsPane( - borrower: borrowers.selectedBorrower, + return Row( + children: [ + Consumer( + builder: (context, borrowers, child) { + return ListPane( + header: PaneHeader( + child: SearchField( + onChanged: (value) { + setState(() => _searchFilter = value); + }, + onClearPressed: () { + setState(() => _searchFilter = ''); + borrowers.clearSelectedBorrower(); + }, + ), ), - ), - ], - ); - }, + child: BorrowersView( + model: borrowers, + searchFilter: _searchFilter, + ), + ); + }, + ), + Expanded( + child: Consumer( + builder: (context, borrowers, child) { + return BorrowerDetailsPane( + borrower: borrowers.selectedBorrower, + ); + }, + ), + ), + ], ); } } diff --git a/lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart b/lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart deleted file mode 100644 index 242afd4..0000000 --- a/lib/src/features/borrowers/widgets/dashboard/borrowers_list_pane.widget.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; -import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; - -import '../borrowers_view.widget.dart'; - -class BorrowersListPane extends StatefulWidget { - const BorrowersListPane({super.key, required this.model}); - - final BorrowersViewModel model; - - @override - State createState() => _BorrowersListPaneState(); -} - -class _BorrowersListPaneState extends State { - String _searchFilter = ''; - - @override - Widget build(BuildContext context) { - return Card( - clipBehavior: Clip.antiAlias, - child: SizedBox( - width: 500, - child: Column( - children: [ - PaneHeader( - child: SearchField( - onChanged: (value) { - setState(() => _searchFilter = value); - }, - onClearPressed: () { - setState(() => _searchFilter = ''); - widget.model.clearSelectedBorrower(); - }, - ), - ), - Expanded( - child: BorrowersView( - model: widget.model, - searchFilter: _searchFilter, - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/src/features/common/widgets/dashboard/list_pane.widget.dart b/lib/src/features/common/widgets/dashboard/list_pane.widget.dart new file mode 100644 index 0000000..e1b0825 --- /dev/null +++ b/lib/src/features/common/widgets/dashboard/list_pane.widget.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +import 'pane_header.widget.dart'; + +class ListPane extends StatelessWidget { + const ListPane({ + super.key, + required this.header, + required this.child, + }); + + final PaneHeader header; + final Widget child; + + @override + Widget build(BuildContext context) { + return Card( + clipBehavior: Clip.antiAlias, + child: SizedBox( + width: 500, + child: Column( + children: [ + header, + Expanded(child: child), + ], + ), + ), + ); + } +} diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart index af5aa6f..b3378df 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/list_pane.widget.dart'; import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; -import 'package:librarian_app/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart'; -import 'package:provider/provider.dart'; +import 'inventory_details_pane.widget.dart'; import '../../data/inventory.vm.dart'; import '../inventory_list/inventory_list_view.widget.dart'; @@ -21,35 +22,23 @@ class _InventoryDesktopLayoutState extends State { Widget build(BuildContext context) { return Row( children: [ - Card( - clipBehavior: Clip.antiAlias, - child: SizedBox( - width: 500, - child: Consumer( - builder: (context, model, child) { - return Column( - children: [ - PaneHeader( - child: SearchField( - onChanged: (value) { - setState(() => _searchFilter = value); - }, - onClearPressed: () { - setState(() => _searchFilter = ''); - model.clearSelection(); - }, - ), - ), - Expanded( - child: InventoryListView( - searchFilter: _searchFilter, - ), - ), - ], - ); - }, - ), - ), + Consumer( + builder: (context, inventory, child) { + return ListPane( + header: PaneHeader( + child: SearchField( + onChanged: (value) { + setState(() => _searchFilter = value); + }, + onClearPressed: () { + setState(() => _searchFilter = ''); + inventory.clearSelection(); + }, + ), + ), + child: InventoryListView(searchFilter: _searchFilter), + ); + }, ), Expanded( child: Consumer( diff --git a/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart b/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart index 7e5c615..b8981ce 100644 --- a/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart +++ b/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/common/widgets/dashboard/list_pane.widget.dart'; import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart'; @@ -21,36 +22,26 @@ class _LoansDesktopLayoutState extends State { Widget build(BuildContext context) { return Row( children: [ - Card( - clipBehavior: Clip.antiAlias, - child: SizedBox( - width: 500, - child: Consumer( - builder: (context, model, child) { - return Column( - children: [ - PaneHeader( - child: SearchField( - onChanged: (value) { - setState(() => _searchFilter = value); - }, - onClearPressed: () { - setState(() => _searchFilter = ''); - model.clearSelectedLoan(); - }, - ), - ), - Expanded( - child: LoansView( - model: model, - searchFilter: _searchFilter, - ), - ), - ], - ); - }, - ), - ), + Consumer( + builder: (context, loans, child) { + return ListPane( + header: PaneHeader( + child: SearchField( + onChanged: (value) { + setState(() => _searchFilter = value); + }, + onClearPressed: () { + setState(() => _searchFilter = ''); + loans.clearSelectedLoan(); + }, + ), + ), + child: LoansView( + model: loans, + searchFilter: _searchFilter, + ), + ); + }, ), Expanded( child: Consumer( From cf17d2cc43d4ab53f0bf4122288fc74be806e97f Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Wed, 12 Jul 2023 08:29:11 -0400 Subject: [PATCH 09/35] Show loading indicator while things are loading; InventoryService --- .../inventory/data/inventory.repo.dart | 15 ++++ .../features/inventory/data/inventory.vm.dart | 45 ++++++------ .../inventory/services/inventory.service.dart | 68 +++++++++++++++++++ .../inventory_list_view.widget.dart | 8 ++- 4 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 lib/src/features/inventory/services/inventory.service.dart diff --git a/lib/src/features/inventory/data/inventory.repo.dart b/lib/src/features/inventory/data/inventory.repo.dart index 98e6211..482502b 100644 --- a/lib/src/features/inventory/data/inventory.repo.dart +++ b/lib/src/features/inventory/data/inventory.repo.dart @@ -13,6 +13,21 @@ class InventoryRepository { things = objects.map((e) => ThingModel.fromJson(e)).toList(); } + List getCachedThings({String? filter}) { + if (filter == null || filter.isEmpty) { + return things; + } + + return things + .where((t) => t.name.toLowerCase().contains(filter.toLowerCase())) + .toList(); + } + + Future> getThings({String? filter}) async { + await refresh(); + return getCachedThings(filter: filter); + } + Future getThingDetails({required String id}) async { final response = await LendingApi.fetchThing(id: id); return DetailedThingModel.fromJson(response.data as Map); diff --git a/lib/src/features/inventory/data/inventory.vm.dart b/lib/src/features/inventory/data/inventory.vm.dart index adf97d9..ad27950 100644 --- a/lib/src/features/inventory/data/inventory.vm.dart +++ b/lib/src/features/inventory/data/inventory.vm.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory.repo.dart'; +import 'package:librarian_app/src/features/inventory/services/inventory.service.dart'; import 'thing.model.dart'; @@ -9,6 +9,17 @@ class InventoryViewModel extends ChangeNotifier { refresh(); } + final _service = InventoryService(); + + bool _refreshing = false; + + bool get refreshing => _refreshing; + + set refreshing(bool value) { + _refreshing = value; + notifyListeners(); + } + bool _editing = false; bool get editing => _editing; @@ -18,34 +29,29 @@ class InventoryViewModel extends ChangeNotifier { notifyListeners(); } - final _repository = InventoryRepository(); - - List get things => _repository.things; + List get things => _service.cachedThings; String? selectedId; - ThingModel? get selected => - selectedId != null ? things.firstWhere((t) => t.id == selectedId) : null; + ThingModel? get selected => _service.getCachedThing(id: selectedId); - List filtered(String filter) { - if (filter.isEmpty) { - return things; - } + List getCachedThings({String? filter}) { + return _service.getCachedThings(filter: filter); + } - return things - .where((t) => t.name.toLowerCase().contains(filter.toLowerCase())) - .toList(); + Future> getThings({String? filter}) async { + return await _service.getThings(filter: filter); } Future getThingDetails({required String id}) async { - return await _repository.getThingDetails(id: id); + return await _service.getThingDetails(id: id); } Future createThing({ required String name, String? spanishName, }) async { - final thing = await _repository.createThing( + final thing = await _service.createThing( name: name, spanishName: spanishName, ); @@ -60,7 +66,7 @@ class InventoryViewModel extends ChangeNotifier { String? name, String? spanishName, }) async { - await _repository.updateThing( + await _service.updateThing( thingId: thingId, name: name, spanishName: spanishName, @@ -76,7 +82,7 @@ class InventoryViewModel extends ChangeNotifier { required String? description, required double? estimatedValue, }) async { - await _repository.createItems( + await _service.createItems( thingId: thingId, quantity: quantity, brand: brand, @@ -99,7 +105,8 @@ class InventoryViewModel extends ChangeNotifier { } Future refresh() async { - await _repository.refresh(); - notifyListeners(); + refreshing = true; + await _service.updateCachedThings(); + refreshing = false; } } diff --git a/lib/src/features/inventory/services/inventory.service.dart b/lib/src/features/inventory/services/inventory.service.dart new file mode 100644 index 0000000..7940f72 --- /dev/null +++ b/lib/src/features/inventory/services/inventory.service.dart @@ -0,0 +1,68 @@ +import '../data/detailed_thing.model.dart'; +import '../data/inventory.repo.dart'; +import '../data/thing.model.dart'; + +class InventoryService { + final _repository = InventoryRepository(); + + List get cachedThings => _repository.things; + + Future updateCachedThings() async { + await _repository.refresh(); + } + + ThingModel? getCachedThing({required String? id}) { + if (id == null || id.isEmpty || _repository.things.isEmpty) { + return null; + } + + return _repository.things.firstWhere((t) => t.id == id); + } + + List getCachedThings({String? filter}) { + return _repository.getCachedThings(filter: filter); + } + + Future> getThings({String? filter}) async { + return await _repository.getThings(filter: filter); + } + + Future getThingDetails({required String id}) async { + return await _repository.getThingDetails(id: id); + } + + Future createThing({ + required String name, + String? spanishName, + }) async { + return await _repository.createThing(name: name, spanishName: spanishName); + } + + Future updateThing({ + required String thingId, + String? name, + String? spanishName, + }) async { + return await _repository.updateThing( + thingId: thingId, + name: name, + spanishName: spanishName, + ); + } + + Future createItems({ + required String thingId, + required int quantity, + required String? brand, + required String? description, + required double? estimatedValue, + }) async { + return await _repository.createItems( + thingId: thingId, + quantity: quantity, + brand: brand, + description: description, + estimatedValue: estimatedValue, + ); + } +} diff --git a/lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart b/lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart index ae8dbdd..67f838a 100644 --- a/lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_list/inventory_list_view.widget.dart @@ -19,10 +19,14 @@ class InventoryListView extends StatelessWidget { Widget build(BuildContext context) { return Consumer( builder: (context, model, child) { - final things = model.filtered(searchFilter); + if (model.refreshing) { + return const Center(child: CircularProgressIndicator()); + } + + final things = model.getCachedThings(filter: searchFilter); if (things.isEmpty) { - return const Center(child: Text('No results found')); + return const Center(child: Text('Nothing to see here')); } return InventoryList( From abc282d0347414c4ec858f2a2ac31de0f55783fe Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Wed, 12 Jul 2023 09:33:20 -0400 Subject: [PATCH 10/35] Remove action from borrowers add button --- lib/src/features/dashboard/pages/dashboard.page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/features/dashboard/pages/dashboard.page.dart b/lib/src/features/dashboard/pages/dashboard.page.dart index 3b0273d..c9bea48 100644 --- a/lib/src/features/dashboard/pages/dashboard.page.dart +++ b/lib/src/features/dashboard/pages/dashboard.page.dart @@ -68,7 +68,7 @@ class _DashboardPageState extends State { ), floatingActionButton: getFloatingActionButton( tooltip: 'Coming Soon', - onPressed: () {}, + onPressed: null, ), ), DashboardModule( @@ -192,7 +192,7 @@ class DashboardModule { } FloatingActionButton getFloatingActionButton({ - required void Function() onPressed, + required void Function()? onPressed, String? tooltip, }) { return FloatingActionButton.small( From b4bdcbc61ae704f50ee32948ab78bb137b5dfef2 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Wed, 12 Jul 2023 09:37:40 -0400 Subject: [PATCH 11/35] Move pane widgets into dashboard feature --- .../widgets/dashboard/borrower_details_pane.widget.dart | 2 +- .../widgets/dashboard/borrowers_desktop_layout.widget.dart | 4 ++-- .../widgets/panes}/list_pane.widget.dart | 0 .../widgets/panes}/pane_header.widget.dart | 0 .../widgets/dashboard/inventory_desktop_layout.widget.dart | 4 ++-- .../widgets/dashboard/inventory_details_pane.widget.dart | 2 +- .../loans/widgets/dashboard/loan_details_pane.widget.dart | 2 +- .../loans/widgets/dashboard/loans_desktop_layout.widget.dart | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) rename lib/src/features/{common/widgets/dashboard => dashboard/widgets/panes}/list_pane.widget.dart (100%) rename lib/src/features/{common/widgets/dashboard => dashboard/widgets/panes}/pane_header.widget.dart (100%) diff --git a/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart b/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart index b24ceb1..613913e 100644 --- a/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrower_details.widget.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import '../../data/borrower.model.dart'; diff --git a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart index aa74baf..230e949 100644 --- a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/list_pane.widget.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:provider/provider.dart'; import '../borrowers_view.widget.dart'; diff --git a/lib/src/features/common/widgets/dashboard/list_pane.widget.dart b/lib/src/features/dashboard/widgets/panes/list_pane.widget.dart similarity index 100% rename from lib/src/features/common/widgets/dashboard/list_pane.widget.dart rename to lib/src/features/dashboard/widgets/panes/list_pane.widget.dart diff --git a/lib/src/features/common/widgets/dashboard/pane_header.widget.dart b/lib/src/features/dashboard/widgets/panes/pane_header.widget.dart similarity index 100% rename from lib/src/features/common/widgets/dashboard/pane_header.widget.dart rename to lib/src/features/dashboard/widgets/panes/pane_header.widget.dart diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart index b3378df..3e18f12 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:provider/provider.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/list_pane.widget.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; import 'inventory_details_pane.widget.dart'; diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart b/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart index d281ce4..730f864 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart +++ b/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; diff --git a/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart index d2332d0..cef2e49 100644 --- a/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import '../../data/loan.model.dart'; import '../../widgets/checkin_dialog.widget.dart'; diff --git a/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart b/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart index b8981ce..6283916 100644 --- a/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart +++ b/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/list_pane.widget.dart'; -import 'package:librarian_app/src/features/common/widgets/dashboard/pane_header.widget.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.widget.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/loans_view.widget.dart'; import 'package:provider/provider.dart'; From c981f52aef26f82814057fe7912c1eea5820a8de Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Wed, 12 Jul 2023 23:56:02 -0400 Subject: [PATCH 12/35] Organize loans widgets --- lib/src/features/dashboard/pages/dashboard.page.dart | 6 +++--- .../inventory_details_pane.widget.dart | 2 +- .../inventory_desktop_layout.widget.dart | 2 +- lib/src/features/loans/pages/loan_details.page.dart | 2 +- lib/src/features/loans/pages/open_loan.page.dart | 4 ++-- .../loans/widgets/{ => checkin}/checkin_dialog.widget.dart | 0 .../loans/widgets/checkout/checkout_stepper.widget.dart | 2 +- .../loans/widgets/{ => checkout}/pick_things.widget.dart | 6 +++--- .../{dashboard => layouts}/loans_desktop_layout.widget.dart | 4 ++-- .../widgets/{ => loan_details}/loan_details.widget.dart | 0 .../loan_details_pane.widget.dart | 6 +++--- .../widgets/{ => loan_details}/thing_number.widget.dart | 0 .../{ => loans_list}/connected_loans_list.widget.dart | 6 +++--- .../loans/widgets/{ => loans_list}/loans_list.widget.dart | 2 +- .../loans/widgets/{ => loans_list}/loans_view.widget.dart | 6 +++--- .../{ => loans_list}/searchable_loans_list.widget.dart | 2 +- .../widgets/{ => things_list}/thing_list_tile.widget.dart | 0 .../loans/widgets/{ => things_list}/things_list.widget.dart | 4 ++-- 18 files changed, 27 insertions(+), 27 deletions(-) rename lib/src/features/inventory/widgets/{dashboard => inventory_details}/inventory_details_pane.widget.dart (98%) rename lib/src/features/inventory/widgets/{dashboard => layouts}/inventory_desktop_layout.widget.dart (96%) rename lib/src/features/loans/widgets/{ => checkin}/checkin_dialog.widget.dart (100%) rename lib/src/features/loans/widgets/{ => checkout}/pick_things.widget.dart (95%) rename lib/src/features/loans/widgets/{dashboard => layouts}/loans_desktop_layout.widget.dart (92%) rename lib/src/features/loans/widgets/{ => loan_details}/loan_details.widget.dart (100%) rename lib/src/features/loans/widgets/{dashboard => loan_details}/loan_details_pane.widget.dart (96%) rename lib/src/features/loans/widgets/{ => loan_details}/thing_number.widget.dart (100%) rename lib/src/features/loans/widgets/{ => loans_list}/connected_loans_list.widget.dart (77%) rename lib/src/features/loans/widgets/{ => loans_list}/loans_list.widget.dart (98%) rename lib/src/features/loans/widgets/{ => loans_list}/loans_view.widget.dart (88%) rename lib/src/features/loans/widgets/{ => loans_list}/searchable_loans_list.widget.dart (92%) rename lib/src/features/loans/widgets/{ => things_list}/thing_list_tile.widget.dart (100%) rename lib/src/features/loans/widgets/{ => things_list}/things_list.widget.dart (91%) diff --git a/lib/src/features/dashboard/pages/dashboard.page.dart b/lib/src/features/dashboard/pages/dashboard.page.dart index c9bea48..f01fd18 100644 --- a/lib/src/features/dashboard/pages/dashboard.page.dart +++ b/lib/src/features/dashboard/pages/dashboard.page.dart @@ -3,14 +3,14 @@ import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrowers import 'package:librarian_app/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; -import 'package:librarian_app/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart'; import 'package:librarian_app/src/features/inventory/pages/inventory_details.page.dart'; import 'package:librarian_app/src/features/inventory/widgets/inventory_list/searchable_inventory_list.widget.dart'; import 'package:librarian_app/src/features/inventory/widgets/dialogs/create_thing_dialog.widget.dart'; import 'package:librarian_app/src/features/loans/pages/checkout.page.dart'; import 'package:librarian_app/src/features/loans/pages/loan_details.page.dart'; -import 'package:librarian_app/src/features/loans/widgets/searchable_loans_list.widget.dart'; -import 'package:librarian_app/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_list/searchable_loans_list.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/layouts/loans_desktop_layout.widget.dart'; import 'package:librarian_app/src/utils/media_query.dart'; import 'package:provider/provider.dart'; diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart similarity index 98% rename from lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart rename to lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart index 730f864..a8392a9 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_details_pane.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart @@ -4,7 +4,7 @@ import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.d import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; import '../../data/thing.model.dart'; -import '../inventory_details/inventory_details.widget.dart'; +import 'inventory_details.widget.dart'; class InventoryDetailsPane extends StatefulWidget { final ThingModel? thing; diff --git a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart similarity index 96% rename from lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart rename to lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart index 3e18f12..7c6df6b 100644 --- a/lib/src/features/inventory/widgets/dashboard/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart @@ -3,7 +3,7 @@ import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.wid import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:provider/provider.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; -import 'inventory_details_pane.widget.dart'; +import '../inventory_details/inventory_details_pane.widget.dart'; import '../../data/inventory.vm.dart'; import '../inventory_list/inventory_list_view.widget.dart'; diff --git a/lib/src/features/loans/pages/loan_details.page.dart b/lib/src/features/loans/pages/loan_details.page.dart index f00216c..4d8c49f 100644 --- a/lib/src/features/loans/pages/loan_details.page.dart +++ b/lib/src/features/loans/pages/loan_details.page.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; -import 'package:librarian_app/src/features/loans/widgets/loan_details.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; import 'package:provider/provider.dart'; import '../data/loan.model.dart'; diff --git a/lib/src/features/loans/pages/open_loan.page.dart b/lib/src/features/loans/pages/open_loan.page.dart index c92c19d..681ece5 100644 --- a/lib/src/features/loans/pages/open_loan.page.dart +++ b/lib/src/features/loans/pages/open_loan.page.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; -import 'package:librarian_app/src/features/loans/widgets/pick_things.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/checkout/pick_things.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; -import 'package:librarian_app/src/features/loans/widgets/loan_details.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart'; import 'package:provider/provider.dart'; diff --git a/lib/src/features/loans/widgets/checkin_dialog.widget.dart b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/checkin_dialog.widget.dart rename to lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart diff --git a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart index 005875a..19c05a1 100644 --- a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart +++ b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart @@ -6,7 +6,7 @@ import 'package:librarian_app/src/features/borrowers/widgets/borrower_search_del import 'package:librarian_app/src/features/loans/data/thing.model.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/checkout_controller.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart'; -import 'package:librarian_app/src/features/loans/widgets/loan_details.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; import 'package:provider/provider.dart'; class CheckoutStepper extends StatefulWidget { diff --git a/lib/src/features/loans/widgets/pick_things.widget.dart b/lib/src/features/loans/widgets/checkout/pick_things.widget.dart similarity index 95% rename from lib/src/features/loans/widgets/pick_things.widget.dart rename to lib/src/features/loans/widgets/checkout/pick_things.widget.dart index 2d9256c..add4f79 100644 --- a/lib/src/features/loans/widgets/pick_things.widget.dart +++ b/lib/src/features/loans/widgets/checkout/pick_things.widget.dart @@ -3,9 +3,9 @@ import 'package:flutter/services.dart'; import 'package:librarian_app/src/features/loans/data/things.vm.dart'; import 'package:provider/provider.dart'; -import '../../common/widgets/submit_text_field.widget.dart'; -import '../data/thing.model.dart'; -import '../widgets/thing_list_tile.widget.dart'; +import '../../../common/widgets/submit_text_field.widget.dart'; +import '../../data/thing.model.dart'; +import '../things_list/thing_list_tile.widget.dart'; class PickThingsView extends StatefulWidget { const PickThingsView({ diff --git a/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart b/lib/src/features/loans/widgets/layouts/loans_desktop_layout.widget.dart similarity index 92% rename from lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart rename to lib/src/features/loans/widgets/layouts/loans_desktop_layout.widget.dart index 6283916..03a72a9 100644 --- a/lib/src/features/loans/widgets/dashboard/loans_desktop_layout.widget.dart +++ b/lib/src/features/loans/widgets/layouts/loans_desktop_layout.widget.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; -import 'package:librarian_app/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart'; -import 'package:librarian_app/src/features/loans/widgets/loans_view.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_list/loans_view.widget.dart'; import 'package:provider/provider.dart'; import '../../data/loans.vm.dart'; diff --git a/lib/src/features/loans/widgets/loan_details.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/loan_details.widget.dart rename to lib/src/features/loans/widgets/loan_details/loan_details.widget.dart diff --git a/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart similarity index 96% rename from lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart rename to lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index cef2e49..4d58a7a 100644 --- a/lib/src/features/loans/widgets/dashboard/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import '../../data/loan.model.dart'; -import '../../widgets/checkin_dialog.widget.dart'; -import '../../widgets/loan_details.widget.dart'; -import '../../widgets/thing_number.widget.dart'; +import '../checkin/checkin_dialog.widget.dart'; +import 'loan_details.widget.dart'; +import 'thing_number.widget.dart'; class LoanDetailsPane extends StatefulWidget { final LoanModel? loan; diff --git a/lib/src/features/loans/widgets/thing_number.widget.dart b/lib/src/features/loans/widgets/loan_details/thing_number.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/thing_number.widget.dart rename to lib/src/features/loans/widgets/loan_details/thing_number.widget.dart diff --git a/lib/src/features/loans/widgets/connected_loans_list.widget.dart b/lib/src/features/loans/widgets/loans_list/connected_loans_list.widget.dart similarity index 77% rename from lib/src/features/loans/widgets/connected_loans_list.widget.dart rename to lib/src/features/loans/widgets/loans_list/connected_loans_list.widget.dart index c973125..7b4c08b 100644 --- a/lib/src/features/loans/widgets/connected_loans_list.widget.dart +++ b/lib/src/features/loans/widgets/loans_list/connected_loans_list.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/widgets/loans_view.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_list/loans_view.widget.dart'; import 'package:provider/provider.dart'; -import '../data/loan.model.dart'; -import '../data/loans.vm.dart'; +import '../../data/loan.model.dart'; +import '../../data/loans.vm.dart'; class ConnectedLoansList extends StatelessWidget { final void Function(LoanModel loan)? onTap; diff --git a/lib/src/features/loans/widgets/loans_list.widget.dart b/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart similarity index 98% rename from lib/src/features/loans/widgets/loans_list.widget.dart rename to lib/src/features/loans/widgets/loans_list/loans_list.widget.dart index 6e4a902..25bd386 100644 --- a/lib/src/features/loans/widgets/loans_list.widget.dart +++ b/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/loan.model.dart'; +import '../../data/loan.model.dart'; class LoansList extends StatelessWidget { final List loans; diff --git a/lib/src/features/loans/widgets/loans_view.widget.dart b/lib/src/features/loans/widgets/loans_list/loans_view.widget.dart similarity index 88% rename from lib/src/features/loans/widgets/loans_view.widget.dart rename to lib/src/features/loans/widgets/loans_list/loans_view.widget.dart index d8a1a45..a55ae18 100644 --- a/lib/src/features/loans/widgets/loans_view.widget.dart +++ b/lib/src/features/loans/widgets/loans_list/loans_view.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import '../data/loan.model.dart'; -import '../data/loans.vm.dart'; -import '../widgets/loans_list.widget.dart'; +import '../../data/loan.model.dart'; +import '../../data/loans.vm.dart'; +import 'loans_list.widget.dart'; class LoansView extends StatelessWidget { const LoansView({ diff --git a/lib/src/features/loans/widgets/searchable_loans_list.widget.dart b/lib/src/features/loans/widgets/loans_list/searchable_loans_list.widget.dart similarity index 92% rename from lib/src/features/loans/widgets/searchable_loans_list.widget.dart rename to lib/src/features/loans/widgets/loans_list/searchable_loans_list.widget.dart index fe77a6c..df1e5a5 100644 --- a/lib/src/features/loans/widgets/searchable_loans_list.widget.dart +++ b/lib/src/features/loans/widgets/loans_list/searchable_loans_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/submit_text_field.widget.dart'; import 'package:librarian_app/src/features/loans/data/loan.model.dart'; -import 'package:librarian_app/src/features/loans/widgets/connected_loans_list.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_list/connected_loans_list.widget.dart'; class SearchableLoansList extends StatefulWidget { final Function(LoanModel)? onLoanTapped; diff --git a/lib/src/features/loans/widgets/thing_list_tile.widget.dart b/lib/src/features/loans/widgets/things_list/thing_list_tile.widget.dart similarity index 100% rename from lib/src/features/loans/widgets/thing_list_tile.widget.dart rename to lib/src/features/loans/widgets/things_list/thing_list_tile.widget.dart diff --git a/lib/src/features/loans/widgets/things_list.widget.dart b/lib/src/features/loans/widgets/things_list/things_list.widget.dart similarity index 91% rename from lib/src/features/loans/widgets/things_list.widget.dart rename to lib/src/features/loans/widgets/things_list/things_list.widget.dart index d143102..a7cdbea 100644 --- a/lib/src/features/loans/widgets/things_list.widget.dart +++ b/lib/src/features/loans/widgets/things_list/things_list.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/loans/data/things.vm.dart'; -import 'package:librarian_app/src/features/loans/widgets/thing_list_tile.widget.dart'; +import 'package:librarian_app/src/features/loans/widgets/things_list/thing_list_tile.widget.dart'; import 'package:provider/provider.dart'; -import '../data/thing.model.dart'; +import '../../data/thing.model.dart'; class ThingsListView extends StatefulWidget { const ThingsListView({ From 5c5fd2796c1147e074bc9a1230b537ad1cd3c57e Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Thu, 13 Jul 2023 07:08:39 -0400 Subject: [PATCH 13/35] Organize borrower widgets --- .../{ => borrower_details}/borrower_details.widget.dart | 4 ++-- .../{ => borrower_details}/borrower_issues.widget.dart | 6 +++--- .../borrowers/widgets/borrower_search_delegate.widget.dart | 2 +- .../widgets/{ => borrowers_list}/borrowers_list.widget.dart | 2 +- .../widgets/{ => borrowers_list}/borrowers_view.widget.dart | 4 ++-- .../connected_borrowers_list.widget.dart | 4 ++-- .../searchable_borrowers_list.widget.dart | 4 ++-- .../widgets/dashboard/borrower_details_pane.widget.dart | 2 +- .../widgets/dashboard/borrowers_desktop_layout.widget.dart | 2 +- .../borrowers/widgets/{ => dialogs}/dues_dialog.widget.dart | 0 .../widgets/{ => dialogs}/record_payment_dialog.widget.dart | 0 lib/src/features/dashboard/pages/dashboard.page.dart | 2 +- lib/src/features/loans/pages/open_loan.page.dart | 2 +- .../loans/widgets/checkout/checkout_stepper.widget.dart | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) rename lib/src/features/borrowers/widgets/{ => borrower_details}/borrower_details.widget.dart (96%) rename lib/src/features/borrowers/widgets/{ => borrower_details}/borrower_issues.widget.dart (93%) rename lib/src/features/borrowers/widgets/{ => borrowers_list}/borrowers_list.widget.dart (96%) rename lib/src/features/borrowers/widgets/{ => borrowers_list}/borrowers_view.widget.dart (92%) rename lib/src/features/borrowers/widgets/{ => borrowers_list}/connected_borrowers_list.widget.dart (89%) rename lib/src/features/borrowers/widgets/{ => borrowers_list}/searchable_borrowers_list.widget.dart (88%) rename lib/src/features/borrowers/widgets/{ => dialogs}/dues_dialog.widget.dart (100%) rename lib/src/features/borrowers/widgets/{ => dialogs}/record_payment_dialog.widget.dart (100%) diff --git a/lib/src/features/borrowers/widgets/borrower_details.widget.dart b/lib/src/features/borrowers/widgets/borrower_details/borrower_details.widget.dart similarity index 96% rename from lib/src/features/borrowers/widgets/borrower_details.widget.dart rename to lib/src/features/borrowers/widgets/borrower_details/borrower_details.widget.dart index 3e35dad..1bfe69b 100644 --- a/lib/src/features/borrowers/widgets/borrower_details.widget.dart +++ b/lib/src/features/borrowers/widgets/borrower_details/borrower_details.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/borrower_issues.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart'; -import '../data/borrower.model.dart'; +import '../../data/borrower.model.dart'; class BorrowerDetails extends StatefulWidget { final BorrowerModel borrower; diff --git a/lib/src/features/borrowers/widgets/borrower_issues.widget.dart b/lib/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart similarity index 93% rename from lib/src/features/borrowers/widgets/borrower_issues.widget.dart rename to lib/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart index 3847ccd..b65ffa0 100644 --- a/lib/src/features/borrowers/widgets/borrower_issues.widget.dart +++ b/lib/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../data/borrower.model.dart'; -import '../data/borrowers.vm.dart'; -import '../widgets/dues_dialog.widget.dart'; +import '../../data/borrower.model.dart'; +import '../../data/borrowers.vm.dart'; +import '../dialogs/dues_dialog.widget.dart'; class BorrowerIssues extends StatelessWidget { final String borrowerId; diff --git a/lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart b/lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart index 5de69c5..2172d3c 100644 --- a/lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart +++ b/lib/src/features/borrowers/widgets/borrower_search_delegate.widget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import '../data/borrower.model.dart'; import '../data/borrowers.vm.dart'; -import 'borrowers_view.widget.dart'; +import 'borrowers_list/borrowers_view.widget.dart'; class BorrowerSearchDelegate extends SearchDelegate { BorrowerSearchDelegate({required this.model}); diff --git a/lib/src/features/borrowers/widgets/borrowers_list.widget.dart b/lib/src/features/borrowers/widgets/borrowers_list/borrowers_list.widget.dart similarity index 96% rename from lib/src/features/borrowers/widgets/borrowers_list.widget.dart rename to lib/src/features/borrowers/widgets/borrowers_list/borrowers_list.widget.dart index 0c3d26f..fa3acaa 100644 --- a/lib/src/features/borrowers/widgets/borrowers_list.widget.dart +++ b/lib/src/features/borrowers/widgets/borrowers_list/borrowers_list.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/utils/media_query.dart'; -import '../data/borrower.model.dart'; +import '../../data/borrower.model.dart'; class BorrowersList extends StatefulWidget { final List borrowers; diff --git a/lib/src/features/borrowers/widgets/borrowers_view.widget.dart b/lib/src/features/borrowers/widgets/borrowers_list/borrowers_view.widget.dart similarity index 92% rename from lib/src/features/borrowers/widgets/borrowers_view.widget.dart rename to lib/src/features/borrowers/widgets/borrowers_list/borrowers_view.widget.dart index 8952e5c..bdae820 100644 --- a/lib/src/features/borrowers/widgets/borrowers_view.widget.dart +++ b/lib/src/features/borrowers/widgets/borrowers_list/borrowers_view.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; -import '../data/borrower.model.dart'; -import '../widgets/borrowers_list.widget.dart'; +import '../../data/borrower.model.dart'; +import 'borrowers_list.widget.dart'; class BorrowersView extends StatelessWidget { const BorrowersView({ diff --git a/lib/src/features/borrowers/widgets/connected_borrowers_list.widget.dart b/lib/src/features/borrowers/widgets/borrowers_list/connected_borrowers_list.widget.dart similarity index 89% rename from lib/src/features/borrowers/widgets/connected_borrowers_list.widget.dart rename to lib/src/features/borrowers/widgets/borrowers_list/connected_borrowers_list.widget.dart index af35bb4..de605f1 100644 --- a/lib/src/features/borrowers/widgets/connected_borrowers_list.widget.dart +++ b/lib/src/features/borrowers/widgets/borrowers_list/connected_borrowers_list.widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/borrowers_view.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrowers_list/borrowers_view.widget.dart'; import 'package:provider/provider.dart'; -import '../data/borrower.model.dart'; +import '../../data/borrower.model.dart'; class ConnectedBorrowersList extends StatelessWidget { final void Function(BorrowerModel)? onTap; diff --git a/lib/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart b/lib/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart similarity index 88% rename from lib/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart rename to lib/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart index 09ec9aa..550d443 100644 --- a/lib/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart +++ b/lib/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/connected_borrowers_list.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrowers_list/connected_borrowers_list.widget.dart'; -import '../../common/widgets/submit_text_field.widget.dart'; +import '../../../common/widgets/submit_text_field.widget.dart'; class SearchableBorrowersList extends StatefulWidget { final void Function(BorrowerModel borrower)? onTapBorrower; diff --git a/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart b/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart index 613913e..62aa152 100644 --- a/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/borrower_details.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/borrower_details.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import '../../data/borrower.model.dart'; diff --git a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart index 230e949..4d1387d 100644 --- a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart +++ b/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart @@ -6,7 +6,7 @@ import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.wid import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:provider/provider.dart'; -import '../borrowers_view.widget.dart'; +import '../borrowers_list/borrowers_view.widget.dart'; class BorrowersDesktopLayout extends StatefulWidget { const BorrowersDesktopLayout({super.key}); diff --git a/lib/src/features/borrowers/widgets/dues_dialog.widget.dart b/lib/src/features/borrowers/widgets/dialogs/dues_dialog.widget.dart similarity index 100% rename from lib/src/features/borrowers/widgets/dues_dialog.widget.dart rename to lib/src/features/borrowers/widgets/dialogs/dues_dialog.widget.dart diff --git a/lib/src/features/borrowers/widgets/record_payment_dialog.widget.dart b/lib/src/features/borrowers/widgets/dialogs/record_payment_dialog.widget.dart similarity index 100% rename from lib/src/features/borrowers/widgets/record_payment_dialog.widget.dart rename to lib/src/features/borrowers/widgets/dialogs/record_payment_dialog.widget.dart diff --git a/lib/src/features/dashboard/pages/dashboard.page.dart b/lib/src/features/dashboard/pages/dashboard.page.dart index f01fd18..123d689 100644 --- a/lib/src/features/dashboard/pages/dashboard.page.dart +++ b/lib/src/features/dashboard/pages/dashboard.page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; import 'package:librarian_app/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart'; diff --git a/lib/src/features/loans/pages/open_loan.page.dart b/lib/src/features/loans/pages/open_loan.page.dart index 681ece5..6297ac5 100644 --- a/lib/src/features/loans/pages/open_loan.page.dart +++ b/lib/src/features/loans/pages/open_loan.page.dart @@ -5,7 +5,7 @@ import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/pick_things.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/searchable_borrowers_list.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart'; import 'package:provider/provider.dart'; import '../data/thing.model.dart'; diff --git a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart index 19c05a1..0657dc0 100644 --- a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart +++ b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/borrower_issues.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrower_search_delegate.widget.dart'; import 'package:librarian_app/src/features/loans/data/thing.model.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/checkout_controller.dart'; From a5ed3592c8215ea5299726f547572d29d99dec44 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Thu, 13 Jul 2023 07:09:49 -0400 Subject: [PATCH 14/35] Move borrower details pane --- .../borrower_details_pane.widget.dart | 0 .../{dashboard => layouts}/borrowers_desktop_layout.widget.dart | 2 +- lib/src/features/dashboard/pages/dashboard.page.dart | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/src/features/borrowers/widgets/{dashboard => borrower_details}/borrower_details_pane.widget.dart (100%) rename lib/src/features/borrowers/widgets/{dashboard => layouts}/borrowers_desktop_layout.widget.dart (94%) diff --git a/lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart b/lib/src/features/borrowers/widgets/borrower_details/borrower_details_pane.widget.dart similarity index 100% rename from lib/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart rename to lib/src/features/borrowers/widgets/borrower_details/borrower_details_pane.widget.dart diff --git a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart b/lib/src/features/borrowers/widgets/layouts/borrowers_desktop_layout.widget.dart similarity index 94% rename from lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart rename to lib/src/features/borrowers/widgets/layouts/borrowers_desktop_layout.widget.dart index 4d1387d..7213c09 100644 --- a/lib/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart +++ b/lib/src/features/borrowers/widgets/layouts/borrowers_desktop_layout.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrower_details_pane.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/borrower_details_pane.widget.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; diff --git a/lib/src/features/dashboard/pages/dashboard.page.dart b/lib/src/features/dashboard/pages/dashboard.page.dart index 123d689..96fcec9 100644 --- a/lib/src/features/dashboard/pages/dashboard.page.dart +++ b/lib/src/features/dashboard/pages/dashboard.page.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/borrowers/widgets/dashboard/borrowers_desktop_layout.widget.dart'; +import 'package:librarian_app/src/features/borrowers/widgets/layouts/borrowers_desktop_layout.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; From fcba32f8026b83d481b9d13d6f1b793820ba8c74 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 14 Jul 2023 07:38:31 -0400 Subject: [PATCH 15/35] Remove ThingsViewModel --- lib/main.dart | 5 ----- .../inventory/data/inventory.repo.dart | 11 ++++++++++ .../features/inventory/data/item.model.dart | 3 +++ .../inventory/services/inventory.service.dart | 5 +++++ lib/src/features/loans/data/loan.model.dart | 5 ++--- lib/src/features/loans/data/loans.vm.dart | 10 ++++++++- lib/src/features/loans/data/loans_mapper.dart | 9 +++----- lib/src/features/loans/data/thing.model.dart | 13 ------------ .../loans/data/thing_summary.model.dart | 19 +++++++++++++++++ lib/src/features/loans/data/things.vm.dart | 21 ------------------- .../features/loans/pages/open_loan.page.dart | 16 +++++++++----- .../checkout/checkout_stepper.widget.dart | 15 +++++++++---- .../connected_thing_search_field.widget.dart | 12 +++++------ .../widgets/checkout/pick_things.widget.dart | 16 +++++++------- .../loan_details/loan_details.widget.dart | 6 +++--- .../things_list/things_list.widget.dart | 9 ++++---- 16 files changed, 95 insertions(+), 80 deletions(-) delete mode 100644 lib/src/features/loans/data/thing.model.dart create mode 100644 lib/src/features/loans/data/thing_summary.model.dart delete mode 100644 lib/src/features/loans/data/things.vm.dart diff --git a/lib/main.dart b/lib/main.dart index 7c7aa40..3a45125 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,8 +8,6 @@ import 'package:librarian_app/src/features/splash/pages/splash.page.dart'; import 'package:provider/provider.dart'; import 'package:supabase_flutter/supabase_flutter.dart' as supabase; -import 'src/features/loans/data/things.vm.dart'; - Future main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -29,9 +27,6 @@ Future main() async { ChangeNotifierProvider( create: (context) => BorrowersViewModel(), ), - ChangeNotifierProvider( - create: (context) => ThingsViewModel(), - ), ChangeNotifierProvider( create: (context) => InventoryViewModel(), ), diff --git a/lib/src/features/inventory/data/inventory.repo.dart b/lib/src/features/inventory/data/inventory.repo.dart index 482502b..bd4d1da 100644 --- a/lib/src/features/inventory/data/inventory.repo.dart +++ b/lib/src/features/inventory/data/inventory.repo.dart @@ -1,6 +1,8 @@ +import 'package:dio/dio.dart'; import 'package:librarian_app/src/features/common/data/lending_api.dart'; import 'detailed_thing.model.dart'; +import 'item.model.dart'; import 'thing.model.dart'; class InventoryRepository { @@ -33,6 +35,15 @@ class InventoryRepository { return DetailedThingModel.fromJson(response.data as Map); } + Future getItem({required int number}) async { + try { + final response = await LendingApi.fetchInventoryItem(number: number); + return ItemModel.fromJson(response.data as Map); + } on DioError { + return null; + } + } + Future createThing({ required String name, String? spanishName, diff --git a/lib/src/features/inventory/data/item.model.dart b/lib/src/features/inventory/data/item.model.dart index 7a48ed6..31a0ba5 100644 --- a/lib/src/features/inventory/data/item.model.dart +++ b/lib/src/features/inventory/data/item.model.dart @@ -2,6 +2,7 @@ class ItemModel { ItemModel({ required this.id, required this.number, + required this.name, required this.available, required this.totalLoans, this.brand, @@ -9,6 +10,7 @@ class ItemModel { final String id; final int number; + final String name; final String? brand; final bool available; final int totalLoans; @@ -17,6 +19,7 @@ class ItemModel { return ItemModel( id: json['id'] as String, number: json['number'] as int, + name: json['name'] as String? ?? 'Unknown Thing', available: json['available'] as bool, totalLoans: json['totalLoans'] as int, brand: json['brand'] as String?, diff --git a/lib/src/features/inventory/services/inventory.service.dart b/lib/src/features/inventory/services/inventory.service.dart index 7940f72..5f213d1 100644 --- a/lib/src/features/inventory/services/inventory.service.dart +++ b/lib/src/features/inventory/services/inventory.service.dart @@ -1,5 +1,6 @@ import '../data/detailed_thing.model.dart'; import '../data/inventory.repo.dart'; +import '../data/item.model.dart'; import '../data/thing.model.dart'; class InventoryService { @@ -31,6 +32,10 @@ class InventoryService { return await _repository.getThingDetails(id: id); } + Future getItem({required int number}) async { + return await _repository.getItem(number: number); + } + Future createThing({ required String name, String? spanishName, diff --git a/lib/src/features/loans/data/loan.model.dart b/lib/src/features/loans/data/loan.model.dart index 8bcd699..bb642cf 100644 --- a/lib/src/features/loans/data/loan.model.dart +++ b/lib/src/features/loans/data/loan.model.dart @@ -1,11 +1,10 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; - -import 'thing.model.dart'; +import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; class LoanModel { final String id; - final ThingModel thing; + final ThingSummaryModel thing; final BorrowerModel borrower; final DateTime checkedOutDate; DateTime dueDate; diff --git a/lib/src/features/loans/data/loans.vm.dart b/lib/src/features/loans/data/loans.vm.dart index f0dd018..3ae12be 100644 --- a/lib/src/features/loans/data/loans.vm.dart +++ b/lib/src/features/loans/data/loans.vm.dart @@ -2,6 +2,8 @@ import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:librarian_app/src/features/common/data/lending_api.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; +import 'package:librarian_app/src/features/inventory/services/inventory.service.dart'; import 'loan.model.dart'; import 'loans_mapper.dart'; @@ -11,6 +13,8 @@ class LoansViewModel extends ChangeNotifier { refresh(); } + final _inventoryService = InventoryService(); + String? errorMessage; bool _isLoading = false; @@ -32,7 +36,7 @@ class LoansViewModel extends ChangeNotifier { return _loans .where((l) => l.borrower.name.toLowerCase().contains(filter.toLowerCase()) || - l.thing.name!.toLowerCase().contains(filter.toLowerCase()) || + l.thing.name.toLowerCase().contains(filter.toLowerCase()) || l.thing.number == int.tryParse(filter)) .toList(); } @@ -56,6 +60,10 @@ class LoansViewModel extends ChangeNotifier { isLoading = false; } + Future getInventoryItem({required int number}) async { + return await _inventoryService.getItem(number: number); + } + Future> getLoans() async { final response = await LendingApi.fetchLoans(); return LoansMapper.map(response.data as List).toList(); diff --git a/lib/src/features/loans/data/loans_mapper.dart b/lib/src/features/loans/data/loans_mapper.dart index ec20212..394dbfa 100644 --- a/lib/src/features/loans/data/loans_mapper.dart +++ b/lib/src/features/loans/data/loans_mapper.dart @@ -1,16 +1,13 @@ +import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; + import '../../borrowers/data/borrower.model.dart'; import 'loan.model.dart'; -import 'thing.model.dart'; class LoansMapper { static Iterable map(Iterable data) { return data.map((e) => LoanModel( id: e['id'] as String? ?? '?', - thing: ThingModel( - name: e['thing']?['name'] as String? ?? '???', - id: e['thing']?['id'] as String? ?? '???', - number: e['thing']?['number'] as int? ?? 0, - ), + thing: ThingSummaryModel.fromJson(e['thing'] as Map), borrower: BorrowerModel( id: e['borrower']?['id'] as String? ?? '?', name: e['borrower']?['name'] as String? ?? '???', diff --git a/lib/src/features/loans/data/thing.model.dart b/lib/src/features/loans/data/thing.model.dart deleted file mode 100644 index 3ff1f6a..0000000 --- a/lib/src/features/loans/data/thing.model.dart +++ /dev/null @@ -1,13 +0,0 @@ -class ThingModel { - final String id; - final int number; - String? name; - bool available; - - ThingModel({ - required this.id, - required this.number, - required this.name, - this.available = true, - }); -} diff --git a/lib/src/features/loans/data/thing_summary.model.dart b/lib/src/features/loans/data/thing_summary.model.dart new file mode 100644 index 0000000..8cb01c8 --- /dev/null +++ b/lib/src/features/loans/data/thing_summary.model.dart @@ -0,0 +1,19 @@ +class ThingSummaryModel { + final String id; + final String name; + final int number; + + const ThingSummaryModel({ + required this.id, + required this.name, + required this.number, + }); + + factory ThingSummaryModel.fromJson(Map json) { + return ThingSummaryModel( + id: json['id'] as String, + name: json['name'] as String, + number: json['number'] as int, + ); + } +} diff --git a/lib/src/features/loans/data/things.vm.dart b/lib/src/features/loans/data/things.vm.dart deleted file mode 100644 index df477f8..0000000 --- a/lib/src/features/loans/data/things.vm.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/data/lending_api.dart'; - -import 'thing.model.dart'; - -class ThingsViewModel extends ChangeNotifier { - Future getOne({required int number}) async { - try { - final response = await LendingApi.fetchInventoryItem(number: number); - final data = response.data; - return ThingModel( - id: data['id'] as String, - number: data['number'] as int, - name: data['name'] as String, - available: data['available'] as bool, - ); - } catch (error) { - return null; - } - } -} diff --git a/lib/src/features/loans/pages/open_loan.page.dart b/lib/src/features/loans/pages/open_loan.page.dart index 6297ac5..168a9b4 100644 --- a/lib/src/features/loans/pages/open_loan.page.dart +++ b/lib/src/features/loans/pages/open_loan.page.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; +import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/pick_things.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/needs_attention_view.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrowers_list/searchable_borrowers_list.widget.dart'; import 'package:provider/provider.dart'; -import '../data/thing.model.dart'; - class OpenLoanPage extends StatefulWidget { const OpenLoanPage({super.key}); @@ -25,7 +25,7 @@ class _OpenLoanPageState extends State { Widget? _floatingActionButton; BorrowerModel _borrower = BorrowerModel(id: '', name: "Borrower", issues: []); - final List _things = []; + final List _things = []; DateTime _dueDate = DateTime.now().add(const Duration(days: 7)); void _configureView() { @@ -55,7 +55,13 @@ class _OpenLoanPageState extends State { padding: const EdgeInsets.all(16), child: LoanDetails( borrower: _borrower, - things: _things, + things: _things + .map((t) => ThingSummaryModel( + id: t.id, + name: t.name, + number: t.number, + )) + .toList(), checkedOutDate: DateTime.now(), dueDate: _dueDate, onDueDateUpdated: (newDate) { @@ -92,7 +98,7 @@ class _OpenLoanPageState extends State { setState(() => _currentView = OpenLoanView.borrowerNeedsAttention); } - void _onTapThing(ThingModel thing) { + void _onTapThing(ItemModel thing) { setState(() { if (_things.contains(thing)) { _things.remove(thing); diff --git a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart index 0657dc0..cb9b642 100644 --- a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart +++ b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart @@ -3,7 +3,8 @@ import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrower_search_delegate.widget.dart'; -import 'package:librarian_app/src/features/loans/data/thing.model.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; +import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/checkout_controller.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; @@ -21,7 +22,7 @@ class _CheckoutStepperState extends State { BorrowerModel? _borrower; DateTime _dueDate = DateTime.now().add(const Duration(days: 7)); - final List _things = []; + final List _things = []; void Function()? _onStepContinueFactory(int index) { switch (index) { @@ -169,7 +170,7 @@ class _CheckoutStepperState extends State { return Card( child: ListTile( leading: Text('#${thing.number}'), - title: Text(thing.name ?? 'Unknown'), + title: Text(thing.name), trailing: IconButton( icon: const Icon(Icons.remove_circle_rounded), onPressed: () { @@ -192,7 +193,13 @@ class _CheckoutStepperState extends State { padding: const EdgeInsets.only(top: 8), child: LoanDetails( borrower: _borrower, - things: _things, + things: _things + .map((t) => ThingSummaryModel( + id: t.id, + name: t.name, + number: t.number, + )) + .toList(), checkedOutDate: DateTime.now(), dueDate: _dueDate, onDueDateUpdated: (newDate) { diff --git a/lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart b/lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart index 1107ebf..406b8f9 100644 --- a/lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart +++ b/lib/src/features/loans/widgets/checkout/connected_thing_search_field.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/data/thing.model.dart'; -import 'package:librarian_app/src/features/loans/data/things.vm.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; import 'package:provider/provider.dart'; class ConnectedThingSearchField extends StatelessWidget { @@ -45,7 +45,7 @@ class ConnectedThingSearchField extends StatelessWidget { class ThingSearchController { final BuildContext context; - final void Function(ThingModel) onMatchFound; + final void Function(ItemModel) onMatchFound; bool isLoading = false; @@ -57,8 +57,8 @@ class ThingSearchController { Future search(String value) async { isLoading = true; - final thingsModel = Provider.of(context, listen: false); - final match = await thingsModel.getOne(number: int.parse(value)); + final loansModel = Provider.of(context, listen: false); + final match = await loansModel.getInventoryItem(number: int.parse(value)); isLoading = false; @@ -73,7 +73,7 @@ class ThingSearchController { } } - void _showThingCheckedOutDialog(ThingModel thing) { + void _showThingCheckedOutDialog(ItemModel thing) { showDialog( context: context, builder: (context) { diff --git a/lib/src/features/loans/widgets/checkout/pick_things.widget.dart b/lib/src/features/loans/widgets/checkout/pick_things.widget.dart index add4f79..afa9507 100644 --- a/lib/src/features/loans/widgets/checkout/pick_things.widget.dart +++ b/lib/src/features/loans/widgets/checkout/pick_things.widget.dart @@ -1,10 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:librarian_app/src/features/loans/data/things.vm.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; import 'package:provider/provider.dart'; import '../../../common/widgets/submit_text_field.widget.dart'; -import '../../data/thing.model.dart'; import '../things_list/thing_list_tile.widget.dart'; class PickThingsView extends StatefulWidget { @@ -14,8 +14,8 @@ class PickThingsView extends StatefulWidget { required this.onThingPicked, }); - final List pickedThings; - final Function(ThingModel thing) onThingPicked; + final List pickedThings; + final Function(ItemModel thing) onThingPicked; @override State createState() { @@ -30,8 +30,8 @@ class _PickThingsViewState extends State { Future _onSearchSubmitted(String value) async { setState(() => _isLoading = true); - final thingsModel = Provider.of(context, listen: false); - final match = await thingsModel.getOne(number: int.parse(value)); + final loansModel = Provider.of(context, listen: false); + final match = await loansModel.getInventoryItem(number: int.parse(value)); setState(() => _isLoading = false); @@ -48,7 +48,7 @@ class _PickThingsViewState extends State { _searchController.clear(); } - void _showThingCheckedOutDialog(ThingModel thing) { + void _showThingCheckedOutDialog(ItemModel thing) { showDialog( context: context, builder: (context) { @@ -115,7 +115,7 @@ class _PickThingsViewState extends State { return ThingListTile( number: thing.number, - name: thing.name ?? 'Unknown Thing', + name: thing.name, available: thing.available, selected: true, onTap: () => widget.onThingPicked(thing), diff --git a/lib/src/features/loans/widgets/loan_details/loan_details.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details.widget.dart index cb7feb6..0a7bc67 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details.widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; -import 'package:librarian_app/src/features/loans/data/thing.model.dart'; +import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; class LoanDetails extends StatelessWidget { const LoanDetails({ @@ -17,7 +17,7 @@ class LoanDetails extends StatelessWidget { final bool editable; final BorrowerModel? borrower; - final List things; + final List things; final DateTime checkedOutDate; final DateTime dueDate; final DateTime? checkedInDate; @@ -60,7 +60,7 @@ class LoanDetails extends StatelessWidget { margin: const EdgeInsets.only(bottom: 16), child: TextField( controller: TextEditingController( - text: '${thing.name ?? 'Unknown'} #${thing.number}'), + text: '${thing.name} #${thing.number}'), readOnly: true, decoration: const InputDecoration( icon: Icon(Icons.build_rounded), diff --git a/lib/src/features/loans/widgets/things_list/things_list.widget.dart b/lib/src/features/loans/widgets/things_list/things_list.widget.dart index a7cdbea..29c49de 100644 --- a/lib/src/features/loans/widgets/things_list/things_list.widget.dart +++ b/lib/src/features/loans/widgets/things_list/things_list.widget.dart @@ -1,17 +1,16 @@ import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/loans/data/things.vm.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; +import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; import 'package:librarian_app/src/features/loans/widgets/things_list/thing_list_tile.widget.dart'; import 'package:provider/provider.dart'; -import '../../data/thing.model.dart'; - class ThingsListView extends StatefulWidget { const ThingsListView({ super.key, required this.onTapThing, }); - final Function(ThingModel) onTapThing; + final Function(ItemModel) onTapThing; @override State createState() => _ThingsListViewState(); @@ -22,7 +21,7 @@ class _ThingsListViewState extends State { @override Widget build(BuildContext context) { - return Consumer( + return Consumer( builder: (context, model, child) { final things = []; From 6778687fbfd1fac830b6f8a44cdeb8bf8732cea7 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 14 Jul 2023 07:39:32 -0400 Subject: [PATCH 16/35] Remove unneeded null checks --- .../loans/widgets/loan_details/loan_details_pane.widget.dart | 2 +- .../features/loans/widgets/loans_list/loans_list.widget.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index 4d58a7a..c2ea00e 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -50,7 +50,7 @@ class _LoanDetailsPaneState extends State { ThingNumber(number: loan.thing.number), const SizedBox(width: 16), Text( - widget.loan!.thing.name!, + widget.loan!.thing.name, style: const TextStyle(fontSize: 24), ), ], diff --git a/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart b/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart index 25bd386..247c3e8 100644 --- a/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart +++ b/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart @@ -33,7 +33,7 @@ class LoansList extends StatelessWidget { final loan = loans[index]; final thingNumber = Text('#${loan.thing.number}'); - final thingName = Text(loan.thing.name ?? 'Unknown Thing'); + final thingName = Text(loan.thing.name); final borrowerInitials = _getBorrowerInitials(loan.borrower.name); return ListTile( From 0a46be236ad6482fa1adca5026646c2a5b66cfca Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 14 Jul 2023 07:48:11 -0400 Subject: [PATCH 17/35] Remove LoansMapper --- lib/src/features/loans/data/loan.model.dart | 21 +++++++++++++++ lib/src/features/loans/data/loans.vm.dart | 3 +-- lib/src/features/loans/data/loans_mapper.dart | 27 ------------------- 3 files changed, 22 insertions(+), 29 deletions(-) delete mode 100644 lib/src/features/loans/data/loans_mapper.dart diff --git a/lib/src/features/loans/data/loan.model.dart b/lib/src/features/loans/data/loan.model.dart index bb642cf..76ad763 100644 --- a/lib/src/features/loans/data/loan.model.dart +++ b/lib/src/features/loans/data/loan.model.dart @@ -25,4 +25,25 @@ class LoanModel { required this.dueDate, this.checkedInDate, }); + + factory LoanModel.fromJson(Map json) { + return LoanModel( + id: json['id'] as String? ?? '?', + thing: ThingSummaryModel.fromJson(json['thing'] as Map), + borrower: BorrowerModel( + id: json['borrower']?['id'] as String? ?? '?', + name: json['borrower']?['name'] as String? ?? '???', + issues: [], + ), + checkedOutDate: json['checkedOutDate'] != null + ? DateTime.parse(json['checkedOutDate'] as String) + : DateTime.now(), + checkedInDate: json['checkedInDate'] != null + ? DateTime.parse(json['checkedInDate'] as String) + : null, + dueDate: json['dueBackDate'] != null + ? DateTime.parse(json['dueBackDate']) + : DateTime.now(), + ); + } } diff --git a/lib/src/features/loans/data/loans.vm.dart b/lib/src/features/loans/data/loans.vm.dart index 3ae12be..3d411c2 100644 --- a/lib/src/features/loans/data/loans.vm.dart +++ b/lib/src/features/loans/data/loans.vm.dart @@ -6,7 +6,6 @@ import 'package:librarian_app/src/features/inventory/data/item.model.dart'; import 'package:librarian_app/src/features/inventory/services/inventory.service.dart'; import 'loan.model.dart'; -import 'loans_mapper.dart'; class LoansViewModel extends ChangeNotifier { LoansViewModel() { @@ -66,7 +65,7 @@ class LoansViewModel extends ChangeNotifier { Future> getLoans() async { final response = await LendingApi.fetchLoans(); - return LoansMapper.map(response.data as List).toList(); + return (response.data as List).map((e) => LoanModel.fromJson(e)).toList(); } LoanModel? _selectedLoan; diff --git a/lib/src/features/loans/data/loans_mapper.dart b/lib/src/features/loans/data/loans_mapper.dart deleted file mode 100644 index 394dbfa..0000000 --- a/lib/src/features/loans/data/loans_mapper.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; - -import '../../borrowers/data/borrower.model.dart'; -import 'loan.model.dart'; - -class LoansMapper { - static Iterable map(Iterable data) { - return data.map((e) => LoanModel( - id: e['id'] as String? ?? '?', - thing: ThingSummaryModel.fromJson(e['thing'] as Map), - borrower: BorrowerModel( - id: e['borrower']?['id'] as String? ?? '?', - name: e['borrower']?['name'] as String? ?? '???', - issues: [], - ), - checkedOutDate: e['checkedOutDate'] != null - ? DateTime.parse(e['checkedOutDate'] as String) - : DateTime.now(), - checkedInDate: e['checkedInDate'] != null - ? DateTime.parse(e['checkedInDate'] as String) - : null, - dueDate: e['dueBackDate'] != null - ? DateTime.parse(e['dueBackDate']) - : DateTime.now(), - )); - } -} From f6bd28bb6c6b4d9714887521139642bc9aeb9c0a Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 14 Jul 2023 12:51:36 -0400 Subject: [PATCH 18/35] Show loading indicator when checking in --- .../widgets/filled_progress_button.dart | 42 +++++++++++++++++++ .../inventory/data/inventory.repo.dart | 3 +- .../checkin/checkin_dialog.widget.dart | 41 +++++++++--------- .../loan_details_pane.widget.dart | 3 +- 4 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 lib/src/features/common/widgets/filled_progress_button.dart diff --git a/lib/src/features/common/widgets/filled_progress_button.dart b/lib/src/features/common/widgets/filled_progress_button.dart new file mode 100644 index 0000000..0c95e19 --- /dev/null +++ b/lib/src/features/common/widgets/filled_progress_button.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +class FilledProgressButton extends StatefulWidget { + const FilledProgressButton({ + super.key, + required this.child, + required this.onPressed, + }); + + final Widget child; + final void Function()? onPressed; + + @override + State createState() => _FilledProgressButtonState(); +} + +class _FilledProgressButtonState extends State { + bool _isLoading = false; + + @override + Widget build(BuildContext context) { + if (_isLoading) { + return FilledButton.icon( + onPressed: null, + icon: const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ), + label: widget.child, + ); + } + + return FilledButton( + onPressed: () { + setState(() => _isLoading = true); + widget.onPressed?.call(); + }, + child: widget.child, + ); + } +} diff --git a/lib/src/features/inventory/data/inventory.repo.dart b/lib/src/features/inventory/data/inventory.repo.dart index bd4d1da..2ce4924 100644 --- a/lib/src/features/inventory/data/inventory.repo.dart +++ b/lib/src/features/inventory/data/inventory.repo.dart @@ -1,4 +1,3 @@ -import 'package:dio/dio.dart'; import 'package:librarian_app/src/features/common/data/lending_api.dart'; import 'detailed_thing.model.dart'; @@ -39,7 +38,7 @@ class InventoryRepository { try { final response = await LendingApi.fetchInventoryItem(number: number); return ItemModel.fromJson(response.data as Map); - } on DioError { + } catch (_) { return null; } } diff --git a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart index 91856f8..82f097a 100644 --- a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart +++ b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/common/widgets/filled_progress_button.dart'; -class CheckinDialog extends StatelessWidget { +class CheckinDialog extends StatefulWidget { final int thingNumber; - final Function()? onCheckin; - final Function()? onPostCheckin; + final Future Function()? onCheckin; + final void Function()? onPostCheckin; const CheckinDialog({ super.key, @@ -12,29 +13,31 @@ class CheckinDialog extends StatelessWidget { this.onPostCheckin, }); + @override + State createState() => _CheckinDialogState(); +} + +class _CheckinDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text("Thing #$thingNumber"), - content: - Text("Are you sure you want to check Thing #$thingNumber back in?"), + title: Text("Thing #${widget.thingNumber}"), + content: Text( + "Are you sure you want to check Thing #${widget.thingNumber} back in?"), actions: [ - TextButton( + OutlinedButton( child: const Text("Cancel"), onPressed: () => Navigator.pop(context), ), - TextButton( - child: const Text("Yes"), - onPressed: () async { - await onCheckin?.call(); - - Future.delayed( - Duration.zero, - () { - Navigator.of(context).pop(); - onPostCheckin?.call(); - }, - ); + FilledProgressButton( + child: const Text('Yes'), + onPressed: () { + Future.delayed(const Duration(seconds: 2), () async { + await widget.onCheckin?.call(); + }).whenComplete(() { + Navigator.of(context).pop(); + widget.onPostCheckin?.call(); + }); }, ), ], diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index c2ea00e..6af4de6 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -65,7 +65,8 @@ class _LoanDetailsPaneState extends State { builder: (context) { return CheckinDialog( thingNumber: loan.thing.number, - onCheckin: widget.onCheckIn, + onCheckin: () async => + Future(widget.onCheckIn), ); }, ); From 2ce0e615a5b8071918b5c7f4dc6d882844a15e9e Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 14 Jul 2023 13:04:31 -0400 Subject: [PATCH 19/35] Make checkin dialog stateless again --- .../widgets/checkin/checkin_dialog.widget.dart | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart index 82f097a..9ef0a69 100644 --- a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart +++ b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/common/widgets/filled_progress_button.dart'; -class CheckinDialog extends StatefulWidget { +class CheckinDialog extends StatelessWidget { final int thingNumber; final Future Function()? onCheckin; final void Function()? onPostCheckin; @@ -13,17 +13,12 @@ class CheckinDialog extends StatefulWidget { this.onPostCheckin, }); - @override - State createState() => _CheckinDialogState(); -} - -class _CheckinDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text("Thing #${widget.thingNumber}"), - content: Text( - "Are you sure you want to check Thing #${widget.thingNumber} back in?"), + title: Text("Thing #$thingNumber"), + content: + Text("Are you sure you want to check Thing #$thingNumber back in?"), actions: [ OutlinedButton( child: const Text("Cancel"), @@ -33,10 +28,10 @@ class _CheckinDialogState extends State { child: const Text('Yes'), onPressed: () { Future.delayed(const Duration(seconds: 2), () async { - await widget.onCheckin?.call(); + await onCheckin?.call(); }).whenComplete(() { Navigator.of(context).pop(); - widget.onPostCheckin?.call(); + onPostCheckin?.call(); }); }, ), From 3df3ff7e108d8940e6423df0cb5093890a1d7da2 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 14 Jul 2023 13:47:09 -0400 Subject: [PATCH 20/35] Show progress after clicking confirm --- .../widgets/checkout/checkout_stepper.widget.dart | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart index cb9b642..32ec5c7 100644 --- a/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart +++ b/lib/src/features/loans/widgets/checkout/checkout_stepper.widget.dart @@ -3,6 +3,7 @@ import 'package:librarian_app/src/features/borrowers/data/borrower.model.dart'; import 'package:librarian_app/src/features/borrowers/data/borrowers.vm.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/borrower_issues.widget.dart'; import 'package:librarian_app/src/features/borrowers/widgets/borrower_search_delegate.widget.dart'; +import 'package:librarian_app/src/features/common/widgets/filled_progress_button.dart'; import 'package:librarian_app/src/features/inventory/data/item.model.dart'; import 'package:librarian_app/src/features/loans/data/thing_summary.model.dart'; import 'package:librarian_app/src/features/loans/widgets/checkout/checkout_controller.dart'; @@ -74,10 +75,15 @@ class _CheckoutStepperState extends State { padding: const EdgeInsets.only(top: 16), child: Row( children: [ - FilledButton( - onPressed: details.onStepContinue, - child: Text(details.stepIndex == 2 ? 'Confirm' : 'Continue'), - ), + details.stepIndex != 2 + ? FilledButton( + onPressed: details.onStepContinue, + child: const Text('Continue'), + ) + : FilledProgressButton( + onPressed: details.onStepContinue, + child: const Text('Confirm'), + ), ], ), ); From ccb0dd342537b9dc56a190862f769dd8e87fbd7b Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Mon, 17 Jul 2023 19:26:31 -0400 Subject: [PATCH 21/35] Load name from thing details --- .../inventory_details_pane.widget.dart | 21 ++++++++++--------- .../inventory_desktop_layout.widget.dart | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart index a8392a9..4d0bfe8 100644 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart @@ -3,16 +3,15 @@ import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.w import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; -import '../../data/thing.model.dart'; import 'inventory_details.widget.dart'; class InventoryDetailsPane extends StatefulWidget { - final ThingModel? thing; + final String? thingId; final InventoryViewModel model; const InventoryDetailsPane({ super.key, - required this.thing, + required this.thingId, required this.model, }); @@ -23,7 +22,7 @@ class InventoryDetailsPane extends StatefulWidget { class _InventoryDetailsPaneState extends State { Future _save(String name, String spanishName) async { await widget.model.updateThing( - thingId: widget.thing!.id, + thingId: widget.thingId!, name: name, spanishName: spanishName, ); @@ -32,16 +31,14 @@ class _InventoryDetailsPaneState extends State { @override Widget build(BuildContext context) { - final thing = widget.thing; - final name = TextEditingController(text: thing?.name); - final spanishName = TextEditingController(text: thing?.spanishName); + final thing = widget.thingId; return Card( clipBehavior: Clip.antiAlias, child: thing == null ? const Center(child: Text('Inventory Details')) : FutureBuilder( - future: widget.model.getThingDetails(id: thing.id), + future: widget.model.getThingDetails(id: thing), builder: (context, snapshot) { if (snapshot.hasError) { return Center( @@ -55,6 +52,10 @@ class _InventoryDetailsPaneState extends State { final thingDetails = snapshot.data; + final name = TextEditingController(text: thingDetails!.name); + final spanishName = + TextEditingController(text: thingDetails.spanishName); + return Column( children: [ PaneHeader( @@ -64,7 +65,7 @@ class _InventoryDetailsPaneState extends State { Row( children: [ Text( - thingDetails!.name, + thingDetails.name, style: const TextStyle(fontSize: 24), ), ], @@ -116,7 +117,7 @@ class _InventoryDetailsPaneState extends State { quantity, ) async { await widget.model.createItems( - thingId: thing.id, + thingId: thing, quantity: quantity, brand: brand, description: description, diff --git a/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart index 7c6df6b..e12d01c 100644 --- a/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart @@ -44,7 +44,7 @@ class _InventoryDesktopLayoutState extends State { child: Consumer( builder: (context, inventory, child) { return InventoryDetailsPane( - thing: inventory.selected, + thingId: inventory.selected?.id, model: inventory, ); }, From b02c6678d76fa091e6e194af1aeb7944b7ce1e29 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Mon, 17 Jul 2023 19:43:15 -0400 Subject: [PATCH 22/35] Show unsaved changes text [loans] --- .../loan_details/loan_details_pane.widget.dart | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index 6af4de6..b897c3f 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -74,7 +74,18 @@ class _LoanDetailsPaneState extends State { tooltip: 'Check in', icon: const Icon(Icons.check_circle_rounded), ), - if (_editMode && _newDueDate != null) + if (_editMode && _newDueDate != null) ...[ + Text( + 'Unsaved Changes', + style: Theme.of(context) + .textTheme + .labelMedium! + .copyWith( + color: Colors.white.withOpacity(0.8), + fontStyle: FontStyle.italic, + ), + ), + const SizedBox(width: 8), IconButton( onPressed: () { widget.onSave(_newDueDate!); @@ -83,6 +94,7 @@ class _LoanDetailsPaneState extends State { icon: const Icon(Icons.save_rounded), tooltip: 'Save', ), + ], const SizedBox(width: 4), _editMode ? IconButton( From f201b142665a99b44ec9f4eb658d0b51cb18416c Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Mon, 17 Jul 2023 20:07:42 -0400 Subject: [PATCH 23/35] Move checkin button, add divider [loans] --- .../loan_details_pane.widget.dart | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index b897c3f..37c8783 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -57,23 +57,6 @@ class _LoanDetailsPaneState extends State { ), Row( children: [ - if (!_editMode) - IconButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return CheckinDialog( - thingNumber: loan.thing.number, - onCheckin: () async => - Future(widget.onCheckIn), - ); - }, - ); - }, - tooltip: 'Check in', - icon: const Icon(Icons.check_circle_rounded), - ), if (_editMode && _newDueDate != null) ...[ Text( 'Unsaved Changes', @@ -105,9 +88,34 @@ class _LoanDetailsPaneState extends State { : IconButton( onPressed: () => setState(() => _editMode = true), - icon: const Icon(Icons.edit_rounded), + icon: const Icon(Icons.edit), tooltip: 'Edit', ), + SizedBox( + height: 24, + width: 24, + child: VerticalDivider( + color: Colors.white.withOpacity(0.3), + ), + ), + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return CheckinDialog( + thingNumber: loan.thing.number, + onCheckin: () async { + _reset(); + await Future(widget.onCheckIn); + }, + ); + }, + ); + }, + tooltip: 'Check in', + icon: const Icon(Icons.check_circle), + ), ], ) ], From 1ebf2cc6096ec0651e2b2065bce5f8b9c5346116 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 18 Jul 2023 08:30:38 -0400 Subject: [PATCH 24/35] Change checkin icon --- .../loans/widgets/loan_details/loan_details_pane.widget.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index 37c8783..921bc77 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -114,7 +114,7 @@ class _LoanDetailsPaneState extends State { ); }, tooltip: 'Check in', - icon: const Icon(Icons.check_circle), + icon: const Icon(Icons.library_add_check), ), ], ) From 7b18661163861327cc61101fe6e0858f2e9fe9c1 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Tue, 18 Jul 2023 08:39:00 -0400 Subject: [PATCH 25/35] Remove edit mode from loans details pane --- .../loan_details_pane.widget.dart | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index 921bc77..b682ce6 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -23,14 +23,16 @@ class LoanDetailsPane extends StatefulWidget { } class _LoanDetailsPaneState extends State { - bool _editMode = false; DateTime? _newDueDate; void _reset() { - _editMode = false; _newDueDate = null; } + bool _hasUnsavedChanges() { + return _newDueDate != null; + } + @override Widget build(BuildContext context) { final loan = widget.loan; @@ -57,7 +59,7 @@ class _LoanDetailsPaneState extends State { ), Row( children: [ - if (_editMode && _newDueDate != null) ...[ + if (_hasUnsavedChanges()) ...[ Text( 'Unsaved Changes', style: Theme.of(context) @@ -69,28 +71,25 @@ class _LoanDetailsPaneState extends State { ), ), const SizedBox(width: 8), - IconButton( - onPressed: () { - widget.onSave(_newDueDate!); - setState(_reset); - }, - icon: const Icon(Icons.save_rounded), - tooltip: 'Save', - ), ], + IconButton( + onPressed: _hasUnsavedChanges() + ? () { + widget.onSave(_newDueDate!); + setState(_reset); + } + : null, + icon: const Icon(Icons.save_rounded), + tooltip: 'Save', + ), const SizedBox(width: 4), - _editMode - ? IconButton( - onPressed: () => setState(_reset), - icon: const Icon(Icons.close_rounded), - tooltip: 'Cancel', - ) - : IconButton( - onPressed: () => - setState(() => _editMode = true), - icon: const Icon(Icons.edit), - tooltip: 'Edit', - ), + IconButton( + onPressed: _hasUnsavedChanges() + ? () => setState(_reset) + : null, + icon: const Icon(Icons.cancel), + tooltip: 'Discard Changes', + ), SizedBox( height: 24, width: 24, @@ -132,7 +131,7 @@ class _LoanDetailsPaneState extends State { onDueDateUpdated: (dueDate) { setState(() => _newDueDate = dueDate); }, - editable: _editMode, + editable: true, ), ), ], From 5f2c368a7f91bf8f1dce608b6c388c5498d815ac Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Thu, 20 Jul 2023 15:07:29 -0400 Subject: [PATCH 26/35] Refactor InventoryDetails using listenable viewmodel pattern --- .../data/inventory_details.vm.dart | 62 ++++++++++ .../new_inventory_details.dart | 50 ++++++++ .../new_inventory_details_pane.dart | 114 ++++++++++++++++++ .../inventory_desktop_layout.widget.dart | 13 +- 4 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 lib/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart create mode 100644 lib/src/features/inventory/widgets/inventory_details/new_inventory_details.dart create mode 100644 lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart diff --git a/lib/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart b/lib/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart new file mode 100644 index 0000000..9106d73 --- /dev/null +++ b/lib/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; +import 'package:librarian_app/src/features/inventory/data/item.model.dart'; + +class InventoryDetailsViewModel extends ChangeNotifier { + InventoryDetailsViewModel({ + required this.inventory, + required this.thingId, + required this.name, + required this.spanishName, + required this.items, + required this.availableItems, + }); + + final InventoryViewModel inventory; + + late final nameController = TextEditingController(text: name); + late final spanishNameController = TextEditingController(text: spanishName); + + final String thingId; + final String name; + final String? spanishName; + final List items; + final int availableItems; + + bool get hasUnsavedChanges => + nameController.text != name || + spanishNameController.text != (spanishName ?? ''); + + void announceChanges() => notifyListeners(); + + Future save() async { + await inventory.updateThing( + thingId: thingId, + name: nameController.text, + spanishName: spanishNameController.text, + ); + } + + Future discardChanges() async { + nameController.value = TextEditingValue(text: name); + spanishNameController.value = spanishName != null + ? TextEditingValue(text: spanishName!) + : TextEditingValue.empty; + notifyListeners(); + } + + Future addItems( + String? brand, + String? description, + double? estimatedValue, + int quantity, + ) async { + await inventory.createItems( + thingId: thingId, + brand: brand, + description: description, + estimatedValue: estimatedValue, + quantity: quantity, + ); + } +} diff --git a/lib/src/features/inventory/widgets/inventory_details/new_inventory_details.dart b/lib/src/features/inventory/widgets/inventory_details/new_inventory_details.dart new file mode 100644 index 0000000..213e72f --- /dev/null +++ b/lib/src/features/inventory/widgets/inventory_details/new_inventory_details.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/dialogs/add_inventory_dialog.widget.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart'; + +class InventoryDetails extends StatelessWidget { + const InventoryDetails({super.key, required this.details}); + + final InventoryDetailsViewModel details; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: details.nameController, + decoration: inputDecoration.copyWith( + icon: const Icon(Icons.build), + labelText: 'Name', + ), + onChanged: (_) => details.announceChanges(), + ), + const SizedBox(height: 16), + TextField( + controller: details.spanishNameController, + decoration: inputDecoration.copyWith( + icon: const Icon(Icons.build), + labelText: 'Name (Spanish)', + ), + onChanged: (_) => details.announceChanges(), + ), + const SizedBox(height: 32), + ItemsCard( + items: details.items, + availableItemsCount: details.availableItems, + onAddItemsPressed: () { + showDialog( + context: context, + builder: (context) => AddInventoryDialog( + onCreate: details.addItems, + ), + ); + }, + ), + ], + ); + } +} diff --git a/lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart b/lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart new file mode 100644 index 0000000..3712312 --- /dev/null +++ b/lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart @@ -0,0 +1,114 @@ +import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; +import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; +import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/new_inventory_details.dart'; +import 'package:provider/provider.dart'; + +class InventoryDetailsPane extends StatelessWidget { + const InventoryDetailsPane({super.key}); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, inventory, child) { + return Card( + clipBehavior: Clip.antiAlias, + child: inventory.selectedId == null + ? const Center(child: Text('Inventory Details')) + : FutureBuilder( + future: inventory.getThingDetails(id: inventory.selectedId!), + builder: (context, snapshot) { + if (snapshot.hasError) { + return Center(child: Text(snapshot.error.toString())); + } + + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } + + final thingDetails = snapshot.data!; + + final details = InventoryDetailsViewModel( + inventory: inventory, + thingId: thingDetails.id, + name: thingDetails.name, + spanishName: thingDetails.spanishName, + items: thingDetails.items, + availableItems: thingDetails.available, + ); + + return Column( + children: [ + ListenableBuilder( + listenable: details, + builder: (context, child) { + return PaneHeader( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + details.name, + style: const TextStyle(fontSize: 24), + ), + ], + ), + Row( + children: [ + if (details.hasUnsavedChanges) ...[ + Text( + 'Unsaved Changes', + style: Theme.of(context) + .textTheme + .labelMedium! + .copyWith( + color: Colors.white + .withOpacity(0.8), + fontStyle: FontStyle.italic, + ), + ), + const SizedBox(width: 8), + ], + IconButton( + onPressed: details.hasUnsavedChanges + ? details.save + : null, + icon: const Icon(Icons.save_rounded), + tooltip: 'Save', + ), + const SizedBox(width: 4), + IconButton( + onPressed: details.hasUnsavedChanges + ? details.discardChanges + : null, + icon: const Icon(Icons.cancel), + tooltip: 'Discard Changes', + ), + ], + ) + ], + ), + ); + }, + ), + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: InventoryDetails(details: details), + ), + ), + ), + ], + ); + }, + ), + ); + }, + ); + } +} diff --git a/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart index e12d01c..0286043 100644 --- a/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart @@ -3,9 +3,9 @@ import 'package:librarian_app/src/features/dashboard/widgets/panes/list_pane.wid import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:provider/provider.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; -import '../inventory_details/inventory_details_pane.widget.dart'; import '../../data/inventory.vm.dart'; +import '../inventory_details/new_inventory_details_pane.dart'; import '../inventory_list/inventory_list_view.widget.dart'; class InventoryDesktopLayout extends StatefulWidget { @@ -40,15 +40,8 @@ class _InventoryDesktopLayoutState extends State { ); }, ), - Expanded( - child: Consumer( - builder: (context, inventory, child) { - return InventoryDetailsPane( - thingId: inventory.selected?.id, - model: inventory, - ); - }, - ), + const Expanded( + child: InventoryDetailsPane(), ), ], ); From 6a27e5c0178660b688d4856ffad61040348509f7 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Thu, 20 Jul 2023 15:49:50 -0400 Subject: [PATCH 27/35] Remove old details and pane, Refactor details page [mobile] --- .../pages/inventory_details.page.dart | 110 +++++++++----- .../inventory_details.widget.dart | 71 --------- .../inventory_details_pane.widget.dart | 137 ------------------ .../inventory_details_view.widget.dart | 37 ++--- 4 files changed, 84 insertions(+), 271 deletions(-) delete mode 100644 lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart delete mode 100644 lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart diff --git a/lib/src/features/inventory/pages/inventory_details.page.dart b/lib/src/features/inventory/pages/inventory_details.page.dart index f7e9505..0cb515a 100644 --- a/lib/src/features/inventory/pages/inventory_details.page.dart +++ b/lib/src/features/inventory/pages/inventory_details.page.dart @@ -2,7 +2,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../data/inventory.vm.dart'; -import '../widgets/inventory_details/inventory_details_view.widget.dart'; +import '../widgets/inventory_details/data/inventory_details.vm.dart'; +import '../widgets/inventory_details/new_inventory_details.dart'; class InventoryDetailsPage extends StatelessWidget { const InventoryDetailsPage({super.key}); @@ -12,47 +13,76 @@ class InventoryDetailsPage extends StatelessWidget { final inventory = Provider.of(context); final selected = inventory.selected!; - final name = TextEditingController(text: selected.name); - final spanishName = TextEditingController(text: selected.spanishName); - - return Scaffold( - appBar: AppBar( - title: Text(selected.name), - actions: [ - if (!inventory.editing) - IconButton( - onPressed: () => inventory.editing = true, - icon: const Icon(Icons.edit), - ), - if (inventory.editing) - IconButton( - onPressed: () async { - await inventory.updateThing( - thingId: selected.id, - name: name.text, - spanishName: spanishName.text, - ); - - inventory.editing = false; - }, - icon: const Icon(Icons.save), - ), - if (inventory.editing) - IconButton( - onPressed: () => inventory.editing = false, - icon: const Icon(Icons.close), + return FutureBuilder( + future: inventory.getThingDetails(id: inventory.selectedId!), + builder: (context, snapshot) { + if (snapshot.hasError) { + return errorScaffold(snapshot.error.toString()); + } + + if (!snapshot.hasData) { + return loadingScaffold; + } + + final thingDetails = snapshot.data!; + + final details = InventoryDetailsViewModel( + inventory: inventory, + thingId: thingDetails.id, + name: thingDetails.name, + spanishName: thingDetails.spanishName, + items: thingDetails.items, + availableItems: thingDetails.available, + ); + + return Scaffold( + appBar: AppBar( + title: Text(selected.name), + actions: [ + ListenableBuilder( + listenable: details, + builder: (context, child) { + return IconButton( + onPressed: details.hasUnsavedChanges ? details.save : null, + icon: const Icon(Icons.save), + ); + }, + ), + ListenableBuilder( + listenable: details, + builder: (context, child) { + return IconButton( + onPressed: details.hasUnsavedChanges + ? details.discardChanges + : null, + icon: const Icon(Icons.cancel), + ); + }, + ), + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: InventoryDetails(details: details), ), - ], - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16), - child: InventoryDetailsView( - nameController: name, - spanishNameController: spanishName, ), - ), - ), + ); + }, ); } } + +Scaffold errorScaffold(String error) { + return Scaffold( + body: Center( + child: Text(error), + ), + ); +} + +const loadingScaffold = Scaffold( + body: Center( + child: CircularProgressIndicator(), + ), +); diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart deleted file mode 100644 index b86f086..0000000 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/common/widgets/input_decoration.widget.dart'; -import 'package:librarian_app/src/features/inventory/widgets/dialogs/add_inventory_dialog.widget.dart'; -import 'package:librarian_app/src/features/inventory/widgets/inventory_details/items_card/items_card.widget.dart'; - -import '../../data/item.model.dart'; - -class InventoryDetails extends StatelessWidget { - const InventoryDetails({ - super.key, - required this.nameController, - required this.spanishNameController, - required this.items, - required this.availableItems, - this.onAddItems, - this.readOnly = true, - }); - - final TextEditingController nameController; - final TextEditingController spanishNameController; - final List items; - final int availableItems; - final bool readOnly; - - final Future Function( - String? brand, - String? description, - double? estimatedValue, - int quantity, - )? onAddItems; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - controller: nameController, - readOnly: readOnly, - decoration: inputDecoration.copyWith( - icon: const Icon(Icons.build), - labelText: 'Name', - ), - ), - const SizedBox(height: 16), - TextField( - controller: spanishNameController, - readOnly: readOnly, - enabled: spanishNameController.text.isNotEmpty || !readOnly, - decoration: inputDecoration.copyWith( - icon: const Icon(Icons.build), - labelText: 'Name (Spanish)', - ), - ), - const SizedBox(height: 32), - ItemsCard( - items: items, - availableItemsCount: availableItems, - onAddItemsPressed: () { - showDialog( - context: context, - builder: (context) => AddInventoryDialog( - onCreate: onAddItems, - ), - ); - }, - ), - ], - ); - } -} diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart deleted file mode 100644 index 4d0bfe8..0000000 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.widget.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; -import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; - -import 'inventory_details.widget.dart'; - -class InventoryDetailsPane extends StatefulWidget { - final String? thingId; - final InventoryViewModel model; - - const InventoryDetailsPane({ - super.key, - required this.thingId, - required this.model, - }); - - @override - State createState() => _InventoryDetailsPaneState(); -} - -class _InventoryDetailsPaneState extends State { - Future _save(String name, String spanishName) async { - await widget.model.updateThing( - thingId: widget.thingId!, - name: name, - spanishName: spanishName, - ); - widget.model.editing = false; - } - - @override - Widget build(BuildContext context) { - final thing = widget.thingId; - - return Card( - clipBehavior: Clip.antiAlias, - child: thing == null - ? const Center(child: Text('Inventory Details')) - : FutureBuilder( - future: widget.model.getThingDetails(id: thing), - builder: (context, snapshot) { - if (snapshot.hasError) { - return Center( - child: Text(snapshot.error.toString()), - ); - } - - if (!snapshot.hasData) { - return const Center(child: CircularProgressIndicator()); - } - - final thingDetails = snapshot.data; - - final name = TextEditingController(text: thingDetails!.name); - final spanishName = - TextEditingController(text: thingDetails.spanishName); - - return Column( - children: [ - PaneHeader( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - thingDetails.name, - style: const TextStyle(fontSize: 24), - ), - ], - ), - Row( - children: [ - if (widget.model.editing) - IconButton( - onPressed: () async => await _save( - name.text, - spanishName.text, - ), - icon: const Icon(Icons.save_rounded), - tooltip: 'Save', - ), - const SizedBox(width: 4), - widget.model.editing - ? IconButton( - onPressed: () => - widget.model.editing = false, - icon: const Icon(Icons.close_rounded), - tooltip: 'Cancel', - ) - : IconButton( - onPressed: () => - widget.model.editing = true, - icon: const Icon(Icons.edit_rounded), - tooltip: 'Edit', - ), - ], - ) - ], - ), - ), - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16), - child: InventoryDetails( - readOnly: !widget.model.editing, - nameController: name, - spanishNameController: spanishName, - items: thingDetails.items, - availableItems: thingDetails.available, - onAddItems: ( - brand, - description, - estimatedValue, - quantity, - ) async { - await widget.model.createItems( - thingId: thing, - quantity: quantity, - brand: brand, - description: description, - estimatedValue: estimatedValue, - ); - }, - ), - ), - ), - ), - ], - ); - }, - ), - ); - } -} diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart index c0c03f3..50c49aa 100644 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; -import 'package:librarian_app/src/features/inventory/widgets/inventory_details/inventory_details.widget.dart'; import 'package:provider/provider.dart'; +import 'data/inventory_details.vm.dart'; +import 'new_inventory_details.dart'; + class InventoryDetailsView extends StatelessWidget { const InventoryDetailsView({ super.key, @@ -28,29 +30,18 @@ class InventoryDetailsView extends StatelessWidget { return const Center(child: CircularProgressIndicator()); } - final details = snapshot.data!; - - return InventoryDetails( - nameController: nameController, - spanishNameController: spanishNameController, - items: details.items, - availableItems: details.available, - readOnly: !inventory.editing, - onAddItems: ( - brand, - description, - estimatedValue, - quantity, - ) async { - await inventory.createItems( - thingId: details.id, - quantity: quantity, - brand: brand, - description: description, - estimatedValue: estimatedValue, - ); - }, + final thingDetails = snapshot.data!; + + final details = InventoryDetailsViewModel( + inventory: inventory, + thingId: thingDetails.id, + name: thingDetails.name, + spanishName: thingDetails.spanishName, + items: thingDetails.items, + availableItems: thingDetails.available, ); + + return InventoryDetails(details: details); }, ); }, From b6511919fa3e29ec19d967e906c6f32a4586f1ce Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Thu, 20 Jul 2023 15:54:27 -0400 Subject: [PATCH 28/35] Rename 'new' inventory details files --- .../pages/inventory_details.page.dart | 2 +- ...ry_details.dart => inventory_details.dart} | 0 ..._pane.dart => inventory_details_pane.dart} | 2 +- .../inventory_details_view.widget.dart | 50 ------------------- .../inventory_desktop_layout.widget.dart | 2 +- 5 files changed, 3 insertions(+), 53 deletions(-) rename lib/src/features/inventory/widgets/inventory_details/{new_inventory_details.dart => inventory_details.dart} (100%) rename lib/src/features/inventory/widgets/inventory_details/{new_inventory_details_pane.dart => inventory_details_pane.dart} (99%) delete mode 100644 lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart diff --git a/lib/src/features/inventory/pages/inventory_details.page.dart b/lib/src/features/inventory/pages/inventory_details.page.dart index 0cb515a..87154c5 100644 --- a/lib/src/features/inventory/pages/inventory_details.page.dart +++ b/lib/src/features/inventory/pages/inventory_details.page.dart @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; import '../data/inventory.vm.dart'; import '../widgets/inventory_details/data/inventory_details.vm.dart'; -import '../widgets/inventory_details/new_inventory_details.dart'; +import '../widgets/inventory_details/inventory_details.dart'; class InventoryDetailsPage extends StatelessWidget { const InventoryDetailsPage({super.key}); diff --git a/lib/src/features/inventory/widgets/inventory_details/new_inventory_details.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details.dart similarity index 100% rename from lib/src/features/inventory/widgets/inventory_details/new_inventory_details.dart rename to lib/src/features/inventory/widgets/inventory_details/inventory_details.dart diff --git a/lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart similarity index 99% rename from lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart rename to lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart index 3712312..0eefe30 100644 --- a/lib/src/features/inventory/widgets/inventory_details/new_inventory_details_pane.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart @@ -3,7 +3,7 @@ import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.w import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; import 'package:librarian_app/src/features/inventory/widgets/inventory_details/data/inventory_details.vm.dart'; -import 'package:librarian_app/src/features/inventory/widgets/inventory_details/new_inventory_details.dart'; +import 'package:librarian_app/src/features/inventory/widgets/inventory_details/inventory_details.dart'; import 'package:provider/provider.dart'; class InventoryDetailsPane extends StatelessWidget { diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart deleted file mode 100644 index 50c49aa..0000000 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details_view.widget.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; -import 'package:provider/provider.dart'; - -import 'data/inventory_details.vm.dart'; -import 'new_inventory_details.dart'; - -class InventoryDetailsView extends StatelessWidget { - const InventoryDetailsView({ - super.key, - required this.nameController, - required this.spanishNameController, - }); - - final TextEditingController nameController; - final TextEditingController spanishNameController; - - @override - Widget build(BuildContext context) { - return Consumer( - builder: (context, inventory, child) { - return FutureBuilder( - future: inventory.getThingDetails(id: inventory.selectedId!), - builder: (context, snapshot) { - if (snapshot.hasError) { - return Center(child: Text(snapshot.error!.toString())); - } - - if (!snapshot.hasData) { - return const Center(child: CircularProgressIndicator()); - } - - final thingDetails = snapshot.data!; - - final details = InventoryDetailsViewModel( - inventory: inventory, - thingId: thingDetails.id, - name: thingDetails.name, - spanishName: thingDetails.spanishName, - items: thingDetails.items, - availableItems: thingDetails.available, - ); - - return InventoryDetails(details: details); - }, - ); - }, - ); - } -} diff --git a/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart index 0286043..14bb66e 100644 --- a/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart +++ b/lib/src/features/inventory/widgets/layouts/inventory_desktop_layout.widget.dart @@ -5,7 +5,7 @@ import 'package:provider/provider.dart'; import 'package:librarian_app/src/features/common/widgets/search_field.widget.dart'; import '../../data/inventory.vm.dart'; -import '../inventory_details/new_inventory_details_pane.dart'; +import '../inventory_details/inventory_details_pane.dart'; import '../inventory_list/inventory_list_view.widget.dart'; class InventoryDesktopLayout extends StatefulWidget { From 9111540d3b4ec71a99b6ca861ad237f9fee028a0 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Thu, 20 Jul 2023 15:58:46 -0400 Subject: [PATCH 29/35] Get thing name from details --- lib/src/features/inventory/pages/inventory_details.page.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/src/features/inventory/pages/inventory_details.page.dart b/lib/src/features/inventory/pages/inventory_details.page.dart index 87154c5..1f5504f 100644 --- a/lib/src/features/inventory/pages/inventory_details.page.dart +++ b/lib/src/features/inventory/pages/inventory_details.page.dart @@ -11,7 +11,6 @@ class InventoryDetailsPage extends StatelessWidget { @override Widget build(BuildContext context) { final inventory = Provider.of(context); - final selected = inventory.selected!; return FutureBuilder( future: inventory.getThingDetails(id: inventory.selectedId!), @@ -37,7 +36,7 @@ class InventoryDetailsPage extends StatelessWidget { return Scaffold( appBar: AppBar( - title: Text(selected.name), + title: Text(details.name), actions: [ ListenableBuilder( listenable: details, From ff92bdb872f8837c58a3d0167b981570d451d850 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Sun, 23 Jul 2023 12:02:11 -0400 Subject: [PATCH 30/35] Confirm before saving loan --- .../common/widgets/save_dialog.widget.dart | 35 +++++++++++++++++++ .../loan_details_pane.widget.dart | 9 +++-- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 lib/src/features/common/widgets/save_dialog.widget.dart diff --git a/lib/src/features/common/widgets/save_dialog.widget.dart b/lib/src/features/common/widgets/save_dialog.widget.dart new file mode 100644 index 0000000..dc0490f --- /dev/null +++ b/lib/src/features/common/widgets/save_dialog.widget.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class SaveDialog extends StatelessWidget { + const SaveDialog({super.key}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Save Changes'), + content: const Text('Are you sure you want to save?'), + actions: [ + OutlinedButton( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: const Text('Cancel'), + ), + FilledButton( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: const Text('Save'), + ) + ], + ); + } +} + +Future showSaveDialog(BuildContext context) async { + return await showDialog( + context: context, + builder: (_) => const SaveDialog(), + ) ?? + false; +} diff --git a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart index b682ce6..aa90120 100644 --- a/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart +++ b/lib/src/features/loans/widgets/loan_details/loan_details_pane.widget.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/common/widgets/save_dialog.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import '../../data/loan.model.dart'; @@ -74,9 +75,11 @@ class _LoanDetailsPaneState extends State { ], IconButton( onPressed: _hasUnsavedChanges() - ? () { - widget.onSave(_newDueDate!); - setState(_reset); + ? () async { + if (await showSaveDialog(context)) { + widget.onSave(_newDueDate!); + setState(_reset); + } } : null, icon: const Icon(Icons.save_rounded), From 401b928a2d0f1d3e301c637aa6838f85bcdd05a4 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Sun, 23 Jul 2023 12:06:05 -0400 Subject: [PATCH 31/35] Confirm before saving thing --- .../widgets/inventory_details/inventory_details_pane.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart index 0eefe30..fa26052 100644 --- a/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart +++ b/lib/src/features/inventory/widgets/inventory_details/inventory_details_pane.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/common/widgets/save_dialog.widget.dart'; import 'package:librarian_app/src/features/dashboard/widgets/panes/pane_header.widget.dart'; import 'package:librarian_app/src/features/inventory/data/detailed_thing.model.dart'; import 'package:librarian_app/src/features/inventory/data/inventory.vm.dart'; @@ -75,7 +76,12 @@ class InventoryDetailsPane extends StatelessWidget { ], IconButton( onPressed: details.hasUnsavedChanges - ? details.save + ? () async { + if (await showSaveDialog( + context)) { + await details.save(); + } + } : null, icon: const Icon(Icons.save_rounded), tooltip: 'Save', From 7ee708bb3b7f86232896f0398c44fb1a67cf54fc Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Sun, 23 Jul 2023 12:14:04 -0400 Subject: [PATCH 32/35] Improve save and checkin dialogs --- lib/src/features/common/widgets/save_dialog.widget.dart | 2 ++ .../features/loans/widgets/checkin/checkin_dialog.widget.dart | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/features/common/widgets/save_dialog.widget.dart b/lib/src/features/common/widgets/save_dialog.widget.dart index dc0490f..a5d76ed 100644 --- a/lib/src/features/common/widgets/save_dialog.widget.dart +++ b/lib/src/features/common/widgets/save_dialog.widget.dart @@ -6,6 +6,7 @@ class SaveDialog extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( + icon: const Icon(Icons.save), title: const Text('Save Changes'), content: const Text('Are you sure you want to save?'), actions: [ @@ -26,6 +27,7 @@ class SaveDialog extends StatelessWidget { } } +// TODO: Should make dialogs more like this from now on. Dialogs should not contain complicated logic. Return a result and let a controller handle what happens next. Future showSaveDialog(BuildContext context) async { return await showDialog( context: context, diff --git a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart index 9ef0a69..781abbc 100644 --- a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart +++ b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart @@ -16,6 +16,7 @@ class CheckinDialog extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( + icon: const Icon(Icons.library_add_check), title: Text("Thing #$thingNumber"), content: Text("Are you sure you want to check Thing #$thingNumber back in?"), @@ -25,7 +26,7 @@ class CheckinDialog extends StatelessWidget { onPressed: () => Navigator.pop(context), ), FilledProgressButton( - child: const Text('Yes'), + child: const Text('Check in'), onPressed: () { Future.delayed(const Duration(seconds: 2), () async { await onCheckin?.call(); From 036386b944d2197bc7ca4741daada2b0059c4fc5 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Sun, 23 Jul 2023 12:54:59 -0400 Subject: [PATCH 33/35] Update loan details upon save --- lib/src/features/common/data/lending_api.dart | 7 + lib/src/features/loans/data/loans.vm.dart | 13 ++ .../loans/pages/loan_details.page.dart | 169 +++++++++--------- 3 files changed, 109 insertions(+), 80 deletions(-) diff --git a/lib/src/features/common/data/lending_api.dart b/lib/src/features/common/data/lending_api.dart index 4d7eed6..01a3b2a 100644 --- a/lib/src/features/common/data/lending_api.dart +++ b/lib/src/features/common/data/lending_api.dart @@ -22,6 +22,13 @@ class LendingApi { return await _client.get('/loans'); } + static Future fetchLoan({ + required String id, + required String thingId, + }) async { + return await _client.get('/loans/$id/$thingId'); + } + static Future createLoan(NewLoan data) async { return await _client.put('/loans', data: { 'borrowerId': data.borrowerId, diff --git a/lib/src/features/loans/data/loans.vm.dart b/lib/src/features/loans/data/loans.vm.dart index 3d411c2..d0ecd36 100644 --- a/lib/src/features/loans/data/loans.vm.dart +++ b/lib/src/features/loans/data/loans.vm.dart @@ -63,6 +63,19 @@ class LoansViewModel extends ChangeNotifier { return await _inventoryService.getItem(number: number); } + Future getLoan({ + required String id, + required String thingId, + }) async { + try { + final response = await LendingApi.fetchLoan(id: id, thingId: thingId); + return LoanModel.fromJson(response.data as Map); + } catch (error) { + errorMessage = error.toString(); + return null; + } + } + Future> getLoans() async { final response = await LendingApi.fetchLoans(); return (response.data as List).map((e) => LoanModel.fromJson(e)).toList(); diff --git a/lib/src/features/loans/pages/loan_details.page.dart b/lib/src/features/loans/pages/loan_details.page.dart index 4d8c49f..4857a65 100644 --- a/lib/src/features/loans/pages/loan_details.page.dart +++ b/lib/src/features/loans/pages/loan_details.page.dart @@ -1,6 +1,9 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:librarian_app/src/features/common/widgets/save_dialog.widget.dart'; +import 'package:librarian_app/src/features/inventory/pages/inventory_details.page.dart'; import 'package:librarian_app/src/features/loans/data/loans.vm.dart'; +import 'package:librarian_app/src/features/loans/widgets/checkin/checkin_dialog.widget.dart'; import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.widget.dart'; import 'package:provider/provider.dart'; @@ -16,17 +19,18 @@ class LoanDetailsPage extends StatefulWidget { } class _LoanDetailsPageState extends State { - bool _editMode = false; - bool _changesMade = false; + bool get _changesMade => _newDueDate != null; DateTime? _newDueDate; + void _discardChanges() { + setState(() => _newDueDate = null); + } + Future _saveChanges(String loanId, String thingId) async { - if (_newDueDate != null) { + if (_newDueDate != null && await showSaveDialog(context)) { await _updateDueDate(loanId, thingId); } - - setState(() => _editMode = false); } Future _updateDueDate(String loanId, String thingId) async { @@ -37,6 +41,11 @@ class _LoanDetailsPageState extends State { thingId: thingId, dueBackDate: _newDueDate!, ); + + setState(() { + _newDueDate = null; + _loanFuture = loans.getLoan(id: loanId, thingId: thingId); + }); } catch (error) { if (kDebugMode) { print(error); @@ -49,91 +58,91 @@ class _LoanDetailsPageState extends State { context: context, builder: (context) { final thing = widget.loan.thing; - return AlertDialog( - title: Text("Thing #${thing.number}"), - content: Text( - "Are you sure you want to check Thing #${thing.number} back in?"), - actions: [ - TextButton( - child: const Text("Cancel"), - onPressed: () => Navigator.pop(context), - ), - TextButton( - child: const Text("Yes"), - onPressed: () async { - final loans = - Provider.of(context, listen: false); - await loans.closeLoan( - loanId: widget.loan.id, thingId: widget.loan.thing.id); - - await Future.delayed( - Duration.zero, - () { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - }, - ); - }, - ), - ], + return CheckinDialog( + thingNumber: thing.number, + onCheckin: () async { + final loans = Provider.of(context, listen: false); + await loans.closeLoan( + loanId: widget.loan.id, + thingId: widget.loan.thing.id, + ); + }, ); }, ); } + late Future _loanFuture; + @override - Widget build(BuildContext context) { + void initState() { + super.initState(); final loan = widget.loan; + _loanFuture = context + .read() + .getLoan(id: loan.id, thingId: loan.thing.id); + } - return Scaffold( - appBar: AppBar( - title: const Text("Loan Details"), - centerTitle: true, - actions: [ - if (_editMode && _changesMade) - IconButton( - onPressed: () => _saveChanges(loan.id, loan.thing.id), - icon: const Icon(Icons.save_rounded), - tooltip: 'Save', - ), - _editMode - ? IconButton( - onPressed: () => setState(() => _editMode = false), - icon: const Icon(Icons.close_rounded), - tooltip: 'Cancel', - ) - : IconButton( - onPressed: () => setState(() => _editMode = true), - icon: const Icon(Icons.edit_rounded), - tooltip: 'Edit', + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, loans, child) { + return FutureBuilder( + future: _loanFuture, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return loadingScaffold; + } + + if (loans.errorMessage != null) { + return errorScaffold(loans.errorMessage!); + } + + final loan = snapshot.data!; + + return Scaffold( + appBar: AppBar( + title: const Text("Loan Details"), + centerTitle: true, + actions: [ + IconButton( + onPressed: _changesMade + ? () => _saveChanges(loan.id, loan.thing.id) + : null, + icon: const Icon(Icons.save_rounded), + tooltip: 'Save', + ), + IconButton( + onPressed: _changesMade ? _discardChanges : null, + icon: const Icon(Icons.cancel), + tooltip: 'Discard Changes', + ), + ], + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: LoanDetails( + borrower: loan.borrower, + things: [loan.thing], + checkedOutDate: loan.checkedOutDate, + dueDate: _newDueDate ?? loan.dueDate, + checkedInDate: loan.checkedInDate, + isOverdue: loan.isOverdue, + editable: true, + onDueDateUpdated: (newDueDate) { + setState(() => _newDueDate = newDueDate); + }, ), - ], - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LoanDetails( - borrower: loan.borrower, - things: [loan.thing], - checkedOutDate: loan.checkedOutDate, - dueDate: _newDueDate ?? loan.dueDate, - checkedInDate: loan.checkedInDate, - isOverdue: loan.isOverdue, - editable: _editMode, - onDueDateUpdated: (newDueDate) { - setState(() { - _newDueDate = newDueDate; - _changesMade = true; - }); + ), + floatingActionButton: FloatingActionButton( + onPressed: _checkIn, + tooltip: 'Check in', + child: const Icon(Icons.check_rounded), + ), + ); }, - ), - ), - floatingActionButton: _editMode - ? null - : FloatingActionButton( - onPressed: _checkIn, - tooltip: 'Check in', - child: const Icon(Icons.check_rounded), - ), + ); + }, ); } } From 8e116d560f89ce5b9fecacb1ec3ed764acf20247 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Sun, 23 Jul 2023 12:58:50 -0400 Subject: [PATCH 34/35] Pop out of loan details when checkin completes --- lib/src/features/loans/pages/loan_details.page.dart | 10 +++++++--- .../loans/widgets/checkin/checkin_dialog.widget.dart | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/src/features/loans/pages/loan_details.page.dart b/lib/src/features/loans/pages/loan_details.page.dart index 4857a65..a82753b 100644 --- a/lib/src/features/loans/pages/loan_details.page.dart +++ b/lib/src/features/loans/pages/loan_details.page.dart @@ -53,8 +53,8 @@ class _LoanDetailsPageState extends State { } } - void _checkIn() { - showDialog( + void _checkIn() async { + showDialog( context: context, builder: (context) { final thing = widget.loan.thing; @@ -69,7 +69,11 @@ class _LoanDetailsPageState extends State { }, ); }, - ); + ).then((result) { + if (result ?? false) { + Navigator.of(context).pop(); + } + }); } late Future _loanFuture; diff --git a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart index 781abbc..c8e8e76 100644 --- a/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart +++ b/lib/src/features/loans/widgets/checkin/checkin_dialog.widget.dart @@ -23,7 +23,7 @@ class CheckinDialog extends StatelessWidget { actions: [ OutlinedButton( child: const Text("Cancel"), - onPressed: () => Navigator.pop(context), + onPressed: () => Navigator.of(context).pop(false), ), FilledProgressButton( child: const Text('Check in'), @@ -31,7 +31,7 @@ class CheckinDialog extends StatelessWidget { Future.delayed(const Duration(seconds: 2), () async { await onCheckin?.call(); }).whenComplete(() { - Navigator.of(context).pop(); + Navigator.of(context).pop(true); onPostCheckin?.call(); }); }, From 4cd1ffa1ab188abdcca2b1a385b0df5c60a0f274 Mon Sep 17 00:00:00 2001 From: Dillon Fagan Date: Fri, 28 Jul 2023 17:32:50 -0400 Subject: [PATCH 35/35] Accomodate more edge cases when building initials --- .../widgets/loans_list/loans_list.widget.dart | 28 +++++++++++-------- test/loans/initials_test.dart | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 test/loans/initials_test.dart diff --git a/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart b/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart index 247c3e8..5cb43ab 100644 --- a/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart +++ b/lib/src/features/loans/widgets/loans_list/loans_list.widget.dart @@ -15,16 +15,6 @@ class LoansList extends StatelessWidget { this.onTap, }); - String _getBorrowerInitials(String name) { - final uppercaseName = name.toUpperCase(); - final firstLetter = uppercaseName[0]; - - final split = uppercaseName.split(' '); - final secondLetter = split.length > 1 ? split[1][0] : uppercaseName[1]; - - return firstLetter + secondLetter; - } - @override Widget build(BuildContext context) { return ListView.builder( @@ -34,7 +24,7 @@ class LoansList extends StatelessWidget { final thingNumber = Text('#${loan.thing.number}'); final thingName = Text(loan.thing.name); - final borrowerInitials = _getBorrowerInitials(loan.borrower.name); + final borrowerInitials = Initials.convert(loan.borrower.name); return ListTile( leading: CircleAvatar( @@ -66,3 +56,19 @@ class LoansList extends StatelessWidget { ); } } + +class Initials { + static String convert(String fullName) { + final trimmedName = fullName.trim().toUpperCase(); + if (trimmedName.isEmpty) { + return '?'; + } + + final firstLetter = trimmedName[0]; + + final split = trimmedName.split(' '); + final secondLetter = split.length > 1 ? split.last[0] : trimmedName[1]; + + return firstLetter + secondLetter; + } +} diff --git a/test/loans/initials_test.dart b/test/loans/initials_test.dart new file mode 100644 index 0000000..1b6245c --- /dev/null +++ b/test/loans/initials_test.dart @@ -0,0 +1,28 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:librarian_app/src/features/loans/widgets/loans_list/loans_list.widget.dart'; + +void main() { + group('Initials', () { + for (TestCase t in [ + const TestCase('Alice Alisson', 'AA'), + const TestCase('Ponce de Leon', 'PL'), + const TestCase('Double Spaces', 'DS'), + const TestCase('NoSpaces', 'NO'), + const TestCase('Weird ness ', 'WN'), + const TestCase(' ', '?'), + const TestCase('', '?'), + ]) { + test('#convert(${t.fullName}) returns ${t.expected}', () { + final result = Initials.convert(t.fullName); + expect(result, t.expected); + }); + } + }); +} + +class TestCase { + const TestCase(this.fullName, this.expected); + + final String fullName; + final String expected; +}