feat: add feature cart integrate eith API and life cycle

This commit is contained in:
pahmiudahgede 2025-05-19 20:58:32 +07:00
parent 0d129218de
commit 83e65714ad
14 changed files with 735 additions and 245 deletions

View File

@ -17,3 +17,5 @@ export 'package:rijig_mobile/features/home/service/about_service.dart';
export 'package:rijig_mobile/globaldata/article/article_repository.dart';
export 'package:rijig_mobile/globaldata/article/article_service.dart';
export 'package:rijig_mobile/globaldata/article/article_vmod.dart';
export 'package:rijig_mobile/features/cart/presentation/viewmodel/cartitem_vmod.dart';
export 'package:rijig_mobile/features/cart/repositories/cartitem_repo.dart';

View File

@ -13,4 +13,5 @@ void init() {
sl.registerFactory(() => AboutViewModel(AboutService(AboutRepository())));
sl.registerFactory(() => AboutDetailViewModel(AboutService(AboutRepository())));
sl.registerFactory(() => ArticleViewModel(ArticleService(ArticleRepository())));
sl.registerFactory(() => CartViewModel(CartRepository()));
}

View File

@ -1,7 +1,7 @@
export 'package:go_router/go_router.dart';
export 'package:rijig_mobile/core/utils/navigation.dart';
export 'package:rijig_mobile/features/activity/presentation/screen/activity_screen.dart';
export 'package:rijig_mobile/features/cart/presentation/cart_screen.dart';
export 'package:rijig_mobile/features/cart/presentation/screens/cart_screen.dart';
export 'package:rijig_mobile/features/home/presentation/screen/home_screen.dart';
export 'package:rijig_mobile/features/profil/presentation/screen/profil_screen.dart';
export 'package:rijig_mobile/features/requestpick/presentation/screen/requestpickup_screen.dart';

View File

