feat(proj): init
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:please_pay_me/core/config/app_config.dart';
|
||||
import 'package:please_pay_me/core/storage/session_storage.dart';
|
||||
import 'package:please_pay_me/data/demo/demo_backend.dart';
|
||||
import 'package:please_pay_me/features/auth/session_controller.dart';
|
||||
import 'package:please_pay_me/features/budgets/budgets_controller.dart';
|
||||
import 'package:please_pay_me/features/journal/journal_controller.dart';
|
||||
import 'package:please_pay_me/features/work/jobs_controller.dart';
|
||||
import 'package:please_pay_me/theme/theme.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
/// Wires real app screens to the in-memory [DemoBackend] so the catalog shows
|
||||
/// production widgets with production state management.
|
||||
class DemoScope extends StatefulWidget {
|
||||
const DemoScope({super.key, required this.child, this.seeded = true});
|
||||
|
||||
final Widget child;
|
||||
|
||||
/// `false` renders the empty states (no budgets / jobs / operations).
|
||||
final bool seeded;
|
||||
|
||||
@override
|
||||
State<DemoScope> createState() => _DemoScopeState();
|
||||
}
|
||||
|
||||
class _DemoScopeState extends State<DemoScope> {
|
||||
late DemoBackend _backend;
|
||||
late SessionController _session;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_build();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(DemoScope oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.seeded != widget.seeded) _build();
|
||||
}
|
||||
|
||||
void _build() {
|
||||
_backend = widget.seeded ? DemoBackend() : DemoBackend.empty();
|
||||
_session = SessionController(
|
||||
config: AppConfig.demo,
|
||||
storage: InMemorySessionStorage(),
|
||||
demoBackend: _backend,
|
||||
)..startDemo();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
key: ValueKey(widget.seeded),
|
||||
providers: [
|
||||
ChangeNotifierProvider<SessionController>.value(value: _session),
|
||||
ChangeNotifierProvider<ThemeController>(
|
||||
create: (_) => ThemeController(store: MemoryThemeStore()),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => BudgetsController(
|
||||
budgets: _backend.budgets,
|
||||
expenses: _backend.expenses,
|
||||
)..load(),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => JournalController(expenses: _backend.expenses)..load(),
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => JobsController(jobs: _backend.jobs)..load(),
|
||||
),
|
||||
],
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:please_pay_me/theme/theme.dart';
|
||||
|
||||
/// Puts a use-case on the iOS grouped background so inset-grouped cards and
|
||||
/// separators read the way they do inside the app.
|
||||
class IosPreview extends StatelessWidget {
|
||||
const IosPreview({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.padding = const EdgeInsets.symmetric(vertical: AppSpacing.s5),
|
||||
this.maxWidth = 420,
|
||||
this.stretch = false,
|
||||
});
|
||||
|
||||
/// Preview for controls that should not be stretched (buttons, chips).
|
||||
const IosPreview.centered({super.key, required this.child})
|
||||
: padding = const EdgeInsets.all(AppSpacing.s5),
|
||||
maxWidth = 420,
|
||||
stretch = false;
|
||||
|
||||
final Widget child;
|
||||
final EdgeInsetsGeometry padding;
|
||||
final double maxWidth;
|
||||
final bool stretch;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ColoredBox(
|
||||
color: AppColors.of(context, AppColors.groupedBackground),
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: padding,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
stretch ? CrossAxisAlignment.stretch : CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [child],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Full-screen preview (screens already bring their own scaffold).
|
||||
class IosScreenPreview extends StatelessWidget {
|
||||
const IosScreenPreview({super.key, required this.child});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => child;
|
||||
}
|
||||
Reference in New Issue
Block a user