88 lines
2.5 KiB
Dart
88 lines
2.5 KiB
Dart
import 'package:flutter/cupertino.dart';
|
|
import 'package:please_pay_me/theme/tokens.dart';
|
|
import 'package:please_pay_me/ui/atoms/app_button.dart';
|
|
import 'package:please_pay_me/ui/atoms/app_icon.dart';
|
|
import 'package:please_pay_me/ui/atoms/app_text.dart';
|
|
import 'package:please_pay_me/ui/feedback/app_progress.dart';
|
|
|
|
/// Centered placeholder for empty collections.
|
|
class AppEmptyState extends StatelessWidget {
|
|
const AppEmptyState({
|
|
super.key,
|
|
required this.title,
|
|
this.message,
|
|
this.icon = CupertinoIcons.tray,
|
|
this.actionLabel,
|
|
this.onAction,
|
|
});
|
|
|
|
final String title;
|
|
final String? message;
|
|
final IconData icon;
|
|
final String? actionLabel;
|
|
final VoidCallback? onAction;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: AppSpacing.s6,
|
|
vertical: AppSpacing.s7,
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
AppIcon(icon, size: 44, color: AppColors.tertiaryLabel),
|
|
const SizedBox(height: AppSpacing.s3),
|
|
AppText.headline(title, textAlign: TextAlign.center),
|
|
if (message != null) ...[
|
|
const SizedBox(height: AppSpacing.s1),
|
|
AppText.subhead(message!, textAlign: TextAlign.center),
|
|
],
|
|
if (actionLabel != null && onAction != null) ...[
|
|
const SizedBox(height: AppSpacing.s4),
|
|
AppButton(
|
|
label: actionLabel!,
|
|
size: AppButtonSize.medium,
|
|
style: AppButtonStyle.tinted,
|
|
expanded: false,
|
|
onPressed: onAction,
|
|
),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Failure placeholder with a retry affordance.
|
|
class AppErrorView extends StatelessWidget {
|
|
const AppErrorView({super.key, required this.message, this.onRetry});
|
|
|
|
final String message;
|
|
final VoidCallback? onRetry;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AppEmptyState(
|
|
icon: CupertinoIcons.exclamationmark_triangle,
|
|
title: 'Не получилось загрузить',
|
|
message: message,
|
|
actionLabel: onRetry == null ? null : 'Повторить',
|
|
onAction: onRetry,
|
|
);
|
|
}
|
|
}
|
|
|
|
class AppLoadingView extends StatelessWidget {
|
|
const AppLoadingView({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return const Padding(
|
|
padding: EdgeInsets.symmetric(vertical: AppSpacing.s7),
|
|
child: Center(child: AppSpinner()),
|
|
);
|
|
}
|
|
}
|