@ -40,9 +40,9 @@ class Tulisan {
);
}
static TextStyle subheading({Color? color}) {
static TextStyle subheading({Color? color, double? fontsize}) {
return GoogleFonts.spaceGrotesk(
fontSize: 18.sp,
fontSize: fontsize?.sp ?? 18.sp,
fontWeight: FontWeight.w500,
color: color ?? blackNavyColor,
);

View File

@ -3,7 +3,7 @@ import 'package:iconsax_flutter/iconsax_flutter.dart';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/core/router.dart';
import 'package:rijig_mobile/features/activity/presentation/screen/activity_screen.dart';
import 'package:rijig_mobile/features/cart/presentation/cart_screen.dart';
import 'package:rijig_mobile/features/cart/presentation/screens/cart_screen.dart';
import 'package:rijig_mobile/features/home/presentation/screen/home_screen.dart';
import 'package:rijig_mobile/features/profil/presentation/screen/profil_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';

View File

@ -0,0 +1,89 @@
import 'dart:convert';
class CartItem {
final String trashId;
final double amount;
CartItem({required this.trashId, required this.amount});
Map<String, dynamic> toJson() => {'trashid': trashId, 'amount': amount};
factory CartItem.fromJson(Map<String, dynamic> json) {
return CartItem(
trashId: json['trashid'],
amount: (json['amount'] as num).toDouble(),
);
}
static String encodeList(List<CartItem> items) =>
jsonEncode(items.map((e) => e.toJson()).toList());
static List<CartItem> decodeList(String source) =>
(jsonDecode(source) as List<dynamic>)
.map((e) => CartItem.fromJson(e))
.toList();
}
class CartItemResponse {
final String trashId;
final String trashIcon;
final String trashName;
final double amount;
final double estimatedSubTotalPrice;
CartItemResponse({
required this.trashId,
required this.trashIcon,
required this.trashName,
required this.amount,
required this.estimatedSubTotalPrice,
});
factory CartItemResponse.fromJson(Map<String, dynamic> json) {
return CartItemResponse(
trashId: json['trashid'],
trashIcon: json['trashicon'] ?? '',
trashName: json['trashname'] ?? '',
amount: (json['amount'] as num).toDouble(),
estimatedSubTotalPrice:
(json['estimated_subtotalprice'] as num).toDouble(),
);
}
}
class CartResponse {
final String id;
final String userId;
final double totalAmount;
final double estimatedTotalPrice;
final String createdAt;
final String updatedAt;
final List<CartItemResponse> cartItems;
CartResponse({
required this.id,
required this.userId,
required this.totalAmount,
required this.estimatedTotalPrice,
required this.createdAt,
required this.updatedAt,
required this.cartItems,
});
factory CartResponse.fromJson(Map<String, dynamic> json) {
var items =
(json['cartitems'] as List<dynamic>)
.map((e) => CartItemResponse.fromJson(e))
.toList();
return CartResponse(
id: json['id'],
userId: json['userid'],
totalAmount: (json['totalamount'] as num).toDouble(),
estimatedTotalPrice: (json['estimated_totalprice'] as num).toDouble(),
createdAt: json['createdAt'],
updatedAt: json['updatedAt'],
cartItems: items,
);
}
}

View File

@ -1,236 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/widget/buttoncard.dart';
import 'package:rijig_mobile/widget/counter_dialog.dart';
class CartScreen extends StatefulWidget {
const CartScreen({super.key});
@override
State<CartScreen> createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen> {
double totalWeight = 1.0;
double pricePerKg = 700;
void _openEditAmountDialog(String itemName) {
showDialog(
context: context,
builder: (BuildContext context) {
return EditAmountDialog(
initialAmount: totalWeight,
itemName: itemName,
pricePerKg: pricePerKg,
onSave: (newAmount) {
setState(() {
totalWeight = newAmount;
});
},
);
},
);
}
void _increment() {
setState(() {
totalWeight += 0.25;
});
}
void _decrement() {
if (totalWeight > 0.25) {
setState(() {
totalWeight -= 0.25;
});
}
}
String formatAmount(double value) {
String formattedValue = value.toStringAsFixed(2);
if (formattedValue.endsWith('.00')) {
return formattedValue.split('.').first;
}
return formattedValue;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: whiteColor,
appBar: AppBar(
title: Text(
'Keranjang Sampah',
style: Tulisan.subheading(color: blackNavyColor),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: PaddingCustom().paddingHorizontal(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.all(20),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withValues(alpha: 0.1),
spreadRadius: 1,
blurRadius: 8,
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Lokasi Penjemputan',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
SizedBox(height: 10),
Text(
'Lokasi harus di Jember',
style: TextStyle(fontSize: 14),
),
Gap(15),
CardButtonOne(
textButton: "Pilih Alamat",
fontSized: 16.sp,
color: primaryColor,
colorText: whiteColor,
borderRadius: 9,
horizontal: double.infinity,
vertical: 40,
onTap: () {
debugPrint("pilih alamat tapped");
},
),
],
),
),
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withValues(alpha: 0.1),
spreadRadius: 1,
blurRadius: 8,
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Jenis Sampah',
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
Row(
children: [
Icon(Icons.delete, color: Colors.blue),
SizedBox(width: 8),
Text('Kertas Campur'),
Spacer(),
GestureDetector(
onTap: () {
_openEditAmountDialog('Kertas Campur');
},
child: Row(
children: [
Text("${formatAmount(totalWeight)} kg"),
Icon(Icons.edit, color: Colors.blue),
],
),
),
],
),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
onPressed: _decrement,
icon: Icon(Icons.remove),
color: Colors.red,
),
SizedBox(width: 10),
IconButton(
onPressed: _increment,
icon: Icon(Icons.add),
color: Colors.green,
),
],
),
],
),
),
SizedBox(height: 20),
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withValues(alpha: 0.1),
spreadRadius: 1,
blurRadius: 8,
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Estimasi Total Berat',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
"${formatAmount(totalWeight)} kg",
style: TextStyle(fontSize: 18),
),
],
),
),
SizedBox(height: 20),
Center(
child: CardButtonOne(
textButton: "Lanjutkan",
fontSized: 16.sp,
color: primaryColor,
colorText: whiteColor,
borderRadius: 9,
horizontal: double.infinity,
vertical: 60,
onTap: () {
debugPrint("lanjutkan tapped");
},
),
),
],
),
),
),
),
);
}
}

View File

