feat: Integrate krow_core package and update WebMobileFrame widget for improved structure

This commit is contained in:
Achintha Isuru
2026-02-01 15:50:04 -05:00
parent b526a672bd
commit 40c43b06cc
4 changed files with 100 additions and 77 deletions

View File

@@ -32,6 +32,8 @@ dependencies:
path: ../../packages/features/client/hubs path: ../../packages/features/client/hubs
client_create_order: client_create_order:
path: ../../packages/features/client/create_order path: ../../packages/features/client/create_order
krow_core:
path: ../../packages/core/krow_core
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
flutter_modular: ^6.3.2 flutter_modular: ^6.3.2

View File

@@ -9,6 +9,7 @@ import 'package:krowwithus_staff/firebase_options.dart';
import 'package:staff_authentication/staff_authentication.dart' import 'package:staff_authentication/staff_authentication.dart'
as staff_authentication; as staff_authentication;
import 'package:staff_main/staff_main.dart' as staff_main; import 'package:staff_main/staff_main.dart' as staff_main;
import 'package:krow_core/core.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@@ -37,33 +38,37 @@ class AppWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider<core_localization.LocaleBloc>( return WebMobileFrame(
create: (BuildContext context) => appName: 'KROW Staff\nApplication',
Modular.get<core_localization.LocaleBloc>(), logo: Image.asset('assets/logo.png'),
child: child: BlocProvider<core_localization.LocaleBloc>(
BlocBuilder< create: (BuildContext context) =>
core_localization.LocaleBloc, Modular.get<core_localization.LocaleBloc>(),
core_localization.LocaleState child:
>( BlocBuilder<
builder: core_localization.LocaleBloc,
(BuildContext context, core_localization.LocaleState state) { core_localization.LocaleState
return core_localization.TranslationProvider( >(
child: MaterialApp.router( builder:
title: "KROW Staff", (BuildContext context, core_localization.LocaleState state) {
theme: UiTheme.light, return core_localization.TranslationProvider(
routerConfig: Modular.routerConfig, child: MaterialApp.router(
locale: state.locale, title: "KROW Staff",
supportedLocales: state.supportedLocales, theme: UiTheme.light,
localizationsDelegates: routerConfig: Modular.routerConfig,
const <LocalizationsDelegate<dynamic>>[ locale: state.locale,
GlobalMaterialLocalizations.delegate, supportedLocales: state.supportedLocales,
GlobalWidgetsLocalizations.delegate, localizationsDelegates:
GlobalCupertinoLocalizations.delegate, const <LocalizationsDelegate<dynamic>>[
], GlobalMaterialLocalizations.delegate,
), GlobalWidgetsLocalizations.delegate,
); GlobalCupertinoLocalizations.delegate,
}, ],
), ),
);
},
),
),
); );
} }
} }

View File

