Skip to content
This repository has been archived by the owner on May 28, 2024. It is now read-only.

Commit

Permalink
Loan Details / Thing Image (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
dillonfagan authored Mar 4, 2024
1 parent 7230bda commit 90f963b
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 168 deletions.
3 changes: 1 addition & 2 deletions lib/src/api/lending_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class LendingApi {
'borrowerId': data.borrowerId,
'thingIds': data.thingIds,
'checkedOutDate': data.checkedOutDate,
'dueBackDate': data.dueBackDate,
'notes': 'This loan was created by the Librarian app!'
'dueBackDate': data.dueBackDate
});
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/features/dashboard/pages/dashboard_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class _DashboardPageState extends ConsumerState<DashboardPage> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoanDetailsPage(loan),
builder: (context) => const LoanDetailsPage(),
),
);
},
Expand Down
8 changes: 5 additions & 3 deletions lib/src/features/loans/data/loans_repository.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:librarian_app/src/api/lending_api.dart';
import 'package:librarian_app/src/features/loans/models/loan_model.dart';

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

class LoansRepository extends Notifier<Future<List<LoanModel>>> {
@override
Future<List<LoanModel>> build() async => await getLoans();

Future<LoanModel?> getLoan({
Future<LoanDetailsModel?> 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<String, dynamic>);
return LoanDetailsModel.fromJson(response.data as Map<String, dynamic>);
} catch (error) {
return null;
}
Expand Down
61 changes: 61 additions & 0 deletions lib/src/features/loans/models/loan_details_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import 'package:librarian_app/src/features/borrowers/models/borrower_model.dart';

import 'thing_summary_model.dart';

class LoanDetailsModel {
final String id;
final int number;
final ThingSummaryModel thing;
final BorrowerModel borrower;
final DateTime checkedOutDate;
final String? notes;
final int remindersSent;
DateTime dueDate;
DateTime? checkedInDate;

bool get isOverdue {
final now = DateTime.now();
return DateUtils.dateOnly(dueDate).isBefore(DateUtils.dateOnly(now));
}

bool get isDueToday => DateUtils.isSameDay(DateTime.now(), dueDate);

LoanDetailsModel({
required this.id,
required this.number,
required this.thing,
required this.borrower,
required this.checkedOutDate,
required this.dueDate,
required this.remindersSent,
this.checkedInDate,
this.notes,
});

factory LoanDetailsModel.fromJson(Map<String, dynamic> json) {
return LoanDetailsModel(
id: json['id'] as String? ?? '?',
number: json['number'] as int,
thing: ThingSummaryModel.fromJson(json['thing'] as Map<String, dynamic>),
borrower: BorrowerModel(
id: json['borrower']?['id'] as String? ?? '?',
name: json['borrower']?['name'] as String? ?? '???',
email: json['borrower']?['contact']['email'] as String?,
phone: json['borrower']?['contact']['phone'] as String?,
issues: [],
),
notes: json['notes'] as String?,
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(),
remindersSent: json['remindersSent'] as int,
);
}
}
10 changes: 2 additions & 8 deletions lib/src/features/loans/models/loan_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ class LoanModel {
final ThingSummaryModel thing;
final BorrowerModel borrower;
final DateTime checkedOutDate;
final String? notes;
final int remindersSent;
DateTime dueDate;
DateTime? checkedInDate;

Expand All @@ -27,9 +25,7 @@ class LoanModel {
required this.borrower,
required this.checkedOutDate,
required this.dueDate,
required this.remindersSent,
this.checkedInDate,
this.notes,
});

factory LoanModel.fromJson(Map<String, dynamic> json) {
Expand All @@ -40,11 +36,10 @@ class LoanModel {
borrower: BorrowerModel(
id: json['borrower']?['id'] as String? ?? '?',
name: json['borrower']?['name'] as String? ?? '???',
email: json['borrower']?['contact']['email'] as String?,
phone: json['borrower']?['contact']['phone'] as String?,
email: null,
phone: null,
issues: [],
),
notes: json['notes'] as String?,
checkedOutDate: json['checkedOutDate'] != null
? DateTime.parse(json['checkedOutDate'] as String)
: DateTime.now(),
Expand All @@ -54,7 +49,6 @@ class LoanModel {
dueDate: json['dueBackDate'] != null
? DateTime.parse(json['dueBackDate'])
: DateTime.now(),
remindersSent: json['remindersSent'] as int,
);
}
}
5 changes: 5 additions & 0 deletions lib/src/features/loans/models/thing_summary_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@ class ThingSummaryModel {
final String id;
final String name;
final int number;
final List<String> images;

const ThingSummaryModel({
required this.id,
required this.name,
required this.number,
required this.images,
});

factory ThingSummaryModel.fromJson(Map<String, dynamic> json) {
return ThingSummaryModel(
id: json['id'] as String,
name: json['name'] as String,
number: json['number'] as int,
images: json['images'] != null
? List<String>.from(json['images'] as List)
: [],
);
}
}
111 changes: 44 additions & 67 deletions lib/src/features/loans/pages/loan_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,24 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/src/features/inventory/pages/inventory_details_page.dart';
import 'package:librarian_app/src/features/loans/providers/loan_details_provider.dart';
import 'package:librarian_app/src/features/loans/providers/loans_repository_provider.dart';
import 'package:librarian_app/src/features/loans/widgets/checkin/checkin_dialog.dart';
import 'package:librarian_app/src/features/loans/widgets/email/send_email_dialog.dart';
import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details.dart';
import 'package:librarian_app/src/features/loans/widgets/loan_details/loan_details_controller.dart';

import '../models/loan_model.dart';
import '../widgets/edit/edit_loan_dialog.dart';

class LoanDetailsPage extends ConsumerStatefulWidget {
const LoanDetailsPage(this.loan, {super.key});

final LoanModel loan;
class LoanDetailsPage extends ConsumerWidget {
const LoanDetailsPage({super.key});

@override
ConsumerState<LoanDetailsPage> createState() => _LoanDetailsPageState();
}

class _LoanDetailsPageState extends ConsumerState<LoanDetailsPage> {
Future<void> _updateLoan(
String loanId, String thingId, DateTime newDueDate, String? notes) async {
final loans = ref.read(loansRepositoryProvider.notifier);
try {
await loans.updateLoan(
loanId: loanId,
thingId: thingId,
dueBackDate: newDueDate,
notes: notes);

setState(() {
_loanFuture = loans.getLoan(id: loanId, thingId: thingId);
});
} catch (error) {
if (kDebugMode) {
print(error);
}
}
}

void _checkIn() async {
showDialog<bool>(
context: context,
builder: (context) {
final thing = widget.loan.thing;
return CheckinDialog(
thingNumber: thing.number,
onCheckin: () async {
final loans = ref.read(loansRepositoryProvider.notifier);
await loans.closeLoan(
loanId: widget.loan.id,
thingId: widget.loan.thing.id,
);
},
);
},
).then((result) {
if (result ?? false) {
Navigator.of(context).pop();
}
});
}

late Future<LoanModel?> _loanFuture;
Widget build(BuildContext context, WidgetRef ref) {
final loanDetailsFuture = ref.watch(loanDetailsProvider);

@override
void initState() {
super.initState();
final loan = widget.loan;
_loanFuture = ref
.read(loansRepositoryProvider.notifier)
.getLoan(id: loan.id, thingId: loan.thing.id);
}

@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _loanFuture,
future: loanDetailsFuture,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return loadingScaffold;
Expand All @@ -90,6 +31,42 @@ class _LoanDetailsPageState extends ConsumerState<LoanDetailsPage> {

final loan = snapshot.data!;

Future<void> updateLoan(String loanId, String thingId,
DateTime newDueDate, String? notes) async {
final loans = ref.read(loansRepositoryProvider.notifier);
try {
await loans.updateLoan(
loanId: loanId,
thingId: thingId,
dueBackDate: newDueDate,
notes: notes);
} catch (error) {
if (kDebugMode) {
print(error);
}
}
}

void checkIn() async {
showDialog<bool>(
context: context,
builder: (context) {
return CheckinDialog(
thingNumber: loan.thing.number,
onCheckin: () async {
final loans = ref.read(loansRepositoryProvider.notifier);
await loans.closeLoan(
loanId: loan.id, thingId: loan.thing.id);
},
);
},
).then((result) {
if (result ?? false) {
Navigator.of(context).pop();
}
});
}

return Scaffold(
appBar: AppBar(
title: Text('#${loan.thing.number}'),
Expand All @@ -104,7 +81,7 @@ class _LoanDetailsPageState extends ConsumerState<LoanDetailsPage> {
dueDate: loan.dueDate,
notes: loan.notes,
onSavePressed: (newDueDate, notes) async {
await _updateLoan(
await updateLoan(
loan.id, loan.thing.id, newDueDate, notes);
},
);
Expand Down Expand Up @@ -157,7 +134,7 @@ class _LoanDetailsPageState extends ConsumerState<LoanDetailsPage> {
),
),
floatingActionButton: FloatingActionButton(
onPressed: _checkIn,
onPressed: checkIn,
tooltip: 'Check in',
child: const Icon(Icons.check_rounded),
),
Expand Down
1 change: 1 addition & 0 deletions lib/src/features/loans/pages/open_loan_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class _OpenLoanPageState extends ConsumerState<OpenLoanPage> {
id: t.id,
name: t.name,
number: t.number,
images: [],
))
.toList(),
checkedOutDate: DateTime.now(),
Expand Down
12 changes: 6 additions & 6 deletions lib/src/features/loans/providers/loan_details_provider.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/src/features/loans/providers/loans_repository_provider.dart';
import 'package:librarian_app/src/features/loans/providers/selected_loan_provider.dart';

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

final loanDetailsProvider = Provider<Future<LoanModel?>>((ref) async {
final loanDetailsProvider = Provider<Future<LoanDetailsModel?>>((ref) async {
ref.watch(loansRepositoryProvider);
final selectedLoan = ref.watch(selectedLoanProvider);
if (selectedLoan == null) {
return null;
}

final loans = await ref.watch(loansRepositoryProvider);
return loans.firstWhereOrNull((loan) =>
loan.id == selectedLoan.id && loan.thing.id == selectedLoan.thing.id);
return await ref
.read(loansRepositoryProvider.notifier)
.getLoan(id: selectedLoan.id, thingId: selectedLoan.thing.id);
});
5 changes: 2 additions & 3 deletions lib/src/features/loans/widgets/checkout/checkout_stepper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:librarian_app/src/features/borrowers/widgets/borrower_details/bo
import 'package:librarian_app/src/features/borrowers/widgets/borrower_search_delegate.dart';
import 'package:librarian_app/src/features/loans/pages/loan_details_page.dart';
import 'package:librarian_app/src/features/loans/providers/loans_controller_provider.dart';
import 'package:librarian_app/src/features/loans/providers/selected_loan_provider.dart';
import 'package:librarian_app/src/utils/media_query.dart';
import 'package:librarian_app/src/widgets/filled_progress_button.dart';
import 'package:librarian_app/src/features/inventory/models/item_model.dart';
Expand Down Expand Up @@ -68,9 +67,8 @@ class _CheckoutStepperState extends ConsumerState<CheckoutStepper> {
);

if (isMobile(context)) {
final loan = ref.read(selectedLoanProvider)!;
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return LoanDetailsPage(loan);
return const LoanDetailsPage();
}));
}
});
Expand Down Expand Up @@ -216,6 +214,7 @@ class _CheckoutStepperState extends ConsumerState<CheckoutStepper> {
id: t.id,
name: t.name,
number: t.number,
images: [],
))
.toList(),
dueDate: _dueDate,
Expand Down
Loading

0 comments on commit 90f963b

Please sign in to comment.