Közös projekt szinkronizációja

This commit is contained in:
2026-07-07 02:21:08 +02:00
parent 2a2ce4bb92
commit ecb4892bc8
9 changed files with 969 additions and 48 deletions
+76 -5
View File
@@ -4,6 +4,7 @@ import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:uuid/uuid.dart';
import '../models/project.dart';
import 'app_database.dart';
import 'ts_sync_service.dart';
class ProjectService extends GetxService {
static ProjectService get to => Get.find();
@@ -76,7 +77,13 @@ class ProjectService extends GetxService {
return await AppDatabase.instance.getProject(id) ?? saved;
}
/// Online projekt — szinkronizál Supabase-szel
/// Közös (szinkronizált) projekt.
///
/// OFFLINE-FIRST: csak lokálisan jön létre (sync_status = 'pending'),
/// a feltöltést a TsSyncService végzi, amint van hálózat — így a
/// projekt-létrehozás net nélkül is működik, és nem ír többé
/// közvetlenül a régi Supabase-táblába.
Future<Project> createOnlineProject({
required String name,
String client = '',
@@ -97,12 +104,18 @@ class ProjectService extends GetxService {
// Lokálisan mentjük
final id = await AppDatabase.instance.insertProject(project);
// Supabase-be is
await Supabase.instance.client
.from('TerepiSeged_Projects')
.insert(project.toMap());
// // Supabase-be is
// await Supabase.instance.client
// .from('TerepiSeged_Projects')
// .insert(project.toMap());
await _loadProjects();
// Ha van net, azonnal fel is megy (és owner-tagság is létrejön).
if (Get.isRegistered<TsSyncService>()) {
TsSyncService.to.syncNow();
}
return await AppDatabase.instance.getProject(id) ?? project;
}
@@ -130,6 +143,64 @@ class ProjectService extends GetxService {
return await AppDatabase.instance.getProject(id) ?? project;
}
// ═════════════════════════════════════════════════════════════════
// Közös projektek — listázás és csatlakozás
// ═════════════════════════════════════════════════════════════════
/// A Supabase-en elérhető közös projektek listája
/// (név, tulajdonos, tagszám, is_member) — a ts_shared_projects view-ból.
Future<List<Map<String, dynamic>>> fetchSharedProjects() async {
final rows = await Supabase.instance.client
.from('terepi_seged_shared_projects')
.select()
.order('name', ascending: true);
return List<Map<String, dynamic>>.from(rows);
}
/// Csatlakozás egy közös projekthez (egyszerűsített modell):
/// 1. tagság-sor beszúrása (az RLS csak saját magunkat engedi felvenni),
/// 2. a projekt lokális sora létrejön a TÁVOLI uuid-dal — innentől a
/// szinkron ugyanúgy kezeli, mint a sajátokat,
/// 3. azonnali szinkron, hogy a projekt eddigi adatai lejöjjenek.
Future<Project> joinSharedProject(Map<String, dynamic> sharedRow) async {
final client = Supabase.instance.client;
final projectUuid = sharedRow['id'] as String;
// 1. Tagság (idempotens: ha már tag, nem hiba).
await client.from('terepi_seged_project_members').upsert(
{
'project_id': projectUuid,
'user_id': client.auth.currentUser!.id,
'role': 'editor',
},
ignoreDuplicates: true,
);
// 2. Lokális projekt-sor a távoli uuid-dal.
final localId =
await AppDatabase.instance.upsertProjectFromRemote(sharedRow);
await _loadProjects();
// 3. Adatok letöltése háttérben.
if (Get.isRegistered<TsSyncService>()) {
TsSyncService.to.syncNow();
}
return (await AppDatabase.instance.getProject(localId))!;
}
/// Kilépés egy közös projektből: a tagság törlődik a szerveren,
/// a lokális adat megmarad (archiválható külön).
Future<void> leaveSharedProject(Project project) async {
final client = Supabase.instance.client;
await client
.from('terepi_seged_project_members')
.delete()
.eq('project_id', project.uuid)
.eq('user_id', client.auth.currentUser!.id);
}
// ═════════════════════════════════════════════════════════════════
Future<void> reloadProjects() => _loadProjects();
Future<Map<String, int>> getStats(int projectId) =>