Adding attachments feature for profile

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
PGAN-MIS 2023-08-07 14:33:38 +08:00
parent c32ed51198
commit 018f3760a5
28 changed files with 1741 additions and 963 deletions

View File

@ -4,7 +4,7 @@ import 'package:unit2/model/profile/educational_background.dart';
import 'package:unit2/sevices/profile/education_services.dart';
import '../../../model/profile/attachment.dart';
import '../../../utils/attachment_categories.dart';
import '../../../utils/attachment_services.dart';
part 'education_event.dart';
part 'education_state.dart';
@ -14,12 +14,12 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
List<School> schools = [];
List<Course> programs = [];
List<Honor> honors = [];
List<AttachmentCategory> attachmentCategories = [];
List<AttachmentCategory> attachmentCategories = [];
EducationBloc() : super(EducationInitial()) {
on<GetEducationalBackground>((event, emit) async {
emit(EducationalBackgroundLoadingState());
try {
if (attachmentCategories.isEmpty) {
if (attachmentCategories.isEmpty) {
attachmentCategories =
await AttachmentServices.instance.getCategories();
}
@ -28,11 +28,13 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
.instace
.getEducationalBackground(event.profileId, event.token);
educationalBackgrounds = educations;
emit(EducationalBackgroundLoadedState(
educationalBackground: educationalBackgrounds, attachmentCategory: attachmentCategories));
emit(EducationalBackgroundLoadedState(
educationalBackground: educationalBackgrounds,
attachmentCategory: attachmentCategories));
} else {
emit(EducationalBackgroundLoadedState(
educationalBackground: educationalBackgrounds,attachmentCategory: attachmentCategories));
educationalBackground: educationalBackgrounds,
attachmentCategory: attachmentCategories));
}
} catch (e) {
emit(EducationalBackgroundErrorState(message: e.toString()));
@ -85,7 +87,8 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
token: event.token,
profileId: event.profileId);
if (status['success']) {
educationalBackgrounds.removeWhere((element) => event.educationalBackground.id == element.id);
educationalBackgrounds.removeWhere(
(element) => event.educationalBackground.id == element.id);
EducationalBackground educationalBackground =
EducationalBackground.fromJson(status['data']);
educationalBackgrounds.add(educationalBackground);
@ -97,7 +100,8 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
////LOAD
on<LoadEducations>((event, emit) {
emit(EducationalBackgroundLoadedState(
educationalBackground: educationalBackgrounds,attachmentCategory: attachmentCategories));
educationalBackground: educationalBackgrounds,
attachmentCategory: attachmentCategories));
});
//// SHOW EDIT FORM
on<ShowEditEducationForm>((event, emit) async {
@ -143,8 +147,12 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
}
});
////Add attachment
on<AddAttachment>((event, emit) async {
on<AddEducationAttachment>((event, emit) async {
emit(EducationalBackgroundLoadingState());
EducationalBackground educationalBackground =
educationalBackgrounds.firstWhere(
(element) => element.id.toString() == event.attachmentModule);
List<Attachment> attachments = [];
try {
Map<dynamic, dynamic> status = await AttachmentServices.instance
.attachment(
@ -153,7 +161,18 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
paths: event.filePaths,
token: event.token,
profileId: event.profileId);
if (status['success']) {
status['data'].forEach((element) {
Attachment newAttachment = Attachment.fromJson(element);
attachments.add(newAttachment);
});
educationalBackground.attachments == null
? educationalBackground.attachments = attachments
: educationalBackground.attachments = [
...educationalBackground.attachments!,
...attachments
];
emit(EducationAddedState(response: status));
} else {
emit(EducationAddedState(response: status));
@ -162,5 +181,30 @@ class EducationBloc extends Bloc<EducationEvent, EducationState> {
emit(EducationalBackgroundErrorState(message: e.toString()));
}
});
on<DeleteEducationAttachment>((event, emit) async {
emit(EducationalBackgroundLoadingState());
try {
final bool success = await AttachmentServices.instance.deleteAttachment(
attachment: event.attachment,
moduleId: event.moduleId,
profileId: event.profileId.toString(),
token: event.token);
if (success) {
final EducationalBackground educationalBackground =
educationalBackgrounds
.firstWhere((element) => element.id == event.moduleId);
educationalBackground.attachments
?.removeWhere((element) => element.id == event.attachment.id);
educationalBackgrounds
.removeWhere((element) => element.id == event.moduleId);
educationalBackgrounds.add(educationalBackground);
emit(EducationAttachmentDeletedState(success: success));
} else {
emit(EducationAttachmentDeletedState(success: success));
}
} catch (e) {
emit(EducationalBackgroundErrorState(message: e.toString()));
}
});
}
}

View File

@ -64,13 +64,22 @@ class DeleteEducation extends EducationEvent{
List<Object> get props => [educationalBackground, profileId, token];
}
////Add attachment
class AddAttachment extends EducationEvent{
class AddEducationAttachment extends EducationEvent{
final String categoryId;
final String attachmentModule;
final List<String> filePaths;
final String token;
final String profileId;
const AddAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
const AddEducationAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
@override
List<Object> get props => [categoryId,attachmentModule,filePaths, token,profileId];
}
////Delete Attachment
class DeleteEducationAttachment extends EducationEvent{
final int moduleId;
final Attachment attachment;
final String token;
final int profileId;
const DeleteEducationAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token});
}

View File

@ -10,9 +10,10 @@ abstract class EducationState extends Equatable {
class EducationInitial extends EducationState {}
class EducationalBackgroundLoadedState extends EducationState {
final List< AttachmentCategory> attachmentCategory;
final List<AttachmentCategory> attachmentCategory;
final List<EducationalBackground> educationalBackground;
const EducationalBackgroundLoadedState({required this.educationalBackground, required this.attachmentCategory});
const EducationalBackgroundLoadedState(
{required this.educationalBackground, required this.attachmentCategory});
@override
List<Object> get props => [educationalBackground];
}
@ -58,6 +59,8 @@ class EducationAddedState extends EducationState {
@override
List<Object> get props => [response];
}
//// Edited State
class EditedEducationState extends EducationState {
final Map<dynamic, dynamic> response;
@ -73,3 +76,17 @@ class EducationDeletedState extends EducationState {
@override
List<Object> get props => [success];
}
////Attachment AddedState
class EducationAttachmentAddedState extends EducationState {
final Map<dynamic, dynamic> response;
const EducationAttachmentAddedState({required this.response});
}
////Attachment Deleted State State
class EducationAttachmentDeletedState extends EducationState {
final bool success;
const EducationAttachmentDeletedState({required this.success});
@override
List<Object> get props => [success];
}

View File

@ -1,6 +1,6 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:unit2/utils/attachment_categories.dart';
import 'package:unit2/utils/attachment_services.dart';
import '../../../model/location/city.dart';
import '../../../model/location/country.dart';
import '../../../model/location/provinces.dart';
@ -39,11 +39,11 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
if (success) {
eligibilities.removeWhere(
((EligibityCert element) => element.id == event.eligibilityId));
emit(DeletedState(
emit(EligibilityDeletedState(
success: success,
));
} else {
emit(DeletedState(success: success));
emit(EligibilityDeletedState(success: success));
}
} catch (e) {
emit(EligibilityErrorState(message: e.toString()));
@ -222,8 +222,11 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
message: "Something went wrong. Please try again"));
});
////Add attachment
on<AddAttachment>((event, emit) async {
on<AddEligibiltyAttachment>((event, emit) async {
emit(EligibilityLoadingState());
List<Attachment> attachments = [];
EligibityCert eligibityCert = eligibilities.firstWhere(
(element) => element.id.toString() == event.attachmentModule);
try {
Map<dynamic, dynamic> status = await AttachmentServices.instance
.attachment(
@ -233,32 +236,44 @@ class EligibilityBloc extends Bloc<EligibilityEvent, EligibilityState> {
token: event.token,
profileId: event.profileId);
if (status['success']) {
emit(EligibilityAddedState(response: status));
status['data'].forEach((element) {
Attachment newAttachment = Attachment.fromJson(element);
attachments.add(newAttachment);
});
eligibityCert.attachments == null
? eligibityCert.attachments = attachments
: eligibityCert.attachments = [
...eligibityCert.attachments!,
...attachments
];
emit(EligibilityAttachmentAddedState(response: status));
} else {
emit(EligibilityAddedState(response: status));
emit(EligibilityAttachmentAddedState(response: status));
}
} catch (e) {
emit(EligibilityErrorState(message: e.toString()));
}
});
on<DeleteAttachment>((event, emit) async {
on<DeleteEligibyAttachment>((event, emit) async {
emit(EligibilityLoadingState());
// try {
final bool success = await EligibilityService.instance.deleteAttachment(
moduleId: int.parse(event.moduleId),
final bool success = await AttachmentServices.instance.deleteAttachment(
attachment: event.attachment,
profileId: event.profileId,
moduleId: int.parse(event.moduleId),
profileId: event.profileId.toString(),
token: event.token);
if (success) {
EligibityCert eligibityCert = eligibilities.firstWhere((element) =>element.id.toString() == event.moduleId);
eligibityCert.attachments!.removeWhere((element){
return event.attachment.id == element.id;
});
emit(DeletedState(
success: success,
));
final EligibityCert eligibityCert = eligibilities
.firstWhere((element) => element.id.toString() == event.moduleId);
eligibityCert.attachments
?.removeWhere((element) => element.id == event.attachment.id);
eligibilities.removeWhere(
(element) => element.id.toString() == event.moduleId);
eligibilities.add(eligibityCert);
emit(EligibilitytAttachmentDeletedState(success: success));
} else {
emit(DeletedState(success: success));
emit(EligibilitytAttachmentDeletedState(success: success));
}
// } catch (e) {
// emit(EligibilityErrorState(message: e.toString()));

View File

@ -68,24 +68,25 @@ class DeleteEligibility extends EligibilityEvent {
class CallErrorState extends EligibilityEvent{
}
class AddAttachment extends EligibilityEvent{
////Add Attachment
class AddEligibiltyAttachment extends EligibilityEvent{
final String categoryId;
final String attachmentModule;
final List<String> filePaths;
final String token;
final String profileId;
const AddAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
const AddEligibiltyAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
@override
List<Object> get props => [categoryId,attachmentModule,filePaths, token,profileId];
}
class DeleteAttachment extends EligibilityEvent{
////Delete Attachment
class DeleteEligibyAttachment extends EligibilityEvent{
final String profileId;
final String token;
final Attachment attachment;
final String moduleId;
const DeleteAttachment({required this.attachment,required this.moduleId, required this.profileId, required this.token});
const DeleteEligibyAttachment({required this.attachment,required this.moduleId, required this.profileId, required this.token});
}

View File

@ -42,9 +42,9 @@ class EditEligibilityState extends EligibilityState {
[isOverseas, eligibityCert, eligibilities, regions, countries];
}
class DeletedState extends EligibilityState {
class EligibilityDeletedState extends EligibilityState {
final bool success;
const DeletedState({required this.success});
const EligibilityDeletedState({required this.success});
@override
List<Object> get props => [success];
}
@ -93,3 +93,17 @@ class EligibilityLoaded extends EligibilityState {
@override
List<Object> get props => [eligibilities];
}
////Attachment AddedState
class EligibilityAttachmentAddedState extends EligibilityState {
final Map<dynamic, dynamic> response;
const EligibilityAttachmentAddedState({required this.response});
}
////Attachment Deleted State State
class EligibilitytAttachmentDeletedState extends EligibilityState {
final bool success;
const EligibilitytAttachmentDeletedState({required this.success});
@override
List<Object> get props => [success];
}

View File

@ -10,7 +10,7 @@ import '../../../model/profile/attachment.dart';
import '../../../model/profile/learning_development.dart';
import '../../../model/utils/agency.dart';
import '../../../model/utils/category.dart';
import '../../../utils/attachment_categories.dart';
import '../../../utils/attachment_services.dart';
import '../../../utils/location_utilities.dart';
import '../../../utils/profile_utilities.dart';
part 'learning_development_event.dart';
@ -273,8 +273,10 @@ class LearningDevelopmentBloc
emit(LearningDevelopmentErrorState(message: event.message));
});
////Add attachment
on<AddAttachment>((event, emit) async {
on<AddALearningDevttachment>((event, emit) async {
emit(LearningDevelopmentLoadingState());
List<Attachment> attachments = [];
LearningDevelopement learningDevelopement = learningsAndDevelopments.firstWhere((element) => element.conductedTraining!.id.toString () == event.attachmentModule);
try {
Map<dynamic, dynamic> status = await AttachmentServices.instance
.attachment(
@ -284,6 +286,11 @@ class LearningDevelopmentBloc
token: event.token,
profileId: event.profileId);
if (status['success']) {
status['data'].forEach((element){
Attachment newAttachment = Attachment.fromJson(element);
attachments.add(newAttachment);
});
learningDevelopement.attachments == null? learningDevelopement.attachments = attachments:learningDevelopement.attachments = [...learningDevelopement.attachments!,...attachments];
emit(LearningDevelopmentAddedState(response: status));
} else {
emit(LearningDevelopmentAddedState(response: status));
@ -292,5 +299,31 @@ class LearningDevelopmentBloc
emit(LearningDevelopmentErrorState(message: e.toString()));
}
});
////Delete Attachment
on<DeleteLearningDevAttachment>((event, emit) async {
emit(LearningDevelopmentLoadingState());
try {
final bool success = await AttachmentServices.instance.deleteAttachment(
attachment: event.attachment,
moduleId: event.moduleId,
profileId: event.profileId.toString(),
token: event.token);
if (success) {
final LearningDevelopement learningDevelopement =
learningsAndDevelopments
.firstWhere((element) => element.conductedTraining!.id == event.moduleId);
learningDevelopement.attachments
?.removeWhere((element) => element.id == event.attachment.id);
learningsAndDevelopments
.removeWhere((element) => element.conductedTraining!.id == event.moduleId);
learningsAndDevelopments.add(learningDevelopement);
emit(LearningDevAttachmentDeletedState(success: success));
} else {
emit(LearningDevAttachmentDeletedState(success: success));
}
} catch (e) {
emit(LearningDevelopmentErrorState(message: e.toString()));
}
});
}
}

View File

@ -67,13 +67,24 @@ class CallErrorState extends LearningDevelopmentEvent{
const CallErrorState({required this.message});
}
class AddAttachment extends LearningDevelopmentEvent{
////Add Attachment
class AddALearningDevttachment extends LearningDevelopmentEvent{
final String categoryId;
final String attachmentModule;
final List<String> filePaths;
final String token;
final String profileId;
const AddAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
const AddALearningDevttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
@override
List<Object> get props => [categoryId,attachmentModule,filePaths, token,profileId];
}
//// Delete Attachment
class DeleteLearningDevAttachment extends LearningDevelopmentEvent{
final int moduleId;
final Attachment attachment;
final String token;
final int profileId;
const DeleteLearningDevAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token});
}

View File

@ -10,9 +10,11 @@ abstract class LearningDevelopmentState extends Equatable {
class LearningDevelopmentInitial extends LearningDevelopmentState {}
class LearningDevelopmentLoadedState extends LearningDevelopmentState {
final List< AttachmentCategory> attachmentCategory;
final List<AttachmentCategory> attachmentCategory;
final List<LearningDevelopement> learningsAndDevelopment;
const LearningDevelopmentLoadedState({required this.learningsAndDevelopment, required this.attachmentCategory});
const LearningDevelopmentLoadedState(
{required this.learningsAndDevelopment,
required this.attachmentCategory});
@override
List<Object> get props => [learningsAndDevelopment];
}
@ -113,3 +115,21 @@ class LearningDevelopmentErrorState extends LearningDevelopmentState {
final String message;
const LearningDevelopmentErrorState({required this.message});
}
////Attachment AddedState
class LearningDevAttachmentAddedState extends LearningDevelopmentState {
final Map<dynamic, dynamic> response;
const LearningDevAttachmentAddedState({required this.response});
@override
List<Object> get props => [response];
}
////Attachment Deleted State State
class LearningDevAttachmentDeletedState extends LearningDevelopmentState {
final bool success;
const LearningDevAttachmentDeletedState({required this.success});
@override
List<Object> get props => [success];
}

View File

@ -60,6 +60,7 @@ class EditVoluntaryWorks extends VoluntaryWorkState{
}
////Adding State
class AddVoluntaryWorkState extends VoluntaryWorkState{
final List<Position> positions;
@ -71,6 +72,11 @@ class AddVoluntaryWorkState extends VoluntaryWorkState{
@override
List<Object> get props => [positions,agencies,countries,regions];
}
////Add Attachment
class AttachmentAddedState extends VoluntaryWorkState {
final Map<dynamic, dynamic> response;
const AttachmentAddedState({required this.response});
}
//// Deleted State
class VoluntaryWorkDeletedState extends VoluntaryWorkState{
final bool success;

View File

@ -10,7 +10,7 @@ import 'package:unit2/utils/profile_utilities.dart';
import '../../../model/profile/attachment.dart';
import '../../../model/utils/category.dart';
import '../../../utils/attachment_categories.dart';
import '../../../utils/attachment_services.dart';
part 'workHistory_event.dart';
part 'workHistory_state.dart';
@ -21,13 +21,13 @@ class WorkHistoryBloc extends Bloc<WorkHistorytEvent, WorkHistoryState> {
List<Agency> agencies = [];
List<AppoinemtStatus> appointmentStatus = [];
List<Category> agencyCategory = [];
List<AttachmentCategory> attachmentCategories = [];
List<AttachmentCategory> attachmentCategories = [];
WorkHistoryBloc() : super(EducationInitial()) {
////GET WORK HISTORIES
on<GetWorkHistories>((event, emit) async {
emit(WorkHistoryLoadingState());
try {
if (attachmentCategories.isEmpty) {
if (attachmentCategories.isEmpty) {
attachmentCategories =
await AttachmentServices.instance.getCategories();
}
@ -36,7 +36,9 @@ class WorkHistoryBloc extends Bloc<WorkHistorytEvent, WorkHistoryState> {
.getWorkExperiences(event.profileId, event.token);
workExperiences = works;
}
emit(WorkHistoryLoaded(workExperiences: workExperiences, attachmentCategory: attachmentCategories));
emit(WorkHistoryLoaded(
workExperiences: workExperiences,
attachmentCategory: attachmentCategories));
} catch (e) {
emit(WorkHistoryErrorState(message: e.toString()));
}
@ -44,7 +46,9 @@ class WorkHistoryBloc extends Bloc<WorkHistorytEvent, WorkHistoryState> {
///// LOAD WORK HISTORIES
on<LoadWorkHistories>((event, emit) {
emit(WorkHistoryLoadingState());
emit(WorkHistoryLoaded(workExperiences: workExperiences,attachmentCategory: attachmentCategories));
emit(WorkHistoryLoaded(
workExperiences: workExperiences,
attachmentCategory: attachmentCategories));
});
////DELETE
on<DeleteWorkHistory>((event, emit) async {
@ -190,8 +194,11 @@ class WorkHistoryBloc extends Bloc<WorkHistorytEvent, WorkHistoryState> {
}
});
////Add Attachment
on<AddAttachment>((event, emit) async {
on<AddWorkHistoryAttachment>((event, emit) async {
emit(WorkHistoryLoadingState());
List<Attachment> attachments = [];
WorkHistory workHistory = workExperiences.firstWhere(
(element) => element.id.toString() == event.attachmentModule);
try {
Map<dynamic, dynamic> status = await AttachmentServices.instance
.attachment(
@ -201,9 +208,45 @@ class WorkHistoryBloc extends Bloc<WorkHistorytEvent, WorkHistoryState> {
token: event.token,
profileId: event.profileId);
if (status['success']) {
emit(WorkHistoryAddedState(response: status));
status['data'].forEach((element) {
Attachment newAttachment = Attachment.fromJson(element);
attachments.add(newAttachment);
});
workHistory.attachments == null
? workHistory.attachments = attachments
: workHistory.attachments = [
...workHistory.attachments!,
...attachments
];
emit(WorkHistoryDevAttachmentAddedState(response: status));
} else {
emit(WorkHistoryAddedState(response: status));
emit(WorkHistoryDevAttachmentAddedState(response: status));
}
} catch (e) {
emit(WorkHistoryErrorState(message: e.toString()));
}
});
////Delete Attachment
on<DeleteWorkHistoryAttachment>((event, emit) async {
emit(WorkHistoryLoadingState());
try {
final bool success = await AttachmentServices.instance.deleteAttachment(
attachment: event.attachment,
moduleId: event.moduleId,
profileId: event.profileId.toString(),
token: event.token);
if (success) {
final WorkHistory workHistory =
workExperiences
.firstWhere((element) => element.id == event.moduleId);
workHistory.attachments
?.removeWhere((element) => element.id == event.attachment.id);
workExperiences
.removeWhere((element) => element.id == event.moduleId);
workExperiences.add(workHistory);
emit(WorkHistoryDevAttachmentDeletedState(success: success));
} else {
emit(WorkHistoryDevAttachmentDeletedState(success: success));
}
} catch (e) {
emit(WorkHistoryErrorState(message: e.toString()));

View File

@ -60,15 +60,27 @@ class AddWorkHostory extends WorkHistorytEvent{
@override
List<Object> get props => [workHistory,profileId,token,isPrivate];
}
class AddAttachment extends WorkHistorytEvent{
////Add Attachment
class AddWorkHistoryAttachment extends WorkHistorytEvent{
final String categoryId;
final String attachmentModule;
final List<String> filePaths;
final String token;
final String profileId;
const AddAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
const AddWorkHistoryAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token});
@override
List<Object> get props => [categoryId,attachmentModule,filePaths, token,profileId];
}
////Delete Attachment
class DeleteWorkHistoryAttachment extends WorkHistorytEvent{
final int moduleId;
final Attachment attachment;
final String token;
final int profileId;
const DeleteWorkHistoryAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token});
}

View File

@ -73,3 +73,22 @@ class WorkHistoryAddedState extends WorkHistoryState{
@override
List<Object> get props => [response];
}
////Attachment AddedState
class WorkHistoryDevAttachmentAddedState extends WorkHistoryState {
final Map<dynamic, dynamic> response;
const WorkHistoryDevAttachmentAddedState({required this.response});
@override
List<Object> get props => [response];
}
////Attachment Deleted State State
class WorkHistoryDevAttachmentDeletedState extends WorkHistoryState {
final bool success;
const WorkHistoryDevAttachmentDeletedState({required this.success});
@override
List<Object> get props => [success];
}

View File

@ -1,24 +1,14 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:device_preview/device_preview.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/utils/app_router.dart';
import 'package:unit2/utils/global_context.dart';
import 'package:unit2/utils/global_context.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
import './utils/router.dart';
import './utils/global.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
var appDirectory = await path_provider.getApplicationDocumentsDirectory();
@ -92,4 +82,3 @@ class MyApp extends StatelessWidget {
);
}
}

View File

@ -1,8 +1,4 @@
// To parse this JSON data, do
//
// final attachment = attachmentFromJson(jsonString);
import 'package:meta/meta.dart';
import 'dart:convert';
Attachment attachmentFromJson(String str) =>
@ -53,9 +49,9 @@ class Attachment {
}
class AttachmentCategory {
final int id;
final Subclass subclass;
final String description;
final int? id;
final Subclass? subclass;
final String? description;
AttachmentCategory({
required this.id,
@ -65,21 +61,21 @@ class AttachmentCategory {
factory AttachmentCategory.fromJson(Map<String, dynamic> json) => AttachmentCategory(
id: json["id"],
subclass: Subclass.fromJson(json["subclass"]),
subclass:json['subclass'] == null? null: Subclass.fromJson(json["subclass"]),
description: json["description"],
);
Map<String, dynamic> toJson() => {
"id": id,
"subclass": subclass.toJson(),
"subclass": subclass?.toJson(),
"description": description,
};
}
class Subclass {
final int id;
final String name;
final AttachmentClass attachmentClass;
final int? id;
final String? name;
final AttachmentClass? attachmentClass;
Subclass({
required this.id,
@ -90,19 +86,19 @@ class Subclass {
factory Subclass.fromJson(Map<String, dynamic> json) => Subclass(
id: json["id"],
name: json["name"],
attachmentClass: AttachmentClass.fromJson(json["attachment_class"]),
attachmentClass: json['attachment_class'] == null? null: AttachmentClass.fromJson(json["attachment_class"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"attachment_class": attachmentClass.toJson(),
"attachment_class": attachmentClass?.toJson(),
};
}
class AttachmentClass {
final int id;
final String name;
final int? id;
final String? name;
AttachmentClass({
required this.id,

View File

@ -26,7 +26,7 @@ class EducationalBackground {
final List<Honor>? honors;
final Education? education;
final String? periodTo;
final List<Attachment>? attachments;
List<Attachment>? attachments;
final String? periodFrom;
final int? unitsEarned;
final String? yearGraduated;

View File

@ -34,7 +34,7 @@ class EligibityCert {
final int? id;
final double? rating;
final DateTime? examDate;
final List<Attachment>? attachments;
List<Attachment>? attachments;
final Eligibility? eligibility;
final ExamAddress? examAddress;

View File

@ -24,7 +24,7 @@ class LearningDevelopement {
this.totalHoursAttended,
});
final List<Attachment>? attachments;
List<Attachment>? attachments;
final Agency? sponsoredBy;
final ConductedTraining? conductedTraining;
final double? totalHoursAttended;

View File

@ -34,7 +34,7 @@ class WorkHistory {
final DateTime? toDate;
final Position? position;
final DateTime? fromDate;
final List<Attachment>? attachments;
List<Attachment>? attachments;
final int? salaryGrade;
final double? monthlySalary;
final String? appointmentStatus;

View File

@ -7,7 +7,10 @@ import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_svg/svg.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart';
import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/model/profile/educational_background.dart';
import 'package:unit2/screens/profile/components/education/add_modal.dart';
@ -16,7 +19,6 @@ import 'package:unit2/theme-data.dart/colors.dart';
import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/empty_data.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../bloc/profile/education/education_bloc.dart';
import '../../../model/profile/attachment.dart';
import '../../../theme-data.dart/btn-style.dart';
@ -33,7 +35,8 @@ class EducationScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final parent = context;
FilePickerResult? result;
List<PlatformFile>? results = [];
AttachmentCategory? selectedAttachmentCategory;
List<AttachmentCategory> attachmentCategories = [];
int profileId;
@ -115,6 +118,28 @@ class EducationScreen extends StatelessWidget {
});
}
}
////ATTACHMENT ADDED STATE
if (state is EducationAttachmentAddedState) {
if (state.response['success']) {
successAlert(context, "Adding Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
} else {
errorAlert(context, "Adding Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
}
}
////EDITED STATE
if (state is EditedEducationState) {
if (state.response['success']) {
@ -157,11 +182,32 @@ class EducationScreen extends StatelessWidget {
});
}
}
////ATTACHMENT DELETED STATE
if (state is EducationAttachmentDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
"Attachment has been deleted successfully",
() {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
} else {
errorAlert(context, "Deletion Failed",
"Error deleting Attachment", () {
Navigator.of(context).pop();
context
.read<EducationBloc>()
.add(LoadEducations());
});
}
}
},
builder: (context, state) {
if (state is EducationalBackgroundLoadedState) {
for (var cat in state.attachmentCategory) {
if (cat.subclass.id == 1) {
if (cat.subclass!.id == 1) {
attachmentCategories.add(cat);
}
}
@ -352,6 +398,7 @@ class EducationScreen extends StatelessWidget {
index]));
}
if (value == 3) {
results.clear();
showDialog(
context: context,
builder:
@ -423,7 +470,7 @@ class EducationScreen extends StatelessWidget {
selectedAttachmentCategory = value;
},
items: attachmentCategories.map((e) {
return DropdownMenuItem(value: e, child: Text(e.description));
return DropdownMenuItem(value: e, child: Text(e.description!));
}).toList()),
const SizedBox(
height:
@ -463,7 +510,9 @@ class EducationScreen extends StatelessWidget {
]);
setState(() {
if (newResult != null) {
result = newResult;
newResult.files.forEach((element) {
results.add(element);
});
}
});
},
@ -479,13 +528,13 @@ class EducationScreen extends StatelessWidget {
SizedBox(
height: 100,
width: double.maxFinite,
child: result == null
child: results.isEmpty
? const SizedBox()
: Expanded(
child: ListView.builder(
itemCount: result!.files.length,
itemCount: results.length,
itemBuilder: (BuildContext context, index) {
final kb = result!.files[index].size / 1024;
final kb = results[index].size / 1024;
final mb = kb / 1024;
final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB';
return Column(
@ -497,19 +546,19 @@ class EducationScreen extends StatelessWidget {
children: [
Flexible(
child: SizedBox(
child: result!.files[index].extension!.toLowerCase() == 'pdf'
child: results[index].extension!.toLowerCase() == 'pdf'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'png'
: results[index].extension!.toLowerCase() == 'png'
? SvgPicture.asset(
'assets/svgs/png.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'jpg' || result!.files[index].extension!.toLowerCase() == 'jpeg'
: results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
height: blockSizeVertical * 3,
@ -519,18 +568,36 @@ class EducationScreen extends StatelessWidget {
const SizedBox(
width: 12,
),
Flexible(
flex: 4,
child: Text(
result!.files[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
Flexible(
flex: 6,
child: Text(
results[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
),
const SizedBox(
width: 12,
),
Flexible(
flex: 2,
child: Text(
size,
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
)),
Flexible(
flex: 1,
child: IconButton(
icon: const Icon(
Icons.close,
color: Colors.grey,
),
const SizedBox(width: 12,),
Flexible(
flex: 2,
child: Text(size))
onPressed: () {
setState(() {
results.removeAt(index);
});
},
))
],
)),
const Divider()
@ -554,12 +621,15 @@ class EducationScreen extends StatelessWidget {
onPressed: () {
List<String> paths = [];
if (selectedAttachmentCategory != null) {
for (var res in result!.files) {
if (selectedAttachmentCategory != null && results.isNotEmpty) {
for (var res in results) {
paths.add(res.path!);
}
setState(() {
results.clear();
});
Navigator.pop(context);
parent.read<EducationBloc>().add(AddAttachment(attachmentModule: state.educationalBackground[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
parent.read<EducationBloc>().add(AddEducationAttachment(attachmentModule: state.educationalBackground[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
}
},
child: const Text("Submit")),
@ -594,6 +664,7 @@ class EducationScreen extends StatelessWidget {
)
],
),
////Show Attachments
SizedBox(
child: state
@ -620,22 +691,45 @@ class EducationScreen extends StatelessWidget {
1
?
////Single Attachment view
SingleAttachment(
onpressed: () {
confirmAlert(
context,
() {},
"Delete?",
"Confirm Delete?");
},
attachment: state
.educationalBackground[
index]
.attachments!
.first,
Column(
children: [
const Divider(),
SingleAttachment(
onpressed:
() {
confirmAlert(
context,
() {
parent.read<EducationBloc>().add(DeleteEducationAttachment(
attachment: state
.educationalBackground[
index]
.attachments!
.first,
moduleId: state
.educationalBackground[
index]
.id!,
profileId:
profileId,
token:
token!));
}, "Delete?",
"Confirm Delete?");
},
attachment: state
.educationalBackground[
index]
.attachments!
.first,
),
],
)
////Multiple Attachments View
: MultipleAttachments(
profileId:
profileId,
token: token!,
eligibilityName: state
.educationalBackground[
index]
@ -646,6 +740,21 @@ class EducationScreen extends StatelessWidget {
.educationalBackground[
index]
.attachments!,
educationBloc:
BlocProvider.of<
EducationBloc>(
parent),
eligibilityBloc:
null,
workHistoryBloc:
null,
learningDevelopmentBloc:
null,
blocId: 1,
moduleId: state
.educationalBackground[
index]
.id!,
))
],
),

View File

@ -1,5 +1,4 @@
import 'dart:io';
import 'package:app_popup_menu/app_popup_menu.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
@ -9,7 +8,10 @@ import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_svg/svg.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:unit2/bloc/profile/education/education_bloc.dart';
import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/model/profile/attachment.dart';
import 'package:unit2/model/profile/eligibility.dart';
@ -38,7 +40,7 @@ class EligibiltyScreen extends StatelessWidget {
BuildContext parent = context;
String? token;
int? profileId;
FilePickerResult? result;
List<PlatformFile>? results = [];
AttachmentCategory? selectedAttachmentCategory;
List<AttachmentCategory> attachmentCategories = [];
@ -101,7 +103,7 @@ class EligibiltyScreen extends StatelessWidget {
if (state is EligibilityLoaded ||
state is AddEligibilityState ||
state is EditEligibilityState ||
state is DeletedState ||
state is EligibilityDeletedState ||
state is EligibilityAddedState ||
state is EligibilityEditedState ||
state is EligibilityErrorState) {
@ -109,7 +111,7 @@ class EligibiltyScreen extends StatelessWidget {
progress!.dismiss();
}
////DELETED STATE
if (state is DeletedState) {
if (state is EligibilityDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
"Eligibility has been deleted successfully",
@ -129,6 +131,28 @@ class EligibiltyScreen extends StatelessWidget {
});
}
}
////ATTACHMENT ADDED STATE
if (state is EligibilityAttachmentAddedState) {
if (state.response['success']) {
successAlert(context, "Adding Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<EligibilityBloc>()
.add(const LoadEligibility());
});
} else {
errorAlert(context, "Adding Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<EligibilityBloc>()
.add(const LoadEligibility());
});
}
}
////ADDED STATE
if (state is EligibilityAddedState) {
if (state.response['success']) {
@ -171,13 +195,34 @@ class EligibiltyScreen extends StatelessWidget {
});
}
}
////ATTACHMENT DELETED STATE
if (state is EligibilitytAttachmentDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
"Attachment has been deleted successfully",
() {
Navigator.of(context).pop();
context
.read<EligibilityBloc>()
.add(const LoadEligibility());
});
} else {
errorAlert(context, "Deletion Failed",
"Error deleting Attachment", () {
Navigator.of(context).pop();
context
.read<EligibilityBloc>()
.add(const LoadEligibility());
});
}
}
},
builder: (context, state) {
return BlocBuilder<EligibilityBloc, EligibilityState>(
builder: (context, state) {
if (state is EligibilityLoaded) {
for (var cat in state.attachmentCategory) {
if (cat.subclass.id == 3) {
if (cat.subclass!.id == 3) {
attachmentCategories.add(cat);
}
}
@ -193,410 +238,460 @@ class EligibiltyScreen extends StatelessWidget {
.eligibility!
.title;
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Container(
width: screenWidth,
padding:
const EdgeInsets.symmetric(
horizontal: 12,
vertical: 8),
decoration: box1(),
child: Row(
child: Column(
children: [
Expanded(
child: Column(
mainAxisSize:
MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
title,
style: Theme.of(
context)
.textTheme
.titleMedium!
.copyWith(
fontWeight:
FontWeight
.w500,
color:
primary),
),
const SizedBox(
height: 5,
),
Text(
"$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}",
style: Theme.of(
context)
.textTheme
.titleSmall),
const SizedBox(
height: 3,
),
Text(
"Rating : ${state.eligibilities[index].rating ?? 'N/A'}",
style: Theme.of(
context)
.textTheme
.titleSmall),
const Divider(),
////Show Attachments
SizedBox(
child: state.eligibilities[index].attachments ==
null ||
state
Row(
children: [
Expanded(
child: Column(
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
title,
style: Theme.of(
context)
.textTheme
.titleMedium!
.copyWith(
fontWeight:
FontWeight
.w500,
color:
primary),
),
const SizedBox(
height: 5,
),
Text(
"$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}",
style: Theme.of(
context)
.textTheme
.titleSmall),
const SizedBox(
height: 3,
),
Text(
"Rating : ${state.eligibilities[index].rating ?? 'N/A'}",
style: Theme.of(
context)
.textTheme
.titleSmall),
]),
),
AppPopupMenu<int>(
offset: const Offset(
-10, -10),
elevation: 3,
onSelected: (value) {
////delete eligibilty-= = = = = = = = =>>
if (value == 2) {
confirmAlert(
context, () {
final progress =
ProgressHUD.of(
context);
progress!
.showWithText(
"Loading...");
BlocProvider
.of<EligibilityBloc>(
context)
.add(DeleteEligibility(
eligibilityId: state
.eligibilities[
index]
.attachments!
.isEmpty
? const SizedBox()
: state.eligibilities[index].attachments !=
null &&
state.eligibilities[index].attachments!.length ==
1
?
////Single Attachment view
SingleAttachment(
onpressed:
() {
confirmAlert(context,
() {
parent.read<EligibilityBloc>().add(DeleteAttachment(attachment: state.eligibilities[index].attachments!.first, moduleId: state.eligibilities[index].attachments!.first.id.toString(), profileId: profileId.toString(), token: token!));
}, "Delete?",
"Confirm Delete?");
},
attachment: state
.eligibilities[index]
.attachments!
.first,
)
////Multiple Attachments View
: MultipleAttachments(
eligibilityName: state
.eligibilities[index]
.eligibility!
.title,
attachments: state
.eligibilities[index]
.attachments!,
))
]),
),
AppPopupMenu<int>(
offset:
const Offset(-10, -10),
elevation: 3,
onSelected: (value) {
////delete eligibilty-= = = = = = = = =>>
if (value == 2) {
confirmAlert(context,
() {
final progress =
ProgressHUD.of(
context);
progress!
.showWithText(
"Loading...");
BlocProvider.of<
EligibilityBloc>(
context)
.add(DeleteEligibility(
eligibilityId: state
.eligibilities[
index]
.id!,
profileId:
profileId
.toString(),
token:
token!));
}, "Delete?",
"Confirm Delete?");
}
if (value == 1) {
////edit eligibilty-= = = = = = = = =>>
final progress =
ProgressHUD.of(
context);
progress!.showWithText(
"Loading...");
EligibityCert
eligibityCert =
state.eligibilities[
index];
bool overseas = eligibityCert
.examAddress!
.country!
.id
.toString() ==
'175'
? false
: true;
eligibityCert.overseas =
overseas;
.id!,
profileId:
profileId
.toString(),
token:
token!));
}, "Delete?",
"Confirm Delete?");
}
if (value == 1) {
////edit eligibilty-= = = = = = = = =>>
final progress =
ProgressHUD.of(
context);
progress!
.showWithText(
"Loading...");
EligibityCert
eligibityCert =
state.eligibilities[
index];
bool overseas = eligibityCert
.examAddress!
.country!
.id
.toString() ==
'175'
? false
: true;
eligibityCert
.overseas =
overseas;
eligibityCert.overseas =
overseas;
eligibityCert
.overseas =
overseas;
context
.read<
EligibilityBloc>()
.add(ShowEditEligibilityForm(
eligibityCert:
eligibityCert));
}
////Attachment
if (value == 3) {
showDialog(
context: context,
builder:
(BuildContext
context) {
return AlertDialog(
contentPadding:
const EdgeInsets
.all(0),
backgroundColor:
Colors.grey
.shade100,
icon:
const Icon(
Icons
.file_copy,
size: 32,
color:
primary,
),
title: const Text(
"File Attachment:"),
content: StatefulBuilder(
builder:
context
.read<
EligibilityBloc>()
.add(ShowEditEligibilityForm(
eligibityCert:
eligibityCert));
}
////Attachment
if (value == 3) {
results.clear();
showDialog(
context:
context,
builder:
(BuildContext
context) {
return AlertDialog(
contentPadding:
const EdgeInsets
.all(0),
backgroundColor:
Colors
.grey
.shade100,
icon:
const Icon(
Icons
.file_copy,
size: 32,
color:
primary,
),
title: const Text(
"File Attachment:"),
content: StatefulBuilder(builder:
(context,
setState) {
return Padding(
padding: const EdgeInsets
.all(
16.0),
child: Column(
mainAxisSize:
MainAxisSize
.min,
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Divider(),
Text(
title,
style:
Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary),
),
const SizedBox(
height:
5,
),
Text(
"$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}",
style: Theme.of(context).textTheme.titleSmall),
const SizedBox(
height:
3,
),
Text(
"Rating : ${state.eligibilities[index].rating ?? 'N/A'}",
style: Theme.of(context).textTheme.titleSmall),
const Divider(),
FormBuilderDropdown(
autovalidateMode: AutovalidateMode.always,
decoration: normalTextFieldStyle("attachment category", "attachment category"),
name: 'attachments_categorues',
validator: FormBuilderValidators.required(errorText: "This field is required"),
onChanged: (value) {
selectedAttachmentCategory = value;
},
items: attachmentCategories.map((e) {
return DropdownMenuItem(value: e, child: Text(e.description));
}).toList()),
const SizedBox(
height:
8,
),
Text(
"You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.",
style:
Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
),
const SizedBox(
height:
5,
),
Text(
"Acceptable Files: PDF, JPEG, PNG",
style:
Theme.of(context).textTheme.bodySmall,
),
Text(
"Max File Size (per attachment): 1MB",
style:
Theme.of(context).textTheme.bodySmall,
),
const Divider(),
ElevatedButton(
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
backgroundColor: MaterialStateProperty.all<Color>(Colors.white),
return Padding(
padding:
const EdgeInsets.all(16.0),
child: Column(
mainAxisSize:
MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Divider(),
Text(
title,
style: Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary),
),
onPressed: () async {
FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [
'jpg',
'png',
'jpeg',
'pdf'
]);
setState(() {
if (newResult != null) {
result = newResult;
}
});
},
child: const Center(
child: Text(
"Select Files",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black),
))),
const Divider(),
SingleChildScrollView(
child:
SizedBox(
height: 100,
width: double.maxFinite,
child: result == null
? const SizedBox()
: Expanded(
child: ListView.builder(
itemCount: result!.files.length,
itemBuilder: (BuildContext context, index) {
final kb = result!.files[index].size / 1024;
final mb = kb / 1024;
final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB';
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: double.infinity,
child: Row(
children: [
Flexible(
child: SizedBox(
child: result!.files[index].extension!.toLowerCase() == 'pdf'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'png'
const SizedBox(
height: 5,
),
Text("$licenseNumber: ${state.eligibilities[index].licenseNumber == null ? 'N/A' : state.eligibilities[index].licenseNumber.toString()}", style: Theme.of(context).textTheme.titleSmall),
const SizedBox(
height: 3,
),
Text("Rating : ${state.eligibilities[index].rating ?? 'N/A'}", style: Theme.of(context).textTheme.titleSmall),
const Divider(),
FormBuilderDropdown(
autovalidateMode: AutovalidateMode.always,
decoration: normalTextFieldStyle("attachment category", "attachment category"),
name: 'attachments_categorues',
validator: FormBuilderValidators.required(errorText: "This field is required"),
onChanged: (value) {
selectedAttachmentCategory = value;
},
items: attachmentCategories.map((e) {
return DropdownMenuItem(value: e, child: Text(e.description!));
}).toList()),
const SizedBox(
height: 8,
),
Text(
"You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.",
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
),
const SizedBox(
height: 5,
),
Text(
"Acceptable Files: PDF, JPEG, PNG",
style: Theme.of(context).textTheme.bodySmall,
),
Text(
"Max File Size (per attachment): 1MB",
style: Theme.of(context).textTheme.bodySmall,
),
const Divider(),
ElevatedButton(
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
backgroundColor: MaterialStateProperty.all<Color>(Colors.white),
),
onPressed: () async {
FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [
'jpg',
'png',
'jpeg',
'pdf'
]);
setState(() {
FilePickerResult? x;
if (newResult != null) {
newResult.files.forEach((element) {
results.add(element);
});
}
});
},
child: const Center(
child: Text(
"Select Files",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black),
))),
const Divider(),
SingleChildScrollView(
child: SizedBox(
height: 100,
width: double.maxFinite,
child: results.isEmpty
? const SizedBox()
: Expanded(
child: ListView.builder(
itemCount: results.length,
itemBuilder: (BuildContext context, index) {
final kb = results[index].size / 1024;
final mb = kb / 1024;
final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB';
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: double.infinity,
child: Row(
children: [
Flexible(
child: SizedBox(
child: results[index].extension!.toLowerCase() == 'pdf'
? SvgPicture.asset(
'assets/svgs/png.svg',
'assets/svgs/pdf.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'jpg' || result!.files[index].extension!.toLowerCase() == 'jpeg'
: results[index].extension!.toLowerCase() == 'png'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
'assets/svgs/png.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: const SizedBox())),
const SizedBox(
width: 12,
),
Flexible(
flex: 4,
child: Text(
result!.files[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
: results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: const SizedBox())),
const SizedBox(
width: 12,
),
Flexible(
flex: 6,
child: Text(
results[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
const SizedBox(width: 8,),
Flexible(
),
const SizedBox(
width: 8,
),
Flexible(
flex: 2,
child: Text(size))
],
)),
const Divider()
],
);
}),
),
),
),
const SizedBox(
height:
12,
),
SizedBox(
width:
double.maxFinite,
height:
50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
List<String> paths = [];
child: Text(
size,
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
)),
Flexible(
flex: 1,
child: IconButton(
icon: const Icon(
Icons.close,
color: Colors.grey,
),
onPressed: () {
setState(() {
results.removeAt(index);
});
},
))
],
)),
const Divider()
],
);
}),
),
),
),
const SizedBox(
height: 12,
),
SizedBox(
width: double.maxFinite,
height: 50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
List<String> paths = [];
if (selectedAttachmentCategory != null) {
for (var res in result!.files) {
paths.add(res.path!);
}
Navigator.pop(context);
parent.read<EligibilityBloc>().add(AddAttachment(attachmentModule: state.eligibilities[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
}
},
child: const Text("Submit")),
)
]),
if (selectedAttachmentCategory != null && results.isNotEmpty) {
for (var res in results) {
paths.add(res.path!);
}
setState(() {
results.clear();
});
Navigator.pop(context);
parent.read<EligibilityBloc>().add(AddEligibiltyAttachment(attachmentModule: state.eligibilities[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
}
},
child: const Text("Submit")),
)
]),
);
}),
);
}),
);
});
}
},
menuItems: [
popMenuItem(
text: "Update",
value: 1,
icon: Icons.edit),
popMenuItem(
text: "Remove",
value: 2,
icon: Icons.delete),
popMenuItem(
text: "Attach",
value: 3,
icon: Icons
.attach_file),
});
}
},
menuItems: [
popMenuItem(
text: "Update",
value: 1,
icon: Icons.edit),
popMenuItem(
text: "Remove",
value: 2,
icon:
Icons.delete),
popMenuItem(
text: "Attach",
value: 3,
icon: Icons
.attach_file),
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
)
],
icon: const Icon(
Icons.more_vert,
color: Colors.grey,
),
tooltip: "Options",
)
),
const Divider(),
////Show Attachments
SizedBox(
width: screenWidth,
child: state
.eligibilities[
index]
.attachments ==
null ||
state
.eligibilities[
index]
.attachments!
.isEmpty
? const SizedBox()
: state.eligibilities[index].attachments !=
null &&
state
.eligibilities[
index]
.attachments!
.length ==
1
?
////Single Attachment view
SingleAttachment(
onpressed:
() {
confirmAlert(
context,
() {
parent.read<EligibilityBloc>().add(DeleteEligibyAttachment(
attachment: state
.eligibilities[
index]
.attachments!
.first,
moduleId: state
.eligibilities[
index]
.id
.toString(),
profileId: profileId
.toString(),
token:
token!));
}, "Delete?",
"Confirm Delete?");
},
attachment: state
.eligibilities[
index]
.attachments!
.first,
)
////Multiple Attachments View
: MultipleAttachments(
profileId:
profileId!,
token: token!,
moduleId: state
.eligibilities[
index]
.eligibility!
.id,
educationBloc:
null,
learningDevelopmentBloc:
null,
workHistoryBloc:
null,
eligibilityBloc:
BlocProvider.of<
EligibilityBloc>(
context),
blocId: 2,
eligibilityName: state
.eligibilities[
index]
.eligibility!
.title,
attachments: state
.eligibilities[
index]
.attachments!,
))
],
),
),

View File

@ -1,19 +1,18 @@
import 'package:app_popup_menu/app_popup_menu.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:intl/intl.dart';
import 'package:unit2/bloc/profile/education/education_bloc.dart';
import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/model/profile/learning_development.dart';
import 'package:unit2/screens/profile/components/learning_development/edit_modal.dart';
import 'package:unit2/theme-data.dart/box_shadow.dart';
import 'package:unit2/theme-data.dart/colors.dart';
@ -41,9 +40,9 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
Widget build(BuildContext context) {
String token;
int profileId;
BuildContext parent = context;
BuildContext parent = context;
DateFormat dteFormat2 = DateFormat.yMMMMd('en_US');
FilePickerResult? result;
List<PlatformFile>? results = [];
AttachmentCategory? selectedAttachmentCategory;
List<AttachmentCategory> attachmentCategories = [];
return Scaffold(
@ -89,13 +88,11 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
backgroundColor: Colors.black87,
child: BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is UserLoggedIn) {
token = state.userData!.user!.login!.token!;
profileId = state.userData!.user!.login!.user!.profileId!;
return BlocBuilder<ProfileBloc, ProfileState>(
builder: (context, state) {
if (state is ProfileLoaded) {
return BlocConsumer<LearningDevelopmentBloc,
LearningDevelopmentState>(
@ -134,6 +131,27 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
});
}
}
////Attachment Added State
if (state is LearningDevAttachmentAddedState) {
if (state.response['success']) {
successAlert(context, "Adding Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<LearningDevelopmentBloc>()
.add(LoadLearniningDevelopment());
});
} else {
errorAlert(context, "Adding Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<LearningDevelopmentBloc>()
.add(LoadLearniningDevelopment());
});
}
}
////Updated State
if (state is LearningDevelopmentUpdatedState) {
if (state.response['success']) {
@ -177,16 +195,36 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
});
}
}
////ATTACHMENT DELETED STATE
if (state is LearningDevAttachmentDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
"Attachment has been deleted successfully",
() {
Navigator.of(context).pop();
context
.read<LearningDevelopmentBloc>()
.add(LoadLearniningDevelopment());
});
} else {
errorAlert(context, "Deletion Failed",
"Error deleting Attachment", () {
Navigator.of(context).pop();
context
.read<LearningDevelopmentBloc>()
.add(LoadLearniningDevelopment());
});
}
}
// TODO: implement listener
},
builder: (context, state) {
if (state is LearningDevelopmentLoadedState) {
for (var cat in state.attachmentCategory) {
if (cat.subclass.id == 2) {
attachmentCategories.add(cat);
}
}
for (var cat in state.attachmentCategory) {
if (cat.subclass!.id == 2) {
attachmentCategories.add(cat);
}
}
if (state.learningsAndDevelopment.isNotEmpty) {
return ListView.builder(
padding: const EdgeInsets.symmetric(
@ -232,28 +270,32 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
Expanded(
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
training,
style: Theme.of(context)
style: Theme.of(
context)
.textTheme
.titleMedium!
.copyWith(
fontWeight:
FontWeight
.w600,
color: primary),
color:
primary),
),
const SizedBox(
height: 8,
),
Text(
provider,
style: Theme.of(context)
style: Theme.of(
context)
.textTheme
.titleSmall,
),
@ -262,7 +304,8 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
),
Text(
"$duration: $start to $end",
style: Theme.of(context)
style: Theme.of(
context)
.textTheme
.labelMedium,
),
@ -272,39 +315,39 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
]),
),
AppPopupMenu<int>(
offset: const Offset(-10, -10),
offset:
const Offset(-10, -10),
elevation: 3,
onSelected: (value) {
////delete -= = = = = = = = =>>
if (value == 2) {
confirmAlert(context, () {
confirmAlert(context,
() {
final progress =
ProgressHUD.of(
context);
progress!.showWithText(
"Loading...");
BlocProvider.of<
LearningDevelopmentBloc>(
context)
.add(DeleteLearningDevelopment(
trainingId: state
.learningsAndDevelopment[
index]
.conductedTraining!
.id!,
hours: state
.learningsAndDevelopment[
index]
.conductedTraining!
.totalHours!,
sponsorId: state
.learningsAndDevelopment[
index]
.sponsoredBy
?.id,
profileId:
profileId,
token: token));
progress!
.showWithText(
"Loading...");
BlocProvider.of<LearningDevelopmentBloc>(context).add(DeleteLearningDevelopment(
trainingId: state
.learningsAndDevelopment[
index]
.conductedTraining!
.id!,
hours: state
.learningsAndDevelopment[
index]
.conductedTraining!
.totalHours!,
sponsorId: state
.learningsAndDevelopment[
index]
.sponsoredBy
?.id,
profileId:
profileId,
token: token));
}, "Delete?",
"Confirm Delete?");
}
@ -312,7 +355,8 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
bool isOverseas;
////edit = = = = = = = =>>
final progress =
ProgressHUD.of(context);
ProgressHUD.of(
context);
progress!.showWithText(
"Loading...");
@ -340,225 +384,246 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
isOverseas:
isOverseas));
}
if(value == 3){
showDialog(
context: context,
builder:
(BuildContext
context) {
return AlertDialog(
contentPadding:
const EdgeInsets
.all(0),
backgroundColor:
Colors.grey
.shade100,
icon:
const Icon(
Icons
.file_copy,
size: 32,
color:
primary,
),
title: const Text(
"File Attachment:"),
content: StatefulBuilder(
builder:
(context,
setState) {
return Padding(
padding: const EdgeInsets
.all(
16.0),
child: Column(
mainAxisSize:
MainAxisSize
.min,
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Divider(),
Text(
training,
style:
Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary),
if (value == 3) {
results.clear();
showDialog(
context: context,
builder:
(BuildContext
context) {
return AlertDialog(
contentPadding:
const EdgeInsets
.all(0),
backgroundColor:
Colors.grey
.shade100,
icon:
const Icon(
Icons
.file_copy,
size: 32,
color:
primary,
),
title: const Text(
"File Attachment:"),
content: StatefulBuilder(
builder:
(context,
setState) {
return Padding(
padding: const EdgeInsets
.all(
16.0),
child: Column(
mainAxisSize:
MainAxisSize
.min,
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Divider(),
Text(
training,
style:
Theme.of(context).textTheme.titleMedium!.copyWith(fontWeight: FontWeight.w500, color: primary),
),
const SizedBox(
height:
5,
),
Text(
provider,
style: Theme.of(context).textTheme.titleSmall),
const SizedBox(
height:
3,
),
Text(
"$start TO $end",
style: Theme.of(context).textTheme.titleSmall),
const Divider(),
FormBuilderDropdown(
autovalidateMode: AutovalidateMode.always,
decoration: normalTextFieldStyle("attachment category", "attachment category"),
name: 'attachments_categorues',
validator: FormBuilderValidators.required(errorText: "This field is required"),
onChanged: (value) {
selectedAttachmentCategory = value;
},
items: attachmentCategories.map((e) {
return DropdownMenuItem(value: e, child: Text(e.description!));
}).toList()),
const SizedBox(
height:
8,
),
Text(
"You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.",
style:
Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
),
const SizedBox(
height:
5,
),
Text(
"Acceptable Files: PDF, JPEG, PNG",
style:
Theme.of(context).textTheme.bodySmall,
),
Text(
"Max File Size (per attachment): 1MB",
style:
Theme.of(context).textTheme.bodySmall,
),
const Divider(),
ElevatedButton(
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
backgroundColor: MaterialStateProperty.all<Color>(Colors.white),
),
const SizedBox(
height:
5,
),
Text(
provider,
style: Theme.of(context).textTheme.titleSmall),
const SizedBox(
height:
3,
),
Text(
"$start TO $end",
style: Theme.of(context).textTheme.titleSmall),
const Divider(),
FormBuilderDropdown(
autovalidateMode: AutovalidateMode.always,
decoration: normalTextFieldStyle("attachment category", "attachment category"),
name: 'attachments_categorues',
validator: FormBuilderValidators.required(errorText: "This field is required"),
onChanged: (value) {
selectedAttachmentCategory = value;
},
items: attachmentCategories.map((e) {
return DropdownMenuItem(value: e, child: Text(e.description));
}).toList()),
const SizedBox(
height:
8,
),
Text(
"You may attach necessary documents such as Transcript of Records (TOR), diploma, and the likes.",
style:
Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),
),
const SizedBox(
height:
5,
),
Text(
"Acceptable Files: PDF, JPEG, PNG",
style:
Theme.of(context).textTheme.bodySmall,
),
Text(
"Max File Size (per attachment): 1MB",
style:
Theme.of(context).textTheme.bodySmall,
),
const Divider(),
ElevatedButton(
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
backgroundColor: MaterialStateProperty.all<Color>(Colors.white),
),
onPressed: () async {
FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [
'jpg',
'png',
'jpeg',
'pdf'
]);
setState(() {
if (newResult != null) {
result = newResult;
}
onPressed: () async {
FilePickerResult? newResult = await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: [
'jpg',
'png',
'jpeg',
'pdf'
]);
setState(() {
if (newResult != null) {
newResult.files.forEach((element) {
results.add(element);
});
},
child: const Center(
child: Text(
"Select Files",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black),
))),
const Divider(),
SingleChildScrollView(
child:
SizedBox(
height: 100,
width: double.maxFinite,
child: result == null
? const SizedBox()
: Expanded(
child: ListView.builder(
itemCount: result!.files.length,
itemBuilder: (BuildContext context, index) {
final kb = result!.files[index].size / 1024;
final mb = kb / 1024;
final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB';
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: double.infinity,
child: Row(
children: [
Flexible(
flex: 1,
child: SizedBox(
child: result!.files[index].extension!.toLowerCase() == 'pdf'
}
});
},
child: const Center(
child: Text(
"Select Files",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black),
))),
const Divider(),
SingleChildScrollView(
child:
SizedBox(
height: 100,
width: double.maxFinite,
child: results.isEmpty
? const SizedBox()
: Expanded(
child: ListView.builder(
itemCount: results.length,
itemBuilder: (BuildContext context, index) {
final kb = results[index].size / 1024;
final mb = kb / 1024;
final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB';
return Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: double.infinity,
child: Row(
children: [
Flexible(
flex: 1,
child: SizedBox(
child: results[index].extension!.toLowerCase() == 'pdf'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: results[index].extension!.toLowerCase() == 'png'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
'assets/svgs/png.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'png'
: results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg'
? SvgPicture.asset(
'assets/svgs/png.svg',
'assets/svgs/jpg.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'jpg' || result!.files[index].extension!.toLowerCase() == 'jpeg'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: const SizedBox())),
const SizedBox(
width: 12,
),
Flexible(
flex: 4,
child: Text(
result!.files[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
),
const SizedBox(width: 12,),
Flexible(
flex: 2,
child: Text(size))
],
)),
const Divider()
],
);
}),
),
),
),
const SizedBox(
height:
12,
),
SizedBox(
width:
double.maxFinite,
height:
50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
List<String> paths = [];
: const SizedBox())),
const SizedBox(
width: 12,
),
Flexible(
flex: 6,
child: Text(
results[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
),
const SizedBox(
width: 8,
),
Flexible(
flex: 2,
child: Text(
size,
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
)),
Flexible(
flex: 1,
child: IconButton(
icon: const Icon(
Icons.close,
color: Colors.grey,
),
onPressed: () {
setState(() {
results.removeAt(index);
});
},
))
],
)),
const Divider()
],
);
}),
),
),
),
const SizedBox(
height:
12,
),
SizedBox(
width:
double.maxFinite,
height:
50,
child: ElevatedButton(
style: mainBtnStyle(primary, Colors.transparent, second),
onPressed: () {
List<String> paths = [];
if (selectedAttachmentCategory != null) {
for (var res in result!.files) {
paths.add(res.path!);
}
Navigator.pop(context);
parent.read<LearningDevelopmentBloc>().add(AddAttachment(attachmentModule: state.learningsAndDevelopment[index].conductedTraining!.id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
}
},
child: const Text("Submit")),
)
]),
);
}),
if (selectedAttachmentCategory != null && results.isNotEmpty) {
for (var res in results) {
paths.add(res.path!);
}
results.clear();
Navigator.pop(context);
parent.read<LearningDevelopmentBloc>().add(AddALearningDevttachment(attachmentModule: state.learningsAndDevelopment[index].conductedTraining!.id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token, profileId: profileId.toString()));
}
},
child: const Text("Submit")),
)
]),
);
});
}),
);
});
}
},
menuItems: [
@ -573,7 +638,8 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
popMenuItem(
text: "Attach",
value: 3,
icon: Icons.attach_file),
icon: Icons
.attach_file),
],
icon: const Icon(
Icons.more_vert,
@ -584,44 +650,92 @@ class LearningAndDevelopmentScreen extends StatelessWidget {
],
),
SizedBox(
child: state.learningsAndDevelopment[index].attachments ==
null ||
state
child: state
.learningsAndDevelopment[
index]
.attachments ==
null ||
state
.learningsAndDevelopment[
index]
.attachments!
.isEmpty
? const SizedBox()
: state
.learningsAndDevelopment[
index]
.attachments !=
null &&
state
.learningsAndDevelopment[
index]
.attachments!
.length ==
1
?
////Single Attachment view
SingleAttachment(
onpressed: () {
confirmAlert(
context,
() {
parent.read<LearningDevelopmentBloc>().add(DeleteLearningDevAttachment(
attachment: state
.learningsAndDevelopment[
index]
.attachments!
.isEmpty
? const SizedBox()
: state.learningsAndDevelopment[index].attachments !=
null &&
state.learningsAndDevelopment[index].attachments!.length ==
1
?
////Single Attachment view
SingleAttachment(
onpressed:
() {
confirmAlert(context,
() {
}, "Delete?",
"Confirm Delete?");
},
attachment: state
.learningsAndDevelopment[index]
.attachments!
.first,
)
////Multiple Attachments View
: MultipleAttachments(
eligibilityName: state
.learningsAndDevelopment[index]
.conductedTraining!.title!.title!,
attachments: state
.learningsAndDevelopment[index]
.attachments!,
))
.first,
moduleId: state
.learningsAndDevelopment[
index]
.conductedTraining!
.id!,
profileId:
profileId,
token:
token));
}, "Delete?",
"Confirm Delete?");
},
attachment: state
.learningsAndDevelopment[
index]
.attachments!
.first,
)
////Multiple Attachments View
: MultipleAttachments(
profileId:
profileId,
token: token,
moduleId: state
.learningsAndDevelopment[
index]
.conductedTraining!
.title!
.id!,
educationBloc:
null,
eligibilityBloc:
null,
learningDevelopmentBloc:
BlocProvider.of<
LearningDevelopmentBloc>(
context),
workHistoryBloc:
null,
blocId: 4,
eligibilityName: state
.learningsAndDevelopment[
index]
.conductedTraining!
.title!
.title!,
attachments: state
.learningsAndDevelopment[
index]
.attachments!,
))
],
),
),

View File

@ -7,9 +7,11 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:intl/intl.dart';
import 'package:unit2/bloc/profile/education/education_bloc.dart';
import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart';
import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart';
import 'package:unit2/bloc/profile/profile_bloc.dart';
import 'package:unit2/bloc/user/user_bloc.dart';
import 'package:unit2/screens/profile/components/work_history/add_modal.dart';
@ -21,7 +23,6 @@ import 'package:unit2/widgets/Leadings/add_leading.dart';
import 'package:unit2/widgets/Leadings/close_leading.dart';
import 'package:unit2/widgets/empty_data.dart';
import 'package:unit2/widgets/error_state.dart';
import '../../../bloc/profile/workHistory/workHistory_bloc.dart';
import '../../../model/profile/attachment.dart';
import '../../../model/profile/work_history.dart';
@ -38,10 +39,11 @@ class WorkHistoryScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
DateFormat dteFormat2 = DateFormat.yMMMMd('en_US');
BuildContext parent = context;
String? token;
int? profileId;
FilePickerResult? result;
List<PlatformFile>? results = [];
AttachmentCategory? selectedAttachmentCategory;
List<AttachmentCategory> attachmentCategories = [];
return Scaffold(
@ -108,7 +110,7 @@ class WorkHistoryScreen extends StatelessWidget {
final progress = ProgressHUD.of(context);
progress!.dismiss();
}
//DELETED STATE
////DELETED STATE
if (state is DeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
@ -149,6 +151,48 @@ class WorkHistoryScreen extends StatelessWidget {
});
}
}
if (state is WorkHistoryDevAttachmentAddedState) {
if (state.response['success']) {
successAlert(context, "Adding Successfull!",
state.response['message'], () {
Navigator.of(context).pop();
context
.read<WorkHistoryBloc>()
.add(LoadWorkHistories());
});
} else {
errorAlert(context, "Adding Failed",
"Something went wrong. Please try again.",
() {
Navigator.of(context).pop();
context
.read<WorkHistoryBloc>()
.add(LoadWorkHistories());
});
}
}
////ATTACHMENT DELETED STATE
if (state is WorkHistoryDevAttachmentDeletedState) {
if (state.success) {
successAlert(context, "Deletion Successfull",
"Attachment has been deleted successfully",
() {
Navigator.of(context).pop();
context
.read<WorkHistoryBloc>()
.add(LoadWorkHistories());
});
} else {
errorAlert(context, "Deletion Failed",
"Error deleting Attachment", () {
Navigator.of(context).pop();
context
.read<WorkHistoryBloc>()
.add(LoadWorkHistories());
});
}
}
//// EDITED STATE
if (state is WorkHistoryEditedState) {
if (state.response['success']) {
@ -174,7 +218,7 @@ class WorkHistoryScreen extends StatelessWidget {
builder: (context, state) {
if (state is WorkHistoryLoaded) {
for (var cat in state.attachmentCategory) {
if (cat.subclass.id == 4) {
if (cat.subclass!.id == 4) {
attachmentCategories.add(cat);
}
}
@ -201,14 +245,8 @@ class WorkHistoryScreen extends StatelessWidget {
.workExperiences[index]
.toDate!);
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Container(
width: screenWidth,
decoration: box1(),
padding: const EdgeInsets.symmetric(
horizontal: 12, vertical: 8),
@ -303,6 +341,7 @@ class WorkHistoryScreen extends StatelessWidget {
}
////Attachment
if (value == 3) {
results.clear();
showDialog(
context: context,
builder: (BuildContext
@ -383,7 +422,7 @@ class WorkHistoryScreen extends StatelessWidget {
selectedAttachmentCategory = value;
},
items: attachmentCategories.map((e) {
return DropdownMenuItem(value: e, child: Text(e.description));
return DropdownMenuItem(value: e, child: Text(e.description!));
}).toList()),
const SizedBox(
height:
@ -429,7 +468,9 @@ class WorkHistoryScreen extends StatelessWidget {
]);
setState(() {
if (newResult != null) {
result = newResult;
newResult.files.forEach((element) {
results.add(element);
});
}
});
},
@ -447,13 +488,13 @@ class WorkHistoryScreen extends StatelessWidget {
100,
width:
double.maxFinite,
child: result == null
child: results.isEmpty
? const SizedBox()
: Expanded(
child: ListView.builder(
itemCount: result!.files.length,
itemCount: results.length,
itemBuilder: (BuildContext context, index) {
final kb = result!.files[index].size / 1024;
final kb = results[index].size / 1024;
final mb = kb / 1024;
final size = mb >= 1 ? '${mb.toStringAsFixed(2)}MB' : '${kb.toStringAsFixed(2)}KB';
return Column(
@ -465,19 +506,19 @@ class WorkHistoryScreen extends StatelessWidget {
children: [
Flexible(
child: SizedBox(
child: result!.files[index].extension!.toLowerCase() == 'pdf'
child: results[index].extension!.toLowerCase() == 'pdf'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'png'
: results[index].extension!.toLowerCase() == 'png'
? SvgPicture.asset(
'assets/svgs/png.svg',
height: blockSizeVertical * 3,
allowDrawingOutsideViewBox: true,
)
: result!.files[index].extension!.toLowerCase() == 'jpg' || result!.files[index].extension!.toLowerCase() == 'jpeg'
: results[index].extension!.toLowerCase() == 'jpg' || results[index].extension!.toLowerCase() == 'jpeg'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
height: blockSizeVertical * 3,
@ -487,18 +528,36 @@ class WorkHistoryScreen extends StatelessWidget {
const SizedBox(
width: 12,
),
Flexible(
flex: 4,
child: Text(
result!.files[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
Flexible(
flex: 6,
child: Text(
results[index].name,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.headlineLarge!.copyWith(fontSize: blockSizeVertical * 2),
),
),
const SizedBox(
width: 6,
),
Flexible(
flex: 2,
child: Text(
size,
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.grey),
)),
Flexible(
flex: 1,
child: IconButton(
icon: const Icon(
Icons.close,
color: Colors.grey,
),
const SizedBox(width: 12,),
Flexible(
flex: 2,
child: Text(size))
onPressed: () {
setState(() {
results.removeAt(index);
});
},
))
],
)),
const Divider()
@ -522,12 +581,15 @@ class WorkHistoryScreen extends StatelessWidget {
onPressed: () {
List<String> paths = [];
if (selectedAttachmentCategory != null) {
for (var res in result!.files) {
if (selectedAttachmentCategory != null && results.isNotEmpty) {
for (var res in results) {
paths.add(res.path!);
}
setState(() {
results.clear();
});
Navigator.pop(context);
parent.read<WorkHistoryBloc>().add(AddAttachment(attachmentModule: state.workExperiences[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
parent.read<WorkHistoryBloc>().add(AddWorkHistoryAttachment(attachmentModule: state.workExperiences[index].id.toString(), filePaths: paths, categoryId: selectedAttachmentCategory!.id.toString(), token: token!, profileId: profileId.toString()));
}
},
child: const Text("Submit")),
@ -592,8 +654,22 @@ class WorkHistoryScreen extends StatelessWidget {
onpressed: () {
confirmAlert(
context,
() {},
"Delete?",
() {
parent.read<WorkHistoryBloc>().add(DeleteWorkHistoryAttachment(
attachment: state
.workExperiences[
index]
.attachments!
.first,
moduleId: state
.workExperiences[
index]
.id!,
profileId:
profileId!,
token:
token!));
}, "Delete?",
"Confirm Delete?");
},
attachment: state
@ -604,6 +680,22 @@ class WorkHistoryScreen extends StatelessWidget {
)
////Multiple Attachments View
: MultipleAttachments(
profileId:
profileId!,
token: token!,
moduleId: state
.workExperiences[
index]
.id!,
educationBloc:
null,
workHistoryBloc:
BlocProvider.of<WorkHistoryBloc>(context),
eligibilityBloc:
null,
learningDevelopmentBloc:
null,
blocId: 3,
eligibilityName: state
.workExperiences[
index]

View File

@ -1,150 +1,234 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttericon/entypo_icons.dart';
import 'package:unit2/bloc/profile/education/education_bloc.dart';
import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart';
import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart';
import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart';
import 'package:unit2/utils/global_context.dart';
import '../../../model/profile/attachment.dart';
import '../../../theme-data.dart/box_shadow.dart';
import '../../../theme-data.dart/colors.dart';
import '../../../utils/alerts.dart';
import '../../../utils/global.dart';
class MultipleAttachments extends StatelessWidget {
final List<Attachment> attachments;
final String eligibilityName;
const MultipleAttachments({
super.key,
required this.attachments,
required this.eligibilityName
});
final EducationBloc? educationBloc;
final EligibilityBloc? eligibilityBloc;
final LearningDevelopmentBloc? learningDevelopmentBloc;
final WorkHistoryBloc? workHistoryBloc;
final int blocId;
final int moduleId;
final int profileId;
final String token;
const MultipleAttachments(
{super.key,
required this.blocId,
required this.educationBloc,
required this.eligibilityBloc,
required this.learningDevelopmentBloc,
required this.workHistoryBloc,
required this.attachments,
required this.eligibilityName,
required this.moduleId,
required this.profileId,
required this.token});
@override
Widget build(BuildContext context) {
return Row(
children: [
Flexible(
flex:
2,
child: Container(
padding: const EdgeInsets.all(5),
decoration: box1().copyWith(color: Colors.grey.shade300, boxShadow: []),
child: Text(
attachments.first.filename!,
overflow: TextOverflow.ellipsis,
))),
const SizedBox(
width:
8,
),
Flexible(
child:
FittedBox(
child:
Container(
padding:
const EdgeInsets.all(3),
decoration:
box1().copyWith(color: Colors.grey.shade300, boxShadow: []),
child:
InkWell(
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("$eligibilityName Attachments",textAlign: TextAlign.center,),
content: Column(
mainAxisSize: MainAxisSize.min,
children: attachments.map((e) {
String ext = e.filename!.substring(e.filename!.lastIndexOf("."));
return Column(
children: [
Row(
children: [
Flexible(
child: SizedBox(
child: ext == '.pdf'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
height: blockSizeVertical * 5,
allowDrawingOutsideViewBox: true,
)
: ext == '.png'
? SvgPicture.asset(
'assets/svgs/png.svg',
height: blockSizeVertical * 5.5,
allowDrawingOutsideViewBox: true,
)
: ext == '.jpg'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
height: blockSizeVertical * 5,
allowDrawingOutsideViewBox: true,
)
: SvgPicture.asset(
'assets/svgs/jpg.svg',
height: blockSizeVertical * 5,
allowDrawingOutsideViewBox: true,
),
),
),
const SizedBox(width: 8,),
Flexible(
flex: 4,
child: Tooltip(
message: e.filename,
child: Text(
e.filename!,
overflow: TextOverflow.ellipsis,
)),
),
const SizedBox(width: 8,),
Flexible(
child: Row(
children: [
Flexible(
flex: 3,
child: Container(
padding: const EdgeInsets.all(5),
decoration:
box1().copyWith(color: Colors.grey.shade300, boxShadow: []),
child: AutoSizeText(
attachments.first.filename!,
wrapWords: false,
maxLines: 1,
))),
const SizedBox(
width: 8,
),
Flexible(
child: FittedBox(
child: Container(
padding: const EdgeInsets.all(3),
decoration:
box1().copyWith(color: Colors.grey.shade300, boxShadow: []),
child: InkWell(
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"$eligibilityName Attachments",
textAlign: TextAlign.center,
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: attachments.map((e) {
String ext = e.filename!
.substring(e.filename!.lastIndexOf("."));
return Column(
children: [
Row(
children: [
Flexible(
child: IconButton(
icon: const Icon(
Entypo.right_open_mini,
color: Colors.black87,
),
onPressed: () {},
),
),
const SizedBox(width: 8,),
Flexible(
child: IconButton(
icon: const Icon(
Icons.delete,
color: primary,
),
onPressed: () {},
child: SizedBox(
child: ext == '.pdf'
? SvgPicture.asset(
'assets/svgs/pdf.svg',
height: blockSizeVertical * 5,
allowDrawingOutsideViewBox:
true,
)
: ext == '.png'
? SvgPicture.asset(
'assets/svgs/png.svg',
height:
blockSizeVertical *
5.5,
allowDrawingOutsideViewBox:
true,
)
: ext == '.jpg'
? SvgPicture.asset(
'assets/svgs/jpg.svg',
height:
blockSizeVertical *
5,
allowDrawingOutsideViewBox:
true,
)
: SvgPicture.asset(
'assets/svgs/jpg.svg',
height:
blockSizeVertical *
5,
allowDrawingOutsideViewBox:
true,
),
),
),
const SizedBox(
width: 8,
),
Flexible(
flex: 4,
child: Tooltip(
message: e.filename,
child: Text(
e.filename!,
overflow: TextOverflow.ellipsis,
)),
),
const SizedBox(
width: 8,
),
Flexible(
child: Row(
children: [
Flexible(
child: IconButton(
icon: const Icon(
Icons.delete,
color: primary,
),
onPressed: () {
confirmAlert(context, () {
if (blocId == 1) {
Navigator.pop(
NavigationService
.navigatorKey
.currentContext!);
educationBloc!.add(
DeleteEducationAttachment(
attachment: e,
moduleId:
moduleId,
profileId:
profileId,
token: token));
} else if (blocId == 2) {
Navigator.pop(
NavigationService
.navigatorKey
.currentContext!);
eligibilityBloc!.add(
DeleteEligibyAttachment(
attachment: e,
moduleId: moduleId
.toString(),
profileId: profileId
.toString(),
token: token));
} else if (blocId == 3) {
Navigator.pop(
NavigationService
.navigatorKey
.currentContext!);
workHistoryBloc!.add(
DeleteWorkHistoryAttachment(
attachment: e,
moduleId:
moduleId,
profileId:
profileId,
token: token));
} else {
Navigator.pop(
NavigationService
.navigatorKey
.currentContext!);
learningDevelopmentBloc!.add(
DeleteLearningDevAttachment(
attachment: e,
moduleId:
moduleId,
profileId:
profileId,
token: token));
}
}, "Delete?",
"Confirm Delete?");
}),
)
],
),
),
],
),
),
],
),
const Divider()
],
);
}).toList(),
));
});
},
child: Row(
children: const [
Text(" See more.."),
Icon(
Icons.keyboard_arrow_right,
color: Colors.black54,
),
],
),
const Divider()
],
);
}).toList(),
));
});
},
child: Row(
children: const [
Text(" See more.."),
Icon(
Icons.keyboard_arrow_right,
color: Colors.black54,
),
],
),
),
)),
],
);
),
)),
],
);
}
}

View File

@ -1,3 +1,4 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -31,9 +32,10 @@ class SingleAttachment extends StatelessWidget {
children: [
Expanded(
child:
Text(
AutoSizeText(
attachment.filename!,
overflow: TextOverflow.ellipsis,
wrapWords: false,
maxLines: 1,
),
),
const SizedBox(

View File

@ -165,11 +165,11 @@ class EligibilityService {
"category": {
"id": attachment.category?.id,
"subclass": {
"id": attachment.category?.subclass.id,
"name": attachment.category?.subclass.name,
"id": attachment.category?.subclass?.id,
"name": attachment.category?.subclass?.name,
"attachment_class": {
"id": attachment.category?.subclass.attachmentClass.id,
"name": attachment.category?.subclass.attachmentClass.name
"id": attachment.category?.subclass?.attachmentClass?.id,
"name": attachment.category?.subclass?.attachmentClass?.name
}
},
"description": attachment.category?.description

View File

@ -32,7 +32,7 @@ class AttachmentServices {
return attachmentCategories;
}
Future<Map<dynamic, dynamic>> attachment(
Future<Map<dynamic, dynamic>> attachment(
{required String categoryId,
required String module,
required List<String> paths,
@ -74,4 +74,57 @@ class AttachmentServices {
}
return response;
}
Future<bool> deleteAttachment(
{required Attachment attachment,
required int moduleId,
required String profileId,
required String token}) async {
bool? success;
String authtoken = "Token $token";
String path = "${Url.instance.attachments()}$profileId/";
Map? body;
body = {
"attachment_module": moduleId,
"attachments": [
{
"id": attachment.id,
"created_at": attachment.createdAt?.toString(),
"source": attachment.source,
"filename": attachment.filename,
"category": {
"id": attachment.category?.id,
"subclass": {
"id": attachment.category?.subclass?.id,
"name": attachment.category?.subclass?.name,
"attachment_class": {
"id": attachment.category?.subclass?.attachmentClass?.id,
"name": attachment.category?.subclass?.attachmentClass?.name
}
},
"description": attachment.category?.description
}
}
]
};
Map<String, dynamic> params = {"force_mode": "true"};
Map<String, String> headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authtoken
};
// try {
http.Response response = await Request.instance.deleteRequest(
path: path, headers: headers, body: body, param: params);
if (response.statusCode == 200) {
Map data = jsonDecode(response.body);
success = data['success'];
} else {
success = false;
}
// } catch (e) {
// throw (e.toString());
// }
return success!;
}
}

View File

@ -6,9 +6,9 @@ class Url {
String host() {
// return '192.168.10.183:3000';
// return 'agusandelnorte.gov.ph';
// return "192.168.10.219:3000";
// return "192.168.10.241";
return "192.168.10.221:3004";
return "192.168.10.219:3000";
// // return "192.168.10.241";
// return "192.168.10.221:3004";
// return "playweb.agusandelnorte.gov.ph";
// return 'devapi.agusandelnorte.gov.ph:3004';
}