feat: Enable the rapid order type, refactor the invoice ready page to use UiAppBar, and adjust rapid action widget colors.
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
import 'package:core_localization/core_localization.dart';
|
import 'package:core_localization/core_localization.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
import 'package:krow_core/core.dart';
|
|
||||||
import '../blocs/billing_bloc.dart';
|
import '../blocs/billing_bloc.dart';
|
||||||
import '../blocs/billing_event.dart';
|
import '../blocs/billing_event.dart';
|
||||||
import '../models/billing_invoice_model.dart';
|
import '../models/billing_invoice_model.dart';
|
||||||
@@ -14,7 +13,8 @@ class ShiftCompletionReviewPage extends StatefulWidget {
|
|||||||
final BillingInvoice? invoice;
|
final BillingInvoice? invoice;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ShiftCompletionReviewPage> createState() => _ShiftCompletionReviewPageState();
|
State<ShiftCompletionReviewPage> createState() =>
|
||||||
|
_ShiftCompletionReviewPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
||||||
@@ -31,99 +31,62 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final List<BillingWorkerRecord> filteredWorkers = invoice.workers.where((BillingWorkerRecord w) {
|
final List<BillingWorkerRecord> filteredWorkers = invoice.workers.where((
|
||||||
|
BillingWorkerRecord w,
|
||||||
|
) {
|
||||||
if (searchQuery.isEmpty) return true;
|
if (searchQuery.isEmpty) return true;
|
||||||
return w.workerName.toLowerCase().contains(searchQuery.toLowerCase()) ||
|
return w.workerName.toLowerCase().contains(searchQuery.toLowerCase()) ||
|
||||||
w.roleName.toLowerCase().contains(searchQuery.toLowerCase());
|
w.roleName.toLowerCase().contains(searchQuery.toLowerCase());
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8FAFC),
|
appBar: UiAppBar(
|
||||||
|
title: invoice.title,
|
||||||
|
subtitle: invoice.clientName,
|
||||||
|
showBackButton: true,
|
||||||
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Column(
|
child: Expanded(
|
||||||
children: <Widget>[
|
child: SingleChildScrollView(
|
||||||
_buildHeader(context),
|
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space5),
|
||||||
Expanded(
|
child: Column(
|
||||||
child: SingleChildScrollView(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space5),
|
children: <Widget>[
|
||||||
child: Column(
|
const SizedBox(height: UiConstants.space4),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
_buildInvoiceInfoCard(),
|
||||||
children: <Widget>[
|
const SizedBox(height: UiConstants.space4),
|
||||||
const SizedBox(height: UiConstants.space4),
|
_buildAmountCard(),
|
||||||
_buildInvoiceInfoCard(),
|
const SizedBox(height: UiConstants.space6),
|
||||||
const SizedBox(height: UiConstants.space4),
|
_buildWorkersHeader(),
|
||||||
_buildAmountCard(),
|
const SizedBox(height: UiConstants.space4),
|
||||||
const SizedBox(height: UiConstants.space6),
|
_buildSearchAndTabs(),
|
||||||
_buildWorkersHeader(),
|
const SizedBox(height: UiConstants.space4),
|
||||||
const SizedBox(height: UiConstants.space4),
|
...filteredWorkers.map(
|
||||||
_buildSearchAndTabs(),
|
(BillingWorkerRecord worker) => _buildWorkerCard(worker),
|
||||||
const SizedBox(height: UiConstants.space4),
|
|
||||||
...filteredWorkers.map((BillingWorkerRecord worker) => _buildWorkerCard(worker)),
|
|
||||||
const SizedBox(height: UiConstants.space6),
|
|
||||||
_buildActionButtons(context),
|
|
||||||
const SizedBox(height: UiConstants.space4),
|
|
||||||
_buildDownloadLink(),
|
|
||||||
const SizedBox(height: UiConstants.space8),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: UiConstants.space6),
|
||||||
|
_buildActionButtons(context),
|
||||||
|
const SizedBox(height: UiConstants.space4),
|
||||||
|
_buildDownloadLink(),
|
||||||
|
const SizedBox(height: UiConstants.space8),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHeader(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.fromLTRB(UiConstants.space5, UiConstants.space4, UiConstants.space5, UiConstants.space4),
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
border: Border(bottom: BorderSide(color: UiColors.border)),
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 40,
|
|
||||||
height: 4,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: UiColors.border,
|
|
||||||
borderRadius: UiConstants.radiusFull,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: UiConstants.space4),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: <Widget>[
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(t.client_billing.invoice_ready, style: UiTypography.headline4b.textPrimary),
|
|
||||||
Text(t.client_billing.review_and_approve_subtitle, style: UiTypography.body2r.textSecondary),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
UiIconButton.secondary(
|
|
||||||
icon: UiIcons.close,
|
|
||||||
onTap: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildInvoiceInfoCard() {
|
Widget _buildInvoiceInfoCard() {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: UiConstants.space1,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(invoice.title, style: UiTypography.headline4b.textPrimary),
|
|
||||||
Text(invoice.clientName, style: UiTypography.body2r.textSecondary),
|
|
||||||
const SizedBox(height: UiConstants.space4),
|
|
||||||
_buildInfoRow(UiIcons.calendar, invoice.date),
|
_buildInfoRow(UiIcons.calendar, invoice.date),
|
||||||
const SizedBox(height: UiConstants.space2),
|
_buildInfoRow(
|
||||||
_buildInfoRow(UiIcons.clock, '${invoice.startTime ?? "--"} - ${invoice.endTime ?? "--"}'),
|
UiIcons.clock,
|
||||||
const SizedBox(height: UiConstants.space2),
|
'${invoice.startTime ?? "--"} - ${invoice.endTime ?? "--"}',
|
||||||
|
),
|
||||||
_buildInfoRow(UiIcons.mapPin, invoice.locationAddress),
|
_buildInfoRow(UiIcons.mapPin, invoice.locationAddress),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -194,7 +157,11 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
onChanged: (String val) => setState(() => searchQuery = val),
|
onChanged: (String val) => setState(() => searchQuery = val),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
icon: const Icon(UiIcons.search, size: 18, color: UiColors.iconSecondary),
|
icon: const Icon(
|
||||||
|
UiIcons.search,
|
||||||
|
size: 18,
|
||||||
|
color: UiColors.iconSecondary,
|
||||||
|
),
|
||||||
hintText: t.client_billing.workers_tab.search_hint,
|
hintText: t.client_billing.workers_tab.search_hint,
|
||||||
hintStyle: UiTypography.body2r.textSecondary,
|
hintStyle: UiTypography.body2r.textSecondary,
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
@@ -205,11 +172,17 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildTabButton(t.client_billing.workers_tab.needs_review(count: 0), 0),
|
child: _buildTabButton(
|
||||||
|
t.client_billing.workers_tab.needs_review(count: 0),
|
||||||
|
0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: UiConstants.space3),
|
const SizedBox(width: UiConstants.space3),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildTabButton(t.client_billing.workers_tab.all(count: invoice.workersCount), 1),
|
child: _buildTabButton(
|
||||||
|
t.client_billing.workers_tab.all(count: invoice.workersCount),
|
||||||
|
1,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -226,7 +199,9 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isSelected ? const Color(0xFF2563EB) : Colors.white,
|
color: isSelected ? const Color(0xFF2563EB) : Colors.white,
|
||||||
borderRadius: UiConstants.radiusMd,
|
borderRadius: UiConstants.radiusMd,
|
||||||
border: Border.all(color: isSelected ? const Color(0xFF2563EB) : UiColors.border),
|
border: Border.all(
|
||||||
|
color: isSelected ? const Color(0xFF2563EB) : UiColors.border,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -257,24 +232,44 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
radius: 20,
|
radius: 20,
|
||||||
backgroundColor: UiColors.bgSecondary,
|
backgroundColor: UiColors.bgSecondary,
|
||||||
backgroundImage: worker.workerAvatarUrl != null ? NetworkImage(worker.workerAvatarUrl!) : null,
|
backgroundImage: worker.workerAvatarUrl != null
|
||||||
child: worker.workerAvatarUrl == null ? const Icon(UiIcons.user, size: 20, color: UiColors.iconSecondary) : null,
|
? NetworkImage(worker.workerAvatarUrl!)
|
||||||
|
: null,
|
||||||
|
child: worker.workerAvatarUrl == null
|
||||||
|
? const Icon(
|
||||||
|
UiIcons.user,
|
||||||
|
size: 20,
|
||||||
|
color: UiColors.iconSecondary,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
const SizedBox(width: UiConstants.space3),
|
const SizedBox(width: UiConstants.space3),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(worker.workerName, style: UiTypography.body1b.textPrimary),
|
Text(
|
||||||
Text(worker.roleName, style: UiTypography.footnote2r.textSecondary),
|
worker.workerName,
|
||||||
|
style: UiTypography.body1b.textPrimary,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
worker.roleName,
|
||||||
|
style: UiTypography.footnote2r.textSecondary,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text('\$${worker.totalAmount.toStringAsFixed(2)}', style: UiTypography.body1b.textPrimary),
|
Text(
|
||||||
Text('${worker.hours}h x \$${worker.rate.toStringAsFixed(2)}/hr', style: UiTypography.footnote2r.textSecondary),
|
'\$${worker.totalAmount.toStringAsFixed(2)}',
|
||||||
|
style: UiTypography.body1b.textPrimary,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${worker.hours}h x \$${worker.rate.toStringAsFixed(2)}/hr',
|
||||||
|
style: UiTypography.footnote2r.textSecondary,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -283,17 +278,26 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: UiConstants.radiusMd,
|
borderRadius: UiConstants.radiusMd,
|
||||||
border: Border.all(color: UiColors.border),
|
border: Border.all(color: UiColors.border),
|
||||||
),
|
),
|
||||||
child: Text('${worker.startTime} - ${worker.endTime}', style: UiTypography.footnote2b.textPrimary),
|
child: Text(
|
||||||
|
'${worker.startTime} - ${worker.endTime}',
|
||||||
|
style: UiTypography.footnote2b.textPrimary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: UiConstants.space2),
|
const SizedBox(width: UiConstants.space2),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: UiConstants.radiusMd,
|
borderRadius: UiConstants.radiusMd,
|
||||||
@@ -301,22 +305,23 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(UiIcons.coffee, size: 12, color: UiColors.iconSecondary),
|
const Icon(
|
||||||
|
UiIcons.coffee,
|
||||||
|
size: 12,
|
||||||
|
color: UiColors.iconSecondary,
|
||||||
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text('${worker.breakMinutes} ${t.client_billing.workers_tab.min_break}', style: UiTypography.footnote2r.textSecondary),
|
Text(
|
||||||
|
'${worker.breakMinutes} ${t.client_billing.workers_tab.min_break}',
|
||||||
|
style: UiTypography.footnote2r.textSecondary,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
UiIconButton.secondary(
|
UiIconButton.secondary(icon: UiIcons.edit, onTap: () {}),
|
||||||
icon: UiIcons.edit,
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
const SizedBox(width: UiConstants.space2),
|
const SizedBox(width: UiConstants.space2),
|
||||||
UiIconButton.secondary(
|
UiIconButton.secondary(icon: UiIcons.warning, onTap: () {}),
|
||||||
icon: UiIcons.warning,
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -333,9 +338,15 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
text: t.client_billing.actions.approve_pay,
|
text: t.client_billing.actions.approve_pay,
|
||||||
leadingIcon: UiIcons.checkCircle,
|
leadingIcon: UiIcons.checkCircle,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Modular.get<BillingBloc>().add(BillingInvoiceApproved(invoice.id));
|
Modular.get<BillingBloc>().add(
|
||||||
|
BillingInvoiceApproved(invoice.id),
|
||||||
|
);
|
||||||
Modular.to.pop();
|
Modular.to.pop();
|
||||||
UiSnackbar.show(context, message: t.client_billing.approved_success, type: UiSnackbarType.success);
|
UiSnackbar.show(
|
||||||
|
context,
|
||||||
|
message: t.client_billing.approved_success,
|
||||||
|
type: UiSnackbarType.success,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
size: UiButtonSize.large,
|
size: UiButtonSize.large,
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
@@ -350,8 +361,8 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: UiConstants.radiusMd,
|
borderRadius: UiConstants.radiusMd,
|
||||||
border: Border.all(color: Colors.orange, width: 2),
|
border: Border.all(color: Colors.orange, width: 2),
|
||||||
),
|
),
|
||||||
child: UiButton.secondary(
|
child: UiButton.secondary(
|
||||||
text: t.client_billing.actions.flag_review,
|
text: t.client_billing.actions.flag_review,
|
||||||
@@ -409,7 +420,11 @@ class _ShiftCompletionReviewPageState extends State<ShiftCompletionReviewPage> {
|
|||||||
);
|
);
|
||||||
Navigator.pop(dialogContext);
|
Navigator.pop(dialogContext);
|
||||||
Modular.to.pop();
|
Modular.to.pop();
|
||||||
UiSnackbar.show(context, message: t.client_billing.flagged_success, type: UiSnackbarType.warning);
|
UiSnackbar.show(
|
||||||
|
context,
|
||||||
|
message: t.client_billing.flagged_success,
|
||||||
|
type: UiSnackbarType.warning,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(t.client_billing.flag_dialog.button),
|
child: Text(t.client_billing.flag_dialog.button),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:design_system/design_system.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_modular/flutter_modular.dart';
|
import 'package:flutter_modular/flutter_modular.dart';
|
||||||
|
|
||||||
import '../blocs/billing_bloc.dart';
|
import '../blocs/billing_bloc.dart';
|
||||||
import '../blocs/billing_event.dart';
|
import '../blocs/billing_event.dart';
|
||||||
import '../blocs/billing_state.dart';
|
import '../blocs/billing_state.dart';
|
||||||
@@ -14,7 +15,7 @@ class InvoiceReadyPage extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider<BillingBloc>.value(
|
return BlocProvider<BillingBloc>.value(
|
||||||
value: Modular.get<BillingBloc>()..add(const BillingLoadStarted()),
|
value: Modular.get<BillingBloc>()..add(const BillingLoadStarted()),
|
||||||
child: const InvoiceReadyView(),
|
child: const Placeholder(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,13 +26,7 @@ class InvoiceReadyView extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: const UiAppBar(title: 'Invoices Ready', showBackButton: true),
|
||||||
title: const Text('Invoices Ready'),
|
|
||||||
leading: UiIconButton.secondary(
|
|
||||||
icon: UiIcons.arrowLeft,
|
|
||||||
onTap: () => Modular.to.pop(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: BlocBuilder<BillingBloc, BillingState>(
|
body: BlocBuilder<BillingBloc, BillingState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state.status == BillingStatus.loading) {
|
if (state.status == BillingStatus.loading) {
|
||||||
@@ -43,12 +38,16 @@ class InvoiceReadyView extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(UiIcons.file, size: 64, color: UiColors.iconSecondary),
|
const Icon(
|
||||||
const SizedBox(height: UiConstants.space4),
|
UiIcons.file,
|
||||||
Text(
|
size: 64,
|
||||||
'No invoices ready yet',
|
color: UiColors.iconSecondary,
|
||||||
style: UiTypography.body1m.textSecondary,
|
),
|
||||||
),
|
const SizedBox(height: UiConstants.space4),
|
||||||
|
Text(
|
||||||
|
'No invoices ready yet',
|
||||||
|
style: UiTypography.body1m.textSecondary,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -96,26 +95,31 @@ class _InvoiceSummaryCard extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: UiColors.success.withValues(alpha: 0.1),
|
color: UiColors.success.withValues(alpha: 0.1),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
'READY',
|
'READY',
|
||||||
style: UiTypography.titleUppercase4b.copyWith(color: UiColors.success),
|
style: UiTypography.titleUppercase4b.copyWith(
|
||||||
|
color: UiColors.success,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(invoice.date, style: UiTypography.footnote2r.textTertiary),
|
||||||
invoice.date,
|
|
||||||
style: UiTypography.footnote2r.textTertiary,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(invoice.title, style: UiTypography.title2b.textPrimary),
|
Text(invoice.title, style: UiTypography.title2b.textPrimary),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(invoice.locationAddress, style: UiTypography.body2r.textSecondary),
|
Text(
|
||||||
|
invoice.locationAddress,
|
||||||
|
style: UiTypography.body2r.textSecondary,
|
||||||
|
),
|
||||||
const Divider(height: 32),
|
const Divider(height: 32),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -123,8 +127,14 @@ class _InvoiceSummaryCard extends StatelessWidget {
|
|||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text('TOTAL AMOUNT', style: UiTypography.titleUppercase4m.textSecondary),
|
Text(
|
||||||
Text('\$${invoice.totalAmount.toStringAsFixed(2)}', style: UiTypography.title2b.primary),
|
'TOTAL AMOUNT',
|
||||||
|
style: UiTypography.titleUppercase4m.textSecondary,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'\$${invoice.totalAmount.toStringAsFixed(2)}',
|
||||||
|
style: UiTypography.title2b.primary,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
UiButton.primary(
|
UiButton.primary(
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class ActionsWidget extends StatelessWidget {
|
|||||||
title: i18n.rapid,
|
title: i18n.rapid,
|
||||||
subtitle: i18n.rapid_subtitle,
|
subtitle: i18n.rapid_subtitle,
|
||||||
icon: UiIcons.zap,
|
icon: UiIcons.zap,
|
||||||
color: UiColors.tagError,
|
color: UiColors.tagError.withValues(alpha: 0.5),
|
||||||
borderColor: UiColors.borderError.withValues(alpha: 0.3),
|
borderColor: UiColors.borderError.withValues(alpha: 0.3),
|
||||||
iconBgColor: UiColors.white,
|
iconBgColor: UiColors.white,
|
||||||
iconColor: UiColors.textError,
|
iconColor: UiColors.textError,
|
||||||
|
|||||||
@@ -12,18 +12,16 @@ class UiOrderType {
|
|||||||
|
|
||||||
/// Order type constants for the create order feature
|
/// Order type constants for the create order feature
|
||||||
const List<UiOrderType> orderTypes = <UiOrderType>[
|
const List<UiOrderType> orderTypes = <UiOrderType>[
|
||||||
/// TODO: FEATURE_NOT_YET_IMPLEMENTED
|
UiOrderType(
|
||||||
// UiOrderType(
|
id: 'rapid',
|
||||||
// id: 'rapid',
|
titleKey: 'client_create_order.types.rapid',
|
||||||
// titleKey: 'client_create_order.types.rapid',
|
descriptionKey: 'client_create_order.types.rapid_desc',
|
||||||
// descriptionKey: 'client_create_order.types.rapid_desc',
|
),
|
||||||
// ),
|
|
||||||
UiOrderType(
|
UiOrderType(
|
||||||
id: 'one-time',
|
id: 'one-time',
|
||||||
titleKey: 'client_create_order.types.one_time',
|
titleKey: 'client_create_order.types.one_time',
|
||||||
descriptionKey: 'client_create_order.types.one_time_desc',
|
descriptionKey: 'client_create_order.types.one_time_desc',
|
||||||
),
|
),
|
||||||
|
|
||||||
UiOrderType(
|
UiOrderType(
|
||||||
id: 'recurring',
|
id: 'recurring',
|
||||||
titleKey: 'client_create_order.types.recurring',
|
titleKey: 'client_create_order.types.recurring',
|
||||||
|
|||||||
Reference in New Issue
Block a user