@ -0,0 +1,460 @@
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:gap/gap.dart';
import 'package:iconsax_flutter/iconsax_flutter.dart';
import 'package:provider/provider.dart';
import 'package:rijig_mobile/core/utils/guide.dart';
import 'package:rijig_mobile/features/cart/model/cartitem_model.dart';
import 'package:rijig_mobile/features/cart/presentation/viewmodel/cartitem_vmod.dart';
import 'package:rijig_mobile/widget/buttoncard.dart';
import 'package:rijig_mobile/widget/skeletonize.dart';
class CartScreen extends StatefulWidget {
const CartScreen({super.key});
@override
State<CartScreen> createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen> with WidgetsBindingObserver {
CartResponse? cart;
bool isLoading = true;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
fetchCart();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
debugPrint("App resumed, flushing cart...");
final vmod = Provider.of<CartViewModel>(context, listen: false);
vmod.flushCartToServer();
}
}
Future<void> fetchCart() async {
final vmod = Provider.of<CartViewModel>(context, listen: false);
final result = await vmod.fetchCartFromServer();
setState(() {
cart = result;
isLoading = false;
});
}
double get totalAmount => cart?.totalAmount ?? 0;
double get totalPrice => cart?.estimatedTotalPrice ?? 0;
String formatAmount(double value) {
String formattedValue = value.toStringAsFixed(2);
return formattedValue.endsWith('.00')
? formattedValue.split('.').first
: formattedValue;
}
void _showEditDialog(String trashId, double currentAmount, int index) {
double editedAmount = currentAmount;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Edit Jumlah'),
content: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.remove),
onPressed: () {
setState(() {
if (editedAmount > 0.25) editedAmount -= 0.25;
});
},
),
Text('${formatAmount(editedAmount)} kg'),
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
setState(() {
editedAmount += 0.25;
});
},
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Batal'),
),
TextButton(
onPressed: () {
final vmod = Provider.of<CartViewModel>(context, listen: false);
vmod.addOrUpdateItem(
CartItem(trashId: trashId, amount: editedAmount),
);
final item = cart!.cartItems[index];
setState(() {
cart!.cartItems[index] = CartItemResponse(
trashIcon: item.trashIcon,
trashName: item.trashName,
amount: editedAmount,
estimatedSubTotalPrice:
editedAmount *
(item.estimatedSubTotalPrice / item.amount),
trashId: item.trashId,
);
});
Navigator.of(context).pop();
},
child: const Text('Simpan'),
),
],
);
},
);
}
void recalculateCartSummary() {
double totalWeight = 0;
double totalPrice = 0;
for (final item in cart!.cartItems) {
totalWeight += item.amount;
totalPrice += item.estimatedSubTotalPrice;
}
setState(() {
cart = CartResponse(
id: cart!.id,
userId: cart!.userId,
totalAmount: totalWeight,
estimatedTotalPrice: totalPrice,
createdAt: cart!.createdAt,
updatedAt: cart!.updatedAt,
cartItems: cart!.cartItems,
);
});
}
@override
Widget build(BuildContext context) {
final String? baseUrl = dotenv.env["BASE_URL"];
return Scaffold(
backgroundColor: whiteColor,
appBar: AppBar(
title: Text("Keranjang Item", style: Tulisan.subheading()),
backgroundColor: whiteColor,
centerTitle: true,
),
body: SafeArea(
child:
isLoading
? ListView.builder(
shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
return SkeletonCard();
},
)
: Padding(
padding: PaddingCustom().paddingOnly(
left: 10,
right: 10,
bottom: 40,
top: 10,
),
child: Column(
children: [
const Gap(20),
Expanded(
child: ListView.builder(
itemCount: cart?.cartItems.length ?? 0,
itemBuilder: (context, index) {
final item = cart!.cartItems[index];
final perKgPrice =
item.estimatedSubTotalPrice / item.amount;
final currentAmount = item.amount;
return Container(
margin: const EdgeInsets.only(bottom: 20),
padding: PaddingCustom().paddingAll(20),
decoration: BoxDecoration(
color: whiteColor,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: greyColor.withValues(alpha: 0.1),
spreadRadius: 1,
blurRadius: 8,
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Image.network(
"$baseUrl${item.trashIcon}",
width: 50,
height: 50,
),
const Gap(10),
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
item.trashName,
style: Tulisan.customText(),
),
Text(
"Rp${perKgPrice.toStringAsFixed(0)} / kg",
style: Tulisan.body(fontsize: 12),
),
],
),
),
IconButton(
onPressed: () {
final vmod =
Provider.of<CartViewModel>(
context,
listen: false,
);
vmod.removeItem(item.trashId);
setState(() {
cart!.cartItems.removeAt(index);
});
recalculateCartSummary();
},
icon: Icon(
Iconsax.trash,
color: redColor,
),
),
],
),
const Gap(10),
Row(
children: [
Text(
"berat",
style: Tulisan.body(fontsize: 12),
),
const Gap(12),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
decoration: BoxDecoration(
border: Border.all(
color: greyAbsolutColor,
),
borderRadius: BorderRadius.circular(
6,
),
),
child: Row(
children: [
GestureDetector(
onTap: () {
final newAmount =
(currentAmount - 0.25)
.clamp(
0.25,
double.infinity,
);
Provider.of<CartViewModel>(
context,
listen: false,
).addOrUpdateItem(
CartItem(
trashId: item.trashId,
amount: newAmount,
),
);
setState(() {
cart!.cartItems[index] =
CartItemResponse(
trashIcon:
item.trashIcon,
trashName:
item.trashName,
amount: newAmount,
estimatedSubTotalPrice:
newAmount *
(item.estimatedSubTotalPrice /
item.amount),
trashId: item.trashId,
);
});
recalculateCartSummary();
},
child: const Icon(
Icons.remove,
size: 20,
),
),
const Gap(8),
GestureDetector(
onTap:
() => _showEditDialog(
item.trashId,
currentAmount,
index,
),
child: Text(
formatAmount(currentAmount),
),
),
const Gap(8),
GestureDetector(
onTap: () {
final newAmount =
currentAmount + 0.25;
Provider.of<CartViewModel>(
context,
listen: false,
).addOrUpdateItem(
CartItem(
trashId: item.trashId,
amount: newAmount,
),
);
setState(() {
cart!.cartItems[index] =
CartItemResponse(
trashIcon:
item.trashIcon,
trashName:
item.trashName,
amount: newAmount,
estimatedSubTotalPrice:
newAmount *
(item.estimatedSubTotalPrice /
item.amount),
trashId: item.trashId,
);
});
recalculateCartSummary();
},
child: const Icon(
Icons.add,
size: 20,
),
),
],
),
),
],
),
],
),
);
},
),
),
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: whiteColor,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: greyAbsolutColor.withValues(alpha: 0.1),
spreadRadius: 1,
blurRadius: 8,
),
],
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Cart Total",
style: Tulisan.subheading(fontsize: 14),
),
Text(
"${formatAmount(totalAmount)} kg",
style: Tulisan.body(fontsize: 14),
),
],
),
const Gap(10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Harga Total",
style: Tulisan.subheading(fontsize: 14),
),
Text(
"Rp${totalPrice.toStringAsFixed(0)}",
style: Tulisan.body(fontsize: 14),
),
],
),
],
),
),
const Gap(20),
SizedBox(
width: double.infinity,
child: CardButtonOne(
textButton: "Request Pickup",
fontSized: 16.sp,
color: primaryColor,
colorText: whiteColor,
borderRadius: 9,
horizontal: double.infinity,
vertical: 50,
onTap: () async {
final vmod = Provider.of<CartViewModel>(
context,
listen: false,
);
await vmod.flushCartToServer();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
"Keranjang berhasil dikirim ke server!",
),
),
);
},
),
),
const Gap(20),
],
),
),
),
);
}
}

