152 lines
4.6 KiB
Dart
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?";
|
|
}
|
|
}
|