feat: create product

This commit is contained in:
efrilm 2025-08-05 19:20:45 +07:00
parent 935b6b9a5b
commit bb9aef55cf
24 changed files with 2750 additions and 848 deletions

View File

@ -1,91 +1,189 @@
import 'dart:io';
import 'package:enaklo_pos/presentation/setting/bloc/upload_file/upload_file_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:image_picker/image_picker.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../assets/assets.gen.dart';
import '../constants/colors.dart';
import '../constants/variables.dart';
import 'buttons.dart';
import 'spaces.dart';
class ImagePickerWidget extends StatefulWidget {
final String label;
final void Function(XFile? file) onChanged;
final void Function(String? uploadedUrl)? onUploaded;
final bool showLabel;
final String? initialImageUrl;
final bool autoUpload;
const ImagePickerWidget({
super.key,
required this.label,
required this.onChanged,
this.onUploaded,
this.showLabel = true,
this.initialImageUrl,
this.autoUpload = false,
});
@override
State<ImagePickerWidget> createState() => _ImagePickerWidgetState();
}
class _ImagePickerWidgetState extends State<ImagePickerWidget> {
class _ImagePickerWidgetState extends State<ImagePickerWidget>
with TickerProviderStateMixin {
String? imagePath;
String? uploadedImageUrl;
bool hasInitialImage = false;
bool isHovering = false;
bool isUploading = false;
late AnimationController _scaleController;
late AnimationController _fadeController;
late AnimationController _uploadController;
late Animation<double> _scaleAnimation;
late Animation<double> _fadeAnimation;
late Animation<double> _uploadAnimation;
@override
void initState() {
super.initState();
hasInitialImage = widget.initialImageUrl != null;
_scaleController = AnimationController(
duration: const Duration(milliseconds: 200),
vsync: this,
);
_fadeController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
_uploadController = AnimationController(
duration: const Duration(milliseconds: 1000),
vsync: this,
);
_scaleAnimation = Tween<double>(
begin: 1.0,
end: 0.95,
).animate(CurvedAnimation(
parent: _scaleController,
curve: Curves.easeInOut,
));
_fadeAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _fadeController,
curve: Curves.easeInOut,
));
_uploadAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _uploadController,
curve: Curves.easeInOut,
));
_fadeController.forward();
}
@override
void dispose() {
_scaleController.dispose();
_fadeController.dispose();
_uploadController.dispose();
super.dispose();
}
Future<void> _pickImage() async {
_scaleController.forward().then((_) {
_scaleController.reverse();
});
final pickedFile = await ImagePicker().pickImage(
source: ImageSource.gallery,
);
setState(() {
if (pickedFile != null) {
if (pickedFile != null) {
setState(() {
imagePath = pickedFile.path;
hasInitialImage = false; // Clear initial image when new image is picked
widget.onChanged(pickedFile);
} else {
debugPrint('No image selected.');
widget.onChanged(null);
hasInitialImage = false;
uploadedImageUrl = null;
});
widget.onChanged(pickedFile);
// Auto upload if enabled
if (widget.autoUpload) {
_uploadImage(pickedFile.path);
}
});
} else {
debugPrint('No image selected.');
widget.onChanged(null);
}
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.showLabel) ...[
Text(
widget.label,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
),
void _uploadImage(String filePath) {
setState(() {
isUploading = true;
});
_uploadController.forward();
context.read<UploadFileBloc>().add(
UploadFileEvent.upload(filePath),
);
}
Widget _buildImageContainer() {
return Container(
width: 100.0,
height: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, 4),
),
const SpaceHeight(12.0),
],
Container(
padding: const EdgeInsets.all(6.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
border: Border.all(color: AppColors.primary),
),
child: Row(
children: [
SizedBox(
width: 80.0,
height: 80.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: imagePath != null
? Image.file(
File(imagePath!),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Stack(
children: [
Positioned.fill(
child: imagePath != null
? Image.file(
File(imagePath!),
fit: BoxFit.cover,
)
: uploadedImageUrl != null
? CachedNetworkImage(
imageUrl: uploadedImageUrl!.contains('http')
? uploadedImageUrl!
: '${Variables.baseUrl}/$uploadedImageUrl',
placeholder: (context, url) => Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppColors.primary.withOpacity(0.1),
AppColors.primary.withOpacity(0.05),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: const Center(
child: CircularProgressIndicator(strokeWidth: 2),
),
),
errorWidget: (context, url, error) =>
_buildPlaceholder(),
fit: BoxFit.cover,
)
: hasInitialImage && widget.initialImageUrl != null
@ -93,38 +191,493 @@ class _ImagePickerWidgetState extends State<ImagePickerWidget> {
imageUrl: widget.initialImageUrl!.contains('http')
? widget.initialImageUrl!
: '${Variables.baseUrl}/${widget.initialImageUrl}',
placeholder: (context, url) =>
const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => Container(
padding: const EdgeInsets.all(16.0),
color: AppColors.black.withOpacity(0.05),
child: Assets.icons.image.svg(),
placeholder: (context, url) => Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppColors.primary.withOpacity(0.1),
AppColors.primary.withOpacity(0.05),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: const Center(
child:
CircularProgressIndicator(strokeWidth: 2),
),
),
errorWidget: (context, url, error) =>
_buildPlaceholder(),
fit: BoxFit.cover,
)
: Container(
padding: const EdgeInsets.all(16.0),
color: AppColors.black.withOpacity(0.05),
child: Assets.icons.image.svg(),
),
: _buildPlaceholder(),
),
// Upload progress overlay
if (isUploading)
Positioned.fill(
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.6),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
value: _uploadAnimation.value == 1.0
? null
: _uploadAnimation.value,
),
),
const SizedBox(height: 8),
const Text(
'Uploading...',
style: TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.w500,
),
),
],
),
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Button.filled(
height: 30.0,
width: 140.0,
onPressed: _pickImage,
label: 'Choose Photo',
fontSize: 12.0,
borderRadius: 5.0,
// Overlay gradient for better button visibility
if ((imagePath != null ||
uploadedImageUrl != null ||
(hasInitialImage && widget.initialImageUrl != null)) &&
!isUploading)
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.transparent,
Colors.black.withOpacity(0.3),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
),
),
],
),
),
);
}
Widget _buildPlaceholder() {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppColors.primary.withOpacity(0.1),
AppColors.primary.withOpacity(0.05),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.add_photo_alternate_outlined,
size: 32,
color: AppColors.primary.withOpacity(0.6),
),
const SizedBox(height: 4),
Text(
'Photo',
style: TextStyle(
fontSize: 10,
color: AppColors.primary.withOpacity(0.6),
fontWeight: FontWeight.w500,
),
),
],
),
),
);
}
Widget _buildActionButton() {
bool hasImage = imagePath != null ||
uploadedImageUrl != null ||
(hasInitialImage && widget.initialImageUrl != null);
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
gradient: LinearGradient(
colors: [
AppColors.primary,
AppColors.primary.withOpacity(0.8),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
boxShadow: [
BoxShadow(
color: AppColors.primary.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: isUploading ? null : _pickImage,
onHover: (hover) {
setState(() {
isHovering = hover;
});
},
borderRadius: BorderRadius.circular(12),
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: isHovering
? Colors.white.withOpacity(0.1)
: Colors.transparent,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
isUploading
? Icons.cloud_upload_outlined
: hasImage
? Icons.edit_outlined
: Icons.add_photo_alternate_outlined,
color: Colors.white,
size: 18,
),
const SizedBox(width: 8),
Text(
isUploading
? 'Uploading...'
: hasImage
? 'Change Photo'
: 'Choose Photo',
style: const TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
),
);
}
Widget _buildUploadButton() {
if (!widget.autoUpload &&
imagePath != null &&
uploadedImageUrl == null &&
!isUploading) {
return Padding(
padding: const EdgeInsets.only(top: 12),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
gradient: LinearGradient(
colors: [
Colors.green.shade600,
Colors.green.shade500,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
boxShadow: [
BoxShadow(
color: Colors.green.withOpacity(0.3),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => _uploadImage(imagePath!),
borderRadius: BorderRadius.circular(12),
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.cloud_upload_outlined,
color: Colors.white,
size: 16,
),
const SizedBox(width: 8),
Text(
'Upload to Server',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
),
),
],
);
}
return const SizedBox.shrink();
}
@override
Widget build(BuildContext context) {
return BlocListener<UploadFileBloc, UploadFileState>(
listener: (context, state) {
state.when(
initial: () {},
loading: () {
if (!isUploading) {
setState(() {
isUploading = true;
});
_uploadController.repeat();
}
},
success: (fileData) {
setState(() {
isUploading = false;
uploadedImageUrl = fileData.fileUrl;
});
_uploadController.reset();
if (widget.onUploaded != null) {
widget.onUploaded!(fileData.fileUrl);
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
Icon(Icons.check_circle, color: Colors.white),
SizedBox(width: 8),
Text('Image uploaded successfully!'),
],
),
backgroundColor: Colors.green,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
duration: Duration(seconds: 2),
),
);
},
error: (message) {
setState(() {
isUploading = false;
});
_uploadController.reset();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
Icon(Icons.error_outline, color: Colors.white),
SizedBox(width: 8),
Expanded(child: Text('Upload failed: $message')),
],
),
backgroundColor: Colors.red,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
duration: Duration(seconds: 3),
),
);
},
);
},
child: FadeTransition(
opacity: _fadeAnimation,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.showLabel) ...[
Text(
widget.label,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: Colors.black87,
),
),
const SpaceHeight(16.0),
],
ScaleTransition(
scale: _scaleAnimation,
child: Container(
padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24.0),
color: Colors.white,
border: Border.all(
color: isUploading
? Colors.orange.withOpacity(0.5)
: uploadedImageUrl != null
? Colors.green.withOpacity(0.5)
: AppColors.primary.withOpacity(0.2),
width: 1.5,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: Column(
children: [
_buildImageContainer(),
const SizedBox(height: 20),
_buildActionButton(),
_buildUploadButton(),
if ((imagePath != null ||
uploadedImageUrl != null ||
(hasInitialImage &&
widget.initialImageUrl != null)) &&
!isUploading) ...[
const SizedBox(height: 12),
TextButton.icon(
onPressed: () {
setState(() {
imagePath = null;
hasInitialImage = false;
uploadedImageUrl = null;
});
widget.onChanged(null);
if (widget.onUploaded != null) {
widget.onUploaded!(null);
}
},
icon: Icon(
Icons.delete_outline,
size: 16,
color: Colors.red.shade400,
),
label: Text(
'Remove Photo',
style: TextStyle(
color: Colors.red.shade400,
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
),
],
// Upload status indicator
if (uploadedImageUrl != null && !isUploading) ...[
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.green.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
border:
Border.all(color: Colors.green.withOpacity(0.3)),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.cloud_done_outlined,
size: 14,
color: Colors.green.shade600,
),
const SizedBox(width: 6),
Text(
'Uploaded',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
color: Colors.green.shade600,
),
),
],
),
),
],
],
),
),
),
],
),
),
);
}
}
/// Cara menggunakan widget ini:
///
/// ```dart
/// // 1. Basic usage tanpa auto upload
/// ImagePickerWidget(
/// label: 'Product Image',
/// onChanged: (file) {
/// // Handle selected file
/// print('Selected file: ${file?.path}');
/// },
/// onUploaded: (url) {
/// // Handle uploaded URL
/// print('Uploaded URL: $url');
/// },
/// )
///
/// // 2. Auto upload setelah memilih gambar
/// ImagePickerWidget(
/// label: 'Profile Picture',
/// autoUpload: true,
/// onChanged: (file) => setState(() => selectedFile = file),
/// onUploaded: (url) => setState(() => profileImageUrl = url),
/// )
///
/// // 3. Dengan initial image
/// ImagePickerWidget(
/// label: 'Banner Image',
/// initialImageUrl: existingImageUrl,
/// onChanged: (file) => handleFileChange(file),
/// onUploaded: (url) => handleUploadSuccess(url),
/// )
/// ```
///
/// Pastikan untuk wrap widget ini dengan BlocProvider:
/// ```dart
/// BlocProvider(
/// create: (context) => UploadFileBloc(
/// context.read<FileRemoteDataSource>(),
/// ),
/// child: ImagePickerWidget(...),
/// )
/// ```