View File

@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:rijig_mobile/features/cart/model/cartitem_model.dart';
import 'package:rijig_mobile/features/cart/repositories/cartitem_repo.dart';
class CartViewModel extends ChangeNotifier {
final CartRepository _repository;
CartViewModel(this._repository);
List<CartItem> _cartItems = [];
List<CartItem> get cartItems => _cartItems;
bool _isLoading = false;
bool get isLoading => _isLoading;
Future<void> loadLocalCart() async {
_isLoading = true;
notifyListeners();
_cartItems = await _repository.getLocalCart();
_isLoading = false;
notifyListeners();
}
void addOrUpdateItem(CartItem item) {
final index = _cartItems.indexWhere((e) => e.trashId == item.trashId);
if (index != -1) {
_cartItems[index] = item;
} else {
_cartItems.add(item);
}
_repository.saveLocalCart(_cartItems);
notifyListeners();
}
void removeItem(String trashId) {
_cartItems.removeWhere((e) => e.trashId == trashId);
_repository.saveLocalCart(_cartItems);
notifyListeners();
}
Future<void> clearLocalCart() async {
_cartItems.clear();
await _repository.clearLocalCart();
notifyListeners();
}
Future<void> flushCartToServer() async {
if (_cartItems.isEmpty) return;
_isLoading = true;
notifyListeners();
await _repository.flushCartToServer();
await clearLocalCart();
_isLoading = false;
notifyListeners();
}
Future<CartResponse?> fetchCartFromServer() async {
try {
return await _repository.getCartFromServer();
} catch (e) {
debugPrint("Error fetching cart: $e");
return null;
}
}
Future<void> commitCart() async {
await _repository.commitCart();
}
Future<void> refreshTTL() async {
await _repository.refreshCartTTL();
}
Future<void> deleteItemFromServer(String trashId) async {
await _repository.deleteCartItemFromServer(trashId);
}
Future<void> clearCartFromServer() async {
await _repository.clearServerCart();
}
}

