fix update page
This commit is contained in:
@@ -53,10 +53,14 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
bool _isSubmitting = false;
|
||||
bool _isLoadingDetail = false;
|
||||
String? _deletingFileId; // Track which file is being deleted
|
||||
bool _isAllowModify = true; // From API detail response
|
||||
|
||||
/// Whether we're editing an existing submission
|
||||
bool get isEditing => widget.submission != null;
|
||||
|
||||
/// Whether the form is read-only (editing but not allowed to modify)
|
||||
bool get isReadOnly => isEditing && !_isAllowModify;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -101,6 +105,9 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
|
||||
// Set existing files from API
|
||||
_existingFiles = detail.filesList;
|
||||
|
||||
// Set modify permission from API
|
||||
_isAllowModify = detail.isAllowModify;
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -146,7 +153,11 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: Text(
|
||||
isEditing ? 'Chỉnh sửa Dự án' : 'Đăng ký Công trình',
|
||||
isReadOnly
|
||||
? 'Chi tiết Dự án'
|
||||
: isEditing
|
||||
? 'Chỉnh sửa Dự án'
|
||||
: 'Đăng ký Công trình',
|
||||
style: TextStyle(color: colorScheme.onSurface),
|
||||
),
|
||||
actions: [
|
||||
@@ -197,10 +208,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
|
||||
// File Upload
|
||||
_buildFileUploadCard(colorScheme),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Submit Button
|
||||
_buildSubmitButton(colorScheme),
|
||||
// Submit Button - only show when not read-only
|
||||
if (!isReadOnly) ...[
|
||||
const SizedBox(height: 24),
|
||||
_buildSubmitButton(colorScheme),
|
||||
],
|
||||
const SizedBox(height: 40),
|
||||
],
|
||||
),
|
||||
@@ -376,49 +389,50 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Upload Area
|
||||
InkWell(
|
||||
onTap: _pickFiles,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 20),
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
width: 2,
|
||||
style: BorderStyle.solid,
|
||||
// Upload Area - only show when not read-only
|
||||
if (!isReadOnly)
|
||||
InkWell(
|
||||
onTap: _pickFiles,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 20),
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
width: 2,
|
||||
style: BorderStyle.solid,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.cloudArrowUp,
|
||||
size: 48,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Kéo thả ảnh vào đây',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'hoặc nhấn để chọn file',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
child: Column(
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.cloudArrowUp,
|
||||
size: 48,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
'Kéo thả ảnh vào đây',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'hoặc nhấn để chọn file',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Existing files from API
|
||||
if (_existingFiles.isNotEmpty) ...[
|
||||
@@ -488,7 +502,9 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
int maxLines = 1,
|
||||
TextInputType? keyboardType,
|
||||
String? helperText,
|
||||
bool? readOnly,
|
||||
}) {
|
||||
final isFieldReadOnly = readOnly ?? isReadOnly;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -517,11 +533,12 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
controller: controller,
|
||||
maxLines: maxLines,
|
||||
keyboardType: keyboardType,
|
||||
readOnly: isFieldReadOnly,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
hintStyle: TextStyle(color: colorScheme.onSurfaceVariant),
|
||||
filled: true,
|
||||
fillColor: colorScheme.surface,
|
||||
fillColor: isFieldReadOnly ? colorScheme.surfaceContainerHighest : colorScheme.surface,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
|
||||
@@ -594,10 +611,10 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
const SizedBox(height: 8),
|
||||
progressListAsync.when(
|
||||
data: (progressList) => DropdownButtonFormField<ProjectProgress>(
|
||||
initialValue: _selectedProgress,
|
||||
value: _selectedProgress,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: colorScheme.surface,
|
||||
fillColor: isReadOnly ? colorScheme.surfaceContainerHighest : colorScheme.surface,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: colorScheme.surfaceContainerHighest),
|
||||
@@ -618,11 +635,13 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
child: Text(progress.status),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_selectedProgress = value;
|
||||
});
|
||||
},
|
||||
onChanged: isReadOnly
|
||||
? null
|
||||
: (value) {
|
||||
setState(() {
|
||||
_selectedProgress = value;
|
||||
});
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return 'Vui lòng chọn tiến độ công trình';
|
||||
@@ -692,11 +711,11 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
InkWell(
|
||||
onTap: _pickExpectedDate,
|
||||
onTap: isReadOnly ? null : _pickExpectedDate,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surface,
|
||||
color: isReadOnly ? colorScheme.surfaceContainerHighest : colorScheme.surface,
|
||||
border: Border.all(color: colorScheme.surfaceContainerHighest),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
@@ -847,8 +866,8 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
// Only show remove button when not uploading
|
||||
if (!_isSubmitting)
|
||||
// Only show remove button when not uploading and not read-only
|
||||
if (!_isSubmitting && !isReadOnly)
|
||||
IconButton(
|
||||
icon: const FaIcon(
|
||||
FontAwesomeIcons.xmark,
|
||||
@@ -961,8 +980,8 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
],
|
||||
),
|
||||
),
|
||||
// Delete button or checkmark
|
||||
if (!_isSubmitting && !isDeleting)
|
||||
// Delete button or checkmark - only show delete when not read-only
|
||||
if (!_isSubmitting && !isDeleting && !isReadOnly)
|
||||
IconButton(
|
||||
icon: const FaIcon(
|
||||
FontAwesomeIcons.trash,
|
||||
@@ -1166,10 +1185,19 @@ class _SubmissionCreatePageState extends ConsumerState<SubmissionCreatePage> {
|
||||
}
|
||||
|
||||
Future<void> _pickExpectedDate() async {
|
||||
final now = DateTime.now();
|
||||
final today = DateTime(now.year, now.month, now.day);
|
||||
|
||||
// For editing mode with past date, allow selecting from that date
|
||||
// Otherwise, start from today
|
||||
final firstDate = (_expectedStartDate != null && _expectedStartDate!.isBefore(today))
|
||||
? _expectedStartDate!
|
||||
: today;
|
||||
|
||||
final date = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: _expectedStartDate ?? DateTime.now(),
|
||||
firstDate: DateTime.now(),
|
||||
initialDate: _expectedStartDate ?? today,
|
||||
firstDate: firstDate,
|
||||
lastDate: DateTime.now().add(const Duration(days: 365 * 3)),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user