srs/lib/features/users/shop_picker.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

93 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import '../../core/models.dart';
import '../../core/theme.dart';
import '../../widgets/ui.dart';
class ShopPicker extends StatelessWidget {
const ShopPicker({
super.key,
required this.shops,
required this.selected,
required this.onToggle,
});
final List<Shop> shops;
final Set<int> selected;
final ValueChanged<int> onToggle;
@override
Widget build(BuildContext context) {
if (shops.isEmpty) {
return Text(
'No active shops available. Add a shop first.',
style: ts(13, c: C.muted),
);
}
return Column(
children: [
for (final s in shops)
Padding(
padding: const EdgeInsets.only(bottom: S.s8),
child: Pressable(
onTap: () => onToggle(s.id),
radius: R.input,
builder: (_, hover) => AnimatedContainer(
duration: const Duration(milliseconds: 140),
padding: const EdgeInsets.symmetric(
horizontal: S.s14,
vertical: S.s12,
),
decoration: BoxDecoration(
color: selected.contains(s.id)
? C.chip
: (hover ? C.hover : Colors.white),
borderRadius: BorderRadius.circular(R.input),
border: Border.all(
color: selected.contains(s.id) ? C.navy : C.border,
),
),
child: Row(
children: [
Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: selected.contains(s.id) ? C.navy : Colors.white,
borderRadius: BorderRadius.circular(R.sm),
border: Border.all(
color: selected.contains(s.id) ? C.navy : C.border2,
width: 1.5,
),
),
child: selected.contains(s.id)
? const Icon(
Icons.check_rounded,
size: 16,
color: Colors.white,
)
: null,
),
const SizedBox(width: S.s12),
Text(
s.code,
style: ts(13, w: w7, c: C.navy),
),
const SizedBox(width: S.s10),
Expanded(
child: Text(
s.name,
style: ts(14, w: w5),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
),
),
],
);
}
}