diff --git a/apps/mobile/apps/client/pubspec.yaml b/apps/mobile/apps/client/pubspec.yaml index 2221f485..77f1325a 100644 --- a/apps/mobile/apps/client/pubspec.yaml +++ b/apps/mobile/apps/client/pubspec.yaml @@ -32,6 +32,8 @@ dependencies: path: ../../packages/features/client/hubs client_create_order: path: ../../packages/features/client/create_order + krow_core: + path: ../../packages/core/krow_core cupertino_icons: ^1.0.8 flutter_modular: ^6.3.2 diff --git a/apps/mobile/apps/staff/lib/main.dart b/apps/mobile/apps/staff/lib/main.dart index 74f7cf77..050ae079 100644 --- a/apps/mobile/apps/staff/lib/main.dart +++ b/apps/mobile/apps/staff/lib/main.dart @@ -9,6 +9,7 @@ import 'package:krowwithus_staff/firebase_options.dart'; import 'package:staff_authentication/staff_authentication.dart' as staff_authentication; import 'package:staff_main/staff_main.dart' as staff_main; +import 'package:krow_core/core.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -37,33 +38,37 @@ class AppWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocProvider( - create: (BuildContext context) => - Modular.get(), - child: - BlocBuilder< - core_localization.LocaleBloc, - core_localization.LocaleState - >( - builder: - (BuildContext context, core_localization.LocaleState state) { - return core_localization.TranslationProvider( - child: MaterialApp.router( - title: "KROW Staff", - theme: UiTheme.light, - routerConfig: Modular.routerConfig, - locale: state.locale, - supportedLocales: state.supportedLocales, - localizationsDelegates: - const >[ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - ), - ); - }, - ), + return WebMobileFrame( + appName: 'KROW Staff\nApplication', + logo: Image.asset('assets/logo.png'), + child: BlocProvider( + create: (BuildContext context) => + Modular.get(), + child: + BlocBuilder< + core_localization.LocaleBloc, + core_localization.LocaleState + >( + builder: + (BuildContext context, core_localization.LocaleState state) { + return core_localization.TranslationProvider( + child: MaterialApp.router( + title: "KROW Staff", + theme: UiTheme.light, + routerConfig: Modular.routerConfig, + locale: state.locale, + supportedLocales: state.supportedLocales, + localizationsDelegates: + const >[ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + ), + ); + }, + ), + ), ); } } diff --git a/apps/mobile/packages/core/lib/src/presentation/widgets/web_mobile_frame.dart b/apps/mobile/packages/core/lib/src/presentation/widgets/web_mobile_frame.dart index 9c636294..6a98c784 100644 --- a/apps/mobile/packages/core/lib/src/presentation/widgets/web_mobile_frame.dart +++ b/apps/mobile/packages/core/lib/src/presentation/widgets/web_mobile_frame.dart @@ -1,13 +1,11 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; /// A wrapper widget that renders the application inside an iPhone-like frame /// specifically for Flutter Web. On other platforms, it simply returns the child. class WebMobileFrame extends StatelessWidget { - final Widget child; - final Widget logo; - final String appName; - const WebMobileFrame({ super.key, required this.child, @@ -15,6 +13,10 @@ class WebMobileFrame extends StatelessWidget { required this.appName, }); + final Widget child; + final Widget logo; + final String appName; + @override Widget build(BuildContext context) { if (!kIsWeb) return child; @@ -22,26 +24,22 @@ class WebMobileFrame extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData.dark(), - home: _WebFrameContent( - logo: logo, - appName: appName, - child: child, - ), + home: _WebFrameContent(logo: logo, appName: appName, child: child), ); } } class _WebFrameContent extends StatefulWidget { - final Widget child; - final Widget logo; - final String appName; - const _WebFrameContent({ required this.child, required this.logo, required this.appName, }); + final Widget child; + final Widget logo; + final String appName; + @override State<_WebFrameContent> createState() => _WebFrameContentState(); } @@ -61,10 +59,10 @@ class _WebFrameContentState extends State<_WebFrameContent> { const double borderThickness = 12.0; return Scaffold( - backgroundColor: const Color(0xFF121212), + backgroundColor: UiColors.foreground, body: MouseRegion( cursor: SystemMouseCursors.none, - onHover: (event) { + onHover: (PointerHoverEvent event) { setState(() { _cursorPosition = event.position; _isHovering = true; @@ -72,7 +70,7 @@ class _WebFrameContentState extends State<_WebFrameContent> { }, onExit: (_) => setState(() => _isHovering = false), child: Stack( - children: [ + children: [ // Logo and Title on the left (Web only) Positioned( left: 60, @@ -84,28 +82,21 @@ class _WebFrameContentState extends State<_WebFrameContent> { child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 140, - child: widget.logo, - ), + children: [ + SizedBox(width: 140, child: widget.logo), const SizedBox(height: 12), Text( widget.appName, textAlign: TextAlign.left, - style: const TextStyle( - color: Colors.white, - fontSize: 28, - fontWeight: FontWeight.bold, - letterSpacing: -0.5, - fontFamily: 'Instrument Sans', // Fallback if available or system + style: UiTypography.display1b.copyWith( + color: UiColors.white, ), ), const SizedBox(height: 4), Container( height: 2, width: 40, - color: Colors.white.withOpacity(0.3), + color: UiColors.white.withOpacity(0.3), ), ], ), @@ -116,11 +107,11 @@ class _WebFrameContentState extends State<_WebFrameContent> { // Frame and Content Center( child: LayoutBuilder( - builder: (context, constraints) { + builder: (BuildContext context, BoxConstraints constraints) { // Scale down if screen is too small - double scaleX = constraints.maxWidth / (frameWidth + 80); - double scaleY = constraints.maxHeight / (frameHeight + 80); - double scale = (scaleX < 1 || scaleY < 1) + final double scaleX = constraints.maxWidth / (frameWidth + 80); + final double scaleY = constraints.maxHeight / (frameHeight + 80); + final double scale = (scaleX < 1 || scaleY < 1) ? (scaleX < scaleY ? scaleX : scaleY) : 1.0; @@ -130,11 +121,11 @@ class _WebFrameContentState extends State<_WebFrameContent> { width: frameWidth, height: frameHeight, decoration: BoxDecoration( - color: Colors.black, + color: UiColors.black, borderRadius: BorderRadius.circular(borderRadius), - boxShadow: [ + boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.6), + color: UiColors.black.withOpacity(0.6), blurRadius: 40, spreadRadius: 10, ), @@ -149,10 +140,10 @@ class _WebFrameContentState extends State<_WebFrameContent> { borderRadius - borderThickness, ), child: Stack( - children: [ + children: [ // The actual app + status bar Column( - children: [ + children: [ // Mock iOS Status Bar Container( height: 48, @@ -160,26 +151,26 @@ class _WebFrameContentState extends State<_WebFrameContent> { horizontal: 24, ), decoration: const BoxDecoration( - color: Color(0xFFF9F6EE), + color: UiColors.background, border: Border( bottom: BorderSide( - color: Color(0xFFEEEEEE), + color: UiColors.border, width: 0.5, ), ), ), - child: Row( + child: const Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + children: [ // Time side - const SizedBox( + SizedBox( width: 80, child: Text( '9:41 PM', textAlign: TextAlign.center, style: TextStyle( - color: Colors.black54, + color: UiColors.black, fontWeight: FontWeight.w700, fontSize: 14, letterSpacing: -0.2, @@ -187,27 +178,27 @@ class _WebFrameContentState extends State<_WebFrameContent> { ), ), // Status Icons side - const SizedBox( + SizedBox( width: 80, child: Row( mainAxisAlignment: MainAxisAlignment.end, spacing: 12, - children: [ + children: [ Icon( Icons.signal_cellular_alt, size: 14, - color: Colors.black54, + color: UiColors.black, ), Icon( Icons.wifi, size: 14, - color: Colors.black54, + color: UiColors.black, ), Icon( Icons.battery_full, size: 14, - color: Colors.black54, + color: UiColors.black, ), ], ), @@ -215,7 +206,7 @@ class _WebFrameContentState extends State<_WebFrameContent> { ], ), ), - // The main app content content + // The main app content Expanded(child: widget.child), ], ), @@ -228,7 +219,7 @@ class _WebFrameContentState extends State<_WebFrameContent> { height: 35, margin: const EdgeInsets.only(top: 10), decoration: BoxDecoration( - color: Colors.black, + color: UiColors.black, borderRadius: BorderRadius.circular(20), ), ), @@ -241,6 +232,29 @@ class _WebFrameContentState extends State<_WebFrameContent> { }, ), ), + if (_isHovering) + Positioned( + left: _cursorPosition.dx - 15, + top: _cursorPosition.dy - 15, + child: IgnorePointer( + child: Container( + width: 30, + height: 30, + decoration: BoxDecoration( + color: UiColors.mutedForeground.withOpacity(0.3), + shape: BoxShape.circle, + border: Border.all(color: UiColors.white.withOpacity(0.7), width: 2), + boxShadow: [ + BoxShadow( + color: UiColors.black.withOpacity(0.2), + blurRadius: 4, + spreadRadius: 1, + ), + ], + ), + ), + ), + ), ], ), ), diff --git a/apps/mobile/packages/core/pubspec.yaml b/apps/mobile/packages/core/pubspec.yaml index 1b14ddda..f0a02c12 100644 --- a/apps/mobile/packages/core/pubspec.yaml +++ b/apps/mobile/packages/core/pubspec.yaml @@ -11,3 +11,5 @@ environment: dependencies: flutter: sdk: flutter + design_system: + path: ../design_system