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

152 lines
4.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:drift/drift.dart';
import 'package:trainhub_flutter/database/database.dart';
class ChatProvider extends ChangeNotifier {
final AppDatabase database;
List<ChatSession> _sessions = [];
List<ChatMessage> _currentMessages = [];
ChatSession? _activeSession;
List<ChatSession> get sessions => _sessions;
List<ChatMessage> get currentMessages => _currentMessages;
ChatSession? get activeSession => _activeSession;
bool _isTyping = false;
bool get isTyping => _isTyping;
ChatProvider(this.database) {
_loadSessions();
}
Future<void> _loadSessions() async {
_sessions =
await (database.select(database.chatSessions)..orderBy([
(t) => OrderingTerm(
expression: t.createdAt,
mode: OrderingMode.desc,
),
]))
.get();
notifyListeners();
}
Future<void> createSession() async {
final id = DateTime.now().toIso8601String();
final session = ChatSessionsCompanion.insert(
id: id,
title: const Value('New Chat'),
createdAt: DateTime.now().toIso8601String(),
updatedAt: DateTime.now().toIso8601String(),
);
await database.into(database.chatSessions).insert(session);
await _loadSessions();
await loadSession(id);
}
Future<void> deleteSession(String id) async {
await (database.delete(
database.chatSessions,
)..where((t) => t.id.equals(id))).go();
if (_activeSession?.id == id) {
_activeSession = null;
_currentMessages = [];
}
await _loadSessions();
}
Future<void> loadSession(String id) async {
final session = await (database.select(
database.chatSessions,
)..where((t) => t.id.equals(id))).getSingleOrNull();
if (session != null) {
_activeSession = session;
await _loadMessages(id);
}
}
Future<void> _loadMessages(String sessionId) async {
_currentMessages =
await (database.select(database.chatMessages)
..where((t) => t.sessionId.equals(sessionId))
..orderBy([
(t) => OrderingTerm(
expression: t.createdAt,
mode: OrderingMode.asc,
),
]))
.get();
notifyListeners();
}
Future<void> sendMessage(String content) async {
if (_activeSession == null) {
await createSession();
}
final sessionId = _activeSession!.id;
// User Message
final userMsgId = DateTime.now().toIso8601String();
await database
.into(database.chatMessages)
.insert(
ChatMessagesCompanion.insert(
id: userMsgId,
sessionId: sessionId,
role: 'user',
content: content,
createdAt: DateTime.now().toIso8601String(),
),
);
await _loadMessages(sessionId);
// AI Response (Mock)
_isTyping = true;
notifyListeners();
await Future.delayed(const Duration(seconds: 1)); // Simulate latency
final aiMsgId = DateTime.now().toIso8601String();
final response = _getMockResponse(content);
await database
.into(database.chatMessages)
.insert(
ChatMessagesCompanion.insert(
id: aiMsgId,
sessionId: sessionId,
role: 'assistant',
content: response,
createdAt: DateTime.now().toIso8601String(),
),
);
// Update session title if it's the first message
if (_currentMessages.length <= 2) {
final newTitle = content.length > 30
? '${content.substring(0, 30)}...'
: content;
await (database.update(database.chatSessions)
..where((t) => t.id.equals(sessionId)))
.write(ChatSessionsCompanion(title: Value(newTitle)));
await _loadSessions();
}
_isTyping = false;
await _loadMessages(sessionId);
}
String _getMockResponse(String input) {
input = input.toLowerCase();
if (input.contains('plan') || input.contains('program')) {
return "I can help you design a training plan! What are your goals? Strength, hypertrophy, or endurance?";
} else if (input.contains('squat') || input.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 (input.contains('nutrition') || input.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?";
}
}