feat: legacy mobile apps created

This commit is contained in:
Achintha Isuru
2025-12-02 23:51:04 -05:00
parent 850441ca64
commit 8e7753b324
1519 changed files with 0 additions and 16 deletions

View File

@@ -0,0 +1,19 @@
import 'package:injectable/injectable.dart';
import 'package:krow/features/profile/faq/data/models/faq_entry_model.dart';
@injectable
class FaqApiProvider {
static const List<FaqEntryModel> localFaqData = [
FaqEntryModel(
question: 'How do I create a profile?',
answer: 'To create a profile, download the app, sign up with your email '
'or phone number, and fill in your basic details, including your '
'skills and experience.',
),
];
Future<List<FaqEntryModel>> fetchFaqData() async {
//TODO: Add additional FAQs either received from the backend or as static local data.
return localFaqData;
}
}

View File

@@ -0,0 +1,24 @@
import 'package:injectable/injectable.dart';
import 'package:krow/features/profile/faq/data/faq_api_provider.dart';
import 'package:krow/features/profile/faq/data/models/faq_entry_model.dart';
import 'package:krow/features/profile/faq/domain/entities/faq_entry.dart';
import 'package:krow/features/profile/faq/domain/faq_repository.dart';
@Injectable(as: FaqRepository)
class FaqRepositoryImpl implements FaqRepository {
FaqRepositoryImpl({required FaqApiProvider provider}) : _provider = provider;
final FaqApiProvider _provider;
FaqEntry _modelConverter(FaqEntryModel data) {
return FaqEntry(question: data.question, answer: data.answer);
}
@override
Future<List<FaqEntry>> getFaqData() async {
return [
for (final entry in await _provider.fetchFaqData())
_modelConverter(entry),
];
}
}

View File

@@ -0,0 +1,14 @@
import 'package:flutter/foundation.dart';
@immutable
class FaqEntryModel {
const FaqEntryModel({required this.question, required this.answer});
factory FaqEntryModel.fromJson(Map<String, dynamic> json) {
//TODO: Add from JSON conversion once the backend is ready.
throw UnimplementedError('Implement from JSON conversion');
}
final String question;
final String answer;
}

View File

@@ -0,0 +1,37 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:krow/core/application/di/injectable.dart';
import 'package:krow/core/data/enums/state_status.dart';
import 'package:krow/features/profile/faq/domain/entities/faq_entry.dart';
import 'package:krow/features/profile/faq/domain/faq_repository.dart';
part 'faq_event.dart';
part 'faq_state.dart';
class FaqBloc extends Bloc<FaqEvent, FaqState> {
FaqBloc() : super(const FaqState()) {
on<InitializeFAQ>((event, emit) async {
emit(state.copyWith(status: StateStatus.loading));
List<FaqEntry> entries = [];
try {
entries = await getIt<FaqRepository>().getFaqData();
} catch (except) {
log('Error in FaqBloc, on InitializeFAQ', error: except);
emit(state.copyWith(status: StateStatus.error));
}
emit(
state.copyWith(
status: StateStatus.idle,
entries: entries,
),
);
});
}
}

View File

@@ -0,0 +1,10 @@
part of 'faq_bloc.dart';
@immutable
sealed class FaqEvent {
const FaqEvent();
}
class InitializeFAQ extends FaqEvent {
const InitializeFAQ();
}

View File

@@ -0,0 +1,22 @@
part of 'faq_bloc.dart';
@immutable
class FaqState {
const FaqState({
this.status = StateStatus.idle,
this.entries = const [],
});
final StateStatus status;
final List<FaqEntry> entries;
FaqState copyWith({
StateStatus? status,
List<FaqEntry>? entries,
}) {
return FaqState(
status: status ?? this.status,
entries: entries ?? this.entries,
);
}
}

View File

@@ -0,0 +1,9 @@
import 'package:flutter/foundation.dart';
@immutable
class FaqEntry {
const FaqEntry({required this.question, required this.answer});
final String question;
final String answer;
}

View File

@@ -0,0 +1,5 @@
import 'package:krow/features/profile/faq/domain/entities/faq_entry.dart';
abstract interface class FaqRepository {
Future<List<FaqEntry>> getFaqData();
}

View File

@@ -0,0 +1,97 @@
import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:gap/gap.dart';
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
import 'package:krow/core/presentation/styles/theme.dart';
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
import 'package:krow/features/profile/faq/domain/bloc/faq_bloc.dart';
@RoutePage()
class FaqScreen extends StatelessWidget implements AutoRouteWrapper {
const FaqScreen({super.key});
@override
Widget wrappedRoute(BuildContext context) {
return BlocProvider(
create: (context) => FaqBloc()..add(const InitializeFAQ()),
child: this,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: KwAppBar(
titleText: 'FAQ',
showNotification: true,
),
body: CustomScrollView(
primary: false,
slivers: [
SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverList.list(
children: [
Text(
'faq_description'.tr(),
style: AppTextStyles.bodyMediumReg.copyWith(
color: AppColors.blackGray,
),
textAlign: TextAlign.start,
),
const Gap(8),
],
),
),
BlocBuilder<FaqBloc, FaqState>(
buildWhen: (previous, current) =>
previous.entries != current.entries,
builder: (context, state) {
return SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverList.separated(
itemCount: state.entries.length,
separatorBuilder: (context, index) =>
const SizedBox(height: 8),
itemBuilder: (context, index) {
return ExpansionTile(
collapsedBackgroundColor: AppColors.graySecondaryFrame,
backgroundColor: AppColors.graySecondaryFrame,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
collapsedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
iconColor: Colors.black,
collapsedIconColor: AppColors.grayStroke,
childrenPadding: const EdgeInsets.only(
left: 12,
right: 12,
bottom: 16,
),
title: Text(
state.entries[index].question,
style: AppTextStyles.bodyLargeMed,
),
children: [
Text(
state.entries[index].answer,
style: AppTextStyles.bodySmallReg.copyWith(
color: AppColors.blackGray,
),
)
],
);
},
),
);
},
)
],
),
);
}
}