Commit 4e559f11 authored by Fahmi's avatar Fahmi

add bookloan

parent 8ece02c3
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class BookLoan {
final String bookTitle;
final String bookImageUrl;
final String memberName;
final DateTime loanDate;
final DateTime dueDate;
final DateTime? returnDate;
final bool isReturned;
BookLoan({
required this.bookTitle,
required this.bookImageUrl,
required this.memberName,
required this.loanDate,
required this.dueDate,
required this.returnDate,
required this.isReturned,
});
factory BookLoan.fromJson(Map<String, dynamic> json) {
return BookLoan(
bookTitle: json['book']['title'],
bookImageUrl: json['book_image_url'],
memberName: json['member']['name'],
loanDate: DateTime.parse(json['loan_date']),
dueDate: DateTime.parse(json['due_date']),
returnDate: json['return_date'] != null
? DateTime.parse(json['return_date'])
: null,
isReturned: json['is_returned'],
);
}
}
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'bookloandetail_page.dart';
class BookLoanPage extends StatefulWidget {
@override
_BookLoanPageState createState() => _BookLoanPageState();
}
class _BookLoanPageState extends State<BookLoanPage> {
late ScrollController _scrollController;
late List<Map<String, dynamic>> _bookLoans;
late String? _nextPageUrl;
@override
void initState() {
super.initState();
_scrollController = ScrollController()..addListener(_scrollListener);
_bookLoans = [];
_nextPageUrl = 'http://10.0.2.2:8000/api/bookloan/';
_loadData();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _scrollListener() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
// Load more data when scrolled to the bottom
_loadData();
}
}
Future<void> _loadData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String accessToken = prefs.getString('access_token') ?? '';
final response = await http.get(
Uri.parse(_nextPageUrl!),
headers: {
"Authorization": "Bearer $accessToken",
},
);
if (response.statusCode == 200) {
final jsonData = jsonDecode(response.body);
final List<dynamic> data = jsonData['results'];
setState(() {
_bookLoans.addAll(data.cast<Map<String, dynamic>>());
_nextPageUrl = jsonData['next'];
});
} else if (response.statusCode == 403) {
throw Exception(
'Access denied. Only librarians are allowed to view book loans.');
} else {
throw Exception('Failed to load book loans');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Book Loans'),
),
body: ListView.builder(
controller: _scrollController,
itemCount: _bookLoans.length,
itemBuilder: (context, index) {
final loan = _bookLoans[index];
return Card(
child: ListTile(
leading: Container(
width: 50,
child: Image.network(
loan['book_image_url'],
fit: BoxFit.cover,
),
),
title: Text(loan['book_title']),
trailing: Text('Returned: ${loan['is_returned'] ? 'Yes' : 'No'}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Loan Member: ${loan['member_name']}'),
// Tampilkan status isReturned
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BookLoanDetailPage(loan: loan),
),
);
},
),
);
},
),
);
}
}
import 'package:flutter/material.dart';
class BookLoanDetailPage extends StatelessWidget {
final Map<String, dynamic> loan;
BookLoanDetailPage({required this.loan});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Book Loan Detail'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Book Title: ${loan['book_title']}',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Image.network(
loan['book_image_url'],
height: 200,
width: 200,
fit: BoxFit.cover,
),
SizedBox(height: 8),
Text('Loan Member: ${loan['member_name']}'),
SizedBox(height: 8),
Text('Loan Date: ${loan['loan_date']}'),
SizedBox(height: 8),
Text('Due Date: ${loan['due_date']}'),
SizedBox(height: 8),
Text('Return Date: ${loan['return_date'] ?? 'Not returned'}'),
SizedBox(height: 8),
Text('Is Returned: ${loan['is_returned'] ? 'Yes' : 'No'}'),
],
),
),
);
}
}
......@@ -9,6 +9,7 @@ import '../model/user_model.dart';
import '../services/auth_service.dart';
import 'bookdetail_page.dart';
import 'bookdetailscreen_page.dart';
import 'bookloan_page.dart';
import 'booksbycategory_page.dart';
import 'changepassword_page.dart';
import 'editprofile_page.dart';
......@@ -212,6 +213,15 @@ class _LibrarianDashboardState extends State<LibrarianDashboard> {
Navigator.pop(context);
},
),
ListTile(
title: Text('Book Loan'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BookLoanPage()),
);
},
),
ListTile(
title: Text('Near Outstanding Book Loan'),
onTap: () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment