Files
tm_app/lib/view_models/board_view_model.dart
T

114 lines
3.4 KiB
Dart

import 'package:flutter/material.dart';
import '../core/utils/result.dart';
import '../data/repositories/board_repositories.dart';
import '../data/services/board_service.dart';
import '../data/services/model/board_response/board_response.dart';
class BoardViewModel with ChangeNotifier {
final BoardRepository _boardRepository;
BoardViewModel({required BoardRepository boardRepository})
: _boardRepository = boardRepository;
bool _isLoading = false;
String? _errorMessage;
Board? _board;
bool get isLoading => _isLoading;
String? get errorMessage => _errorMessage;
Board? get board => _board;
List<BoardColumn> get columns => _board?.columns ?? const [];
bool get hasData => _board != null && columns.isNotEmpty;
Future<void> getBoard() async {
_isLoading = true;
_errorMessage = null;
notifyListeners();
final result = await _boardRepository.getBoard();
switch (result) {
case Ok<BoardResponse>():
_board = result.value.data?.board;
if (_board == null) {
_errorMessage = result.value.error?.message ?? 'No board data';
}
break;
case Error<BoardResponse>():
_errorMessage = result.error.toString();
break;
}
_isLoading = false;
notifyListeners();
}
/// Look up the column a given card currently lives in.
BoardColumn? columnForCard(String cardId) {
for (final column in columns) {
if (column.cards.any((c) => c.id == cardId)) return column;
}
return null;
}
/// Move a card to [targetColumnId] at the end of that column.
/// Optimistically updates local state, then calls the API; rolls back on
/// failure.
Future<Result<MoveCardResponse>> moveCard({
required BoardCard card,
required BoardColumn targetColumn,
}) async {
final cardId = card.id;
final targetColumnId = targetColumn.id;
if (cardId == null || targetColumnId == null || _board == null) {
return Result.error(Exception('Invalid card or column'));
}
final sourceColumn = columnForCard(cardId);
if (sourceColumn == null) {
return Result.error(Exception('Card not found in any column'));
}
if (sourceColumn.id == targetColumnId) {
return Result.ok(MoveCardResponse(success: true, message: 'No change'));
}
final previousColumns = _board!.columns;
final newOrder = targetColumn.cards.length;
_board = _board!.copyWith(
columns:
previousColumns.map((column) {
if (column.id == sourceColumn.id) {
final remaining =
column.cards.where((c) => c.id != cardId).toList();
return column.copyWith(
cards: remaining,
cardCount: remaining.length,
);
}
if (column.id == targetColumnId) {
final updated = List<BoardCard>.from(column.cards)
..add(card.copyWith(columnId: targetColumnId, order: newOrder));
return column.copyWith(
cards: updated,
cardCount: updated.length,
);
}
return column;
}).toList(),
);
notifyListeners();
final result = await _boardRepository.moveCard(
cardId: cardId,
columnId: targetColumnId,
newOrder: newOrder,
);
if (result is Error<MoveCardResponse>) {
_board = _board!.copyWith(columns: previousColumns);
notifyListeners();
}
return result;
}
}