Files
intaleq_admin/lib/views/invoice/add_invoice_page.dart
2026-01-20 23:39:59 +03:00

190 lines
6.7 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:sefer_admin1/constant/colors.dart';
import 'package:sefer_admin1/constant/links.dart';
import 'package:sefer_admin1/views/widgets/my_scafold.dart';
import 'package:sefer_admin1/views/widgets/my_textField.dart';
import '../../constant/box_name.dart';
import '../../constant/info.dart';
import '../../controller/functions/encrypt_decrypt.dart';
import '../../main.dart';
class AddInvoicePage extends StatefulWidget {
const AddInvoicePage({super.key});
@override
State<AddInvoicePage> createState() => _AddInvoicePageState();
}
class _AddInvoicePageState extends State<AddInvoicePage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _itemNameController = TextEditingController();
final TextEditingController _amountController = TextEditingController();
File? _imageFile;
bool _isLoading = false;
String generateInvoiceNumber() {
final now = DateTime.now();
return "INV-${now.year}${now.month.toString().padLeft(2, '0')}${now.day.toString().padLeft(2, '0')}-${now.microsecond}";
}
Future<void> uploadInvoice() async {
if (!_formKey.currentState!.validate()) return;
final driverID = '123'; // ← عدّله حسب نظامك
final invoiceNumber = generateInvoiceNumber();
final amount = _amountController.text.trim();
final itemName = _itemNameController.text.trim();
final date = DateTime.now().toIso8601String().split('T').first;
setState(() => _isLoading = true);
try {
final headers = {
'Authorization':
'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}',
'X-HMAC-Auth': '${box.read(BoxName.hmac)}',
};
final uri = Uri.parse(AppLink.addInvoice);
final request = http.MultipartRequest('POST', uri)
..fields['driverID'] = driverID
..fields['invoiceNumber'] = invoiceNumber
..fields['amount'] = amount
..fields['name'] = itemName
..fields['date'] = date
..headers.addAll(headers);
if (_imageFile != null) {
final imageName = _imageFile!.path.split('/').last;
final imageStream = http.ByteStream(_imageFile!.openRead());
final imageLength = await _imageFile!.length();
request.files.add(http.MultipartFile(
'image',
imageStream,
imageLength,
filename: imageName,
));
} else {}
final response = await request.send();
final respStr = await response.stream.bytesToString();
final data = jsonDecode(respStr);
if (data['status'] == 'success') {
Get.snackbar('تم الحفظ', 'تم حفظ الفاتورة بنجاح',
backgroundColor: Colors.green.shade100);
_itemNameController.clear();
_amountController.clear();
setState(() => _imageFile = null);
Get.back(); // العودة للصفحة السابقة
} else {
Get.snackbar('خطأ', data['message'],
backgroundColor: Colors.red.shade100);
}
} catch (e, stacktrace) {
Get.snackbar('فشل الإرسال', e.toString(),
backgroundColor: Colors.red.shade100);
} finally {
setState(() => _isLoading = false);
}
}
Future<void> pickInvoiceImage() async {
final picker = ImagePicker();
final picked = await picker.pickImage(source: ImageSource.gallery);
if (picked != null) {
setState(() => _imageFile = File(picked.path));
}
}
@override
void dispose() {
_itemNameController.dispose();
_amountController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MyScafolld(
title: 'إضافة فاتورة جديدة',
body: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: ListView(
children: [
MyTextForm(
controller: _itemNameController,
label: 'اسم البضاعة',
hint: 'مثال: قطع غيار',
type: TextInputType.text,
// validator: (val) =>
// val!.isEmpty ? 'الرجاء إدخال اسم البضاعة' : null,
),
const SizedBox(height: 16),
MyTextForm(
controller: _amountController,
label: 'قيمة الفاتورة',
hint: 'مثال: 150.75',
type: TextInputType.numberWithOptions(decimal: true),
// validator: (val) =>
// val!.isEmpty ? 'الرجاء إدخال المبلغ' : null,
),
const SizedBox(height: 20),
Text('صورة الفاتورة (اختياري)',
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 10),
Container(
height: 180,
decoration: BoxDecoration(
color: Colors.grey.shade200,
border: Border.all(color: Colors.grey.shade400),
borderRadius: BorderRadius.circular(10),
),
child: _imageFile != null
? ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.file(_imageFile!, fit: BoxFit.cover),
)
: const Center(child: Text('لم يتم اختيار صورة')),
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: pickInvoiceImage,
icon: const Icon(Icons.image),
label: const Text('اختيار صورة'),
),
const SizedBox(height: 30),
ElevatedButton(
onPressed: _isLoading ? null : uploadInvoice,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: AppColor.primaryColor,
),
child: _isLoading
? const CircularProgressIndicator(color: Colors.white)
: const Text(
'حفظ الفاتورة',
style: TextStyle(color: Colors.white),
),
),
],
),
),
),
],
isleading: true,
);
}
}