@@ -1,13 +1,11 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/// A wrapper widget that renders the application inside an iPhone-like frame /// A wrapper widget that renders the application inside an iPhone-like frame
/// specifically for Flutter Web. On other platforms, it simply returns the child. /// specifically for Flutter Web. On other platforms, it simply returns the child.
class WebMobileFrame extends StatelessWidget { class WebMobileFrame extends StatelessWidget {
final Widget child;
final Widget logo;
final String appName;
const WebMobileFrame({ const WebMobileFrame({
super.key, super.key,
required this.child, required this.child,
@@ -15,6 +13,10 @@ class WebMobileFrame extends StatelessWidget {
required this.appName, required this.appName,
}); });
final Widget child;
final Widget logo;
final String appName;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (!kIsWeb) return child; if (!kIsWeb) return child;
@@ -22,26 +24,22 @@ class WebMobileFrame extends StatelessWidget {
return MaterialApp( return MaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
theme: ThemeData.dark(), theme: ThemeData.dark(),
home: _WebFrameContent( home: _WebFrameContent(logo: logo, appName: appName, child: child),
logo: logo,
appName: appName,
child: child,
),
); );
} }
} }
class _WebFrameContent extends StatefulWidget { class _WebFrameContent extends StatefulWidget {
final Widget child;
final Widget logo;
final String appName;
const _WebFrameContent({ const _WebFrameContent({
required this.child, required this.child,
required this.logo, required this.logo,
required this.appName, required this.appName,
}); });
final Widget child;
final Widget logo;
final String appName;
@override @override
State<_WebFrameContent> createState() => _WebFrameContentState(); State<_WebFrameContent> createState() => _WebFrameContentState();
} }
@@ -61,10 +59,10 @@ class _WebFrameContentState extends State<_WebFrameContent> {
const double borderThickness = 12.0; const double borderThickness = 12.0;
return Scaffold( return Scaffold(
backgroundColor: const Color(0xFF121212), backgroundColor: UiColors.foreground,
body: MouseRegion( body: MouseRegion(
cursor: SystemMouseCursors.none, cursor: SystemMouseCursors.none,
onHover: (event) { onHover: (PointerHoverEvent event) {
setState(() { setState(() {
_cursorPosition = event.position; _cursorPosition = event.position;
_isHovering = true; _isHovering = true;
@@ -72,7 +70,7 @@ class _WebFrameContentState extends State<_WebFrameContent> {
}, },
onExit: (_) => setState(() => _isHovering = false), onExit: (_) => setState(() => _isHovering = false),
child: Stack( child: Stack(
children: [ children: <Widget>[
// Logo and Title on the left (Web only) // Logo and Title on the left (Web only)
Positioned( Positioned(
left: 60, left: 60,
@@ -84,28 +82,21 @@ class _WebFrameContentState extends State<_WebFrameContent> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: <Widget>[
SizedBox( SizedBox(width: 140, child: widget.logo),
width: 140,
child: widget.logo,
),
const SizedBox(height: 12), const SizedBox(height: 12),
Text( Text(
widget.appName, widget.appName,
textAlign: TextAlign.left, textAlign: TextAlign.left,
style: const TextStyle( style: UiTypography.display1b.copyWith(
color: Colors.white, color: UiColors.white,
fontSize: 28,
fontWeight: FontWeight.bold,
letterSpacing: -0.5,
fontFamily: 'Instrument Sans', // Fallback if available or system
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Container( Container(
height: 2, height: 2,
width: 40, 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 // Frame and Content
Center( Center(
child: LayoutBuilder( child: LayoutBuilder(
builder: (context, constraints) { builder: (BuildContext context, BoxConstraints constraints) {
// Scale down if screen is too small // Scale down if screen is too small
double scaleX = constraints.maxWidth / (frameWidth + 80); final double scaleX = constraints.maxWidth / (frameWidth + 80);
double scaleY = constraints.maxHeight / (frameHeight + 80); final double scaleY = constraints.maxHeight / (frameHeight + 80);
double scale = (scaleX < 1 || scaleY < 1) final double scale = (scaleX < 1 || scaleY < 1)
? (scaleX < scaleY ? scaleX : scaleY) ? (scaleX < scaleY ? scaleX : scaleY)
: 1.0; : 1.0;
@@ -130,11 +121,11 @@ class _WebFrameContentState extends State<_WebFrameContent> {
width: frameWidth, width: frameWidth,
height: frameHeight, height: frameHeight,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.black, color: UiColors.black,
borderRadius: BorderRadius.circular(borderRadius), borderRadius: BorderRadius.circular(borderRadius),
boxShadow: [ boxShadow: <BoxShadow>[
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.6), color: UiColors.black.withOpacity(0.6),
blurRadius: 40, blurRadius: 40,
spreadRadius: 10, spreadRadius: 10,
), ),
@@ -149,10 +140,10 @@ class _WebFrameContentState extends State<_WebFrameContent> {
borderRadius - borderThickness, borderRadius - borderThickness,
), ),
child: Stack( child: Stack(
children: [ children: <Widget>[
// The actual app + status bar // The actual app + status bar
Column( Column(
children: [ children: <Widget>[
// Mock iOS Status Bar // Mock iOS Status Bar
Container( Container(
height: 48, height: 48,
@@ -160,26 +151,26 @@ class _WebFrameContentState extends State<_WebFrameContent> {
horizontal: 24, horizontal: 24,
), ),
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Color(0xFFF9F6EE), color: UiColors.background,
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(
color: Color(0xFFEEEEEE), color: UiColors.border,
width: 0.5, width: 0.5,
), ),
), ),
), ),
child: Row( child: const Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.spaceBetween, MainAxisAlignment.spaceBetween,
children: [ children: <Widget>[
// Time side // Time side
const SizedBox( SizedBox(
width: 80, width: 80,
child: Text( child: Text(
'9:41 PM', '9:41 PM',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
color: Colors.black54, color: UiColors.black,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
fontSize: 14, fontSize: 14,
letterSpacing: -0.2, letterSpacing: -0.2,
@@ -187,27 +178,27 @@ class _WebFrameContentState extends State<_WebFrameContent> {
), ),
), ),
// Status Icons side // Status Icons side
const SizedBox( SizedBox(
width: 80, width: 80,
child: Row( child: Row(
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.end, MainAxisAlignment.end,
spacing: 12, spacing: 12,
children: [ children: <Widget>[
Icon( Icon(
Icons.signal_cellular_alt, Icons.signal_cellular_alt,
size: 14, size: 14,
color: Colors.black54, color: UiColors.black,
), ),
Icon( Icon(
Icons.wifi, Icons.wifi,
size: 14, size: 14,
color: Colors.black54, color: UiColors.black,
), ),
Icon( Icon(
Icons.battery_full, Icons.battery_full,
size: 14, 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), Expanded(child: widget.child),
], ],
), ),
@@ -228,7 +219,7 @@ class _WebFrameContentState extends State<_WebFrameContent> {
height: 35, height: 35,
margin: const EdgeInsets.only(top: 10), margin: const EdgeInsets.only(top: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.black, color: UiColors.black,
borderRadius: BorderRadius.circular(20), 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>[
BoxShadow(
color: UiColors.black.withOpacity(0.2),
blurRadius: 4,
spreadRadius: 1,
),
],
),
),
),
),
], ],
), ),
), ),

View File

@@ -11,3 +11,5 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
design_system:
path: ../design_system