diff --git a/lib/core/cache/generic_cache.dart b/lib/core/cache/generic_cache.dart new file mode 100644 index 0000000..8828530 --- /dev/null +++ b/lib/core/cache/generic_cache.dart @@ -0,0 +1,5 @@ +abstract class GenericCache { + Future saveItems(List items); + + Future?> getCachedItems(); +} diff --git a/lib/core/cache/in_memory_cache.dart b/lib/core/cache/in_memory_cache.dart new file mode 100644 index 0000000..8a58184 --- /dev/null +++ b/lib/core/cache/in_memory_cache.dart @@ -0,0 +1,15 @@ +import 'package:devcon_hub/core/cache/generic_cache.dart'; + +class InMemoryCache implements GenericCache { + List? _cache; + + @override + Future saveItems(List items) async { + _cache = items; + } + + @override + Future?> getCachedItems() async { + return _cache; + } +} diff --git a/lib/features/home/data/repositories/agenda_repository_impl.dart b/lib/features/home/data/repositories/agenda_repository_impl.dart index 1e0dd5e..1cbec49 100644 --- a/lib/features/home/data/repositories/agenda_repository_impl.dart +++ b/lib/features/home/data/repositories/agenda_repository_impl.dart @@ -1,3 +1,4 @@ +import 'package:devcon_hub/core/cache/generic_cache.dart'; import 'package:devcon_hub/features/home/data/datasources/agenda_datasource.dart'; import 'package:devcon_hub/features/home/data/models/agenda_item_response.dart'; import 'package:devcon_hub/features/home/domain/entities/agenda_item.dart'; @@ -8,14 +9,27 @@ import 'package:devcon_hub/features/home/domain/repositories/agenda_repository.d // Maps AgendaResponse to the domain entity AgendaItem using a toEntity() extension or method. class AgendaRepositoryImpl implements AgendaRepository { final AgendaDataSource _datasource; + final GenericCache _cache; - AgendaRepositoryImpl(this._datasource); + AgendaRepositoryImpl(this._datasource, this._cache); @override Future> getAgendaItems() async { + final cached = await _cache.getCachedItems(); + if (cached != null && cached.isNotEmpty) { + return cached; + } + final items = await _datasource.fetchAgenda(); - final agendaItems = items.map((item) => item.toEntity()).toList(); + final agendaItems = _mapAndSort(items); + + await _cache.saveItems(agendaItems); + + return agendaItems; + } + List _mapAndSort(List responses) { + final agendaItems = responses.map((e) => e.toEntity()).toList(); agendaItems.sort((a, b) => a.startTime!.compareTo(b.startTime!)); return agendaItems; } diff --git a/lib/features/home/di/di.dart b/lib/features/home/di/di.dart index 1c0efc4..d1ba769 100644 --- a/lib/features/home/di/di.dart +++ b/lib/features/home/di/di.dart @@ -1,6 +1,9 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:devcon_hub/core/cache/generic_cache.dart'; +import 'package:devcon_hub/core/cache/in_memory_cache.dart'; import 'package:devcon_hub/features/home/data/datasources/agenda_datasource.dart'; import 'package:devcon_hub/features/home/data/repositories/agenda_repository_impl.dart'; +import 'package:devcon_hub/features/home/domain/entities/agenda_item.dart'; import 'package:devcon_hub/features/home/domain/repositories/agenda_repository.dart'; import 'package:devcon_hub/features/home/domain/usecases/get_agenda.dart'; import 'package:get_it/get_it.dart'; @@ -11,8 +14,12 @@ class AgendaInjector { ..registerLazySingleton( () => AgendaDataSource(FirebaseFirestore.instance), ) + ..registerLazySingleton>( + () => InMemoryCache(), + ) ..registerLazySingleton( - () => AgendaRepositoryImpl(injector()), + () => AgendaRepositoryImpl( + injector(), injector>()), ) ..registerLazySingleton( () => GetAgendaUseCase(injector()), diff --git a/test/core/cache/in_memory_cache_test.dart b/test/core/cache/in_memory_cache_test.dart new file mode 100644 index 0000000..291b69d --- /dev/null +++ b/test/core/cache/in_memory_cache_test.dart @@ -0,0 +1,36 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:devcon_hub/core/cache/in_memory_cache.dart'; + +void main() { + group('InMemoryCache', () { + late InMemoryCache cache; + + setUp(() { + cache = InMemoryCache(); + }); + + test('initially returns null when cache is empty', () async { + final result = await cache.getCachedItems(); + expect(result, isNull); + }); + + test('saves and retrieves cached items correctly', () async { + final items = ['a', 'b', 'c']; + + await cache.saveItems(items); + final result = await cache.getCachedItems(); + + expect(result, isNotNull); + expect(result, equals(items)); + }); + + test('overwrites previous cache when saveItems is called again', () async { + await cache.saveItems(['a']); + await cache.saveItems(['x', 'y']); + + final result = await cache.getCachedItems(); + + expect(result, equals(['x', 'y'])); + }); + }); +} diff --git a/test/features/agenda/data/repositories/agenda_repository_impl_test.dart b/test/features/agenda/data/repositories/agenda_repository_impl_test.dart index 761215d..366dbd4 100644 --- a/test/features/agenda/data/repositories/agenda_repository_impl_test.dart +++ b/test/features/agenda/data/repositories/agenda_repository_impl_test.dart @@ -1,3 +1,5 @@ +import 'package:devcon_hub/core/cache/generic_cache.dart'; +import 'package:devcon_hub/core/cache/in_memory_cache.dart'; import 'package:devcon_hub/features/home/data/datasources/agenda_datasource.dart'; import 'package:devcon_hub/features/home/data/models/agenda_item_response.dart'; import 'package:devcon_hub/features/home/data/repositories/agenda_repository_impl.dart'; @@ -10,10 +12,12 @@ class MockAgendaDataSource extends Mock implements AgendaDataSource {} void main() { late AgendaRepositoryImpl repository; late MockAgendaDataSource mockDataSource; + late GenericCache agendaCache; setUp(() { mockDataSource = MockAgendaDataSource(); - repository = AgendaRepositoryImpl(mockDataSource); + agendaCache = InMemoryCache(); + repository = AgendaRepositoryImpl(mockDataSource, agendaCache); }); test('getAgenda returns list of Agenda entities', () async {