Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release #21

Merged
merged 10 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/api/services/inventory/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ const fetchItem = async (id) => {
pageSize: 100
}).all();

if (records.length === 0) {
return null;
}

return mapItem(records[0]);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:librarian_app/modules/borrowers/models/borrower_model.dart';
import 'package:librarian_app/modules/loans/models/thing_summary_model.dart';
import 'package:librarian_app/core/api/models/thing_summary_model.dart';

class LoanModel {
final String id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:librarian_app/core/api/api.dart' as API;

import '../models/loan_details_model.dart';
import '../models/loan_model.dart';
import '../api/models/loan_details_model.dart';
import '../api/models/loan_model.dart';

class LoansRepository extends Notifier<Future<List<LoanModel>>> {
@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import 'package:librarian_app/widgets/panes/list_pane.dart';
import 'package:librarian_app/widgets/panes/pane_header.dart';
import 'package:librarian_app/modules/loans/providers/loans_filter_provider.dart';
import 'package:librarian_app/modules/loans/providers/selected_loan_provider.dart';
import 'package:librarian_app/modules/loans/widgets/loan_details/loan_details_pane.dart';
import 'package:librarian_app/modules/loans/widgets/loans_list/loans_list_view.dart';
import 'package:librarian_app/modules/loans/details/loan_details_pane.dart';
import 'package:librarian_app/modules/loans/list/loans_list_view.dart';

class LoansDesktopLayout extends ConsumerWidget {
const LoansDesktopLayout({super.key});
Expand Down
34 changes: 18 additions & 16 deletions apps/librarian/lib/dashboard/pages/dashboard_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/dashboard/providers/create_loan_controller.dart';
import 'package:librarian_app/dashboard/providers/workspace.dart';
import 'package:librarian_app/modules/authentication/providers/auth_service_provider.dart';
import 'package:librarian_app/modules/authentication/providers/user_tray.dart';
import 'package:librarian_app/modules/borrowers/widgets/layouts/borrowers_desktop_layout.dart';
Expand All @@ -12,10 +14,9 @@ import 'package:librarian_app/dashboard/layouts/inventory_desktop_layout.dart';
import 'package:librarian_app/modules/things/details/inventory_details_page.dart';
import 'package:librarian_app/modules/things/details/inventory/inventory_list/searchable_inventory_list.dart';
import 'package:librarian_app/modules/things/create/create_thing_dialog.dart';
import 'package:librarian_app/modules/loans/pages/checkout_page.dart';
import 'package:librarian_app/modules/loans/pages/loan_details_page.dart';
import 'package:librarian_app/modules/loans/widgets/loans_list/searchable_loans_list.dart';
import 'package:librarian_app/modules/loans/widgets/layouts/loans_desktop_layout.dart';
import 'package:librarian_app/modules/loans/details/loan_details_page.dart';
import 'package:librarian_app/modules/loans/list/searchable_loans_list.dart';
import 'package:librarian_app/dashboard/layouts/loans_desktop_layout.dart';
import 'package:librarian_app/modules/updates/widgets/update_dialog_controller.dart';
import 'package:librarian_app/modules/updates/notifiers/update_notifier.dart';
import 'package:librarian_app/utils/media_query.dart';
Expand Down Expand Up @@ -107,6 +108,7 @@ class _DashboardPageState extends ConsumerState<DashboardPage> {

@override
Widget build(BuildContext context) {
final ws = ref.watch(workspace);
final mobile = isMobile(context);
final module = _modules[_moduleIndex];

Expand All @@ -120,18 +122,18 @@ class _DashboardPageState extends ConsumerState<DashboardPage> {
context: context,
leadingIcon: const Icon(Icons.handshake_rounded),
text: 'Create Loan',
onTap: () async {
_menuController.close();
setState(() => _moduleIndex = 0);
await Future.delayed(const Duration(milliseconds: 150), () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CheckoutPage(),
),
);
});
},
tooltip: ws.hasItem
? 'Another "Create Loan" window is already in use.'
: null,
onTap: ws.hasItem
? null
: () async {
_menuController.close();
setState(() => _moduleIndex = 0);
await Future.delayed(const Duration(milliseconds: 150), () {
ref.read(createLoan).createLoan(context);
});
},
),
createMenuItem(
context: context,
Expand Down
37 changes: 37 additions & 0 deletions apps/librarian/lib/dashboard/providers/create_loan_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/dashboard/providers/workspace.dart';
import 'package:librarian_app/dashboard/widgets/workspace_window.dart';
import 'package:librarian_app/modules/loans/checkout/checkout_page.dart';
import 'package:librarian_app/modules/loans/checkout/checkout_stepper.dart';
import 'package:librarian_app/utils/media_query.dart';

class CreateLoanController {
CreateLoanController(this.ref);

final Ref ref;

void createLoan(BuildContext context) {
if (isMobile(context)) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CheckoutPage(),
),
);
return;
}

final ws = ref.read(workspace);
final window = WorkspaceWindow(
title: 'Create Loan',
content: CheckoutStepper(
onFinish: () => ws.closeWindow(),
),
);

ws.open(window);
}
}

