Enhanced material design 3 implementation

This commit is contained in:
2026-03-20 15:15:38 +08:00
parent 27ebb89052
commit 74197c525d
26 changed files with 1345 additions and 515 deletions
+41 -14
View File
@@ -21,6 +21,8 @@ import '../../widgets/tasq_adaptive_list.dart';
import '../../widgets/typing_dots.dart';
import '../../theme/app_surfaces.dart';
import '../../utils/snackbar.dart';
import '../../widgets/app_page_header.dart';
import '../../widgets/app_state_view.dart';
class TicketsListScreen extends ConsumerStatefulWidget {
const TicketsListScreen({super.key});
@@ -90,6 +92,14 @@ class _TicketsListScreenState extends ConsumerState<TicketsListScreen> {
builder: (context) {
// Build the list UI immediately so `Skeletonizer` can
// render placeholders while providers are still loading.
if (ticketsAsync.hasError && !ticketsAsync.hasValue) {
return AppErrorView(
error: ticketsAsync.error!,
title: 'Could not load tickets',
onRetry: () => ref.invalidate(ticketsProvider),
);
}
final tickets = ticketsAsync.valueOrNull ?? <Ticket>[];
final officeById = <String, Office>{
for (final office in officesAsync.valueOrNull ?? <Office>[])
@@ -205,6 +215,31 @@ class _TicketsListScreenState extends ConsumerState<TicketsListScreen> {
],
);
if (filteredTickets.isEmpty && !effectiveShowSkeleton) {
final hasFilters = _hasTicketFilters;
return Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const AppPageHeader(
title: 'Tickets',
subtitle: 'Support requests and service tickets',
),
Expanded(
child: AppEmptyView(
icon: Icons.confirmation_number_outlined,
title: hasFilters
? 'No matching tickets'
: 'No tickets yet',
subtitle: hasFilters
? 'Try adjusting your filters.'
: 'Tickets submitted by your team will appear here.',
),
),
],
);
}
final listBody = TasQAdaptiveList<Ticket>(
items: filteredTickets,
onRowTap: (ticket) => context.go('/tickets/${ticket.id}'),
@@ -303,12 +338,12 @@ class _TicketsListScreenState extends ConsumerState<TicketsListScreen> {
),
],
if (hasMention)
const Padding(
padding: EdgeInsets.only(left: 8),
Padding(
padding: const EdgeInsets.only(left: 8),
child: Icon(
Icons.circle,
size: 10,
color: Colors.red,
color: Theme.of(context).colorScheme.error,
),
),
],
@@ -323,17 +358,9 @@ class _TicketsListScreenState extends ConsumerState<TicketsListScreen> {
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(top: 16, bottom: 8),
child: Align(
alignment: Alignment.center,
child: Text(
'Tickets',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge
?.copyWith(fontWeight: FontWeight.w700),
),
),
const AppPageHeader(
title: 'Tickets',
subtitle: 'Support requests and service tickets',
),
Expanded(child: listBody),
],