View File

@ -0,0 +1,55 @@
import 'package:rijig_mobile/features/cart/model/cartitem_model.dart';
import 'package:rijig_mobile/features/cart/service/cartitem_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
class CartRepository {
final CartService _cartService = CartService();
final String _localCartKey = 'local_cart';
Future<List<CartItem>> getLocalCart() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(_localCartKey);
if (raw == null || raw.isEmpty) return [];
return CartItem.decodeList(raw);
}
Future<void> saveLocalCart(List<CartItem> items) async {
final prefs = await SharedPreferences.getInstance();
final encoded = CartItem.encodeList(items);
await prefs.setString(_localCartKey, encoded);
}
Future<void> clearLocalCart() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_localCartKey);
}
Future<void> flushCartToServer() async {
final items = await getLocalCart();
if (items.isEmpty) return;
await _cartService.postCart(items);
await clearLocalCart();
}
Future<CartResponse> getCartFromServer() async {
return await _cartService.getCart();
}
Future<void> commitCart() async {
await _cartService.commitCart();
}
Future<void> clearServerCart() async {
await _cartService.clearCart();
}
Future<void> deleteCartItemFromServer(String trashId) async {
await _cartService.deleteCartItem(trashId);
}
Future<void> refreshCartTTL() async {
await _cartService.refreshCartTTL();
}
}

View File

@ -0,0 +1,33 @@
import 'package:rijig_mobile/core/api/api_services.dart';
import 'package:rijig_mobile/features/cart/model/cartitem_model.dart';
class CartService {
final Https _https = Https();
Future<void> postCart(List<CartItem> items) async {
final body = {"items": items.map((e) => e.toJson()).toList()};
await _https.post("/cart", body: body);
}
Future<CartResponse> getCart() async {
final response = await _https.get("/cart");
return CartResponse.fromJson(response['data']);
}
Future<void> deleteCartItem(String trashId) async {
await _https.delete("/cart/$trashId");
}
Future<void> clearCart() async {
await _https.delete("/cart");
}
Future<void> refreshCartTTL() async {
await _https.put("/cart/refresh");
}
Future<void> commitCart() async {
await _https.post("/cart/commit");
}
}

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:rijig_mobile/core/api/api_services.dart';
import 'package:rijig_mobile/features/home/model/about_model.dart';
@ -7,14 +6,14 @@ class AboutRepository {
Future<List<AboutModel>> getAboutList() async {
final response = await _https.get('/about');
debugPrint("response about: $response");
// debugPrint("response about: $response");
final List data = response['data'] ?? [];
return data.map((e) => AboutModel.fromJson(e)).toList();
}
Future<List<AboutDetailModel>> getAboutDetail(String id) async {
final response = await _https.get('/about/$id');
debugPrint("response about detail: $response");
// debugPrint("response about detail: $response");
final List aboutDetail = response['data']['about_detail'] ?? [];
return aboutDetail.map((e) => AboutDetailModel.fromJson(e)).toList();
}

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:rijig_mobile/core/api/api_services.dart';
import 'package:rijig_mobile/globaldata/article/article_model.dart';
@ -7,7 +6,7 @@ class ArticleRepository {
Future<List<ArticleModel>> fetchArticles() async {
final response = await _https.get('/article-rijik/view-article');
debugPrint("reponse article: $response");
// debugPrint("reponse article: $response");
final List data = response['data'];
return data.map((json) => ArticleModel.fromJson(json)).toList();
}

View File

@ -34,6 +34,7 @@ class MyApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => sl<AboutViewModel>()),
ChangeNotifierProvider(create: (_) => sl<AboutDetailViewModel>()),
ChangeNotifierProvider(create: (_) => sl<ArticleViewModel>()),
ChangeNotifierProvider(create: (_) => sl<CartViewModel>()),
],
child: ScreenUtilInit(
designSize: const Size(375, 812),