Enhanced material design 3 implementation
This commit is contained in:
@@ -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),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user