Single Flutter codebase under client/app/ with web enabled (mobile/desktop can be added later; lib/ is platform-agnostic). Talks to the NestJS backend via a thin REST wrapper; API_BASE is a --dart-define (defaults to the local backend). Screens: - Login: Konfi/guest (invite code), local Teamer password login, Teamer invite redemption. Token persisted in shared_preferences, restored on start; GET /auth/me drives a role-aware home. - Workshop-Wahl (guests): loads /wahl/guest/overview, ordered pick of up to 3 workshops, submits to /wahl/:id/teilnehmer. - Dateien: /files/:kcId list. - Chat: channel + message list (read-only; WS send is a follow-up). State: AppState (ChangeNotifier) exposed via an InheritedNotifier (AppScope) — no third-party state package. flutter analyze clean, flutter build web --release passes, one widget smoke test. Also: interim client/web/ HTML placeholder stays as-is (per plan it is superseded by this Flutter web build). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
59 lines
1.6 KiB
Dart
59 lines
1.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import 'api.dart';
|
|
import 'screens/home_screen.dart';
|
|
import 'screens/login_screen.dart';
|
|
|
|
void main() {
|
|
final state = AppState(Api(http.Client()))..bootstrap();
|
|
runApp(KcApp(state: state));
|
|
}
|
|
|
|
/// Minimal InheritedNotifier so screens can read `AppState.of(context)` and
|
|
/// rebuild on change — no third-party state management.
|
|
class AppScope extends InheritedNotifier<AppState> {
|
|
const AppScope({super.key, required AppState state, required super.child})
|
|
: super(notifier: state);
|
|
|
|
static AppState of(BuildContext context) {
|
|
final scope = context.dependOnInheritedWidgetOfExactType<AppScope>();
|
|
assert(scope != null, 'AppScope missing above this widget');
|
|
return scope!.notifier!;
|
|
}
|
|
}
|
|
|
|
class KcApp extends StatelessWidget {
|
|
const KcApp({super.key, required this.state});
|
|
final AppState state;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AppScope(
|
|
state: state,
|
|
child: MaterialApp(
|
|
title: 'KC-App',
|
|
debugShowCheckedModeBanner: false,
|
|
theme: ThemeData(
|
|
colorSchemeSeed: const Color(0xFF3B5BA5),
|
|
useMaterial3: true,
|
|
),
|
|
home: const _AuthGate(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _AuthGate extends StatelessWidget {
|
|
const _AuthGate();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final state = AppScope.of(context);
|
|
if (state.loading) {
|
|
return const Scaffold(body: Center(child: CircularProgressIndicator()));
|
|
}
|
|
return state.isLoggedIn ? const HomeScreen() : const LoginScreen();
|
|
}
|
|
}
|