Remove TaskStatus enum and related extensions, refactor BoardService and BoardResponse models for improved API integration, and update BoardViewModel to handle card movements between columns. Adjust UI components to reflect these changes and enhance error handling for card operations.

This commit is contained in:
AmirReza Jamali
2026-05-26 10:41:34 +03:30
parent 4b1260a437
commit 02057988dc
10 changed files with 542 additions and 1012 deletions
@@ -1,34 +1,229 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../../../core/utils/date_utils.dart';
import '../error/error_model.dart';
part 'board_response.freezed.dart';
part 'board_response.g.dart';
class BoardResponse {
BoardResponse({
required this.success,
required this.message,
required this.data,
required this.error,
});
@freezed
abstract class BoardResponse with _$BoardResponse {
const factory BoardResponse({
required bool? success,
required String? message,
required List<BoardData>? data,
required ErrorModel? error,
}) = _BoardResponse;
final bool? success;
final String? message;
final BoardDetailData? data;
final ErrorModel? error;
factory BoardResponse.fromJson(Map<String, Object?> json) =>
_$BoardResponseFromJson(json);
factory BoardResponse.fromJson(Map<String, dynamic> json) {
final dataJson = json['data'];
final errorJson = json['error'];
return BoardResponse(
success: json['success'] as bool?,
message: json['message'] as String?,
data:
dataJson is Map<String, dynamic>
? BoardDetailData.fromJson(dataJson)
: null,
error:
errorJson is Map<String, dynamic>
? ErrorModel.fromJson(errorJson)
: null,
);
}
}
@freezed
abstract class BoardData with _$BoardData {
const factory BoardData({
required String? id,
required String? description,
required DateTime? deadline,
required String? assignedTo,
required bool? isReady,
required String? status,
}) = _BoardData;
class BoardDetailData {
BoardDetailData({required this.board});
factory BoardData.fromJson(Map<String, Object?> json) =>
_$BoardDataFromJson(json);
final Board? board;
factory BoardDetailData.fromJson(Map<String, dynamic> json) {
final boardJson = json['board'];
return BoardDetailData(
board:
boardJson is Map<String, dynamic> ? Board.fromJson(boardJson) : null,
);
}
}
class Board {
Board({
required this.id,
required this.name,
required this.description,
required this.columns,
required this.isDefault,
required this.userId,
required this.createdAt,
required this.updatedAt,
});
final String? id;
final String? name;
final String? description;
final List<BoardColumn> columns;
final bool? isDefault;
final String? userId;
final int? createdAt;
final int? updatedAt;
factory Board.fromJson(Map<String, dynamic> json) {
final columnsJson = json['columns'];
return Board(
id: json['id'] as String?,
name: json['name'] as String?,
description: json['description'] as String?,
columns:
columnsJson is List
? columnsJson
.whereType<Map<String, dynamic>>()
.map(BoardColumn.fromJson)
.toList()
: <BoardColumn>[],
isDefault: json['is_default'] as bool?,
userId: json['user_id'] as String?,
createdAt: unixTimestampFromJson(json['created_at']),
updatedAt: unixTimestampFromJson(json['updated_at']),
);
}
Board copyWith({List<BoardColumn>? columns}) {
return Board(
id: id,
name: name,
description: description,
columns: columns ?? this.columns,
isDefault: isDefault,
userId: userId,
createdAt: createdAt,
updatedAt: updatedAt,
);
}
}
class BoardColumn {
BoardColumn({
required this.id,
required this.boardId,
required this.name,
required this.order,
required this.color,
required this.limit,
required this.cards,
required this.cardCount,
required this.isOverLimit,
required this.createdAt,
required this.updatedAt,
});
final String? id;
final String? boardId;
final String? name;
final int? order;
final String? color;
final int? limit;
final List<BoardCard> cards;
final int? cardCount;
final bool? isOverLimit;
final int? createdAt;
final int? updatedAt;
factory BoardColumn.fromJson(Map<String, dynamic> json) {
final cardsJson = json['cards'];
return BoardColumn(
id: json['id'] as String?,
boardId: json['board_id'] as String?,
name: json['name'] as String?,
order: (json['order'] as num?)?.toInt(),
color: json['color'] as String?,
limit: (json['limit'] as num?)?.toInt(),
cards:
cardsJson is List
? cardsJson
.whereType<Map<String, dynamic>>()
.map(BoardCard.fromJson)
.toList()
: <BoardCard>[],
cardCount: (json['card_count'] as num?)?.toInt(),
isOverLimit: json['is_over_limit'] as bool?,
createdAt: unixTimestampFromJson(json['created_at']),
updatedAt: unixTimestampFromJson(json['updated_at']),
);
}
BoardColumn copyWith({List<BoardCard>? cards, int? cardCount}) {
return BoardColumn(
id: id,
boardId: boardId,
name: name,
order: order,
color: color,
limit: limit,
cards: cards ?? this.cards,
cardCount: cardCount ?? this.cardCount,
isOverLimit: isOverLimit,
createdAt: createdAt,
updatedAt: updatedAt,
);
}
}
class BoardCard {
BoardCard({
required this.id,
required this.columnId,
required this.tenderId,
required this.title,
required this.order,
required this.priority,
required this.labels,
required this.dueDate,
required this.createdAt,
required this.updatedAt,
});
final String? id;
final String? columnId;
final String? tenderId;
final String? title;
final int? order;
final String? priority;
final List<String> labels;
final int? dueDate;
final int? createdAt;
final int? updatedAt;
factory BoardCard.fromJson(Map<String, dynamic> json) {
final labelsJson = json['labels'];
return BoardCard(
id: json['id'] as String?,
columnId: json['column_id'] as String?,
tenderId: json['tender_id'] as String?,
title: json['title'] as String?,
order: (json['order'] as num?)?.toInt(),
priority: json['priority'] as String?,
labels:
labelsJson is List
? labelsJson.whereType<String>().toList()
: <String>[],
dueDate: unixTimestampFromJson(json['due_date']),
createdAt: unixTimestampFromJson(json['created_at']),
updatedAt: unixTimestampFromJson(json['updated_at']),
);
}
BoardCard copyWith({String? columnId, int? order}) {
return BoardCard(
id: id,
columnId: columnId ?? this.columnId,
tenderId: tenderId,
title: title,
order: order ?? this.order,
priority: priority,
labels: labels,
dueDate: dueDate,
createdAt: createdAt,
updatedAt: updatedAt,
);
}
}