Update: 2026-08-07 05:03:39
This commit is contained in:
@@ -2,11 +2,158 @@ 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) {
|
||||
return MyScaffold(title: "View complaint".tr, isleading: true, body: []);
|
||||
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();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user