Files
trainhub-flutter/lib/presentation/chat/chat_controller.dart
Kazimierz Ciołek 782986a632 Initial commit
2026-02-19 02:49:29 +01:00

110 lines
3.8 KiB
Dart

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:trainhub_flutter/injection.dart';
import 'package:trainhub_flutter/domain/repositories/chat_repository.dart';
import 'package:trainhub_flutter/presentation/chat/chat_state.dart';
part 'chat_controller.g.dart';
@riverpod
class ChatController extends _$ChatController {
late final ChatRepository _repo;
@override
Future<ChatState> build() async {
_repo = getIt<ChatRepository>();
final sessions = await _repo.getAllSessions();
return ChatState(sessions: sessions);
}
Future<void> createSession() async {
final session = await _repo.createSession();
final sessions = await _repo.getAllSessions();
state = AsyncValue.data(
ChatState(sessions: sessions, activeSession: session),
);
}
Future<void> loadSession(String id) async {
final session = await _repo.getSession(id);
if (session == null) return;
final messages = await _repo.getMessages(id);
final current = state.valueOrNull ?? const ChatState();
state = AsyncValue.data(
current.copyWith(activeSession: session, messages: messages),
);
}
Future<void> deleteSession(String id) async {
await _repo.deleteSession(id);
final sessions = await _repo.getAllSessions();
final current = state.valueOrNull ?? const ChatState();
state = AsyncValue.data(
current.copyWith(
sessions: sessions,
activeSession:
current.activeSession?.id == id ? null : current.activeSession,
messages: current.activeSession?.id == id ? [] : current.messages,
),
);
}
Future<void> sendMessage(String content) async {
final current = state.valueOrNull;
if (current == null) return;
String sessionId;
if (current.activeSession == null) {
final session = await _repo.createSession();
sessionId = session.id;
final sessions = await _repo.getAllSessions();
state = AsyncValue.data(
current.copyWith(sessions: sessions, activeSession: session),
);
} else {
sessionId = current.activeSession!.id;
}
await _repo.addMessage(
sessionId: sessionId,
role: 'user',
content: content,
);
final messagesAfterUser = await _repo.getMessages(sessionId);
state = AsyncValue.data(
state.valueOrNull!.copyWith(messages: messagesAfterUser, isTyping: true),
);
await Future<void>.delayed(const Duration(seconds: 1));
final String response = _getMockResponse(content);
await _repo.addMessage(
sessionId: sessionId,
role: 'assistant',
content: response,
);
final messagesAfterAi = await _repo.getMessages(sessionId);
if (messagesAfterAi.length <= 2) {
final title = content.length > 30
? '${content.substring(0, 30)}...'
: content;
await _repo.updateSessionTitle(sessionId, title);
}
final sessions = await _repo.getAllSessions();
state = AsyncValue.data(
state.valueOrNull!.copyWith(
messages: messagesAfterAi,
isTyping: false,
sessions: sessions,
),
);
}
String _getMockResponse(String input) {
final String lower = input.toLowerCase();
if (lower.contains('plan') || lower.contains('program')) {
return "I can help you design a training plan! What are your goals? Strength, hypertrophy, or endurance?";
} else if (lower.contains('squat') || lower.contains('bench')) {
return "Compound movements are great. Remember to maintain proper form. For squats, keep your chest up and knees tracking over toes.";
} else if (lower.contains('nutrition') || lower.contains('eat')) {
return "Nutrition is key. Aim for 1.6-2.2g of protein per kg of bodyweight if you're training hard.";
}
return "I'm your AI training assistant. How can I help you today?";
}
}