feat: deploy infrastructure + disk/drive, calendar, presentation, workspaces, onboarding, demo user
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user