final createLoan = Provider((ref) => CreateLoanController(ref));
104 changes: 104 additions & 0 deletions apps/librarian/lib/dashboard/providers/workspace.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/dashboard/widgets/workspace_window.dart';

class WorkspaceController {
WorkspaceController(this.ref);

final Ref ref;
final List<WorkspaceItem> _items = [];
final Map<String, WorkspaceItem> _minimized = {};

bool get hasItem => _items.isNotEmpty;

ActiveWorkspaceItem? get activeItem {
if (_items.isEmpty) {
return null;
}

final item = _items.last;

return ActiveWorkspaceItem(
isMinimized: isMinimized(item.id),
widget: item.widget,
);
}

List<MapEntry<String, WorkspaceItem>> get minimizedItems {
return _minimized.entries.toList();
}

void open(WorkspaceWindow window) {
_items.add(WorkspaceItem(
id: window.id,
title: window.title,
widget: window,
));

ref.notifyListeners();
}

void closeWindow() {
_items.removeLast();
ref.notifyListeners();
}

void close(String id) {
_items.removeWhere((i) => i.id == id);
_minimized.remove(id);

ref.notifyListeners();
}

void maximize(String id) {
// minimize current active item
final activeItem = _items.last;
_minimized[activeItem.id] = activeItem;

// make active
final item = _items.firstWhere((i) => i.id == id);
_items.remove(item);
_items.add(item);

// maximize
_minimized.remove(id);

ref.notifyListeners();
}

void minimize(
String id, {
String? title,
}) {
_minimized[id] = _items.last;
ref.notifyListeners();
}

bool isMinimized(String id) {
return _minimized.containsKey(id);
}
}

class WorkspaceItem {
WorkspaceItem({
required this.id,
required this.widget,
this.title,
});

final String id;
final String? title;
final Widget widget;
}

class ActiveWorkspaceItem {
const ActiveWorkspaceItem({
required this.isMinimized,
required this.widget,
});

final bool isMinimized;
final Widget widget;
}

final workspace = Provider((ref) => WorkspaceController(ref));
14 changes: 12 additions & 2 deletions apps/librarian/lib/dashboard/widgets/create_menu_item.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import 'package:flutter/material.dart';

Widget createMenuItem({
required void Function() onTap,
required void Function()? onTap,
required String text,
required BuildContext context,
Widget? leadingIcon,
String? tooltip,
}) {
return MenuItemButton(
final button = MenuItemButton(
onPressed: onTap,
leadingIcon: leadingIcon,
trailingIcon: const Icon(Icons.add),
Expand All @@ -15,4 +16,13 @@ Widget createMenuItem({
style: Theme.of(context).textTheme.titleMedium,
),
);

if (tooltip != null) {
return Tooltip(
message: tooltip,
child: button,
);
}

return button;
}
82 changes: 41 additions & 41 deletions apps/librarian/lib/dashboard/widgets/desktop_dashboard.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:librarian_app/dashboard/widgets/workspace.dart';

class DesktopDashboard extends StatelessWidget {
const DesktopDashboard({
Expand All @@ -16,49 +17,48 @@ class DesktopDashboard extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Row(
children: [
NavigationRail(
labelType: NavigationRailLabelType.selected,
leading: leading,
destinations: const [
NavigationRailDestination(
selectedIcon: Icon(Icons.handshake),
icon: Icon(Icons.handshake_outlined),
label: Text('Loans'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
selectedIcon: Icon(Icons.people),
icon: Icon(Icons.people_outlined),
label: Text('Borrowers'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
selectedIcon: Icon(Icons.build),
icon: Icon(Icons.build_outlined),
label: Text('Things'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
selectedIcon: Icon(Icons.electric_bolt),
icon: Icon(Icons.electric_bolt_outlined),
label: Text('Actions'),
padding: EdgeInsets.symmetric(vertical: 8),
),
],
selectedIndex: selectedIndex,
onDestinationSelected: (index) {
onDestinationSelected?.call(index);
},
),
Expanded(
child: Container(
margin: const EdgeInsets.only(right: 8, bottom: 8),
return Workspace(
child: Row(
children: [
NavigationRail(
labelType: NavigationRailLabelType.selected,
leading: leading,
destinations: const [
NavigationRailDestination(
selectedIcon: Icon(Icons.handshake),
icon: Icon(Icons.handshake_outlined),
label: Text('Loans'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
selectedIcon: Icon(Icons.people),
icon: Icon(Icons.people_outlined),
label: Text('Borrowers'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
selectedIcon: Icon(Icons.build),
icon: Icon(Icons.build_outlined),
label: Text('Things'),
padding: EdgeInsets.symmetric(vertical: 8),
),
NavigationRailDestination(
selectedIcon: Icon(Icons.electric_bolt),
icon: Icon(Icons.electric_bolt_outlined),
label: Text('Actions'),
padding: EdgeInsets.symmetric(vertical: 8),
),
],
selectedIndex: selectedIndex,
onDestinationSelected: (index) {
onDestinationSelected?.call(index);
},
),
Expanded(
child: child,
),
),
],
],
),
);
}
}
Loading