Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
library-app-flutter
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ilham Maulana
library-app-flutter
Commits
68feb6a9
Commit
68feb6a9
authored
Aug 01, 2024
by
Ilham Maulana
💻
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: near outstanding loans and overdued loans (admin or librarian access)
parent
ff094e41
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
273 additions
and
52 deletions
+273
-52
auth_provider.dart
lib/src/providers/auth_provider.dart
+47
-0
admin_list_screen.dart
lib/src/screens/admin_list_screen.dart
+6
-9
home.dart
lib/src/widgets/home.dart
+44
-43
overdued_loan_list.dart
lib/src/widgets/loans/overdued_loan_list.dart
+88
-0
upcoming_loan_list.dart
lib/src/widgets/loans/upcoming_loan_list.dart
+88
-0
No files found.
lib/src/providers/auth_provider.dart
View file @
68feb6a9
...
...
@@ -23,6 +23,10 @@ class AuthProvider with ChangeNotifier {
bool
resetPasswordTokenSended
=
false
;
bool
resetPasswordSucced
=
false
;
List
<
dynamic
>?
loans
;
List
<
dynamic
>?
nearOutstandingLoans
;
List
<
dynamic
>?
overduedLoans
;
Future
<
void
>
storeAccessToken
(
String
accessToken
)
async
{
await
storage
.
write
(
key:
'access_token'
,
value:
accessToken
);
}
...
...
@@ -366,4 +370,47 @@ class AuthProvider with ChangeNotifier {
debugPrint
(
"Failed to create member loan.
$error
"
);
}
}
// for admin or librarian
Future
<
void
>
getLoans
(
String
?
type
)
async
{
final
token
=
await
storage
.
read
(
key:
'access_token'
);
String
url
=
baseUrl
;
if
(
type
==
"upcoming"
)
{
url
+=
"/upcoming-loans/"
;
}
else
if
(
type
==
"overdue"
)
{
url
+=
"/overdued-loans/"
;
}
else
{
url
+=
"/book-loans/"
;
}
if
(
token
!=
null
)
{
try
{
final
response
=
await
http
.
get
(
Uri
.
parse
(
url
),
headers:
{
'Content-Type'
:
'application/json'
,
'Authorization'
:
'Bearer
$token
'
,
},
);
if
(
response
.
statusCode
==
200
)
{
final
data
=
jsonDecode
(
response
.
body
);
if
(
type
==
"upcoming"
)
{
nearOutstandingLoans
=
data
[
"results"
];
}
else
if
(
type
==
"overdue"
)
{
overduedLoans
=
data
[
"results"
];
}
else
{
loans
=
data
[
"results"
];
}
}
else
{
final
code
=
response
.
statusCode
;
debugPrint
(
"Error: Fetch upcoming loans failed,
$code
"
);
}
notifyListeners
();
}
catch
(
error
)
{
debugPrint
(
"Error: Fetch upcoming loans failed,
$error
"
);
}
}
}
}
lib/src/screens/admin_list_screen.dart
View file @
68feb6a9
...
...
@@ -6,8 +6,9 @@ import 'package:library_app/src/providers/book_provider.dart';
import
'package:library_app/src/providers/navigations_provider.dart'
;
import
'package:library_app/src/widgets/home.dart'
;
import
'package:library_app/src/widgets/loans/loan_list.dart'
;
import
'package:library_app/src/widgets/profile.dart'
;
import
'package:library_app/src/widgets/loans/overdued_loan_list.dart'
;
import
'package:library_app/src/widgets/loans/upcoming_loan_list.dart'
;
class
AdminListScreen
extends
StatefulWidget
{
const
AdminListScreen
({
super
.
key
});
...
...
@@ -59,14 +60,10 @@ class _AdminListScreen extends State<AdminListScreen> {
body:
<
Widget
>[
// Home
const
HomePage
(),
// Books
LoanList
(
memberId:
authProvider
.
user
?.
accountId
??
0
,
),
// Loans
LoanList
(
memberId:
authProvider
.
user
?.
accountId
??
0
,
),
// Near Outstanding Loans
const
UpcomingLoanList
(),
// Overdued Loans
const
OverduedLoanList
(),
// Profile
const
Profile
(),
][
navProvider
.
currentPageIndex
],
...
...
lib/src/widgets/home.dart
View file @
68feb6a9
...
...
@@ -29,49 +29,50 @@ class _HomePage extends State<HomePage> {
return
Consumer2
<
NavigationsProvider
,
AuthProvider
>(
builder:
(
context
,
navProvider
,
authProvider
,
child
)
{
return
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
[
const
TopBar
(
title:
title
),
];
},
body:
ListView
(
children:
<
Widget
>[
const
Padding
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
20.0
),
child:
Text
(
"Shortcut"
),
),
Shortcut
(
icon:
authProvider
.
user
!.
isStaff
?
Icons
.
timer_outlined
:
Icons
.
book_rounded
,
title:
authProvider
.
user
!.
isStaff
?
"Near Outstanding Loans"
:
"Books"
,
subtitle:
authProvider
.
user
!.
isStaff
?
"Discover near outstanding users loans."
:
"Discover many amazing books."
,
onTap:
()
{
navProvider
.
navigate
(
1
);
},
),
Shortcut
(
icon:
authProvider
.
user
!.
isStaff
?
Icons
.
timer_off_rounded
:
Icons
.
date_range_rounded
,
title:
authProvider
.
user
!.
isStaff
?
"Overdued Loans"
:
"Book Loans"
,
subtitle:
authProvider
.
user
!.
isStaff
?
"Discover Overdued users loans."
:
"Manage your book loan very easy."
,
onTap:
()
{
navProvider
.
navigate
(
2
);
},
),
],
),
);
final
user
=
authProvider
.
user
;
if
(
user
!=
null
)
{
return
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
[
const
TopBar
(
title:
title
),
];
},
body:
ListView
(
children:
<
Widget
>[
const
Padding
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
20.0
),
child:
Text
(
"Shortcut"
),
),
Shortcut
(
icon:
user
.
isStaff
?
Icons
.
timer_outlined
:
Icons
.
book_rounded
,
title:
user
.
isStaff
?
"Near Outstanding Loans"
:
"Books"
,
subtitle:
user
.
isStaff
?
"Discover near outstanding users loans."
:
"Discover many amazing books."
,
onTap:
()
{
navProvider
.
navigate
(
1
);
},
),
Shortcut
(
icon:
user
.
isStaff
?
Icons
.
timer_off_rounded
:
Icons
.
date_range_rounded
,
title:
user
.
isStaff
?
"Overdued Loans"
:
"Book Loans"
,
subtitle:
user
.
isStaff
?
"Discover Overdued users loans."
:
"Manage your book loan very easy."
,
onTap:
()
{
navProvider
.
navigate
(
2
);
},
),
],
),
);
}
return
Container
();
},
);
}
...
...
lib/src/widgets/loans/overdued_loan_list.dart
0 → 100644
View file @
68feb6a9
import
'package:flutter/material.dart'
;
import
'package:library_app/src/models/book.dart'
;
import
'package:library_app/src/providers/auth_provider.dart'
;
import
'package:provider/provider.dart'
;
import
'package:library_app/src/models/loan.dart'
;
import
'package:library_app/src/widgets/loans/loan_item.dart'
;
class
OverduedLoanList
extends
StatefulWidget
{
const
OverduedLoanList
({
super
.
key
});
@override
State
<
OverduedLoanList
>
createState
()
=>
_OverduedLoanList
();
}
class
_OverduedLoanList
extends
State
<
OverduedLoanList
>
{
@override
void
initState
()
{
super
.
initState
();
Provider
.
of
<
AuthProvider
>(
context
,
listen:
false
).
getLoans
(
"overdue"
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
Consumer
<
AuthProvider
>(
builder:
(
context
,
loanProvider
,
child
)
{
if
(
loanProvider
.
overduedLoans
!=
null
)
{
var
loans
=
loanProvider
.
overduedLoans
!.
map
(
(
loan
)
{
var
book
=
Book
.
fromJson
(
loan
[
"book_detail"
]);
return
Loan
(
book
,
loan
[
"loan_date"
],
loan
[
"due_date"
],
loan
[
"remaining_loan_time"
],
loan
[
"is_overdue"
],
);
},
);
return
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
[
const
TopAppBar
(
title:
"Overdued Loans"
)];
},
body:
ListView
(
children:
List
.
generate
(
loans
.
length
,
(
index
)
{
return
LoanItem
(
loans
.
elementAt
(
index
));
}),
),
);
}
else
{
return
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
[
const
TopAppBar
(
title:
"Book Loans"
)];
},
body:
const
Center
(
child:
Text
(
"the loan is currently empty"
),
),
);
}
});
}
}
class
TopAppBar
extends
StatefulWidget
{
final
String
title
;
const
TopAppBar
({
super
.
key
,
required
this
.
title
});
@override
_TopAppBar
createState
()
=>
_TopAppBar
();
}
class
_TopAppBar
extends
State
<
TopAppBar
>
{
String
get
title
=>
widget
.
title
;
bool
showWidget
=
false
;
@override
Widget
build
(
BuildContext
context
)
{
return
SliverAppBar
(
title:
Text
(
title
),
elevation:
10.0
,
automaticallyImplyLeading:
false
,
expandedHeight:
50
,
floating:
true
,
snap:
true
,
);
}
}
lib/src/widgets/loans/upcoming_loan_list.dart
0 → 100644
View file @
68feb6a9
import
'package:flutter/material.dart'
;
import
'package:library_app/src/models/book.dart'
;
import
'package:library_app/src/providers/auth_provider.dart'
;
import
'package:provider/provider.dart'
;
import
'package:library_app/src/models/loan.dart'
;
import
'package:library_app/src/widgets/loans/loan_item.dart'
;
class
UpcomingLoanList
extends
StatefulWidget
{
const
UpcomingLoanList
({
super
.
key
});
@override
State
<
UpcomingLoanList
>
createState
()
=>
_UpcomingLoanList
();
}
class
_UpcomingLoanList
extends
State
<
UpcomingLoanList
>
{
@override
void
initState
()
{
super
.
initState
();
Provider
.
of
<
AuthProvider
>(
context
,
listen:
false
).
getLoans
(
"upcoming"
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
Consumer
<
AuthProvider
>(
builder:
(
context
,
loanProvider
,
child
)
{
if
(
loanProvider
.
nearOutstandingLoans
!=
null
)
{
var
loans
=
loanProvider
.
nearOutstandingLoans
!.
map
(
(
loan
)
{
var
book
=
Book
.
fromJson
(
loan
[
"book_detail"
]);
return
Loan
(
book
,
loan
[
"loan_date"
],
loan
[
"due_date"
],
loan
[
"remaining_loan_time"
],
loan
[
"is_overdue"
],
);
},
);
return
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
[
const
TopAppBar
(
title:
"Near Outstanding Loans"
)];
},
body:
ListView
(
children:
List
.
generate
(
loans
.
length
,
(
index
)
{
return
LoanItem
(
loans
.
elementAt
(
index
));
}),
),
);
}
else
{
return
NestedScrollView
(
headerSliverBuilder:
(
BuildContext
context
,
bool
innerBoxIsScrolled
)
{
return
[
const
TopAppBar
(
title:
"Book Loans"
)];
},
body:
const
Center
(
child:
Text
(
"the loan is currently empty"
),
),
);
}
});
}
}
class
TopAppBar
extends
StatefulWidget
{
final
String
title
;
const
TopAppBar
({
super
.
key
,
required
this
.
title
});
@override
_TopAppBar
createState
()
=>
_TopAppBar
();
}
class
_TopAppBar
extends
State
<
TopAppBar
>
{
String
get
title
=>
widget
.
title
;
bool
showWidget
=
false
;
@override
Widget
build
(
BuildContext
context
)
{
return
SliverAppBar
(
title:
Text
(
title
),
elevation:
10.0
,
automaticallyImplyLeading:
false
,
expandedHeight:
50
,
floating:
true
,
snap:
true
,
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment