srs/lib/widgets/account_sheet.dart
Aswin Biju 45fcdcebfb Initial commit
Add SRS app: results, shops, orders and users, wired to srs-api
Flutter web/PWA for the lottery agency, built on Riverpod and go_router,
talking to srs-api over HTTP (HttpApi, token kept in SharedPreferences).

- Results, Shops, Orders and Users tabs (Users for admins only), with
  phone, tablet and desktop layouts and shared widgets and theme tokens
- Users: list with search and Active/Inactive filters; user detail with
  shops, sign-in details, and an Access card
- WhatsApp results switch on each user (sendResults on
  PATCH /api/users/:id). Shows the WhatsApp logo (Simple Icons, CC0,
  drawn with flutter_svg), green only when results will really go out.
  Can't be turned on without a phone number ("Add a phone number first"
  opens the phone sheet), and is paused while the user is inactive. The
  users list marks people who get results with the logo.
- Each Access switch has a one-line description; the explanation
  paragraphs are gone
- Remove demo mode: the app always uses the real AP
  test/support and is used only by tests.
2026-11-04 23:21:50 +05:30

86 lines
2.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/format.dart';
import '../core/providers.dart';
import '../core/theme.dart';
import 'ui.dart';
/// Signed-in user and Sign out. A sheet on phones, a dialog on wider windows.
void showAccountSheet(BuildContext context, WidgetRef ref) {
final u = ref.read(sessionProvider);
if (u == null) return;
showSheet<void>(context, (ctx) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Avatar(name: u.username, size: 52),
const SizedBox(width: S.s14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(u.username, style: ts(17, w: w7)),
const SizedBox(height: S.s4),
Row(
children: [
Pill(u.isAdmin ? 'Admin' : 'User'),
const SizedBox(width: S.s8),
Text(
u.isAdmin
? 'All shops'
: plural(u.shopIds.length, 'shop'),
style: ts(12, c: C.muted),
),
],
),
],
),
),
],
),
const SizedBox(height: S.s22),
BigButton(
'Sign out',
outline: true,
icon: Icons.logout_rounded,
onPressed: () {
Navigator.pop(ctx);
ref.read(sessionProvider.notifier).logout();
},
),
],
);
});
}
/// Initials in a rounded square.
class Avatar extends StatelessWidget {
const Avatar({
super.key,
required this.name,
this.size = 46,
this.dark = false,
});
final String name;
final double size;
final bool dark;
@override
Widget build(BuildContext context) => Container(
width: size,
height: size,
alignment: Alignment.center,
decoration: BoxDecoration(
color: dark ? C.navy : C.chip,
borderRadius: BorderRadius.circular(size * 0.3),
),
child: Text(
initials(name),
style: ts(size * 0.33, w: w7, c: dark ? Colors.white : C.navy),
),
);
}