wip: buat input component lib
# besok lanjut forms library (reactive form)
This commit is contained in:
parent
47c9386eb2
commit
c9e784fb73
6
makefile
6
makefile
|
@ -2,6 +2,12 @@ PACKAGES := $(wildcard packages/*)
|
||||||
FEATURES := $(wildcard packages/features/*)
|
FEATURES := $(wildcard packages/features/*)
|
||||||
BUILD-RUNNER := packages/golektruk_api
|
BUILD-RUNNER := packages/golektruk_api
|
||||||
|
|
||||||
|
run:
|
||||||
|
flutter run lib/main.dart
|
||||||
|
|
||||||
|
story:
|
||||||
|
flutter run packages/component_library/example/main.dart
|
||||||
|
|
||||||
intl:
|
intl:
|
||||||
flutter gen-l10n
|
flutter gen-l10n
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,57 @@
|
||||||
import 'package:component_library/component_library.dart';
|
import 'package:component_library/component_library.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:storybook_flutter/storybook_flutter.dart';
|
import 'package:storybook_flutter/storybook_flutter.dart';
|
||||||
|
|
||||||
List<Story> getStories(GolekThemeData theme) {
|
List<Story> getStories(GolekThemeData theme) {
|
||||||
return [
|
return [
|
||||||
|
Story(
|
||||||
|
name: 'Plain Input Field',
|
||||||
|
section: 'Form Input',
|
||||||
|
builder: (_, k) => InputField(
|
||||||
|
errorMessage: k.text(label: 'errorMessage'),
|
||||||
|
placeholder: k.text(
|
||||||
|
label: 'placeholder',
|
||||||
|
initial: 'Placeholder',
|
||||||
|
),
|
||||||
|
label: k.text(label: 'Label', initial: 'Label'),
|
||||||
|
obscureText: k.boolean(label: 'obscureText', initial: false),
|
||||||
|
textInputType: k.options<TextInputType>(
|
||||||
|
label: 'textInputType',
|
||||||
|
initial: TextInputType.text,
|
||||||
|
options: [
|
||||||
|
const Option('Email', TextInputType.emailAddress),
|
||||||
|
const Option('Number', TextInputType.number),
|
||||||
|
const Option('Date Time', TextInputType.datetime),
|
||||||
|
]),
|
||||||
|
inputFormatters: k.options<List<TextInputFormatter>>(
|
||||||
|
label: 'inputFormatters',
|
||||||
|
initial: [],
|
||||||
|
options: [
|
||||||
|
Option(
|
||||||
|
'Maximum Text Input Formatter',
|
||||||
|
[LengthLimitingTextInputFormatter(12)],
|
||||||
|
),
|
||||||
|
Option(
|
||||||
|
'Regex Filter Text Input Formatter',
|
||||||
|
[FilteringTextInputFormatter.allow(RegExp(r'^[2-9][0-9]*'))],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
isDisabled: k.boolean(
|
||||||
|
label: 'disabled',
|
||||||
|
initial: false,
|
||||||
|
),
|
||||||
|
isTouched: k.boolean(
|
||||||
|
label: 'touched',
|
||||||
|
initial: false,
|
||||||
|
),
|
||||||
|
isError: k.boolean(
|
||||||
|
label: 'error',
|
||||||
|
initial: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Story.simple(
|
Story.simple(
|
||||||
name: 'Simple Expanded Elevated Button',
|
name: 'Simple Expanded Elevated Button',
|
||||||
section: 'Buttons',
|
section: 'Buttons',
|
||||||
|
@ -27,7 +75,7 @@ List<Story> getStories(GolekThemeData theme) {
|
||||||
? () {}
|
? () {}
|
||||||
: null,
|
: null,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
k.options(
|
k.options<IconData>(
|
||||||
label: 'icon',
|
label: 'icon',
|
||||||
initial: Icons.home,
|
initial: Icons.home,
|
||||||
options: const [
|
options: const [
|
||||||
|
@ -58,247 +106,5 @@ List<Story> getStories(GolekThemeData theme) {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Story(
|
|
||||||
name: 'InProgress Text Button',
|
|
||||||
section: 'Buttons',
|
|
||||||
builder: (_, k) => InProgressTextButton(
|
|
||||||
label: k.text(
|
|
||||||
label: 'label',
|
|
||||||
initial: 'Processing',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Story(
|
|
||||||
name: 'Favorite Button',
|
|
||||||
section: 'Buttons',
|
|
||||||
builder: (_, k) => FavoriteIconButton(
|
|
||||||
onTap: () {},
|
|
||||||
isFavorite: k.boolean(
|
|
||||||
label: 'isFavorite',
|
|
||||||
initial: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Story.simple(
|
|
||||||
name: 'Share Icon Button',
|
|
||||||
section: 'Buttons',
|
|
||||||
child: ShareIconButton(onTap: () {}),
|
|
||||||
),
|
|
||||||
Story(
|
|
||||||
name: 'Count Indicator Icon Button',
|
|
||||||
section: 'Count Indicator Buttons',
|
|
||||||
builder: (_, k) => CountIndicatorIconButton(
|
|
||||||
count: k.sliderInt(
|
|
||||||
label: 'count',
|
|
||||||
),
|
|
||||||
iconData: k.options(
|
|
||||||
label: 'iconData',
|
|
||||||
initial: Icons.arrow_upward,
|
|
||||||
options: const [
|
|
||||||
Option(
|
|
||||||
'Upward',
|
|
||||||
Icons.arrow_upward,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Downward',
|
|
||||||
Icons.arrow_downward,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
tooltip: k.text(
|
|
||||||
label: 'tooltip',
|
|
||||||
initial: 'Count indicator',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Story(
|
|
||||||
name: 'Exception Indicator',
|
|
||||||
section: 'Indicators',
|
|
||||||
builder: (_, k) => ExceptionIndicator(
|
|
||||||
title: k.text(
|
|
||||||
label: 'title',
|
|
||||||
initial: 'Exception title',
|
|
||||||
),
|
|
||||||
message: k.text(
|
|
||||||
label: 'message',
|
|
||||||
initial: 'Exception message',
|
|
||||||
),
|
|
||||||
onTryAgain: k.boolean(
|
|
||||||
label: 'onTryAgain',
|
|
||||||
initial: false,
|
|
||||||
)
|
|
||||||
? () {}
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Story.simple(
|
|
||||||
name: 'Centered Circular Progress Indicator',
|
|
||||||
child: const CenteredCircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
Story(
|
|
||||||
name: 'Rounded Choice Chip',
|
|
||||||
padding: const EdgeInsets.all(
|
|
||||||
Spacing.medium,
|
|
||||||
),
|
|
||||||
builder: (_, k) => RoundedChoiceChip(
|
|
||||||
label: k.text(
|
|
||||||
label: 'label',
|
|
||||||
initial: 'I am a Chip!',
|
|
||||||
),
|
|
||||||
isSelected: k.boolean(
|
|
||||||
label: 'isSelected',
|
|
||||||
initial: false,
|
|
||||||
),
|
|
||||||
avatar: k.boolean(
|
|
||||||
label: 'avatar',
|
|
||||||
initial: false,
|
|
||||||
)
|
|
||||||
? Icon(
|
|
||||||
Icons.favorite,
|
|
||||||
color: theme.warningMainColor,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
onSelected: k.boolean(
|
|
||||||
label: 'onSelected',
|
|
||||||
initial: true,
|
|
||||||
)
|
|
||||||
? (_) {}
|
|
||||||
: null,
|
|
||||||
backgroundColor: k.options(
|
|
||||||
label: 'backgroundColor',
|
|
||||||
initial: null,
|
|
||||||
options: const [
|
|
||||||
Option(
|
|
||||||
'Light blue',
|
|
||||||
Colors.lightBlue,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Red accent',
|
|
||||||
Colors.redAccent,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
selectedBackgroundColor: k.options(
|
|
||||||
label: 'selectedBackgroundColor',
|
|
||||||
initial: null,
|
|
||||||
options: const [
|
|
||||||
Option(
|
|
||||||
'Green',
|
|
||||||
Colors.green,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Amber accent',
|
|
||||||
Colors.amberAccent,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
labelColor: k.options(
|
|
||||||
label: 'labelColor',
|
|
||||||
initial: null,
|
|
||||||
options: const [
|
|
||||||
Option(
|
|
||||||
'Teal',
|
|
||||||
Colors.teal,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Orange accent',
|
|
||||||
Colors.orangeAccent,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
selectedLabelColor: k.options(
|
|
||||||
label: 'selectedLabelColor',
|
|
||||||
initial: null,
|
|
||||||
options: const [
|
|
||||||
Option(
|
|
||||||
'Deep purple accent',
|
|
||||||
Colors.deepPurpleAccent,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Amber accent',
|
|
||||||
Colors.amberAccent,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Story(
|
|
||||||
name: 'Chevron List Tile',
|
|
||||||
padding: const EdgeInsets.all(
|
|
||||||
Spacing.medium,
|
|
||||||
),
|
|
||||||
builder: (_, k) => ChevronListTile(
|
|
||||||
label: k.text(
|
|
||||||
label: 'label',
|
|
||||||
initial: 'Update Profile',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Story.simple(
|
|
||||||
name: 'Search Bar',
|
|
||||||
child: const SearchBar(),
|
|
||||||
),
|
|
||||||
Story(
|
|
||||||
name: 'Shrinkable Text',
|
|
||||||
builder: (_, k) => SafeArea(
|
|
||||||
child: ShrinkableText(
|
|
||||||
k.text(
|
|
||||||
label: 'text',
|
|
||||||
initial:
|
|
||||||
'I am shrinkable text. I can resize myself automatically within a space.',
|
|
||||||
),
|
|
||||||
style: k.options(
|
|
||||||
label: 'style',
|
|
||||||
initial: theme.textStyle.copyWith(
|
|
||||||
fontSize: FontSize.style24,
|
|
||||||
),
|
|
||||||
options: [
|
|
||||||
Option(
|
|
||||||
'XX large',
|
|
||||||
theme.textStyle.copyWith(
|
|
||||||
fontSize: FontSize.style24,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Small',
|
|
||||||
theme.textStyle.copyWith(
|
|
||||||
fontSize: FontSize.style12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
textAlign: k.options(
|
|
||||||
label: 'textAlign',
|
|
||||||
initial: null,
|
|
||||||
options: const [
|
|
||||||
Option(
|
|
||||||
'Start',
|
|
||||||
TextAlign.start,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'End',
|
|
||||||
TextAlign.end,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Center',
|
|
||||||
TextAlign.center,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Justify',
|
|
||||||
TextAlign.justify,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Left',
|
|
||||||
TextAlign.left,
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
'Right',
|
|
||||||
TextAlign.right,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
// gestures. You can also use WidgetTester to find child landing_page in the widget
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
|
@ -1,21 +1,9 @@
|
||||||
export 'src/chevron_list_tile.dart';
|
|
||||||
export 'src/count_indicator_icon_button.dart';
|
|
||||||
export 'src/downvote_icon_button.dart';
|
|
||||||
export 'src/exception_indicator.dart';
|
|
||||||
export 'src/expanded_elevated_button.dart';
|
export 'src/expanded_elevated_button.dart';
|
||||||
export 'src/in_progress_text_button.dart';
|
|
||||||
export 'src/favorite_icon_button.dart';
|
|
||||||
export 'src/l10n/component_library_localizations.dart';
|
export 'src/l10n/component_library_localizations.dart';
|
||||||
export 'src/centered_circular_progress_indicator.dart';
|
|
||||||
export 'src/rounded_choice_chip.dart';
|
|
||||||
export 'src/generic_error_snack_bar.dart';
|
|
||||||
export 'src/authentication_required_error_snack_bar.dart';
|
|
||||||
export 'src/row_app_bar.dart';
|
|
||||||
export 'src/search_bar.dart';
|
|
||||||
export 'src/share_icon_button.dart';
|
|
||||||
export 'src/shrinkable_text.dart';
|
|
||||||
export 'src/styled_status_bar.dart';
|
|
||||||
export 'src/theme/font_size.dart';
|
export 'src/theme/font_size.dart';
|
||||||
export 'src/theme/spacing.dart';
|
export 'src/theme/spacing.dart';
|
||||||
export 'src/theme/golek_theme.dart';
|
export 'src/theme/golek_theme.dart';
|
||||||
export 'src/theme/golek_theme_data.dart';
|
export 'src/theme/golek_theme_data.dart';
|
||||||
|
export 'src/input_field.dart';
|
||||||
|
export 'src/error_message_builder.dart';
|
||||||
|
export 'src/favorite_icon_button.dart';
|
|
@ -1,23 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class AuthenticationRequiredErrorSnackBar extends SnackBar {
|
|
||||||
const AuthenticationRequiredErrorSnackBar({Key? key})
|
|
||||||
: super(
|
|
||||||
key: key,
|
|
||||||
content: const _AuthenticationRequiredErrorSnackBarMessage(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AuthenticationRequiredErrorSnackBarMessage extends StatelessWidget {
|
|
||||||
const _AuthenticationRequiredErrorSnackBarMessage({Key? key})
|
|
||||||
: super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final l10n = ComponentLibraryLocalizations.of(context);
|
|
||||||
return Text(
|
|
||||||
l10n.authenticationRequiredErrorSnackbarMessage,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class CenteredCircularProgressIndicator extends StatelessWidget {
|
|
||||||
const CenteredCircularProgressIndicator({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const Center(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import 'package:component_library/src/theme/font_size.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class ChevronListTile extends StatelessWidget {
|
|
||||||
const ChevronListTile({
|
|
||||||
required this.label,
|
|
||||||
this.onTap,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String label;
|
|
||||||
final VoidCallback? onTap;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(
|
|
||||||
label,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: FontSize.style18,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: const Icon(
|
|
||||||
Icons.chevron_right_outlined,
|
|
||||||
),
|
|
||||||
onTap: onTap,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class CountIndicatorIconButton extends StatelessWidget {
|
|
||||||
const CountIndicatorIconButton({
|
|
||||||
required this.count,
|
|
||||||
required this.iconData,
|
|
||||||
this.iconColor,
|
|
||||||
this.tooltip,
|
|
||||||
this.onTap,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final int count;
|
|
||||||
final IconData iconData;
|
|
||||||
final Color? iconColor;
|
|
||||||
final String? tooltip;
|
|
||||||
final VoidCallback? onTap;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return IconButton(
|
|
||||||
onPressed: onTap,
|
|
||||||
tooltip: tooltip,
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
icon: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
iconData,
|
|
||||||
color: iconColor,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
count.toString(),
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: FontSize.style12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class DownvoteIconButton extends StatelessWidget {
|
|
||||||
const DownvoteIconButton({
|
|
||||||
required this.count,
|
|
||||||
required this.isDownvoted,
|
|
||||||
this.onTap,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final int count;
|
|
||||||
final VoidCallback? onTap;
|
|
||||||
final bool isDownvoted;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final l10n = ComponentLibraryLocalizations.of(context);
|
|
||||||
final theme = GolekTheme.of(context);
|
|
||||||
return CountIndicatorIconButton(
|
|
||||||
onTap: onTap,
|
|
||||||
tooltip: l10n.downvoteIconButtonTooltip,
|
|
||||||
iconData: Icons.arrow_downward_sharp,
|
|
||||||
iconColor:
|
|
||||||
isDownvoted ? theme.warningMainColor : theme.neutral20Color,
|
|
||||||
count: count,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import 'package:component_library/component_library.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ErrorMessageBuilder extends StatelessWidget {
|
||||||
|
const ErrorMessageBuilder({
|
||||||
|
Key? key,
|
||||||
|
required this.inputLabel,
|
||||||
|
required this.messageError,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
/// input label ditampilkan title ketika error
|
||||||
|
final String inputLabel;
|
||||||
|
/// pesan error yang ditampilkan
|
||||||
|
final String messageError;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = GolekTheme.of(context);
|
||||||
|
|
||||||
|
return Text(
|
||||||
|
messageError,
|
||||||
|
style: theme.textStyle.copyWith(
|
||||||
|
fontSize: FontSize.style12,
|
||||||
|
color: theme.dangerMainColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,67 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class ExceptionIndicator extends StatelessWidget {
|
|
||||||
const ExceptionIndicator({
|
|
||||||
this.title,
|
|
||||||
this.message,
|
|
||||||
this.onTryAgain,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String? title;
|
|
||||||
final String? message;
|
|
||||||
final VoidCallback? onTryAgain;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final l10n = ComponentLibraryLocalizations.of(context);
|
|
||||||
return Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 32,
|
|
||||||
horizontal: 16,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.error,
|
|
||||||
size: 48,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: Spacing.xxLarge,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
title ?? l10n.exceptionIndicatorGenericTitle,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: FontSize.style16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
title ?? l10n.exceptionIndicatorGenericMessage,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
if (onTryAgain != null)
|
|
||||||
const SizedBox(
|
|
||||||
height: Spacing.xxxLarge,
|
|
||||||
),
|
|
||||||
if (onTryAgain != null)
|
|
||||||
ExpandedElevatedButton(
|
|
||||||
onTap: onTryAgain,
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.refresh,
|
|
||||||
),
|
|
||||||
label: l10n.exceptionIndicatorTryAgainButton,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class GenericErrorSnackBar extends SnackBar {
|
|
||||||
const GenericErrorSnackBar({Key? key})
|
|
||||||
: super(
|
|
||||||
key: key,
|
|
||||||
content: const _GenericErrorSnackBarMessage(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _GenericErrorSnackBarMessage extends StatelessWidget {
|
|
||||||
const _GenericErrorSnackBarMessage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final l10n = ComponentLibraryLocalizations.of(context);
|
|
||||||
return Text(
|
|
||||||
l10n.genericErrorSnackbarMessage,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class InProgressTextButton extends StatelessWidget {
|
|
||||||
const InProgressTextButton({
|
|
||||||
required this.label,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String label;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return TextButton.icon(
|
|
||||||
icon: Transform.scale(
|
|
||||||
scale: 0.5,
|
|
||||||
child: const CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
label: Text(
|
|
||||||
label,
|
|
||||||
),
|
|
||||||
onPressed: null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:component_library/component_library.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'error_message_builder.dart';
|
||||||
|
|
||||||
|
class InputField<T> extends StatefulWidget {
|
||||||
|
final String? label;
|
||||||
|
final String placeholder;
|
||||||
|
final Widget? suffixIcon;
|
||||||
|
final Widget? suffix;
|
||||||
|
final Widget? prefix;
|
||||||
|
final Widget? prefixIcon;
|
||||||
|
final String? errorMessage;
|
||||||
|
final bool obscureText;
|
||||||
|
final TextInputType textInputType;
|
||||||
|
final List<TextInputFormatter>? inputFormatters;
|
||||||
|
final bool isDisabled;
|
||||||
|
final bool isTouched;
|
||||||
|
final bool isError;
|
||||||
|
|
||||||
|
const InputField({
|
||||||
|
Key? key,
|
||||||
|
required this.placeholder,
|
||||||
|
this.label,
|
||||||
|
this.suffixIcon,
|
||||||
|
this.suffix,
|
||||||
|
this.prefix,
|
||||||
|
this.prefixIcon,
|
||||||
|
this.obscureText = false,
|
||||||
|
this.textInputType = TextInputType.text,
|
||||||
|
this.inputFormatters = const [],
|
||||||
|
this.errorMessage,
|
||||||
|
required this.isDisabled,
|
||||||
|
required this.isTouched,
|
||||||
|
required this.isError,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InputField> createState() => _InputFieldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InputFieldState extends State<InputField> {
|
||||||
|
bool _hasFocus = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = GolekTheme.of(context);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (widget.label != null && widget.label?.isEmpty == true) ...[
|
||||||
|
Text(
|
||||||
|
widget.label!,
|
||||||
|
style: theme.textStyle.copyWith(fontSize: FontSize.style14),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Focus(
|
||||||
|
onFocusChange: (value) {
|
||||||
|
setState(() => _hasFocus = value);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 52,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color:
|
||||||
|
_hasFocus ? theme.successBorderColor : Colors.transparent,
|
||||||
|
width: 3,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
inputFormatters: widget.inputFormatters,
|
||||||
|
keyboardType: widget.textInputType,
|
||||||
|
obscureText: widget.obscureText,
|
||||||
|
selectionHeightStyle: BoxHeightStyle.strut,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 9.5,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
counterText: '',
|
||||||
|
fillColor: widget.isDisabled
|
||||||
|
? const Color(0xffededed)
|
||||||
|
: Colors.transparent,
|
||||||
|
filled: true,
|
||||||
|
prefix: widget.prefix,
|
||||||
|
prefixIcon: widget.prefixIcon,
|
||||||
|
suffix: widget.suffix,
|
||||||
|
suffixIcon: widget.suffixIcon,
|
||||||
|
errorStyle: theme.textStyle.copyWith(
|
||||||
|
fontSize: 0,
|
||||||
|
),
|
||||||
|
prefixIconConstraints: const BoxConstraints(
|
||||||
|
minHeight: 24,
|
||||||
|
minWidth: 40,
|
||||||
|
),
|
||||||
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: BorderSide(color: theme.primaryBorderColor),
|
||||||
|
),
|
||||||
|
label: Text(
|
||||||
|
widget.placeholder,
|
||||||
|
style: theme.textStyle.copyWith(
|
||||||
|
fontSize: FontSize.style14,
|
||||||
|
color: widget.isTouched && widget.isError
|
||||||
|
? theme.dangerMainColor
|
||||||
|
: theme.neutral70Color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
),
|
||||||
|
style: theme.textStyle.copyWith(fontSize: FontSize.style14),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ErrorMessageBuilder(
|
||||||
|
inputLabel: widget.label ?? '',
|
||||||
|
messageError: widget.errorMessage ?? '',
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class RoundedChoiceChip extends StatelessWidget {
|
|
||||||
const RoundedChoiceChip({
|
|
||||||
required this.label,
|
|
||||||
required this.isSelected,
|
|
||||||
this.avatar,
|
|
||||||
this.labelColor,
|
|
||||||
this.selectedLabelColor,
|
|
||||||
this.backgroundColor,
|
|
||||||
this.selectedBackgroundColor,
|
|
||||||
this.onSelected,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String label;
|
|
||||||
final Widget? avatar;
|
|
||||||
final ValueChanged<bool>? onSelected;
|
|
||||||
final Color? labelColor;
|
|
||||||
final Color? selectedLabelColor;
|
|
||||||
final Color? backgroundColor;
|
|
||||||
final Color? selectedBackgroundColor;
|
|
||||||
final bool isSelected;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final theme = GolekTheme.of(context);
|
|
||||||
return ChoiceChip(
|
|
||||||
shape: const StadiumBorder(
|
|
||||||
side: BorderSide(),
|
|
||||||
),
|
|
||||||
avatar: avatar,
|
|
||||||
label: Text(
|
|
||||||
label,
|
|
||||||
style: TextStyle(
|
|
||||||
color: isSelected
|
|
||||||
? (selectedLabelColor ?? theme.primaryMainColor)
|
|
||||||
: (labelColor ?? theme.primarySurfaceColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onSelected: onSelected,
|
|
||||||
selected: isSelected,
|
|
||||||
backgroundColor:
|
|
||||||
(backgroundColor ?? theme.primaryMainColor),
|
|
||||||
selectedColor: (selectedBackgroundColor ??
|
|
||||||
theme.primarySurfaceColor),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:component_library/src/theme/spacing.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class RowAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|
||||||
const RowAppBar({
|
|
||||||
Key? key,
|
|
||||||
this.children = const [],
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final List<Widget> children;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return SafeArea(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: Spacing.small,
|
|
||||||
left: Spacing.small,
|
|
||||||
right: Spacing.small,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
const BackButton(),
|
|
||||||
...children,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class SearchBar extends StatelessWidget {
|
|
||||||
const SearchBar({
|
|
||||||
this.controller,
|
|
||||||
this.onChanged,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final TextEditingController? controller;
|
|
||||||
final ValueChanged<String>? onChanged;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final l10n = ComponentLibraryLocalizations.of(context);
|
|
||||||
return TextField(
|
|
||||||
controller: controller,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
suffixIcon: const Icon(
|
|
||||||
Icons.search,
|
|
||||||
),
|
|
||||||
hintText: l10n.searchBarHintText,
|
|
||||||
labelText: l10n.searchBarLabelText,
|
|
||||||
),
|
|
||||||
onChanged: onChanged,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
import 'package:component_library/component_library.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class ShareIconButton extends StatelessWidget {
|
|
||||||
const ShareIconButton({
|
|
||||||
Key? key,
|
|
||||||
this.onTap,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final VoidCallback? onTap;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final l10n = ComponentLibraryLocalizations.of(context);
|
|
||||||
return IconButton(
|
|
||||||
onPressed: onTap,
|
|
||||||
tooltip: l10n.shareIconButtonTooltip,
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.share,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class ShrinkableText extends StatelessWidget {
|
|
||||||
const ShrinkableText(
|
|
||||||
this.data, {
|
|
||||||
this.style,
|
|
||||||
this.textAlign = TextAlign.center,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String data;
|
|
||||||
final TextStyle? style;
|
|
||||||
final TextAlign? textAlign;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AutoSizeText(
|
|
||||||
data,
|
|
||||||
style: style,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
// Useful for changing the status bar color when the screen doesn't have an
|
|
||||||
// AppBar. For screens with AppBars, please use the [] property.
|
|
||||||
class StyledStatusBar extends StatelessWidget {
|
|
||||||
const StyledStatusBar._({
|
|
||||||
required this.child,
|
|
||||||
required this.style,
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
const StyledStatusBar.light({
|
|
||||||
required Widget child,
|
|
||||||
Key? key,
|
|
||||||
}) : this._(
|
|
||||||
child: child,
|
|
||||||
style: SystemUiOverlayStyle.light,
|
|
||||||
key: key,
|
|
||||||
);
|
|
||||||
|
|
||||||
const StyledStatusBar.dark({
|
|
||||||
required Widget child,
|
|
||||||
Key? key,
|
|
||||||
}) : this._(
|
|
||||||
child: child,
|
|
||||||
style: SystemUiOverlayStyle.dark,
|
|
||||||
key: key,
|
|
||||||
);
|
|
||||||
|
|
||||||
final Widget child;
|
|
||||||
final SystemUiOverlayStyle style;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
|
||||||
value: style,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -117,6 +117,60 @@ class LightGolekThemeData extends GolekThemeData {
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
primarySwatch: Colors.black.toMaterialColor(),
|
primarySwatch: Colors.black.toMaterialColor(),
|
||||||
dividerTheme: _dividerThemeData,
|
dividerTheme: _dividerThemeData,
|
||||||
|
backgroundColor: neutral10Color,
|
||||||
|
appBarTheme: const AppBarTheme(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
elevation: 0,
|
||||||
|
),
|
||||||
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
backgroundColor: primaryMainColor,
|
||||||
|
side: const BorderSide(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
primaryColor: primaryMainColor,
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
errorStyle: const TextStyle(fontSize: 0, height: 1),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: BorderSide(color: neutral50Color),
|
||||||
|
),
|
||||||
|
disabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: BorderSide(color: neutral50Color),
|
||||||
|
),
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: BorderSide(color: neutral50Color),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: primaryBorderColor,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
hintStyle: textStyle.copyWith(
|
||||||
|
fontSize: FontSize.style14,
|
||||||
|
color: neutral70Color,
|
||||||
|
),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||||
|
),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
primary: primaryMainColor, // header background color
|
||||||
|
onSurface: secondaryMainColor, // body text color
|
||||||
|
),
|
||||||
|
textButtonTheme: TextButtonThemeData(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor: primaryMainColor, // button text color
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -219,13 +273,13 @@ class LightGolekThemeData extends GolekThemeData {
|
||||||
Color get successPressedColor => const Color(0xff18D48C);
|
Color get successPressedColor => const Color(0xff18D48C);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get successSurfaceColor => const Color(0xffECFFF8);
|
Color get successSurfaceColor => const Color(0xffECFFF8);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get tertiaryBorderColor => const Color(0xffDCE6F6);
|
Color get tertiaryBorderColor => const Color(0xffDCE6F6);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get tertiaryFocusColor => const Color.fromRGBO(198, 207, 221, 0.2);
|
Color get tertiaryFocusColor => const Color.fromRGBO(198, 207, 221, 0.2);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get tertiaryHoverColor => const Color(0xffB0B8C5);
|
Color get tertiaryHoverColor => const Color(0xffB0B8C5);
|
||||||
|
@ -237,22 +291,22 @@ class LightGolekThemeData extends GolekThemeData {
|
||||||
Color get tertiaryPressedColor => const Color(0xff9AA1AC);
|
Color get tertiaryPressedColor => const Color(0xff9AA1AC);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get tertiarySurfaceColor =>const Color(0xffF5F5F5);
|
Color get tertiarySurfaceColor => const Color(0xffF5F5F5);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get warningBorderColor => const Color(0xffFFF9CF);
|
Color get warningBorderColor => const Color(0xffFFF9CF);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get warningHoverColor => const Color(0xffFEE31A);
|
Color get warningHoverColor => const Color(0xffFEE31A);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get warningMainColor => const Color(0xffFFEE6E);
|
Color get warningMainColor => const Color(0xffFFEE6E);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get warningPressedColor => const Color(0xffCBB511);
|
Color get warningPressedColor => const Color(0xffCBB511);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color get warningSurfaceColor => const Color(0xffFFFCE2);
|
Color get warningSurfaceColor => const Color(0xffFFFCE2);
|
||||||
}
|
}
|
||||||
|
|
||||||
class DarkGolekThemeData extends GolekThemeData {
|
class DarkGolekThemeData extends GolekThemeData {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
|
@ -1,7 +1,6 @@
|
||||||
import 'package:component_library/component_library.dart';
|
import 'package:component_library/component_library.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'landing_page/landing_app_bar.dart';
|
||||||
import 'package:landing_menu/src/widgets/landing_app_bar.dart';
|
|
||||||
|
|
||||||
class LandingPage extends StatefulWidget {
|
class LandingPage extends StatefulWidget {
|
||||||
const LandingPage({Key? key}) : super(key: key);
|
const LandingPage({Key? key}) : super(key: key);
|
||||||
|
@ -57,7 +56,8 @@ class _LandingPageState extends State<LandingPage> {
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'assets/images/truckershipper.png',
|
'assets/trucker_shipper.png',
|
||||||
|
package: 'features/landing_menu',
|
||||||
width: 300,
|
width: 300,
|
||||||
height: 200,
|
height: 200,
|
||||||
),
|
),
|
||||||
|
@ -94,7 +94,7 @@ class _LandingPageState extends State<LandingPage> {
|
||||||
onClickInfo: () => {},
|
onClickInfo: () => {},
|
||||||
label: 'Cari Truk',
|
label: 'Cari Truk',
|
||||||
description: 'Pengirim Muatan',
|
description: 'Pengirim Muatan',
|
||||||
assets: 'assets/images/box_shipper.png',
|
assets: 'assets/box_shipper.png',
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 14),
|
const SizedBox(width: 14),
|
||||||
|
@ -102,7 +102,7 @@ class _LandingPageState extends State<LandingPage> {
|
||||||
onClickInfo: () => {},
|
onClickInfo: () => {},
|
||||||
label: 'Cari Muatan',
|
label: 'Cari Muatan',
|
||||||
description: 'Penyedia Angkutan',
|
description: 'Penyedia Angkutan',
|
||||||
assets: 'assets/images/truk_trucker.png',
|
assets: 'assets/truk_trucker.png',
|
||||||
onTap: () async {},
|
onTap: () async {},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -173,7 +173,7 @@ class CardProduct extends StatelessWidget {
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Image(
|
Image(
|
||||||
image: AssetImage(assets),
|
image: AssetImage(assets, package: 'features/landing_menu'),
|
||||||
width: 131,
|
width: 131,
|
||||||
height: 100,
|
height: 100,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
|
|
|
@ -11,6 +11,7 @@ class LandingAppBar extends StatelessWidget with PreferredSizeWidget {
|
||||||
final theme = GolekTheme.of(context);
|
final theme = GolekTheme.of(context);
|
||||||
|
|
||||||
return AppBar(
|
return AppBar(
|
||||||
|
elevation: 0,
|
||||||
backgroundColor: theme.primaryMainColor,
|
backgroundColor: theme.primaryMainColor,
|
||||||
actions: [
|
actions: [
|
||||||
CompositedTransformTarget(
|
CompositedTransformTarget(
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
// utility that Flutter provides. For example, you can send tap and scroll
|
// utility that Flutter provides. For example, you can send tap and scroll
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
// gestures. You can also use WidgetTester to find child landing_page in the widget
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
// utility that Flutter provides. For example, you can send tap and scroll
|
// utility that Flutter provides. For example, you can send tap and scroll
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
// gestures. You can also use WidgetTester to find child landing_page in the widget
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
|
@ -34,3 +34,5 @@ dev_dependencies:
|
||||||
build_runner: ^2.3.2
|
build_runner: ^2.3.2
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
assets:
|
||||||
|
- packages/features/landing_menu/assets/
|
Loading…
Reference in New Issue