feat(claude): shared account budget in Team tab + meta-sidebar card facelift (T-158)
Implements T-158 option A: the forwarded /usage budget (already parsed for the Activity tab, T-415) now also renders in the Team tab as a single ACCOUNT card, captioned "shared across the team". Usage is per-account — every team session shares one ~/.claude login — so it's shown once, not split per member (which would just repeat identical numbers). Facelift: the Activity, Team, and Config tabs now render their sections as elevated cards (panelHeader fill, dividerColor hairline, 6px radius) under small-caps mono headers, matching the settings overlay's card design (settings_category_view). Shared helpers — metaSectionHeader / metaCard / metaCardRow — live in meta_sidebar/models.dart; the SESSION control strip and the pinned Config SETTINGS block adopt the same card. The shared ClideAccordion (also used by decisions/tickets) is left untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/// T-158: the Team tab carries the shared account budget — a single ACCOUNT
|
||||
/// card from the forwarded `/usage`, NOT a per-member split (usage is
|
||||
/// per-account: every team session shares one ~/.claude login).
|
||||
library;
|
||||
|
||||
import 'package:clide/builtin/claude/src/claude_status.dart' show ClaudeUsage;
|
||||
import 'package:clide/builtin/claude/src/meta_sidebar/team_tab.dart';
|
||||
import 'package:clide/widgets/widgets.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../helpers/kernel_fixture.dart';
|
||||
import '../../helpers/widget_harness.dart';
|
||||
|
||||
void main() {
|
||||
late KernelFixture f;
|
||||
late TextEditingController inject;
|
||||
|
||||
setUp(() async {
|
||||
f = await KernelFixture.create();
|
||||
inject = TextEditingController();
|
||||
});
|
||||
tearDown(() {
|
||||
inject.dispose();
|
||||
f.dispose();
|
||||
});
|
||||
|
||||
// No team members + no catalog seeded, so labels fall back to their English
|
||||
// placeholders ('ACCOUNT' is the uppercased section header).
|
||||
TeamTabView view({ClaudeUsage? usage}) => TeamTabView(
|
||||
members: const [],
|
||||
memberStatus: const {},
|
||||
orchestrator: null,
|
||||
tasks: const [],
|
||||
injectingAgentId: null,
|
||||
injectController: inject,
|
||||
onToggleInject: (_) {},
|
||||
onInjectSubmit: (_, _) {},
|
||||
onClose: (_) {},
|
||||
onSetPermissionMode: (_, _) {},
|
||||
onFork: (_) {},
|
||||
onOpenChatPane: () {},
|
||||
usage: usage,
|
||||
);
|
||||
|
||||
testWidgets('renders the shared ACCOUNT budget card when usage is present', (tester) async {
|
||||
await tester.pumpWidget(harness(f, view(usage: const ClaudeUsage(session: '15% used', week: '53% used', weekSonnet: '0% used'))));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('ACCOUNT'), findsOneWidget);
|
||||
expect(find.text('15% used'), findsOneWidget);
|
||||
expect(find.text('53% used'), findsOneWidget);
|
||||
expect(find.text('0% used'), findsOneWidget);
|
||||
// Labelled shared, not per-member.
|
||||
expect(find.text('Shared across the team'), findsOneWidget);
|
||||
// Solo (no members) still shows the budget above the empty-team notice.
|
||||
expect(find.text('No team active.'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('omits the ACCOUNT card when no usage has been fetched', (tester) async {
|
||||
await tester.pumpWidget(harness(f, view()));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('ACCOUNT'), findsNothing);
|
||||
expect(find.text('Shared across the team'), findsNothing);
|
||||
expect(find.text('No team active.'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('omits the ACCOUNT card when the usage result is empty', (tester) async {
|
||||
await tester.pumpWidget(harness(f, view(usage: const ClaudeUsage())));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('ACCOUNT'), findsNothing);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user