Files
voidea/flutter/lib/providers/ideas_provider.dart
T

270 lines
7.5 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/api/client.dart';
import '../core/api/endpoints.dart';
import '../core/api/exceptions.dart';
import '../models/idea.dart';
import '../models/collaboration.dart';
class IdeasState {
final List<Idea> ideas;
final Idea? selectedIdea;
final bool isLoading;
final String? error;
final String viewMode;
IdeasState({
this.ideas = const [],
this.selectedIdea,
this.isLoading = false,
this.error,
this.viewMode = 'list',
});
IdeasState copyWith({
List<Idea>? ideas,
Idea? selectedIdea,
bool? isLoading,
String? error,
String? viewMode,
}) =>
IdeasState(
ideas: ideas ?? this.ideas,
selectedIdea: selectedIdea ?? this.selectedIdea,
isLoading: isLoading ?? this.isLoading,
error: error,
viewMode: viewMode ?? this.viewMode,
);
}
class IdeasNotifier extends StateNotifier<IdeasState> {
final ApiClient _api;
IdeasNotifier(this._api) : super(IdeasState());
Future<void> loadIdeas({String? workspaceId}) async {
state = state.copyWith(isLoading: true, error: null);
try {
final params = <String, dynamic>{};
if (workspaceId != null) params['workspace_id'] = workspaceId;
final response = await _api.get(Endpoints.ideas, params: params);
final list = (response.data as List<dynamic>)
.map((e) => Idea.fromJson(e as Map<String, dynamic>))
.toList();
state = state.copyWith(ideas: list, isLoading: false);
} on ApiException catch (e) {
state = state.copyWith(isLoading: false, error: e.message);
}
}
Future<void> loadIdea(String id) async {
state = state.copyWith(isLoading: true, error: null);
try {
final response = await _api.get(Endpoints.idea(id));
final idea =
Idea.fromJson(response.data as Map<String, dynamic>);
state = state.copyWith(selectedIdea: idea, isLoading: false);
} on ApiException catch (e) {
state = state.copyWith(isLoading: false, error: e.message);
}
}
Future<bool> createIdea(CreateIdeaRequest request) async {
try {
final response = await _api.post(Endpoints.ideas, data: request.toJson());
final idea =
Idea.fromJson(response.data as Map<String, dynamic>);
state = state.copyWith(
ideas: [idea, ...state.ideas],
selectedIdea: idea,
);
return true;
} on ApiException catch (e) {
state = state.copyWith(error: e.message);
return false;
}
}
Future<bool> updateIdea(String id, UpdateIdeaRequest request) async {
try {
final response =
await _api.patch(Endpoints.idea(id), data: request.toJson());
final updated =
Idea.fromJson(response.data as Map<String, dynamic>);
state = state.copyWith(
ideas: state.ideas.map((i) => i.id == id ? updated : i).toList(),
selectedIdea: updated,
);
return true;
} on ApiException catch (e) {
state = state.copyWith(error: e.message);
return false;
}
}
Future<bool> deleteIdea(String id) async {
try {
await _api.delete(Endpoints.idea(id));
state = state.copyWith(
ideas: state.ideas.where((i) => i.id != id).toList(),
selectedIdea: null,
);
return true;
} on ApiException catch (e) {
state = state.copyWith(error: e.message);
return false;
}
}
Future<bool> updateFunnel(String ideaId, String status) async {
try {
final response = await _api.post(Endpoints.ideaFunnel(ideaId), data: {
'status': status,
});
final updated =
Idea.fromJson(response.data as Map<String, dynamic>);
state = state.copyWith(
ideas: state.ideas.map((i) => i.id == ideaId ? updated : i).toList(),
selectedIdea: updated,
);
return true;
} on ApiException catch (e) {
state = state.copyWith(error: e.message);
return false;
}
}
void setViewMode(String mode) {
state = state.copyWith(viewMode: mode);
}
void clearError() {
state = state.copyWith(error: null);
}
}
final ideasProvider =
StateNotifierProvider<IdeasNotifier, IdeasState>((ref) {
final api = ref.read(apiClientProvider);
return IdeasNotifier(api);
});
class IdeaCommentsState {
final List<Comment> comments;
final bool isLoading;
final String? error;
IdeaCommentsState({
this.comments = const [],
this.isLoading = false,
this.error,
});
IdeaCommentsState copyWith({
List<Comment>? comments,
bool? isLoading,
String? error,
}) =>
IdeaCommentsState(
comments: comments ?? this.comments,
isLoading: isLoading ?? this.isLoading,
error: error,
);
}
class IdeaCommentsNotifier extends StateNotifier<IdeaCommentsState> {
final ApiClient _api;
final String ideaId;
IdeaCommentsNotifier(this._api, this.ideaId) : super(IdeaCommentsState());
Future<void> loadComments() async {
state = state.copyWith(isLoading: true);
try {
final response = await _api.get(Endpoints.ideaComments(ideaId));
final list = (response.data as List<dynamic>)
.map((e) => Comment.fromJson(e as Map<String, dynamic>))
.toList();
state = state.copyWith(comments: list, isLoading: false);
} on ApiException catch (e) {
state = state.copyWith(isLoading: false, error: e.message);
}
}
Future<bool> addComment(String body, {String? parentId}) async {
try {
final response = await _api.post(Endpoints.ideaComments(ideaId), data: {
'body': body,
if (parentId != null) 'parent_id': parentId,
});
final comment =
Comment.fromJson(response.data as Map<String, dynamic>);
state = state.copyWith(comments: [...state.comments, comment]);
return true;
} on ApiException catch (e) {
state = state.copyWith(error: e.message);
return false;
}
}
Future<void> toggleVote(String ideaId) async {
try {
await _api.post(Endpoints.ideaVote(ideaId));
} on ApiException catch (e) {
state = state.copyWith(error: e.message);
}
}
}
final ideaCommentsProvider =
StateNotifierProvider.family<IdeaCommentsNotifier, IdeaCommentsState, String>(
(ref, ideaId) {
final api = ref.read(apiClientProvider);
return IdeaCommentsNotifier(api, ideaId);
});
class IdeaActivityState {
final List<Activity> activities;
final bool isLoading;
IdeaActivityState({
this.activities = const [],
this.isLoading = false,
});
IdeaActivityState copyWith({
List<Activity>? activities,
bool? isLoading,
}) =>
IdeaActivityState(
activities: activities ?? this.activities,
isLoading: isLoading ?? this.isLoading,
);
}
class IdeaActivityNotifier extends StateNotifier<IdeaActivityState> {
final ApiClient _api;
final String ideaId;
IdeaActivityNotifier(this._api, this.ideaId) : super(IdeaActivityState());
Future<void> loadActivities() async {
state = state.copyWith(isLoading: true);
try {
final response = await _api.get(Endpoints.ideaActivity(ideaId));
final list = (response.data as List<dynamic>)
.map((e) => Activity.fromJson(e as Map<String, dynamic>))
.toList();
state = state.copyWith(activities: list, isLoading: false);
} catch (_) {
state = state.copyWith(isLoading: false);
}
}
}
final ideaActivityProvider =
StateNotifierProvider.family<IdeaActivityNotifier, IdeaActivityState, String>(
(ref, ideaId) {
final api = ref.read(apiClientProvider);
return IdeaActivityNotifier(api, ideaId);
});