Skip to content

Commit

Permalink
Merge pull request #74 from OpenPecha/home
Browse files Browse the repository at this point in the history
Home
  • Loading branch information
tentamdin authored Feb 4, 2025
2 parents 039ad5c + b7d4137 commit 6e170bd
Show file tree
Hide file tree
Showing 14 changed files with 1,061 additions and 293 deletions.
3 changes: 2 additions & 1 deletion lib/l10n/app_bo.arb
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@
"gelug": "དགེ་ལུགས།",
"bon": "བོན།",
"jonang": "ཇོ་ནང།",
"others": "གཞན།"
"others": "གཞན།",
"allGonpa": "དགོན་པ་ཡོངས་རྫོགས་"
}
3 changes: 2 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@
"gelug": "Gelug",
"bon": "Bon",
"jonang": "Jonang",
"others": "Others"
"others": "Others",
"allGonpa": "All Gonpa"
}
67 changes: 59 additions & 8 deletions lib/repo/database_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ class DatabaseRepository<T> {
final rawQuery = '''
SELECT *,
CASE
WHEN LOWER(tbTitle) LIKE LOWER('%$escapedQuery%') THEN 1
WHEN LOWER(enTitle) LIKE LOWER('%$escapedQuery%') THEN 2
WHEN LOWER(enTitle) LIKE LOWER('%$escapedQuery%') THEN 1
WHEN LOWER(enContent) LIKE LOWER('%$escapedQuery%') THEN 2
ELSE 3
END AS match_priority
FROM $tableName
WHERE
LOWER(tbContent) LIKE LOWER('%$escapedQuery%') OR
LOWER(enTitle) LIKE LOWER('%$escapedQuery%') OR
LOWER(enContent) LIKE LOWER('%$escapedQuery%')
ORDER BY match_priority ASC
''';
Expand All @@ -79,6 +79,55 @@ class DatabaseRepository<T> {
return maps.map((map) => fromMap(map)).toList();
}

// search festival by title and content
Future<List<T>> searchFestivalByTitleAndContent(String query) async {
final db = await dbHelper.database;
final escapedQuery = query.replaceAll("'", "''");

final rawQuery = '''
SELECT *,
CASE
WHEN LOWER(event_enname) LIKE LOWER('%$escapedQuery%') THEN 1
WHEN LOWER(event_tbname) LIKE LOWER('%$escapedQuery%') THEN 2
ELSE 3
END AS match_priority
FROM $tableName
WHERE
LOWER(event_enname) LIKE LOWER('%$escapedQuery%') OR
LOWER(event_tbname) LIKE LOWER('%$escapedQuery%')
ORDER BY match_priority ASC
''';

final maps = await db.rawQuery(rawQuery);
return maps.map((map) => fromMap(map)).toList();
}

// search by title, content and category
Future<List<T>> searchByTitleAndContentAndCategory(
String query, List<String> category) async {
final db = await dbHelper.database;
final escapedQuery = query.replaceAll("'", "''");
final sanitizedCategory = category.join("','"); // Prevent SQL injection

final rawQuery = '''
SELECT *,
CASE
WHEN LOWER(enTitle) LIKE LOWER('%$escapedQuery%') THEN 1
WHEN LOWER(enContent) LIKE LOWER('%$escapedQuery%') THEN 2
ELSE 3
END AS match_priority
FROM $tableName
WHERE
LOWER(enTitle) LIKE LOWER('%$escapedQuery%') OR
LOWER(enContent) LIKE LOWER('%$escapedQuery%') AND
categories LIKE '%$sanitizedCategory%'
ORDER BY match_priority ASC
''';

final maps = await db.rawQuery(rawQuery);
return maps.map((map) => fromMap(map)).toList();
}

Future<int> insert(T item) async {
final db = await dbHelper.database;
return await db.insert(
Expand Down Expand Up @@ -117,14 +166,16 @@ class DatabaseRepository<T> {
}

Future<List<T>> getSortedPaginatedOrganization(
int page, int pageSize, String category) async {
int page, int pageSize, List<String> categories) async {
final db = await dbHelper.database;
final sanitizedCategory =
category.replaceAll("'", "''"); // Prevent SQL injection

// Create placeholders for the IN clause
final placeholders = List.filled(categories.length, '?').join(', ');

final maps = await db.query(
tableName,
where: 'categories LIKE ?',
whereArgs: ['%$sanitizedCategory%'],
where: 'categories IN ($placeholders)',
whereArgs: categories,
limit: pageSize,
offset: page * pageSize,
);
Expand Down
2 changes: 1 addition & 1 deletion lib/states/festival_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class FestivalNotifier extends StateNotifier<FestivalListState> {
Future<void> searchFestivals(String query) async {
state = state.copyWith(isLoading: true);
try {
final results = await repository.searchByTitleAndContent(query);
final results = await repository.searchFestivalByTitleAndContent(query);
state = state.copyWith(
festivals: results,
isLoading: false,
Expand Down
110 changes: 102 additions & 8 deletions lib/states/organization_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/organization_model.dart';
import '../repo/database_repository.dart';
import 'database_state.dart';
import 'package:sqflite/sqflite.dart';

class OrganizationListState {
final List<Organization> organizations;
Expand Down Expand Up @@ -56,7 +57,55 @@ class OrganizationNotifier extends StateNotifier<OrganizationListState> {
OrganizationNotifier(this.repository)
: super(OrganizationListState.initial());

Future<void> fetchInitialOrganizations(String category) async {
// Fetch initial organizations
Future<void> fetchInitialOrganizations() async {
state = state.copyWith(isLoading: true);
try {
final initialOrganizations =
await repository.getAllPaginated(0, state.pageSize);
state = state.copyWith(
organizations: initialOrganizations,
page: 1,
isLoading: false,
hasReachedMax: initialOrganizations.length < state.pageSize,
);
} catch (e) {
state = state.copyWith(
isLoading: false,
error: e.toString(),
);
}
}

// fetch paginated organizations
Future<void> fetchPaginatedOrganizations() async {
if (state.isLoading || state.hasReachedMax) return;

try {
state = state.copyWith(isLoading: true);

final newOrganizations =
await repository.getAllPaginated(state.page, state.pageSize);

final hasReachedMax = newOrganizations.length < state.pageSize;

state = state.copyWith(
organizations: [...state.organizations, ...newOrganizations],
page: state.page + 1,
isLoading: false,
hasReachedMax: hasReachedMax,
);
} catch (e) {
state = state.copyWith(
isLoading: false,
error: e.toString(),
);
}
}

// Fetch initial organizations based on category
Future<void> fetchCategorisedInitialOrganizations(
List<String> category) async {
state = state.copyWith(isLoading: true);
try {
final initialOrganizations = await repository
Expand All @@ -75,16 +124,27 @@ class OrganizationNotifier extends StateNotifier<OrganizationListState> {
}
}

// Fetch all organizations
Future<void> fetchOrganizations() async {
List<Organization> results = await repository.getAll();
state = state.copyWith(
organizations: results,
isLoading: false,
hasReachedMax: true,
);
state = state.copyWith(isLoading: true);
try {
final results = await repository.getAll();
state = state.copyWith(
organizations: results,
isLoading: false,
hasReachedMax: true,
);
} catch (e) {
state = state.copyWith(
isLoading: false,
error: e.toString(),
);
}
}

Future<void> fetchPaginatedOrganizations(String category) async {
// Fetch paginated organizations based on category
Future<void> fetchPaginatedCategorisedOrganizations(
List<String> category) async {
if (state.isLoading || state.hasReachedMax) return;

try {
Expand All @@ -109,6 +169,7 @@ class OrganizationNotifier extends StateNotifier<OrganizationListState> {
}
}

// Fetch organization by slug
Future<Organization?> fetchOrganizationBySlug(String slug) async {
return await repository.getBySlug(slug);
}
Expand All @@ -130,11 +191,44 @@ class OrganizationNotifier extends StateNotifier<OrganizationListState> {
}
}

// search organizations based on category
Future<void> searchOrganizationsByCategory(
String query, List<String> category) async {
state = state.copyWith(isLoading: true);
try {
final results =
await repository.searchByTitleAndContentAndCategory(query, category);
state = state.copyWith(
organizations: results,
isLoading: false,
hasReachedMax: true,
);
} catch (e) {
state = state.copyWith(
isLoading: false,
error: e.toString(),
);
}
}

// get total number of organizations
Future<int> getOrganizationCount() async {
return await repository.getCount();
}

// get total number of organizations based on category
Future<List<Map<String, dynamic>>> getOrganizationCountByCategory() async {
final db = await repository.dbHelper.database;

final List<Map<String, dynamic>> maps = await db.rawQuery('''
SELECT categories, COUNT(*) as count
FROM organization
GROUP BY categories
''');

return maps;
}

void clearSearchResults() {
state = OrganizationListState.initial();
}
Expand Down
18 changes: 7 additions & 11 deletions lib/ui/screen/deities_list_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:gompa_tour/states/bottom_nav_state.dart';
import 'package:gompa_tour/states/recent_search.dart';
import 'package:gompa_tour/states/search_state.dart';
import 'package:gompa_tour/ui/screen/home_screen.dart';
import 'package:gompa_tour/ui/screen/skeleton_screen.dart';
import 'package:gompa_tour/ui/widget/gonpa_app_bar.dart';
import 'package:gompa_tour/ui/widget/search_card_item.dart';
import 'package:gompa_tour/util/search_debouncer.dart';

import '../../states/deties_state.dart';
Expand Down Expand Up @@ -184,13 +180,6 @@ class _DeitiesListScreenState extends ConsumerState<DeitiesListScreen> {
},
)
: const SizedBox(),
IconButton(
icon: Icon(Icons.qr_code),
onPressed: () {
ref.read(bottomNavProvider.notifier).setAndPersistValue(2);
Navigator.pop(context);
},
)
],
hintText: 'Search here....',
onChanged: (value) {
Expand All @@ -203,4 +192,11 @@ class _DeitiesListScreenState extends ConsumerState<DeitiesListScreen> {
void _clearSearchResults() {
ref.read(detiesNotifierProvider.notifier).clearSearchResults();
}

@override
void dispose() {
_searchController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
}
Loading

0 comments on commit 6e170bd

Please sign in to comment.