update theme

This commit is contained in:
Phuoc Nguyen
2025-12-02 15:20:54 +07:00
parent 12bd70479c
commit 49a41d24eb
78 changed files with 3263 additions and 2756 deletions

View File

@@ -131,26 +131,28 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
backgroundColor: colorScheme.surfaceContainerLowest,
appBar: AppBar(
leading: IconButton(
icon: const FaIcon(
icon: FaIcon(
FontAwesomeIcons.arrowLeft,
color: Colors.black,
color: colorScheme.onSurface,
size: 20,
),
onPressed: () => Navigator.of(context).pop(),
),
title: Text(
isEditing ? 'Chỉnh sửa Dự án' : 'Đăng ký Công trình',
style: const TextStyle(color: Colors.black),
style: TextStyle(color: colorScheme.onSurface),
),
actions: [
IconButton(
icon: const FaIcon(
icon: FaIcon(
FontAwesomeIcons.circleInfo,
color: Colors.black,
color: colorScheme.onSurface,
size: 20,
),
onPressed: _showInfoDialog,
@@ -158,19 +160,19 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(width: AppSpacing.sm),
],
elevation: AppBarSpecs.elevation,
backgroundColor: AppColors.white,
backgroundColor: colorScheme.surface,
centerTitle: false,
),
body: _isLoadingDetail
? const Center(
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(
'Đang tải thông tin dự án...',
style: TextStyle(color: AppColors.grey500),
style: TextStyle(color: colorScheme.onSurfaceVariant),
),
],
),
@@ -181,23 +183,23 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
padding: const EdgeInsets.all(4),
children: [
// Basic Information
_buildBasicInfoCard(),
_buildBasicInfoCard(colorScheme),
const SizedBox(height: 16),
// Project Details
_buildProjectDetailsCard(),
_buildProjectDetailsCard(colorScheme),
const SizedBox(height: 16),
// Additional Information
_buildAdditionalInfoCard(),
_buildAdditionalInfoCard(colorScheme),
const SizedBox(height: 16),
// File Upload
_buildFileUploadCard(),
_buildFileUploadCard(colorScheme),
const SizedBox(height: 24),
// Submit Button
_buildSubmitButton(),
_buildSubmitButton(colorScheme),
const SizedBox(height: 40),
],
),
@@ -205,7 +207,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildBasicInfoCard() {
Widget _buildBasicInfoCard(ColorScheme colorScheme) {
return Card(
elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
@@ -214,17 +216,18 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'Thông tin cơ bản',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _projectNameController,
label: 'Tên công trình',
required: true,
@@ -233,6 +236,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _addressController,
label: 'Địa chỉ',
required: true,
@@ -242,6 +246,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _ownerController,
label: 'Chủ đầu tư',
required: true,
@@ -250,6 +255,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _designUnitController,
label: 'Đơn vị thiết kế',
hint: 'Tên đơn vị thiết kế',
@@ -257,6 +263,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _constructionUnitController,
label: 'Đơn vị thi công',
hint: 'Tên đơn vị thi công',
@@ -267,7 +274,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildProjectDetailsCard() {
Widget _buildProjectDetailsCard(ColorScheme colorScheme) {
return Card(
elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
@@ -276,17 +283,18 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'Chi tiết dự án',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _areaController,
label: 'Tổng diện tích',
required: true,
@@ -296,6 +304,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _productsController,
label: 'Sản phẩm đưa vào thiết kế',
required: true,
@@ -305,17 +314,17 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
),
const SizedBox(height: 16),
_buildProgressDropdown(),
_buildProgressDropdown(colorScheme),
const SizedBox(height: 16),
_buildExpectedDateField(),
_buildExpectedDateField(colorScheme),
],
),
),
);
}
Widget _buildAdditionalInfoCard() {
Widget _buildAdditionalInfoCard(ColorScheme colorScheme) {
return Card(
elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
@@ -324,17 +333,18 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'Thông tin bổ sung',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 16),
_buildTextField(
colorScheme: colorScheme,
controller: _descriptionController,
label: 'Mô tả công trình',
hint: 'Mô tả ngắn gọn về công trình, diện tích, đặc điểm nổi bật...',
@@ -346,7 +356,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildFileUploadCard() {
Widget _buildFileUploadCard(ColorScheme colorScheme) {
return Card(
elevation: 1,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
@@ -355,12 +365,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'Ảnh minh chứng',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 16),
@@ -374,34 +384,34 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(
color: AppColors.grey100,
color: colorScheme.surfaceContainerHighest,
width: 2,
style: BorderStyle.solid,
),
borderRadius: BorderRadius.circular(8),
),
child: const Column(
child: Column(
children: [
FaIcon(
FontAwesomeIcons.cloudArrowUp,
size: 48,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
SizedBox(height: 12),
const SizedBox(height: 12),
Text(
'Kéo thả ảnh vào đây',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
SizedBox(height: 4),
const SizedBox(height: 4),
Text(
'hoặc nhấn để chọn file',
style: TextStyle(
fontSize: 14,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
),
],
@@ -412,12 +422,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
// Existing files from API
if (_existingFiles.isNotEmpty) ...[
const SizedBox(height: 16),
const Text(
Text(
'Ảnh đã tải lên',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
),
const SizedBox(height: 8),
@@ -426,7 +436,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
final file = entry.value;
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildExistingFileItem(file, index),
child: _buildExistingFileItem(file, index, colorScheme),
);
}),
],
@@ -435,12 +445,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
if (_uploadedFiles.isNotEmpty) ...[
const SizedBox(height: 16),
if (_existingFiles.isNotEmpty)
const Text(
Text(
'Ảnh mới',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
),
if (_existingFiles.isNotEmpty) const SizedBox(height: 8),
@@ -449,17 +459,17 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
final file = entry.value;
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: _buildFileItem(file, index),
child: _buildFileItem(file, index, colorScheme),
);
}),
],
const SizedBox(height: 8),
const Text(
Text(
'Hỗ trợ: JPG, PNG, PDF. Tối đa 10MB mỗi file.',
style: TextStyle(
fontSize: 12,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
),
],
@@ -469,6 +479,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
}
Widget _buildTextField({
required ColorScheme colorScheme,
required TextEditingController controller,
required String label,
String? hint,
@@ -484,10 +495,10 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
children: [
Text(
label,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
if (required)
@@ -507,20 +518,20 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
keyboardType: keyboardType,
decoration: InputDecoration(
hintText: hint,
hintStyle: const TextStyle(color: AppColors.grey500),
hintStyle: TextStyle(color: colorScheme.onSurfaceVariant),
filled: true,
fillColor: AppColors.white,
fillColor: colorScheme.surface,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.grey100),
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.grey100),
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.primaryBlue, width: 2),
borderSide: BorderSide(color: colorScheme.primary, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
@@ -544,9 +555,9 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
const SizedBox(height: 4),
Text(
helperText,
style: const TextStyle(
style: TextStyle(
fontSize: 12,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
),
],
@@ -554,23 +565,23 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildProgressDropdown() {
Widget _buildProgressDropdown(ColorScheme colorScheme) {
final progressListAsync = ref.watch(projectProgressListProvider);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
Row(
children: [
Text(
'Tiến độ công trình',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
Text(
const Text(
' *',
style: TextStyle(
fontSize: 14,
@@ -585,14 +596,14 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
initialValue: _selectedProgress,
decoration: InputDecoration(
filled: true,
fillColor: AppColors.white,
fillColor: colorScheme.surface,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.grey100),
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.grey100),
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
@@ -621,26 +632,26 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
loading: () => Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: AppColors.white,
border: Border.all(color: AppColors.grey100),
color: colorScheme.surface,
border: Border.all(color: colorScheme.surfaceContainerHighest),
borderRadius: BorderRadius.circular(8),
),
child: const Row(
child: Row(
children: [
SizedBox(
const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
SizedBox(width: 12),
Text('Đang tải...', style: TextStyle(color: AppColors.grey500)),
const SizedBox(width: 12),
Text('Đang tải...', style: TextStyle(color: colorScheme.onSurfaceVariant)),
],
),
),
error: (error, _) => Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: AppColors.white,
color: colorScheme.surface,
border: Border.all(color: AppColors.danger),
borderRadius: BorderRadius.circular(8),
),
@@ -666,16 +677,16 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildExpectedDateField() {
Widget _buildExpectedDateField(ColorScheme colorScheme) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'Ngày dự kiến khởi công',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 8),
@@ -684,8 +695,8 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: AppColors.white,
border: Border.all(color: AppColors.grey100),
color: colorScheme.surface,
border: Border.all(color: colorScheme.surfaceContainerHighest),
borderRadius: BorderRadius.circular(8),
),
child: Row(
@@ -697,14 +708,14 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
: 'Chọn ngày',
style: TextStyle(
color: _expectedStartDate != null
? AppColors.grey900
: AppColors.grey500,
? colorScheme.onSurface
: colorScheme.onSurfaceVariant,
),
),
const FaIcon(
FaIcon(
FontAwesomeIcons.calendar,
size: 16,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
],
),
@@ -714,7 +725,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildFileItem(File file, int index) {
Widget _buildFileItem(File file, int index, ColorScheme colorScheme) {
final fileName = file.path.split('/').last;
final fileSizeInBytes = file.lengthSync();
final fileSizeInMB = (fileSizeInBytes / (1024 * 1024)).toStringAsFixed(2);
@@ -728,13 +739,13 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFF8F9FA),
color: colorScheme.surfaceContainerLowest,
border: Border.all(
color: hasError
? AppColors.danger
: isUploaded
? AppColors.success
: AppColors.grey100,
: colorScheme.surfaceContainerHighest,
),
borderRadius: BorderRadius.circular(6),
),
@@ -754,11 +765,11 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
return Container(
width: 48,
height: 48,
color: AppColors.grey100,
child: const FaIcon(
color: colorScheme.surfaceContainerHighest,
child: FaIcon(
FontAwesomeIcons.image,
size: 24,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
);
},
@@ -810,9 +821,9 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
children: [
Text(
fileName,
style: const TextStyle(
style: TextStyle(
fontWeight: FontWeight.w500,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
@@ -832,7 +843,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
? AppColors.danger
: isUploaded
? AppColors.success
: AppColors.grey500,
: colorScheme.onSurfaceVariant,
),
),
],
@@ -857,16 +868,16 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
);
}
Widget _buildExistingFileItem(ProjectFile file, int index) {
Widget _buildExistingFileItem(ProjectFile file, int index, ColorScheme colorScheme) {
final fileName = file.fileUrl.split('/').last;
final isDeleting = _deletingFileId == file.id;
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFF8F9FA),
color: colorScheme.surfaceContainerLowest,
border: Border.all(
color: isDeleting ? AppColors.grey500 : AppColors.success,
color: isDeleting ? colorScheme.onSurfaceVariant : AppColors.success,
),
borderRadius: BorderRadius.circular(6),
),
@@ -885,7 +896,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
placeholder: (context, url) => Container(
width: 48,
height: 48,
color: AppColors.grey100,
color: colorScheme.surfaceContainerHighest,
child: const Center(
child: SizedBox(
width: 16,
@@ -897,12 +908,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
errorWidget: (context, url, error) => Container(
width: 48,
height: 48,
color: AppColors.grey100,
child: const Center(
color: colorScheme.surfaceContainerHighest,
child: Center(
child: FaIcon(
FontAwesomeIcons.image,
size: 24,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
),
),
@@ -939,7 +950,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
fileName,
style: TextStyle(
fontWeight: FontWeight.w500,
color: isDeleting ? AppColors.grey500 : AppColors.grey900,
color: isDeleting ? colorScheme.onSurfaceVariant : colorScheme.onSurface,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
@@ -949,7 +960,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
isDeleting ? 'Đang xóa...' : 'Đã tải lên',
style: TextStyle(
fontSize: 12,
color: isDeleting ? AppColors.grey500 : AppColors.success,
color: isDeleting ? colorScheme.onSurfaceVariant : AppColors.success,
),
),
],
@@ -980,6 +991,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
/// Show confirmation dialog before deleting an existing file
Future<void> _showDeleteConfirmDialog(ProjectFile file) async {
final fileName = file.fileUrl.split('/').last;
final colorScheme = Theme.of(context).colorScheme;
final confirmed = await showDialog<bool>(
context: context,
@@ -1004,7 +1016,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: AppColors.grey100,
color: colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(8),
),
child: Row(
@@ -1019,12 +1031,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
placeholder: (context, url) => Container(
width: 48,
height: 48,
color: AppColors.grey100,
color: colorScheme.surfaceContainerHighest,
),
errorWidget: (context, url, error) => Container(
width: 48,
height: 48,
color: AppColors.grey100,
color: colorScheme.surfaceContainerHighest,
child: const Center(child: FaIcon(FontAwesomeIcons.image, size: 20)),
),
),
@@ -1033,9 +1045,9 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
Expanded(
child: Text(
fileName,
style: const TextStyle(
style: TextStyle(
fontSize: 13,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
@@ -1118,17 +1130,17 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
}
}
Widget _buildSubmitButton() {
Widget _buildSubmitButton(ColorScheme colorScheme) {
return SizedBox(
width: double.infinity,
height: 48,
child: ElevatedButton(
onPressed: _isSubmitting ? null : _handleSubmit,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryBlue,
foregroundColor: AppColors.white,
disabledBackgroundColor: AppColors.primaryBlue.withValues(alpha: 0.6),
disabledForegroundColor: AppColors.white,
backgroundColor: colorScheme.primary,
foregroundColor: Colors.white,
disabledBackgroundColor: colorScheme.primary.withValues(alpha: 0.6),
disabledForegroundColor: Colors.white,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
@@ -1140,7 +1152,7 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(AppColors.white),
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: const Row(

View File

@@ -20,25 +20,26 @@ class SubmissionsPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final colorScheme = Theme.of(context).colorScheme;
final submissionsAsync = ref.watch(filteredSubmissionsProvider);
final statusListAsync = ref.watch(projectStatusListProvider);
final filter = ref.watch(submissionsFilterProvider);
final selectedStatus = filter.selectedStatus;
return Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
backgroundColor: colorScheme.surfaceContainerLowest,
appBar: AppBar(
leading: IconButton(
icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
icon: FaIcon(FontAwesomeIcons.arrowLeft, color: colorScheme.onSurface, size: 20),
onPressed: () => Navigator.of(context).pop(),
),
title: const Text(
title: Text(
'Danh sách Dự án',
style: TextStyle(color: Colors.black),
style: TextStyle(color: colorScheme.onSurface),
),
actions: [
IconButton(
icon: const FaIcon(FontAwesomeIcons.plus, color: Colors.black, size: 20),
icon: FaIcon(FontAwesomeIcons.plus, color: colorScheme.onSurface, size: 20),
onPressed: () async {
final result = await context.push<bool>(RouteNames.submissionCreate);
if (result == true) {
@@ -50,7 +51,7 @@ class SubmissionsPage extends ConsumerWidget {
const SizedBox(width: AppSpacing.sm),
],
elevation: AppBarSpecs.elevation,
backgroundColor: AppColors.white,
backgroundColor: colorScheme.surface,
centerTitle: false,
),
body: Column(
@@ -61,16 +62,16 @@ class SubmissionsPage extends ConsumerWidget {
child: TextField(
decoration: InputDecoration(
hintText: 'Mã dự án hoặc tên công trình',
prefixIcon: const Icon(Icons.search, color: AppColors.grey500),
prefixIcon: Icon(Icons.search, color: colorScheme.onSurfaceVariant),
filled: true,
fillColor: AppColors.white,
fillColor: colorScheme.surface,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.grey100),
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: AppColors.grey100),
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
),
),
onChanged: (value) {
@@ -88,6 +89,7 @@ class SubmissionsPage extends ConsumerWidget {
_buildFilterChip(
context,
ref,
colorScheme,
label: 'Tất cả',
isSelected: selectedStatus == null,
onTap: () => ref.read(submissionsFilterProvider.notifier).clearStatusFilter(),
@@ -101,6 +103,7 @@ class SubmissionsPage extends ConsumerWidget {
child: _buildFilterChip(
context,
ref,
colorScheme,
label: status.label,
isSelected: selectedStatus == status.label,
onTap: () => ref.read(submissionsFilterProvider.notifier).selectStatus(status.label),
@@ -130,28 +133,28 @@ class SubmissionsPage extends ConsumerWidget {
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.5,
child: const Center(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FaIcon(
FontAwesomeIcons.folderOpen,
size: 64,
color: AppColors.grey500,
color: colorScheme.onSurfaceVariant,
),
SizedBox(height: 16),
const SizedBox(height: 16),
Text(
'Không có dự án nào',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
SizedBox(height: 8),
const SizedBox(height: 8),
Text(
'Không tìm thấy dự án phù hợp',
style: TextStyle(color: AppColors.grey500),
style: TextStyle(color: colorScheme.onSurfaceVariant),
),
],
),
@@ -171,7 +174,7 @@ class SubmissionsPage extends ConsumerWidget {
itemCount: submissions.length,
itemBuilder: (context, index) {
final submission = submissions[index];
return _buildSubmissionCard(context, ref, submission);
return _buildSubmissionCard(context, ref, colorScheme, submission);
},
),
);
@@ -198,24 +201,24 @@ class SubmissionsPage extends ConsumerWidget {
color: AppColors.danger,
),
const SizedBox(height: 16),
const Text(
Text(
'Có lỗi xảy ra',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 8),
Text(
error.toString(),
style: const TextStyle(color: AppColors.grey500),
style: TextStyle(color: colorScheme.onSurfaceVariant),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
const Text(
Text(
'Kéo xuống để thử lại',
style: TextStyle(color: AppColors.grey500),
style: TextStyle(color: colorScheme.onSurfaceVariant),
),
],
),
@@ -233,7 +236,8 @@ class SubmissionsPage extends ConsumerWidget {
Widget _buildFilterChip(
BuildContext context,
WidgetRef ref, {
WidgetRef ref,
ColorScheme colorScheme, {
required String label,
required bool isSelected,
required VoidCallback onTap,
@@ -243,16 +247,16 @@ class SubmissionsPage extends ConsumerWidget {
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: isSelected ? AppColors.primaryBlue : AppColors.white,
color: isSelected ? colorScheme.primary : colorScheme.surface,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: isSelected ? AppColors.primaryBlue : AppColors.grey100,
color: isSelected ? colorScheme.primary : colorScheme.surfaceContainerHighest,
),
),
child: Text(
label,
style: TextStyle(
color: isSelected ? AppColors.white : AppColors.grey900,
color: isSelected ? colorScheme.onPrimary : colorScheme.onSurface,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
),
),
@@ -260,7 +264,7 @@ class SubmissionsPage extends ConsumerWidget {
);
}
Widget _buildSubmissionCard(BuildContext context, WidgetRef ref, ProjectSubmission submission) {
Widget _buildSubmissionCard(BuildContext context, WidgetRef ref, ColorScheme colorScheme, ProjectSubmission submission) {
return Card(
margin: const EdgeInsets.only(bottom: 12),
elevation: 1,
@@ -288,13 +292,13 @@ class SubmissionsPage extends ConsumerWidget {
children: [
Text(
submission.designedArea,
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
_buildStatusBadge(submission.status, submission.statusColor),
_buildStatusBadge(colorScheme, submission.status, submission.statusColor),
],
),
const SizedBox(height: 8),
@@ -308,17 +312,17 @@ class SubmissionsPage extends ConsumerWidget {
// const SizedBox(height: 4),
Text(
'Ngày nộp: ${DateFormat('dd/MM/yyyy HH:mm').format(submission.requestDate)}',
style: const TextStyle(
style: TextStyle(
fontSize: 14,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
const SizedBox(height: 4),
Text(
'Diện tích: ${submission.designArea}',
style: const TextStyle(
style: TextStyle(
fontSize: 13,
color: AppColors.grey900,
color: colorScheme.onSurface,
),
),
if (submission.reasonForRejection != null) ...[
@@ -357,8 +361,8 @@ class SubmissionsPage extends ConsumerWidget {
);
}
Widget _buildStatusBadge(String status, String statusColor) {
final color = _getColorFromStatusColor(statusColor);
Widget _buildStatusBadge(ColorScheme colorScheme, String status, String statusColor) {
final color = _getColorFromStatusColor(colorScheme, statusColor);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
decoration: BoxDecoration(
@@ -376,7 +380,7 @@ class SubmissionsPage extends ConsumerWidget {
);
}
Color _getColorFromStatusColor(String statusColor) {
Color _getColorFromStatusColor(ColorScheme colorScheme, String statusColor) {
switch (statusColor) {
case 'Warning':
return AppColors.warning;
@@ -387,7 +391,7 @@ class SubmissionsPage extends ConsumerWidget {
case 'Info':
return AppColors.info;
default:
return AppColors.grey500;
return colorScheme.onSurfaceVariant;
}
}
}