Merge branch 'dev' into feature/centralized-data-error-handling and resolve conflicts
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// The sign-out button widget.
|
||||
///
|
||||
@@ -14,31 +13,33 @@ class LogoutButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final i18n = t.staff.profile.header;
|
||||
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Material(
|
||||
color: const Color(0x00000000),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: UiConstants.space4),
|
||||
padding: const EdgeInsets.symmetric(vertical: UiConstants.space4),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(LucideIcons.logOut, color: UiColors.destructive, size: 20),
|
||||
SizedBox(width: UiConstants.space2),
|
||||
const Icon(
|
||||
UiIcons.logOut,
|
||||
color: UiColors.destructive,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space2),
|
||||
Text(
|
||||
i18n.sign_out,
|
||||
style: UiTypography.body1m.copyWith(
|
||||
color: UiColors.destructive,
|
||||
),
|
||||
style: UiTypography.body1m.textError,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -34,13 +34,13 @@ class ProfileHeader extends StatelessWidget {
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
UiConstants.space5,
|
||||
UiConstants.space5,
|
||||
UiConstants.space5,
|
||||
UiConstants.space16,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.primary,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
bottom: Radius.circular(UiConstants.space6),
|
||||
@@ -56,22 +56,20 @@ class ProfileHeader extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
i18n.title,
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.primaryForeground,
|
||||
),
|
||||
style: UiTypography.headline4m.textSecondary,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: onSignOutTap,
|
||||
child: Text(
|
||||
i18n.sign_out,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.primaryForeground.withOpacity(0.8),
|
||||
color: UiColors.primaryForeground.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: UiConstants.space8),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
// Avatar Section
|
||||
Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
@@ -79,7 +77,7 @@ class ProfileHeader extends StatelessWidget {
|
||||
Container(
|
||||
width: 112,
|
||||
height: 112,
|
||||
padding: EdgeInsets.all(UiConstants.space1),
|
||||
padding: const EdgeInsets.all(UiConstants.space1),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
@@ -87,13 +85,13 @@ class ProfileHeader extends StatelessWidget {
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
UiColors.accent,
|
||||
UiColors.accent.withOpacity(0.5),
|
||||
UiColors.accent.withValues(alpha: 0.5),
|
||||
UiColors.primaryForeground,
|
||||
],
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiColors.foreground.withOpacity(0.2),
|
||||
color: UiColors.foreground.withValues(alpha: 0.2),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
@@ -103,7 +101,7 @@ class ProfileHeader extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: UiColors.primaryForeground.withOpacity(0.2),
|
||||
color: UiColors.primaryForeground.withValues(alpha: 0.2),
|
||||
width: 4,
|
||||
),
|
||||
),
|
||||
@@ -123,16 +121,16 @@ class ProfileHeader extends StatelessWidget {
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
UiColors.accent,
|
||||
UiColors.accent.withOpacity(0.7),
|
||||
UiColors.accent.withValues(alpha: 0.7),
|
||||
],
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
fullName.isNotEmpty ? fullName[0].toUpperCase() : 'K',
|
||||
style: UiTypography.displayM.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
fullName.isNotEmpty
|
||||
? fullName[0].toUpperCase()
|
||||
: 'K',
|
||||
style: UiTypography.displayM.primary,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
@@ -148,7 +146,7 @@ class ProfileHeader extends StatelessWidget {
|
||||
border: Border.all(color: UiColors.primary, width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiColors.foreground.withOpacity(0.1),
|
||||
color: UiColors.foreground.withValues(alpha: 0.1),
|
||||
blurRadius: 4,
|
||||
),
|
||||
],
|
||||
@@ -161,28 +159,24 @@ class ProfileHeader extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
fullName,
|
||||
style: UiTypography.headline3m.copyWith(
|
||||
color: UiColors.primaryForeground,
|
||||
),
|
||||
style: UiTypography.headline3m.textPlaceholder,
|
||||
),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space3,
|
||||
vertical: UiConstants.space1,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.accent.withOpacity(0.2),
|
||||
color: UiColors.accent.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(UiConstants.space5),
|
||||
),
|
||||
child: Text(
|
||||
level,
|
||||
style: UiTypography.footnote1b.copyWith(
|
||||
color: UiColors.accent,
|
||||
),
|
||||
style: UiTypography.footnote1b.accent,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -25,10 +25,10 @@ class ProfileMenuItem extends StatelessWidget {
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
padding: EdgeInsets.all(UiConstants.space2),
|
||||
padding: const EdgeInsets.all(UiConstants.space2),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.0,
|
||||
child: Stack(
|
||||
@@ -42,24 +42,23 @@ class ProfileMenuItem extends StatelessWidget {
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.08),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
color: UiColors.primary.withValues(alpha: 0.08),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Icon(icon, color: UiColors.primary, size: 20),
|
||||
),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: UiConstants.space1),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space1,
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: UiTypography.footnote1m.copyWith(
|
||||
color: UiColors.foreground,
|
||||
height: 1.2,
|
||||
),
|
||||
style: UiTypography.footnote1m.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -76,16 +75,18 @@ class ProfileMenuItem extends StatelessWidget {
|
||||
shape: BoxShape.circle,
|
||||
color: completed!
|
||||
? UiColors.primary
|
||||
: UiColors.primary.withOpacity(0.1),
|
||||
: UiColors.primary.withValues(alpha: 0.1),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: completed!
|
||||
? const Icon(Icons.check, size: 10, color: UiColors.primaryForeground)
|
||||
? const Icon(
|
||||
UiIcons.check,
|
||||
size: 10,
|
||||
color: UiColors.primaryForeground,
|
||||
)
|
||||
: Text(
|
||||
"!",
|
||||
style: UiTypography.footnote2b.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.footnote2b.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -19,10 +19,10 @@ class ReliabilityScoreBar extends StatelessWidget {
|
||||
final score = (reliabilityScore ?? 0) / 100;
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -32,19 +32,15 @@ class ReliabilityScoreBar extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
i18n.title,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.body2m.primary,
|
||||
),
|
||||
Text(
|
||||
"${reliabilityScore ?? 0}%",
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.headline4m.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: UiConstants.space2),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(UiConstants.space1),
|
||||
child: LinearProgressIndicator(
|
||||
@@ -55,12 +51,10 @@ class ReliabilityScoreBar extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: UiConstants.space2),
|
||||
padding: const EdgeInsets.only(top: UiConstants.space2),
|
||||
child: Text(
|
||||
i18n.description,
|
||||
style: UiTypography.footnote2r.copyWith(
|
||||
color: UiColors.mutedForeground,
|
||||
),
|
||||
style: UiTypography.footnote2r.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Displays the staff member's reliability statistics (Shifts, Rating, On Time, etc.).
|
||||
///
|
||||
@@ -24,14 +23,14 @@ class ReliabilityStatsCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: UiColors.foreground.withOpacity(0.05),
|
||||
color: UiColors.foreground.withValues(alpha: 0.05),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 1),
|
||||
),
|
||||
@@ -42,31 +41,31 @@ class ReliabilityStatsCard extends StatelessWidget {
|
||||
children: [
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.briefcase,
|
||||
UiIcons.briefcase,
|
||||
"${totalShifts ?? 0}",
|
||||
"Shifts",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.star,
|
||||
UiIcons.star,
|
||||
(averageRating ?? 0.0).toStringAsFixed(1),
|
||||
"Rating",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.clock,
|
||||
UiIcons.clock,
|
||||
"${onTimeRate ?? 0}%",
|
||||
"On Time",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.xCircle,
|
||||
UiIcons.xCircle,
|
||||
"${noShowCount ?? 0}",
|
||||
"No Shows",
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
LucideIcons.ban,
|
||||
UiIcons.ban,
|
||||
"${cancellationCount ?? 0}",
|
||||
"Cancel.",
|
||||
),
|
||||
@@ -88,26 +87,22 @@ class ReliabilityStatsCard extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusMdValue),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Icon(icon, size: 20, color: UiColors.primary),
|
||||
),
|
||||
SizedBox(height: UiConstants.space1),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Text(
|
||||
value,
|
||||
style: UiTypography.body1b.copyWith(
|
||||
color: UiColors.foreground,
|
||||
),
|
||||
style: UiTypography.body1b.textSecondary,
|
||||
),
|
||||
FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Text(
|
||||
label,
|
||||
style: UiTypography.footnote2r.copyWith(
|
||||
color: UiColors.mutedForeground,
|
||||
),
|
||||
style: UiTypography.footnote2r.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -13,14 +13,11 @@ class SectionTitle extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.only(left: UiConstants.space1),
|
||||
margin: EdgeInsets.only(bottom: UiConstants.space3),
|
||||
padding: const EdgeInsets.only(left: UiConstants.space1),
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space3),
|
||||
child: Text(
|
||||
title.toUpperCase(),
|
||||
style: UiTypography.footnote1b.copyWith(
|
||||
color: UiColors.mutedForeground,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
style: UiTypography.footnote1b.textSecondary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user