feat: added search
This commit is contained in:
parent
b54b825dad
commit
166ee5b389
7 changed files with 193 additions and 60 deletions
|
|
@ -3,6 +3,7 @@ import 'package:seshat/domain/models/bal.dart';
|
|||
import 'package:seshat/domain/models/book.dart';
|
||||
import 'package:seshat/domain/models/book_instance.dart';
|
||||
import 'package:seshat/domain/models/owner.dart';
|
||||
import 'package:seshat/domain/models/search_result.dart';
|
||||
import 'package:seshat/utils/result.dart';
|
||||
|
||||
class BookInstanceRepository {
|
||||
|
|
@ -15,6 +16,14 @@ class BookInstanceRepository {
|
|||
return await _apiClient.getBookInstanceByEAN(balId, ean);
|
||||
}
|
||||
|
||||
Future<Result<List<SearchResult>>> getBySearch(
|
||||
int balId,
|
||||
String title,
|
||||
String author,
|
||||
) async {
|
||||
return await _apiClient.getBookInstanceBySearch(balId, title, author);
|
||||
}
|
||||
|
||||
Future<Result<BookInstance>> sendBook(
|
||||
Book book,
|
||||
Owner owner,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:seshat/domain/models/bal.dart';
|
|||
import 'package:seshat/domain/models/book.dart';
|
||||
import 'package:seshat/domain/models/book_instance.dart';
|
||||
import 'package:seshat/domain/models/owner.dart';
|
||||
import 'package:seshat/domain/models/search_result.dart';
|
||||
import 'package:seshat/utils/command.dart';
|
||||
import 'package:seshat/utils/result.dart';
|
||||
|
||||
|
|
@ -284,6 +285,36 @@ class ApiClient {
|
|||
* =============================
|
||||
*/
|
||||
|
||||
Future<Result<List<SearchResult>>> getBookInstanceBySearch(
|
||||
int balId,
|
||||
String title,
|
||||
String author,
|
||||
) async {
|
||||
final client = Client();
|
||||
try {
|
||||
final headers = await _getHeaders({"Content-Type": "application/json"});
|
||||
final body = jsonEncode({"title": title, "author": author});
|
||||
debugPrint("\n\n\n\n$body\n\n\n\n");
|
||||
final response = await client.post(
|
||||
Uri.parse("https://$apiBasePath/bal/${balId.toString()}/search"),
|
||||
headers: headers,
|
||||
body: body,
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
final json = jsonDecode(response.body) as List<dynamic>;
|
||||
debugPrint("\n\n\n\nJSON : $json\n\n\n\n");
|
||||
return Result.ok(json.map((el) => SearchResult.fromJSON(el)).toList());
|
||||
} else {
|
||||
throw "Unknown Error";
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("\n\n\n\nERROR: ${e.toString()}\n\n\n\n");
|
||||
return Result.error(Exception("API $e"));
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Result<List<BookInstance>>> getBookInstanceByEAN(
|
||||
int balId,
|
||||
int ean,
|
||||
|
|
|
|||
16
lib/domain/models/search_result.dart
Normal file
16
lib/domain/models/search_result.dart
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import 'package:seshat/domain/models/book.dart';
|
||||
import 'package:seshat/domain/models/book_instance.dart';
|
||||
|
||||
class SearchResult {
|
||||
SearchResult(this.instance, this.book);
|
||||
BookInstance instance;
|
||||
Book book;
|
||||
|
||||
factory SearchResult.fromJSON(Map<String, dynamic> json) {
|
||||
BookInstance instance = BookInstance.fromJSON(json["book_instance"]);
|
||||
|
||||
Book book = Book.fromJSON(json["book"]);
|
||||
|
||||
return SearchResult(instance, book);
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import 'package:seshat/domain/models/book.dart';
|
|||
import 'package:seshat/domain/models/book_instance.dart';
|
||||
import 'package:seshat/domain/models/book_stack.dart';
|
||||
import 'package:seshat/domain/models/owner.dart';
|
||||
import 'package:seshat/domain/models/search_result.dart';
|
||||
import 'package:seshat/utils/command.dart';
|
||||
import 'package:seshat/utils/result.dart';
|
||||
|
||||
|
|
@ -93,7 +94,54 @@ class SellViewModel extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> searchBook(String title, String author) async {
|
||||
Bal? bal = await _balRepository.ongoingBal();
|
||||
isScanLoaded = false;
|
||||
_scannedBooks.clear();
|
||||
|
||||
final result = await _bookInstanceRepository.getBySearch(
|
||||
bal!.id,
|
||||
title,
|
||||
author,
|
||||
);
|
||||
switch (result) {
|
||||
case Ok():
|
||||
for (SearchResult searchResult in result.value) {
|
||||
if (searchResult.instance.available == false) {
|
||||
continue;
|
||||
}
|
||||
if (_soldBooks
|
||||
.where((book) => book.instance.id == searchResult.instance.id)
|
||||
.isNotEmpty) {
|
||||
continue;
|
||||
}
|
||||
Owner owner;
|
||||
final result2 = await _ownerRepository.getOwnerById(
|
||||
searchResult.instance.ownerId,
|
||||
);
|
||||
switch (result2) {
|
||||
case Ok():
|
||||
owner = result2.value;
|
||||
break;
|
||||
case Error():
|
||||
continue;
|
||||
}
|
||||
_scannedBooks.add(
|
||||
BookStack(searchResult.book, searchResult.instance, owner),
|
||||
);
|
||||
}
|
||||
break;
|
||||
case Error():
|
||||
break;
|
||||
}
|
||||
|
||||
isScanLoaded = true;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
Future<void> scanBook(BarcodeCapture barcode) async {
|
||||
isScanLoaded = false;
|
||||
int ean = int.parse(barcode.barcodes.first.rawValue!);
|
||||
Bal? bal = await _balRepository.ongoingBal();
|
||||
_scannedBooks.clear();
|
||||
|
|
@ -101,6 +149,17 @@ class SellViewModel extends ChangeNotifier {
|
|||
final result = await _bookInstanceRepository.getByEan(bal!.id, ean);
|
||||
switch (result) {
|
||||
case Ok():
|
||||
Book book;
|
||||
final result2 = await _bookRepository.getBookById(
|
||||
result.value.first.bookId,
|
||||
);
|
||||
switch (result2) {
|
||||
case Ok():
|
||||
book = result2.value;
|
||||
break;
|
||||
case Error():
|
||||
return;
|
||||
}
|
||||
for (BookInstance instance in result.value) {
|
||||
if (instance.available == false) {
|
||||
continue;
|
||||
|
|
@ -110,15 +169,6 @@ class SellViewModel extends ChangeNotifier {
|
|||
.isNotEmpty) {
|
||||
continue;
|
||||
}
|
||||
Book book;
|
||||
final result2 = await _bookRepository.getBookById(instance.bookId);
|
||||
switch (result2) {
|
||||
case Ok():
|
||||
book = result2.value;
|
||||
break;
|
||||
case Error():
|
||||
continue;
|
||||
}
|
||||
Owner owner;
|
||||
final result3 = await _ownerRepository.getOwnerById(instance.ownerId);
|
||||
switch (result3) {
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:seshat/ui/sell_page/view_model/sell_view_model.dart';
|
||||
|
||||
class ManualScanPopup extends StatelessWidget {
|
||||
const ManualScanPopup({
|
||||
super.key,
|
||||
required this.viewModel,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
final SellViewModel viewModel;
|
||||
final MobileScannerController controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("Recherche manuelle"),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Rechercher",
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () {},
|
||||
icon: Icon(Icons.arrow_forward),
|
||||
),
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 200),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
controller.start();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text("Annuler"),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
75
lib/ui/sell_page/widgets/manual_search_popup.dart
Normal file
75
lib/ui/sell_page/widgets/manual_search_popup.dart
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:seshat/ui/sell_page/view_model/sell_view_model.dart';
|
||||
import 'package:seshat/ui/sell_page/widgets/sell_choice_popup.dart';
|
||||
|
||||
class ManualSearchPopup extends StatefulWidget {
|
||||
const ManualSearchPopup({super.key, required this.viewModel});
|
||||
|
||||
final SellViewModel viewModel;
|
||||
|
||||
@override
|
||||
State<ManualSearchPopup> createState() => _ManualSearchPopupState();
|
||||
}
|
||||
|
||||
class _ManualSearchPopupState extends State<ManualSearchPopup> {
|
||||
String? title = "";
|
||||
String? author = "";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
GlobalKey<FormState> _form = GlobalKey<FormState>();
|
||||
|
||||
return AlertDialog(
|
||||
title: Text("Recherche manuelle"),
|
||||
content: Form(
|
||||
key: _form,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Titre",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onSaved: (newValue) => setState(() {
|
||||
title = newValue;
|
||||
}),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: "Auteur",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onSaved: (newValue) => setState(() {
|
||||
author = newValue;
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text("Annuler"),
|
||||
),
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_form.currentState!.save();
|
||||
Navigator.of(context).pop();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
SellChoicePopup(viewModel: widget.viewModel),
|
||||
);
|
||||
widget.viewModel.searchBook(title ?? "", author ?? "");
|
||||
},
|
||||
child: Text("Rechercher"),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:seshat/ui/sell_page/view_model/sell_view_model.dart';
|
||||
import 'package:seshat/ui/sell_page/widgets/manual_scan_popup.dart';
|
||||
import 'package:seshat/ui/sell_page/widgets/manual_search_popup.dart';
|
||||
import 'package:seshat/ui/sell_page/widgets/sell_choice_popup.dart';
|
||||
|
||||
class ScanScreen extends StatefulWidget {
|
||||
|
|
@ -78,10 +78,8 @@ class _ScanScreenState extends State<ScanScreen> {
|
|||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => ManualScanPopup(
|
||||
viewModel: widget.viewModel,
|
||||
controller: controller,
|
||||
),
|
||||
builder: (context) =>
|
||||
ManualSearchPopup(viewModel: widget.viewModel),
|
||||
);
|
||||
},
|
||||
child: Text("Vendre un livre sans scanner"),
|
||||
|
|
|
|||
Reference in a new issue