Adds SignInPrompt (sign in / create account), showSignInPromptProvider, HomeScreen as ConsumerWidget, l10n de/en, widget/unit tests and a Playwright web test (#49 criterion 1, QUE-09 criterion 13, QUE-06). Refs #49 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
75 lines
2.8 KiB
Dart
75 lines
2.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:shuffle/core/l10n/l10n.dart';
|
|
import 'package:shuffle/core/routing/app_routes.dart';
|
|
import 'package:shuffle/core/theme/app_spacing.dart';
|
|
import 'package:shuffle/core/widgets/app_primary_button.dart';
|
|
|
|
/// Hint card for signed-out users with the way to sign in and to register
|
|
/// (Spec #49 E1, QUE-09 Kriterium 13). Contains no logic: the host decides
|
|
/// whether to show it (see `showSignInPromptProvider`).
|
|
///
|
|
/// At most [AppBreakpoints.authCardMaxWidth] wide. Heading, text and both
|
|
/// buttons are separate semantics nodes in reading and tab order.
|
|
class SignInPrompt extends StatelessWidget {
|
|
const SignInPrompt({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = context.l10n;
|
|
final textTheme = Theme.of(context).textTheme;
|
|
return ConstrainedBox(
|
|
constraints: const BoxConstraints(
|
|
maxWidth: AppBreakpoints.authCardMaxWidth,
|
|
),
|
|
child: Card(
|
|
key: const Key('sign_in_prompt'),
|
|
// Card is a semantics container; keep the children separate.
|
|
child: Semantics(
|
|
explicitChildNodes: true,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(AppSpacing.xl),
|
|
child: FocusTraversalGroup(
|
|
policy: ReadingOrderTraversalPolicy(),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Semantics(
|
|
header: true,
|
|
child: Text(
|
|
l10n.signInPromptTitle,
|
|
key: const Key('sign_in_prompt_title'),
|
|
style: textTheme.titleLarge,
|
|
),
|
|
),
|
|
const SizedBox(height: AppSpacing.sm),
|
|
Text(
|
|
l10n.signInPromptBody,
|
|
key: const Key('sign_in_prompt_body'),
|
|
style: textTheme.bodyMedium,
|
|
),
|
|
const SizedBox(height: AppSpacing.xl),
|
|
AppPrimaryButton(
|
|
key: const Key('sign_in_prompt_sign_in'),
|
|
label: l10n.signInPromptSignIn,
|
|
onPressed: () => context.go(AppRoutes.login),
|
|
),
|
|
const SizedBox(height: AppSpacing.md),
|
|
OutlinedButton(
|
|
key: const Key('sign_in_prompt_register'),
|
|
onPressed: () => context.go(AppRoutes.register),
|
|
child: Text(
|
|
l10n.signInPromptRegister,
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|