View File

@ -1,27 +1,48 @@
import 'dart:developer';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:enaklo_pos/core/constants/variables.dart';
import 'package:enaklo_pos/core/network/dio_client.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
import 'package:enaklo_pos/data/models/response/category_response_model.dart';
import 'package:http/http.dart' as http;
class CategoryRemoteDatasource {
Future<Either<String, CategroyResponseModel>> getCategories() async {
final Dio dio = DioClient.instance;
Future<Either<String, CategoryResponseModel>> getCategories({
int page = 1,
int limit = 10,
bool isActive = true,
}) async {
final authData = await AuthLocalDataSource().getAuthData();
final Map<String, String> headers = {
final headers = {
'Authorization': 'Bearer ${authData.token}',
'Accept': 'application/json',
};
final response = await http.get(
Uri.parse('${Variables.baseUrl}/api/api-categories'),
headers: headers);
log(response.statusCode.toString());
log(response.body);
if (response.statusCode == 200) {
return right(CategroyResponseModel.fromJson(response.body));
} else {
return left(response.body);
try {
final response = await dio.get(
'${Variables.baseUrl}/api/v1/categories',
queryParameters: {
'page': page,
'limit': limit,
'is_active': isActive,
},
options: Options(headers: headers),
);
if (response.statusCode == 200) {
return right(CategoryResponseModel.fromMap(response.data));
} else {
return left(response.data.toString());
}
} on DioException catch (e) {
log('Dio error: ${e.message}');
return left(e.response?.data.toString() ?? e.message ?? 'Unknown error');
} catch (e) {
log('Unexpected error: $e');
return left('Unexpected error occurred');
}
}
}

View File

@ -0,0 +1,53 @@
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';
import 'package:enaklo_pos/core/constants/variables.dart';
import 'package:enaklo_pos/core/network/dio_client.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
import 'package:enaklo_pos/data/models/response/file_response_model.dart';
class FileRemoteDataSource {
final Dio dio = DioClient.instance;
Future<Either<String, FileResponseModel>> uploadFile({
required String filePath,
required String fileType,
required String description,
}) async {
final url = '${Variables.baseUrl}/api/v1/files/upload';
try {
final authData = await AuthLocalDataSource().getAuthData();
// Membuat FormData
final formData = FormData.fromMap({
'file': await MultipartFile.fromFile(filePath,
filename: filePath.split('/').last),
'file_type': fileType,
'description': description,
});
final response = await dio.post(
url,
data: formData,
options: Options(
headers: {
'Authorization': 'Bearer ${authData.token}',
'Accept': 'application/json',
// Content-Type otomatis diatur oleh Dio untuk FormData
},
),
);
if (response.statusCode == 201 || response.statusCode == 200) {
// Misal response.data['url'] adalah URL file yang diupload
return Right(FileResponseModel.fromJson(response.data));
} else {
return Left('Upload gagal: ${response.statusMessage}');
}
} on DioException catch (e) {
return Left(e.response?.data['message'] ?? 'Upload gagal');
} catch (e) {
return Left('Unexpected error: $e');
}
}
}

View File

@ -6,7 +6,6 @@ import 'package:enaklo_pos/core/network/dio_client.dart';
import 'package:enaklo_pos/data/models/request/product_request_model.dart';
import 'package:enaklo_pos/data/models/response/add_product_response_model.dart';
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
import 'package:http/http.dart' as http;
import '../../core/constants/variables.dart';
import 'auth_local_datasource.dart';
@ -21,6 +20,10 @@ class ProductRemoteDatasource {
final response = await dio.get(
url,
queryParameters: {
'page': 1,
'limit': 30,
},
options: Options(
headers: {
'Authorization': 'Bearer ${authData.token}',
@ -45,67 +48,64 @@ class ProductRemoteDatasource {
Future<Either<String, AddProductResponseModel>> addProduct(
ProductRequestModel productRequestModel) async {
final authData = await AuthLocalDataSource().getAuthData();
final Map<String, String> headers = {
'Authorization': 'Bearer ${authData.token}',
};
var request = http.MultipartRequest(
'POST', Uri.parse('${Variables.baseUrl}/api/products'));
request.fields.addAll(productRequestModel.toMap());
request.files.add(await http.MultipartFile.fromPath(
'image', productRequestModel.image!.path));
request.headers.addAll(headers);
try {
final authData = await AuthLocalDataSource().getAuthData();
final url = '${Variables.baseUrl}/api/v1/products';
http.StreamedResponse response = await request.send();
final response = await dio.post(
url,
data: productRequestModel.toMap(),
options: Options(
headers: {
'Authorization': 'Bearer ${authData.token}',
'Accept': 'application/json',
},
),
);
final String body = await response.stream.bytesToString();
log(response.stream.toString());
log(response.statusCode.toString());
if (response.statusCode == 201) {
return right(AddProductResponseModel.fromJson(body));
} else {
return left(body);
if (response.statusCode == 200) {
return Right(AddProductResponseModel.fromMap(response.data));
} else {
return const Left('Failed to create products');
}
} on DioException catch (e) {
log("Dio error: ${e.message}");
return Left(e.response?.data['message'] ?? 'Gagal menambah produk');
} catch (e) {
log("Unexpected error: $e");
return const Left('Unexpected error occurred');
}
}
Future<Either<String, AddProductResponseModel>> updateProduct(
ProductRequestModel productRequestModel) async {
final authData = await AuthLocalDataSource().getAuthData();
final Map<String, String> headers = {
'Authorization': 'Bearer ${authData.token}',
};
try {
final authData = await AuthLocalDataSource().getAuthData();
final url =
'${Variables.baseUrl}/api/v1/products/${productRequestModel.id}';
log("Update Product Request Data: ${productRequestModel.toMap()}");
log("Update Product ID: ${productRequestModel.id}");
log("Update Product Name: ${productRequestModel.name}");
log("Update Product Price: ${productRequestModel.price}");
log("Update Product Stock: ${productRequestModel.stock}");
log("Update Product Category ID: ${productRequestModel.categoryId}");
log("Update Product Is Best Seller: ${productRequestModel.isBestSeller}");
log("Update Product Printer Type: ${productRequestModel.printerType}");
log("Update Product Has Image: ${productRequestModel.image != null}");
final response = await dio.put(
url,
data: productRequestModel.toMap(),
options: Options(
headers: {
'Authorization': 'Bearer ${authData.token}',
'Accept': 'application/json',
},
),
);
var request = http.MultipartRequest(
'POST', Uri.parse('${Variables.baseUrl}/api/products/edit'));
request.fields.addAll(productRequestModel.toMap());
if (productRequestModel.image != null) {
request.files.add(await http.MultipartFile.fromPath(
'image', productRequestModel.image!.path));
}
request.headers.addAll(headers);
log("Update Product Request Fields: ${request.fields}");
log("Update Product Request Files: ${request.files.length}");
http.StreamedResponse response = await request.send();
final String body = await response.stream.bytesToString();
log("Update Product Status Code: ${response.statusCode}");
log("Update Product Body: $body");
if (response.statusCode == 200) {
return right(AddProductResponseModel.fromJson(body));
} else {
return left(body);
if (response.statusCode == 200) {
return Right(AddProductResponseModel.fromMap(response.data));
} else {
return const Left('Failed to update products');
}
} on DioException catch (e) {
log("Dio error: ${e.message}");
return Left(e.response?.data['message'] ?? 'Gagal update produk');
} catch (e) {
log("Unexpected error: $e");
return const Left('Unexpected error occurred');
}
}
}

View File

@ -1,40 +1,49 @@
import 'dart:developer';
import 'package:image_picker/image_picker.dart';
class ProductRequestModel {
final String? id;
final String name;
final String? description;
final String categoryId;
final String? sku;
final String? barcode;
final int price;
final int stock;
final int categoryId;
final int isBestSeller;
final XFile? image;
final int cost;
final bool isActive;
final bool hasVariants;
final String imageUrl;
final String? printerType;
ProductRequestModel({
this.id,
required this.name,
required this.price,
required this.stock,
this.description,
required this.categoryId,
required this.isBestSeller,
this.image,
this.sku,
this.barcode,
required this.price,
required this.cost,
this.isActive = true,
this.hasVariants = false,
required this.imageUrl,
this.printerType,
});
Map<String, String> toMap() {
log("toMap: $isBestSeller");
final map = {
Map<String, dynamic> toMap() {
final map = <String, dynamic>{
'name': name,
'price': price.toString(),
'stock': stock.toString(),
'category_id': categoryId.toString(),
'is_best_seller': isBestSeller.toString(),
'description': description ?? '',
'category_id': categoryId,
'sku': sku ?? '',
'barcode': barcode ?? '',
'price': price,
'cost': cost,
'is_active': isActive,
'has_variants': hasVariants,
'image_url': imageUrl,
'printer_type': printerType ?? '',
};
if (id != null) {
map['id'] = id.toString();
map['id'] = id;
}
return map;

View File

@ -4,12 +4,10 @@ import 'package:enaklo_pos/data/models/response/product_response_model.dart';
class AddProductResponseModel {
final bool success;
final String message;
final Product data;
AddProductResponseModel({
required this.success,
required this.message,
required this.data,
});
@ -21,13 +19,11 @@ class AddProductResponseModel {
factory AddProductResponseModel.fromMap(Map<String, dynamic> json) =>
AddProductResponseModel(
success: json["success"],
message: json["message"],
data: Product.fromMap(json["data"]),
);
Map<String, dynamic> toMap() => {
"success": success,
"message": message,
"data": data.toMap(),
};
}

View File

@ -1,91 +1,120 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';
class CategroyResponseModel {
final String status;
final List<CategoryModel> data;
class CategoryResponseModel {
final bool success;
final CategoryData data;
final dynamic errors;
CategroyResponseModel({
required this.status,
CategoryResponseModel({
required this.success,
required this.data,
this.errors,
});
Map<String, dynamic> toMap() {
return <String, dynamic>{
'status': status,
'data': data.map((x) => x.toMap()).toList(),
};
}
factory CategroyResponseModel.fromMap(Map<String, dynamic> map) {
return CategroyResponseModel(
status: map['status'] as String,
data: List<CategoryModel>.from(
(map['data']).map<CategoryModel>(
(x) => CategoryModel.fromMap(x as Map<String, dynamic>),
),
),
factory CategoryResponseModel.fromMap(Map<String, dynamic> map) {
return CategoryResponseModel(
success: map['success'] as bool,
data: CategoryData.fromMap(map['data'] as Map<String, dynamic>),
errors: map['errors'],
);
}
factory CategroyResponseModel.fromJson(String str) =>
CategroyResponseModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
}
class CategoryModel {
int? id;
String? name;
int? categoryId;
int? isSync;
String? image;
// DateTime createdAt;
// DateTime updatedAt;
CategoryModel({this.id, this.name, this.categoryId, this.isSync, this.image});
factory CategoryResponseModel.fromJson(String str) =>
CategoryResponseModel.fromMap(json.decode(str));
Map<String, dynamic> toMap() {
return <String, dynamic>{
// 'id': id,
'name': name,
'is_sync': isSync ?? 1,
'category_id': id,
'image': image
return {
'success': success,
'data': data.toMap(),
'errors': errors,
};
}
factory CategoryModel.fromMap(Map<String, dynamic> map) {
return CategoryModel(
id: map['id'] as int?,
name: map['name'] as String?,
isSync: map['is_sync'] as int?,
categoryId: map['id'],
image: map['image']);
}
factory CategoryModel.fromJson(String str) =>
CategoryModel.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
}
@override
bool operator ==(covariant CategoryModel other) {
if (identical(this, other)) return true;
class CategoryData {
final List<CategoryModel> categories;
final int totalCount;
final int page;
final int limit;
final int totalPages;
return other.id == id &&
other.name == name &&
other.categoryId == categoryId &&
other.isSync == isSync &&
other.image == image;
CategoryData({
required this.categories,
required this.totalCount,
required this.page,
required this.limit,
required this.totalPages,
});
factory CategoryData.fromMap(Map<String, dynamic> map) {
return CategoryData(
categories: List<CategoryModel>.from(
(map['categories'] as List).map((x) => CategoryModel.fromMap(x)),
),
totalCount: map['total_count'] as int,
page: map['page'] as int,
limit: map['limit'] as int,
totalPages: map['total_pages'] as int,
);
}
@override
int get hashCode {
return id.hashCode ^
name.hashCode ^
categoryId.hashCode ^
isSync.hashCode ^
image.hashCode;
Map<String, dynamic> toMap() {
return {
'categories': categories.map((x) => x.toMap()).toList(),
'total_count': totalCount,
'page': page,
'limit': limit,
'total_pages': totalPages,
};
}
}
class CategoryModel {
String id;
final String organizationId;
final String name;
final String? description;
final String businessType;
final Map<String, dynamic> metadata;
final DateTime createdAt;
final DateTime updatedAt;
CategoryModel({
required this.id,
required this.organizationId,
required this.name,
this.description,
required this.businessType,
required this.metadata,
required this.createdAt,
required this.updatedAt,
});
factory CategoryModel.fromMap(Map<String, dynamic> map) {
return CategoryModel(
id: map['id'] as String,
organizationId: map['organization_id'] as String,
name: map['name'] as String,
description: map['description'] as String?,
businessType: map['business_type'] as String,
metadata: Map<String, dynamic>.from(map['metadata'] ?? {}),
createdAt: DateTime.parse(map['created_at'] as String),
updatedAt: DateTime.parse(map['updated_at'] as String),
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'organization_id': organizationId,
'name': name,
'description': description,
'business_type': businessType,
'metadata': metadata,
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.toIso8601String(),
};
}
}

View File

@ -0,0 +1,154 @@
class FileResponseModel {
final FileModel data;
final String message;
final bool success;
FileResponseModel({
required this.data,
required this.message,
required this.success,
});
factory FileResponseModel.fromJson(Map<String, dynamic> json) {
return FileResponseModel(
data: FileModel.fromJson(json['data']),
message: json['message'] as String,
success: json['success'] as bool,
);
}
Map<String, dynamic> toJson() => {
'data': data.toJson(),
'message': message,
'success': success,
};
factory FileResponseModel.fromMap(Map<String, dynamic> map) =>
FileResponseModel.fromJson(map);
Map<String, dynamic> toMap() => toJson();
FileResponseModel copyWith({
FileModel? data,
String? message,
bool? success,
}) {
return FileResponseModel(
data: data ?? this.data,
message: message ?? this.message,
success: success ?? this.success,
);
}
@override
String toString() =>
'FileResponseModel(data: $data, message: $message, success: $success)';
}
class FileModel {
final String id;
final String organizationId;
final String userId;
final String fileName;
final String originalName;
final String fileUrl;
final int fileSize;
final String mimeType;
final String fileType;
final String uploadPath;
final bool isPublic;
final DateTime createdAt;
final DateTime updatedAt;
FileModel({
required this.id,
required this.organizationId,
required this.userId,
required this.fileName,
required this.originalName,
required this.fileUrl,
required this.fileSize,
required this.mimeType,
required this.fileType,
required this.uploadPath,
required this.isPublic,
required this.createdAt,
required this.updatedAt,
});
factory FileModel.fromJson(Map<String, dynamic> json) {
return FileModel(
id: json['id'] as String,
organizationId: json['organization_id'] as String,
userId: json['user_id'] as String,
fileName: json['file_name'] as String,
originalName: json['original_name'] as String,
fileUrl: json['file_url'] as String,
fileSize: json['file_size'] as int,
mimeType: json['mime_type'] as String,
fileType: json['file_type'] as String,
uploadPath: json['upload_path'] as String,
isPublic: json['is_public'] as bool,
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: DateTime.parse(json['updated_at'] as String),
);
}
Map<String, dynamic> toJson() => {
'id': id,
'organization_id': organizationId,
'user_id': userId,
'file_name': fileName,
'original_name': originalName,
'file_url': fileUrl,
'file_size': fileSize,
'mime_type': mimeType,
'file_type': fileType,
'upload_path': uploadPath,
'is_public': isPublic,
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.toIso8601String(),
};
factory FileModel.fromMap(Map<String, dynamic> map) =>
FileModel.fromJson(map);
Map<String, dynamic> toMap() => toJson();
FileModel copyWith({
String? id,
String? organizationId,
String? userId,
String? fileName,
String? originalName,
String? fileUrl,
int? fileSize,
String? mimeType,
String? fileType,
String? uploadPath,
bool? isPublic,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return FileModel(
id: id ?? this.id,
organizationId: organizationId ?? this.organizationId,
userId: userId ?? this.userId,
fileName: fileName ?? this.fileName,
originalName: originalName ?? this.originalName,
fileUrl: fileUrl ?? this.fileUrl,
fileSize: fileSize ?? this.fileSize,
mimeType: mimeType ?? this.mimeType,
fileType: fileType ?? this.fileType,
uploadPath: uploadPath ?? this.uploadPath,
isPublic: isPublic ?? this.isPublic,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
@override
String toString() {
return 'FileModel(id: $id, organizationId: $organizationId, userId: $userId, fileName: $fileName, originalName: $originalName, fileUrl: $fileUrl, fileSize: $fileSize, mimeType: $mimeType, fileType: $fileType, uploadPath: $uploadPath, isPublic: $isPublic, createdAt: $createdAt, updatedAt: $updatedAt)';
}
}

View File

@ -1,6 +1,7 @@
import 'dart:developer';
import 'package:enaklo_pos/core/constants/theme.dart';
import 'package:enaklo_pos/data/datasources/customer_remote_datasource.dart';
import 'package:enaklo_pos/data/datasources/file_remote_datasource.dart';
import 'package:enaklo_pos/data/datasources/outlet_remote_data_source.dart';
import 'package:enaklo_pos/data/datasources/table_remote_datasource.dart';
import 'package:enaklo_pos/data/datasources/user_remote_datasource.dart';
@ -14,6 +15,7 @@ import 'package:enaklo_pos/presentation/home/bloc/user_update_outlet/user_update
import 'package:enaklo_pos/presentation/refund/bloc/refund_bloc.dart';
import 'package:enaklo_pos/presentation/sales/blocs/order_loader/order_loader_bloc.dart';
import 'package:enaklo_pos/presentation/sales/blocs/payment_form/payment_form_bloc.dart';
import 'package:enaklo_pos/presentation/setting/bloc/upload_file/upload_file_bloc.dart';
import 'package:enaklo_pos/presentation/void/bloc/void_order_bloc.dart';
import 'package:flutter/material.dart';
import 'package:enaklo_pos/data/datasources/auth_local_datasource.dart';
@ -265,6 +267,9 @@ class _MyAppState extends State<MyApp> {
BlocProvider(
create: (context) => UserUpdateOutletBloc(UserRemoteDatasource()),
),
BlocProvider(
create: (context) => UploadFileBloc(FileRemoteDataSource()),
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,

View File

@ -1,11 +1,7 @@
import 'dart:developer';
import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/product_remote_datasource.dart';
import 'package:enaklo_pos/data/models/request/product_request_model.dart';
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:image_picker/image_picker.dart';
part 'add_product_event.dart';
part 'add_product_state.dart';
@ -18,21 +14,12 @@ class AddProductBloc extends Bloc<AddProductEvent, AddProductState> {
) : super(const _Initial()) {
on<_AddProduct>((event, emit) async {
emit(const _Loading());
final requestData = ProductRequestModel(
name: event.product.name!,
price: event.product.price!,
stock: 0,
categoryId: 0,
isBestSeller: 0,
image: event.image,
);
log("requestData: ${requestData.toString()}");
final response = await datasource.addProduct(requestData);
final response = await datasource.addProduct(event.product);
// products.add(newProduct);
response.fold(
(l) => emit(_Error(l)),
(r) {
emit(_Success('Add Product Success'));
emit(_Success('Produk berhasil ditambahkan'));
},
);
});

View File

@ -19,19 +19,19 @@ mixin _$AddProductEvent {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() started,
required TResult Function(Product product, XFile image) addProduct,
required TResult Function(ProductRequestModel product) addProduct,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? started,
TResult? Function(Product product, XFile image)? addProduct,
TResult? Function(ProductRequestModel product)? addProduct,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? started,
TResult Function(Product product, XFile image)? addProduct,
TResult Function(ProductRequestModel product)? addProduct,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@ -119,7 +119,7 @@ class _$StartedImpl implements _Started {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() started,
required TResult Function(Product product, XFile image) addProduct,
required TResult Function(ProductRequestModel product) addProduct,
}) {
return started();
}
@ -128,7 +128,7 @@ class _$StartedImpl implements _Started {
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? started,
TResult? Function(Product product, XFile image)? addProduct,
TResult? Function(ProductRequestModel product)? addProduct,
}) {
return started?.call();
}
@ -137,7 +137,7 @@ class _$StartedImpl implements _Started {
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? started,
TResult Function(Product product, XFile image)? addProduct,
TResult Function(ProductRequestModel product)? addProduct,
required TResult orElse(),
}) {
if (started != null) {
@ -188,7 +188,7 @@ abstract class _$$AddProductImplCopyWith<$Res> {
_$AddProductImpl value, $Res Function(_$AddProductImpl) then) =
__$$AddProductImplCopyWithImpl<$Res>;
@useResult
$Res call({Product product, XFile image});
$Res call({ProductRequestModel product});
}
/// @nodoc
@ -205,17 +205,12 @@ class __$$AddProductImplCopyWithImpl<$Res>
@override
$Res call({
Object? product = null,
Object? image = null,
}) {
return _then(_$AddProductImpl(
null == product
? _value.product
: product // ignore: cast_nullable_to_non_nullable
as Product,
null == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as XFile,
as ProductRequestModel,
));
}
}
@ -223,16 +218,14 @@ class __$$AddProductImplCopyWithImpl<$Res>
/// @nodoc
class _$AddProductImpl implements _AddProduct {
const _$AddProductImpl(this.product, this.image);
const _$AddProductImpl(this.product);
@override
final Product product;
@override
final XFile image;
final ProductRequestModel product;
@override
String toString() {
return 'AddProductEvent.addProduct(product: $product, image: $image)';
return 'AddProductEvent.addProduct(product: $product)';
}
@override
@ -240,12 +233,11 @@ class _$AddProductImpl implements _AddProduct {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$AddProductImpl &&
(identical(other.product, product) || other.product == product) &&
(identical(other.image, image) || other.image == image));
(identical(other.product, product) || other.product == product));
}
@override
int get hashCode => Object.hash(runtimeType, product, image);
int get hashCode => Object.hash(runtimeType, product);
/// Create a copy of AddProductEvent
/// with the given fields replaced by the non-null parameter values.
@ -259,29 +251,29 @@ class _$AddProductImpl implements _AddProduct {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() started,
required TResult Function(Product product, XFile image) addProduct,
required TResult Function(ProductRequestModel product) addProduct,
}) {
return addProduct(product, image);
return addProduct(product);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? started,
TResult? Function(Product product, XFile image)? addProduct,
TResult? Function(ProductRequestModel product)? addProduct,
}) {
return addProduct?.call(product, image);
return addProduct?.call(product);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? started,
TResult Function(Product product, XFile image)? addProduct,
TResult Function(ProductRequestModel product)? addProduct,
required TResult orElse(),
}) {
if (addProduct != null) {
return addProduct(product, image);
return addProduct(product);
}
return orElse();
}
@ -319,11 +311,10 @@ class _$AddProductImpl implements _AddProduct {
}
abstract class _AddProduct implements AddProductEvent {
const factory _AddProduct(final Product product, final XFile image) =
const factory _AddProduct(final ProductRequestModel product) =
_$AddProductImpl;
Product get product;
XFile get image;
ProductRequestModel get product;
/// Create a copy of AddProductEvent
/// with the given fields replaced by the non-null parameter values.

View File

@ -3,6 +3,6 @@ part of 'add_product_bloc.dart';
@freezed
class AddProductEvent with _$AddProductEvent {
const factory AddProductEvent.started() = _Started;
const factory AddProductEvent.addProduct(Product product, XFile image) =
const factory AddProductEvent.addProduct(ProductRequestModel product) =
_AddProduct;
}

View File

@ -1,4 +1,3 @@
import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/category_remote_datasource.dart';
import 'package:enaklo_pos/data/models/response/category_response_model.dart';
@ -15,11 +14,11 @@ class GetCategoriesBloc extends Bloc<GetCategoriesEvent, GetCategoriesState> {
) : super(const _Initial()) {
on<_Fetch>((event, emit) async {
emit(const _Loading());
final result = await datasource.getCategories();
final result = await datasource.getCategories(limit: 50);
result.fold(
(l) => emit(_Error(l)),
(r) async {
emit(_Success(r.data));
emit(_Success(r.data.categories));
},
);
});

View File

@ -1,12 +1,9 @@
import 'dart:developer';
import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/product_local_datasource.dart';
import 'package:enaklo_pos/data/datasources/product_remote_datasource.dart';
import 'package:enaklo_pos/data/models/request/product_request_model.dart';
import 'package:enaklo_pos/data/models/response/product_response_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:image_picker/image_picker.dart';
part 'update_product_event.dart';
part 'update_product_state.dart';
@ -21,61 +18,11 @@ class UpdateProductBloc extends Bloc<UpdateProductEvent, UpdateProductState> {
emit(const _Loading());
try {
// Validate required fields
if (event.product.name == null || event.product.name!.isEmpty) {
emit(_Error('Product name is required'));
return;
}
if (event.product.price == null || event.product.price == 0) {
emit(_Error('Product price is required'));
return;
}
// if (event.product.stock == null) {
// emit(_Error('Product stock is required'));
// return;
// }
if (event.product.categoryId == null) {
emit(_Error('Product category is required'));
return;
}
// Parse price safely
final price = event.product.price!;
if (price == 0) {
emit(_Error('Invalid price format'));
return;
}
final requestData = ProductRequestModel(
id: event.product.id,
name: event.product.name!,
price: price,
stock: 0,
categoryId: 0,
isBestSeller: 0, // Default to 0 if null
image: event.image,
printerType: 'kitchen', // Default to kitchen if null
);
log("Update requestData: ${requestData.toString()}");
log("Request map: ${requestData.toMap()}");
final response = await datasource.updateProduct(requestData);
final response = await datasource.updateProduct(event.product);
response.fold(
(l) => emit(_Error(l)),
(r) async {
// Update local database after successful API update
try {
await ProductLocalDatasource.instance
.updateProduct(event.product);
log("Local product updated successfully");
} catch (e) {
log("Error updating local product: $e");
}
emit(_Success('Update Product Success'));
emit(_Success('Product berhasil diupdate'));
},
);
} catch (e) {

View File

@ -16,21 +16,20 @@ final _privateConstructorUsedError = UnsupportedError(
/// @nodoc
mixin _$UpdateProductEvent {
Product get product => throw _privateConstructorUsedError;
XFile? get image => throw _privateConstructorUsedError;
ProductRequestModel get product => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(Product product, XFile? image) updateProduct,
required TResult Function(ProductRequestModel product) updateProduct,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(Product product, XFile? image)? updateProduct,
TResult? Function(ProductRequestModel product)? updateProduct,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(Product product, XFile? image)? updateProduct,
TResult Function(ProductRequestModel product)? updateProduct,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@ -64,7 +63,7 @@ abstract class $UpdateProductEventCopyWith<$Res> {
UpdateProductEvent value, $Res Function(UpdateProductEvent) then) =
_$UpdateProductEventCopyWithImpl<$Res, UpdateProductEvent>;
@useResult
$Res call({Product product, XFile? image});
$Res call({ProductRequestModel product});
}
/// @nodoc
@ -83,17 +82,12 @@ class _$UpdateProductEventCopyWithImpl<$Res, $Val extends UpdateProductEvent>
@override
$Res call({
Object? product = null,
Object? image = freezed,
}) {
return _then(_value.copyWith(
product: null == product
? _value.product
: product // ignore: cast_nullable_to_non_nullable
as Product,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as XFile?,
as ProductRequestModel,
) as $Val);
}
}
@ -106,7 +100,7 @@ abstract class _$$UpdateProductImplCopyWith<$Res>
__$$UpdateProductImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({Product product, XFile? image});
$Res call({ProductRequestModel product});
}
/// @nodoc
@ -123,17 +117,12 @@ class __$$UpdateProductImplCopyWithImpl<$Res>
@override
$Res call({
Object? product = null,
Object? image = freezed,
}) {
return _then(_$UpdateProductImpl(
null == product
? _value.product
: product // ignore: cast_nullable_to_non_nullable
as Product,
freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as XFile?,
as ProductRequestModel,
));
}
}
@ -141,16 +130,14 @@ class __$$UpdateProductImplCopyWithImpl<$Res>
/// @nodoc
class _$UpdateProductImpl implements _UpdateProduct {
const _$UpdateProductImpl(this.product, this.image);
const _$UpdateProductImpl(this.product);
@override
final Product product;
@override
final XFile? image;
final ProductRequestModel product;
@override
String toString() {
return 'UpdateProductEvent.updateProduct(product: $product, image: $image)';
return 'UpdateProductEvent.updateProduct(product: $product)';
}
@override
@ -158,12 +145,11 @@ class _$UpdateProductImpl implements _UpdateProduct {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UpdateProductImpl &&
(identical(other.product, product) || other.product == product) &&
(identical(other.image, image) || other.image == image));
(identical(other.product, product) || other.product == product));
}
@override
int get hashCode => Object.hash(runtimeType, product, image);
int get hashCode => Object.hash(runtimeType, product);
/// Create a copy of UpdateProductEvent
/// with the given fields replaced by the non-null parameter values.
@ -176,27 +162,27 @@ class _$UpdateProductImpl implements _UpdateProduct {
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(Product product, XFile? image) updateProduct,
required TResult Function(ProductRequestModel product) updateProduct,
}) {
return updateProduct(product, image);
return updateProduct(product);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(Product product, XFile? image)? updateProduct,
TResult? Function(ProductRequestModel product)? updateProduct,
}) {
return updateProduct?.call(product, image);
return updateProduct?.call(product);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(Product product, XFile? image)? updateProduct,
TResult Function(ProductRequestModel product)? updateProduct,
required TResult orElse(),
}) {
if (updateProduct != null) {
return updateProduct(product, image);
return updateProduct(product);
}
return orElse();
}
@ -231,13 +217,11 @@ class _$UpdateProductImpl implements _UpdateProduct {
}
abstract class _UpdateProduct implements UpdateProductEvent {
const factory _UpdateProduct(final Product product, final XFile? image) =
const factory _UpdateProduct(final ProductRequestModel product) =
_$UpdateProductImpl;
@override
Product get product;
@override
XFile? get image;
ProductRequestModel get product;
/// Create a copy of UpdateProductEvent
/// with the given fields replaced by the non-null parameter values.

View File

@ -2,5 +2,6 @@ part of 'update_product_bloc.dart';
@freezed
class UpdateProductEvent with _$UpdateProductEvent {
const factory UpdateProductEvent.updateProduct(Product product, XFile? image) = _UpdateProduct;
}
const factory UpdateProductEvent.updateProduct(ProductRequestModel product) =
_UpdateProduct;
}

View File

@ -0,0 +1,29 @@
import 'package:bloc/bloc.dart';
import 'package:enaklo_pos/data/datasources/file_remote_datasource.dart';
import 'package:enaklo_pos/data/models/response/file_response_model.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'upload_file_event.dart';
part 'upload_file_state.dart';
part 'upload_file_bloc.freezed.dart';
class UploadFileBloc extends Bloc<UploadFileEvent, UploadFileState> {
final FileRemoteDataSource _fileRemoteDataSource;
UploadFileBloc(this._fileRemoteDataSource)
: super(UploadFileState.initial()) {
on<_Upload>((event, emit) async {
emit(_Loading());
final result = await _fileRemoteDataSource.uploadFile(
filePath: event.filePath,
fileType: 'image',
description: 'Product Image',
);
result.fold((l) {
emit(_Error(l));
}, (r) {
emit(_Success(r.data));
});
});
}
}

View File

@ -0,0 +1,845 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'upload_file_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$UploadFileEvent {
String get filePath => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String filePath) upload,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String filePath)? upload,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String filePath)? upload,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Upload value) upload,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Upload value)? upload,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Upload value)? upload,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
/// Create a copy of UploadFileEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$UploadFileEventCopyWith<UploadFileEvent> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UploadFileEventCopyWith<$Res> {
factory $UploadFileEventCopyWith(
UploadFileEvent value, $Res Function(UploadFileEvent) then) =
_$UploadFileEventCopyWithImpl<$Res, UploadFileEvent>;
@useResult
$Res call({String filePath});
}
/// @nodoc
class _$UploadFileEventCopyWithImpl<$Res, $Val extends UploadFileEvent>
implements $UploadFileEventCopyWith<$Res> {
_$UploadFileEventCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UploadFileEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? filePath = null,
}) {
return _then(_value.copyWith(
filePath: null == filePath
? _value.filePath
: filePath // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
}
/// @nodoc
abstract class _$$UploadImplCopyWith<$Res>
implements $UploadFileEventCopyWith<$Res> {
factory _$$UploadImplCopyWith(
_$UploadImpl value, $Res Function(_$UploadImpl) then) =
__$$UploadImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String filePath});
}
/// @nodoc
class __$$UploadImplCopyWithImpl<$Res>
extends _$UploadFileEventCopyWithImpl<$Res, _$UploadImpl>
implements _$$UploadImplCopyWith<$Res> {
__$$UploadImplCopyWithImpl(
_$UploadImpl _value, $Res Function(_$UploadImpl) _then)
: super(_value, _then);
/// Create a copy of UploadFileEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? filePath = null,
}) {
return _then(_$UploadImpl(
null == filePath
? _value.filePath
: filePath // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$UploadImpl implements _Upload {
const _$UploadImpl(this.filePath);
@override
final String filePath;
@override
String toString() {
return 'UploadFileEvent.upload(filePath: $filePath)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$UploadImpl &&
(identical(other.filePath, filePath) ||
other.filePath == filePath));
}
@override
int get hashCode => Object.hash(runtimeType, filePath);
/// Create a copy of UploadFileEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$UploadImplCopyWith<_$UploadImpl> get copyWith =>
__$$UploadImplCopyWithImpl<_$UploadImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(String filePath) upload,
}) {
return upload(filePath);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(String filePath)? upload,
}) {
return upload?.call(filePath);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(String filePath)? upload,
required TResult orElse(),
}) {
if (upload != null) {
return upload(filePath);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Upload value) upload,
}) {
return upload(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Upload value)? upload,
}) {
return upload?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Upload value)? upload,
required TResult orElse(),
}) {
if (upload != null) {
return upload(this);
}
return orElse();
}
}
abstract class _Upload implements UploadFileEvent {
const factory _Upload(final String filePath) = _$UploadImpl;
@override
String get filePath;
/// Create a copy of UploadFileEvent
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$UploadImplCopyWith<_$UploadImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
mixin _$UploadFileState {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(FileModel file) success,
required TResult Function(String message) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(FileModel file)? success,
TResult? Function(String message)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(FileModel file)? success,
TResult Function(String message)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $UploadFileStateCopyWith<$Res> {
factory $UploadFileStateCopyWith(
UploadFileState value, $Res Function(UploadFileState) then) =
_$UploadFileStateCopyWithImpl<$Res, UploadFileState>;
}
/// @nodoc
class _$UploadFileStateCopyWithImpl<$Res, $Val extends UploadFileState>
implements $UploadFileStateCopyWith<$Res> {
_$UploadFileStateCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
abstract class _$$InitialImplCopyWith<$Res> {
factory _$$InitialImplCopyWith(
_$InitialImpl value, $Res Function(_$InitialImpl) then) =
__$$InitialImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$InitialImplCopyWithImpl<$Res>
extends _$UploadFileStateCopyWithImpl<$Res, _$InitialImpl>
implements _$$InitialImplCopyWith<$Res> {
__$$InitialImplCopyWithImpl(
_$InitialImpl _value, $Res Function(_$InitialImpl) _then)
: super(_value, _then);
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$InitialImpl implements _Initial {
const _$InitialImpl();
@override
String toString() {
return 'UploadFileState.initial()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$InitialImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(FileModel file) success,
required TResult Function(String message) error,
}) {
return initial();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(FileModel file)? success,
TResult? Function(String message)? error,
}) {
return initial?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(FileModel file)? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (initial != null) {
return initial();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return initial(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return initial?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (initial != null) {
return initial(this);
}
return orElse();
}
}
abstract class _Initial implements UploadFileState {
const factory _Initial() = _$InitialImpl;
}
/// @nodoc
abstract class _$$LoadingImplCopyWith<$Res> {
factory _$$LoadingImplCopyWith(
_$LoadingImpl value, $Res Function(_$LoadingImpl) then) =
__$$LoadingImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$LoadingImplCopyWithImpl<$Res>
extends _$UploadFileStateCopyWithImpl<$Res, _$LoadingImpl>
implements _$$LoadingImplCopyWith<$Res> {
__$$LoadingImplCopyWithImpl(
_$LoadingImpl _value, $Res Function(_$LoadingImpl) _then)
: super(_value, _then);
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
}
/// @nodoc
class _$LoadingImpl implements _Loading {
const _$LoadingImpl();
@override
String toString() {
return 'UploadFileState.loading()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$LoadingImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(FileModel file) success,
required TResult Function(String message) error,
}) {
return loading();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(FileModel file)? success,
TResult? Function(String message)? error,
}) {
return loading?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(FileModel file)? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return loading(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return loading?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (loading != null) {
return loading(this);
}
return orElse();
}
}
abstract class _Loading implements UploadFileState {
const factory _Loading() = _$LoadingImpl;
}
/// @nodoc
abstract class _$$SuccessImplCopyWith<$Res> {
factory _$$SuccessImplCopyWith(
_$SuccessImpl value, $Res Function(_$SuccessImpl) then) =
__$$SuccessImplCopyWithImpl<$Res>;
@useResult
$Res call({FileModel file});
}
/// @nodoc
class __$$SuccessImplCopyWithImpl<$Res>
extends _$UploadFileStateCopyWithImpl<$Res, _$SuccessImpl>
implements _$$SuccessImplCopyWith<$Res> {
__$$SuccessImplCopyWithImpl(
_$SuccessImpl _value, $Res Function(_$SuccessImpl) _then)
: super(_value, _then);
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? file = null,
}) {
return _then(_$SuccessImpl(
null == file
? _value.file
: file // ignore: cast_nullable_to_non_nullable
as FileModel,
));
}
}
/// @nodoc
class _$SuccessImpl implements _Success {
const _$SuccessImpl(this.file);
@override
final FileModel file;
@override
String toString() {
return 'UploadFileState.success(file: $file)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$SuccessImpl &&
(identical(other.file, file) || other.file == file));
}
@override
int get hashCode => Object.hash(runtimeType, file);
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$SuccessImplCopyWith<_$SuccessImpl> get copyWith =>
__$$SuccessImplCopyWithImpl<_$SuccessImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(FileModel file) success,
required TResult Function(String message) error,
}) {
return success(file);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(FileModel file)? success,
TResult? Function(String message)? error,
}) {
return success?.call(file);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(FileModel file)? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (success != null) {
return success(file);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return success(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return success?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (success != null) {
return success(this);
}
return orElse();
}
}
abstract class _Success implements UploadFileState {
const factory _Success(final FileModel file) = _$SuccessImpl;
FileModel get file;
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$SuccessImplCopyWith<_$SuccessImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class _$$ErrorImplCopyWith<$Res> {
factory _$$ErrorImplCopyWith(
_$ErrorImpl value, $Res Function(_$ErrorImpl) then) =
__$$ErrorImplCopyWithImpl<$Res>;
@useResult
$Res call({String message});
}
/// @nodoc
class __$$ErrorImplCopyWithImpl<$Res>
extends _$UploadFileStateCopyWithImpl<$Res, _$ErrorImpl>
implements _$$ErrorImplCopyWith<$Res> {
__$$ErrorImplCopyWithImpl(
_$ErrorImpl _value, $Res Function(_$ErrorImpl) _then)
: super(_value, _then);
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? message = null,
}) {
return _then(_$ErrorImpl(
null == message
? _value.message
: message // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _$ErrorImpl implements _Error {
const _$ErrorImpl(this.message);
@override
final String message;
@override
String toString() {
return 'UploadFileState.error(message: $message)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ErrorImpl &&
(identical(other.message, message) || other.message == message));
}
@override
int get hashCode => Object.hash(runtimeType, message);
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$ErrorImplCopyWith<_$ErrorImpl> get copyWith =>
__$$ErrorImplCopyWithImpl<_$ErrorImpl>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() loading,
required TResult Function(FileModel file) success,
required TResult Function(String message) error,
}) {
return error(message);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? initial,
TResult? Function()? loading,
TResult? Function(FileModel file)? success,
TResult? Function(String message)? error,
}) {
return error?.call(message);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? loading,
TResult Function(FileModel file)? success,
TResult Function(String message)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(message);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_Initial value) initial,
required TResult Function(_Loading value) loading,
required TResult Function(_Success value) success,
required TResult Function(_Error value) error,
}) {
return error(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_Initial value)? initial,
TResult? Function(_Loading value)? loading,
TResult? Function(_Success value)? success,
TResult? Function(_Error value)? error,
}) {
return error?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_Initial value)? initial,
TResult Function(_Loading value)? loading,
TResult Function(_Success value)? success,
TResult Function(_Error value)? error,
required TResult orElse(),
}) {
if (error != null) {
return error(this);
}
return orElse();
}
}
abstract class _Error implements UploadFileState {
const factory _Error(final String message) = _$ErrorImpl;
String get message;
/// Create a copy of UploadFileState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
_$$ErrorImplCopyWith<_$ErrorImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -0,0 +1,6 @@
part of 'upload_file_bloc.dart';
@freezed
class UploadFileEvent with _$UploadFileEvent {
const factory UploadFileEvent.upload(String filePath) = _Upload;
}

View File

@ -0,0 +1,9 @@
part of 'upload_file_bloc.dart';
@freezed
class UploadFileState with _$UploadFileState {
const factory UploadFileState.initial() = _Initial;
const factory UploadFileState.loading() = _Loading;
const factory UploadFileState.success(FileModel file) = _Success;
const factory UploadFileState.error(String message) = _Error;
}

File diff suppressed because it is too large Load Diff

View File

@ -58,18 +58,18 @@ class _SyncDataPageState extends State<SyncDataPage> {
);
},
loaded: (productResponseModel) async {
await ProductLocalDatasource.instance
.deleteAllProducts();
await ProductLocalDatasource.instance
.insertProducts(
productResponseModel.data!.products!,
);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Sync Product Success2'),
backgroundColor: Colors.green,
),
);
// await ProductLocalDatasource.instance
// .deleteAllProducts();
// await ProductLocalDatasource.instance
// .insertProducts(
// productResponseModel.data!.products!,
// );
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text('Sync Product Success2'),
// backgroundColor: Colors.green,
// ),
// );
},
);
},
@ -127,12 +127,12 @@ class _SyncDataPageState extends State<SyncDataPage> {
);
},
loaded: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Sync Order Success'),
backgroundColor: Colors.green,
),
);
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(
// content: Text('Sync Order Success'),
// backgroundColor: Colors.green,
// ),
// );
},
);
},

View File

@ -366,6 +366,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
dropdown_search:
dependency: "direct main"
description:
name: dropdown_search
sha256: "55106e8290acaa97ed15bea1fdad82c3cf0c248dd410e651f5a8ac6870f783ab"
url: "https://pub.dev"
source: hosted
version: "5.0.6"
esc_pos_utils_plus:
dependency: "direct main"
description:

View File

@ -62,6 +62,7 @@ dependencies:
dio: ^5.8.0+1
awesome_dio_interceptor: ^1.3.0
another_flushbar: ^1.12.30
dropdown_search: ^5.0.6
# imin_printer: ^0.6.10
dev_dependencies: