160 lines
5.4 KiB
Dart
160 lines
5.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:siro_service/views/widgets/my_scafold.dart';
|
|
|
|
import '../complaints/complaint_list_controller.dart';
|
|
import '../../../views/home/complaints/complaint_resolve_page.dart';
|
|
|
|
/// شاشة الشكاوى لموظف خدمة العملاء.
|
|
///
|
|
/// كانت هيكلاً فارغاً (`body: []`). الآن: قائمة مرتّبة بغير المحلول أولاً،
|
|
/// وتنبيه بالمتأخر، وفتح أداة التسوية بضغطة.
|
|
class Complaint extends StatelessWidget {
|
|
const Complaint({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final c = Get.put(ComplaintListController());
|
|
final cs = Theme.of(context).colorScheme;
|
|
|
|
return MyScaffold(
|
|
title: "View complaint".tr,
|
|
isleading: true,
|
|
body: [
|
|
Obx(() {
|
|
if (c.isLoading.value && c.complaints.isEmpty) {
|
|
return const Padding(
|
|
padding: EdgeInsets.only(top: 60),
|
|
child: Center(child: CircularProgressIndicator()),
|
|
);
|
|
}
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// المتأخر أولاً وبصرياً: رقم يجب ألا يكبر، فإخفاؤه في قائمة
|
|
// طويلة يعني أن أحداً لن يلاحظه.
|
|
if (c.staleCount > 0)
|
|
Container(
|
|
margin: const EdgeInsets.only(bottom: 12),
|
|
padding: const EdgeInsets.all(14),
|
|
decoration: BoxDecoration(
|
|
color: cs.error.withOpacity(0.08),
|
|
borderRadius: BorderRadius.circular(14),
|
|
border: Border.all(color: cs.error.withOpacity(0.3)),
|
|
),
|
|
child: Row(children: [
|
|
Icon(Icons.warning_amber_rounded, color: cs.error, size: 20),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Text(
|
|
'${c.staleCount} شكوى مفتوحة منذ أكثر من أسبوع',
|
|
style: TextStyle(
|
|
color: cs.error,
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.bold),
|
|
),
|
|
),
|
|
]),
|
|
),
|
|
|
|
_Filters(c: c),
|
|
const SizedBox(height: 8),
|
|
|
|
if (c.visible.isEmpty)
|
|
const Padding(
|
|
padding: EdgeInsets.only(top: 60),
|
|
child: Center(child: Text('لا شكاوى')),
|
|
)
|
|
else
|
|
...c.visible.map((item) => _ComplaintTile(item: item, c: c)),
|
|
],
|
|
);
|
|
}),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _Filters extends StatelessWidget {
|
|
const _Filters({required this.c});
|
|
final ComplaintListController c;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
const options = <String, String>{
|
|
'': 'الكل',
|
|
'Open': 'مفتوحة',
|
|
'In Progress': 'قيد المعالجة',
|
|
'Resolved': 'محلولة',
|
|
};
|
|
|
|
return Obx(() => Wrap(
|
|
spacing: 8,
|
|
children: options.entries
|
|
.map((e) => ChoiceChip(
|
|
label: Text(e.value, style: const TextStyle(fontSize: 12)),
|
|
selected: c.statusFilter.value == e.key,
|
|
onSelected: (_) => c.statusFilter.value = e.key,
|
|
))
|
|
.toList(),
|
|
));
|
|
}
|
|
}
|
|
|
|
class _ComplaintTile extends StatelessWidget {
|
|
const _ComplaintTile({required this.item, required this.c});
|
|
final Map<String, dynamic> item;
|
|
final ComplaintListController c;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final cs = Theme.of(context).colorScheme;
|
|
final status = item['statusComplaint']?.toString() ?? 'Open';
|
|
|
|
final color = status == 'Resolved'
|
|
? Colors.green
|
|
: status == 'In Progress'
|
|
? Colors.orange
|
|
: cs.error;
|
|
|
|
return Card(
|
|
margin: const EdgeInsets.only(bottom: 10),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
|
|
child: ListTile(
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
|
|
leading: Container(
|
|
width: 8,
|
|
height: 44,
|
|
decoration: BoxDecoration(
|
|
color: color,
|
|
borderRadius: BorderRadius.circular(4),
|
|
),
|
|
),
|
|
title: Text(
|
|
item['description']?.toString().trim().isNotEmpty == true
|
|
? item['description'].toString()
|
|
: 'بدون وصف',
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Padding(
|
|
padding: const EdgeInsets.only(top: 4),
|
|
child: Text(
|
|
'رحلة ${item['ride_id']} · ${item['complaint_type'] ?? 'عام'}'
|
|
' · ${item['date_filed'] ?? ''}',
|
|
style: TextStyle(fontSize: 11, color: cs.onSurfaceVariant),
|
|
),
|
|
),
|
|
trailing: Icon(Icons.chevron_left, color: cs.onSurfaceVariant),
|
|
onTap: () async {
|
|
final changed = await Get.to(
|
|
() => ComplaintResolvePage(complaint: item));
|
|
if (changed == true) c.fetch();
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|